diff --git a/AUTHORS b/AUTHORS index 7b3f031..c57c053 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -277,6 +277,7 @@ Hari Singh <hari.singh1@samsung.com> Harpreet Singh Khurana <harpreet.sk@samsung.com> Harshikesh Kumar <harshikeshnobug@gmail.com> +Hassan Salehe Matar <hassansalehe@gmail.com> Hautio Kari <khautio@gmail.com> Heejin R. Chung <heejin.r.chung@samsung.com> Heeyoun Lee <heeyoun.lee@samsung.com> @@ -807,7 +808,7 @@ Wesley Wigham <wwigham@gmail.com> Will Hirsch <chromium@willhirsch.co.uk> Will Shackleton <w.shackleton@gmail.com> -William Xie <william.xie@chromium.com> +William Xie <william.xie@chromium.org> William Xie <william.xie@intel.com> Xiang Long <xiang.long@intel.com> Xiangze Zhang <xiangze.zhang@intel.com>
diff --git a/DEPS b/DEPS index 2b667b55..292ce50 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': 'f9ec4707ee13db1cb76b368762ad551fe0cd3555', + 'skia_revision': 'd1f5b4908fba8218cb9de57ec440befaf1fa7a1d', # 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': 'b0cb35c7c2a189e1594deb6cd83b6fb25bd0e2aa', + 'v8_revision': 'c93158d2347dcab8e7ecdbe3af2749ffec02c7d1', # 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. @@ -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': '07b4727a34d2f4aff851f0dc420faf617caca220', + 'pdfium_revision': '120c19b6a19377c341658c342c4351eccbb59741', # 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. @@ -106,7 +106,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': '6cc352e216938d78b65fb8ccbeebfc1f7f7486c4', + 'boringssl_revision': '8793942c5c7f4a46dcadea3a686c50f2b1c312ed', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -303,12 +303,12 @@ }, 'src/third_party/custom_tabs_client/src': { - 'url': Var('chromium_git') + '/external/github.com/GoogleChrome/custom-tabs-client.git' + '@' + 'afe8a13457103292fb1ba49877a0b0e5abdc2f36', + 'url': Var('chromium_git') + '/custom-tabs-client.git' + '@' + 'afe8a13457103292fb1ba49877a0b0e5abdc2f36', 'condition': 'checkout_android', }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ddfead3483f2c1b49419de2b9f561cb32763f2b3', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '7227d2175a9efdf5c1b9482e6fae0e5e5b00b3de', # DevTools node modules. Used on Linux buildbots only. 'src/third_party/devtools-node-modules': { @@ -330,7 +330,7 @@ }, 'src/third_party/ffmpeg': - Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '252244150ad759fe86470f40642514bf2a7aec98', + Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '168dfaa19bfdaa60e58a675eea67d2ee700fcdf9', 'src/third_party/findbugs': { 'url': Var('chromium_git') + '/chromium/deps/findbugs.git' + '@' + '4275d9ac8610db6b1bc9a5e887f97e41b33fac67', @@ -624,7 +624,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'e4919fa03c74bd561dcabf3e61668fa3c7e54353', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '2707fb2782e7a47d0f53cf8e561bef0bc00fad66', # commit position 20628 + Var('webrtc_git') + '/src.git' + '@' + '202be3957d9528cbd92a2d212e1fd11ce9da2bb8', # commit position 20628 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/WATCHLISTS b/WATCHLISTS index 511cd34..4361ed9 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -84,7 +84,8 @@ 'filepath': 'android_webview/', }, 'app_list': { - 'filepath': 'chrome/browser/ui/app_list'\ + 'filepath': 'ash/app_list'\ + '|chrome/browser/ui/app_list'\ '|chrome/browser/ui/ash/app_list'\ '|chrome/browser/ui/views/app_list'\ '|ui/app_list/' @@ -1946,8 +1947,7 @@ 'components_deps': ['blundell+watchlist@chromium.org', 'droger+watchlist@chromium.org', 'sdefresne+watchlist@chromium.org'], - 'content': ['darin-cc@chromium.org', - 'jam@chromium.org'], + 'content': ['jam@chromium.org'], 'content_bluetooth': ['cco3+watch@chromium.org', 'mattreynolds+watch@chromium.org', 'ortuno+watch@chromium.org', @@ -2080,8 +2080,7 @@ 'liaoyuke+watch@chromium.org'], 'ios_web': ['ios-reviews+web@chromium.org', 'eugenebut@chromium.org'], - 'ipc': ['darin-cc@chromium.org', - 'jam@chromium.org'], + 'ipc': ['jam@chromium.org'], 'libvpx': ['fgalligan@chromium.org', 'johannkoenig@chromium.org', 'jzern@chromium.org',
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index 984f2f9..407bbbd 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc
@@ -340,8 +340,7 @@ content::ResourceContext* context, const std::vector<std::pair<int, int> >& render_frames, base::Callback<void(bool)> callback) { - // Android WebView does not yet support web workers. - callback.Run(false); + callback.Run(true); } bool AwContentBrowserClient::AllowWorkerIndexedDB( @@ -349,8 +348,7 @@ const base::string16& name, content::ResourceContext* context, const std::vector<std::pair<int, int> >& render_frames) { - // Android WebView does not yet support web workers. - return false; + return true; } content::QuotaPermissionContext*
diff --git a/android_webview/browser/aw_cookie_access_policy.cc b/android_webview/browser/aw_cookie_access_policy.cc index b88f947..e2562ee 100644 --- a/android_webview/browser/aw_cookie_access_policy.cc +++ b/android_webview/browser/aw_cookie_access_policy.cc
@@ -85,7 +85,7 @@ } bool AwCookieAccessPolicy::OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) { bool global = GetShouldAcceptCookies(); bool thirdParty = GetShouldAcceptThirdPartyCookies(request);
diff --git a/android_webview/browser/aw_cookie_access_policy.h b/android_webview/browser/aw_cookie_access_policy.h index 32b8d3f..32dd517 100644 --- a/android_webview/browser/aw_cookie_access_policy.h +++ b/android_webview/browser/aw_cookie_access_policy.h
@@ -45,7 +45,7 @@ bool OnCanGetCookies(const net::URLRequest& request, const net::CookieList& cookie_list); bool OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options); // These are the functions called when operating over cookies from the
diff --git a/android_webview/browser/aw_safe_browsing_blocking_page.cc b/android_webview/browser/aw_safe_browsing_blocking_page.cc index 80ebf77..559c69c 100644 --- a/android_webview/browser/aw_safe_browsing_blocking_page.cc +++ b/android_webview/browser/aw_safe_browsing_blocking_page.cc
@@ -7,6 +7,7 @@ #include "android_webview/browser/aw_browser_context.h" #include "android_webview/browser/aw_safe_browsing_ui_manager.h" #include "android_webview/browser/net/aw_url_request_context_getter.h" +#include "base/metrics/histogram_macros.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/browser/threat_details.h" #include "components/safe_browsing/triggers/trigger_manager.h" @@ -41,6 +42,8 @@ std::move(controller_client), display_options), threat_details_in_progress_(false) { + UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.Interstitial.Type", errorUiType, + ErrorUiType::COUNT); if (errorUiType == ErrorUiType::QUIET_SMALL || errorUiType == ErrorUiType::QUIET_GIANT) { set_sb_error_ui(base::MakeUnique<SafeBrowsingQuietErrorUI>(
diff --git a/android_webview/browser/aw_safe_browsing_blocking_page.h b/android_webview/browser/aw_safe_browsing_blocking_page.h index b65c192..7820624 100644 --- a/android_webview/browser/aw_safe_browsing_blocking_page.h +++ b/android_webview/browser/aw_safe_browsing_blocking_page.h
@@ -29,8 +29,10 @@ protected: // Used to specify which BaseSafeBrowsingErrorUI to instantiate, and // parameters they require. + // Note: these values are persisted in UMA logs, so they should never be + // renumbered nor reused. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.android_webview - enum class ErrorUiType { LOUD, QUIET_SMALL, QUIET_GIANT }; + enum class ErrorUiType { LOUD, QUIET_SMALL, QUIET_GIANT, COUNT }; // Don't instantiate this class directly, use ShowBlockingPage instead. AwSafeBrowsingBlockingPage(
diff --git a/android_webview/browser/aw_safe_browsing_ui_manager.cc b/android_webview/browser/aw_safe_browsing_ui_manager.cc index ca87019..b74ae0c 100644 --- a/android_webview/browser/aw_safe_browsing_ui_manager.cc +++ b/android_webview/browser/aw_safe_browsing_ui_manager.cc
@@ -8,6 +8,7 @@ #include "android_webview/browser/net/aw_url_request_context_getter.h" #include "android_webview/common/aw_paths.h" #include "base/command_line.h" +#include "base/metrics/histogram_macros.h" #include "base/path_service.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/base_ping_manager.h" @@ -27,6 +28,11 @@ return "android_webview"; } +// UMA_HISTOGRAM_* macros expand to a lot of code, so wrap this in a helper. +void RecordIsWebViewViewable(bool isViewable) { + UMA_HISTOGRAM_BOOLEAN("SafeBrowsing.WebView.Viewable", isViewable); +} + } // namespace namespace android_webview { @@ -58,11 +64,12 @@ // Check the size of the view UIManagerClient* client = UIManagerClient::FromWebContents(web_contents); if (!client || !client->CanShowInterstitial()) { - LOG(WARNING) << "The view is not suitable to show the SB interstitial"; + RecordIsWebViewViewable(false); OnBlockingPageDone(std::vector<UnsafeResource>{resource}, false, web_contents, resource.url.GetWithEmptyPath()); return; } + RecordIsWebViewViewable(true); safe_browsing::BaseUIManager::DisplayBlockingPage(resource); }
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc index d4d0c82..164015542 100644 --- a/android_webview/browser/hardware_renderer.cc +++ b/android_webview/browser/hardware_renderer.cc
@@ -178,6 +178,7 @@ surfaces_->RemoveChildId(viz::SurfaceId(frame_sink_id_, child_id_)); support_->EvictCurrentSurface(); child_id_ = viz::LocalSurfaceId(); + surfaces_->GetFrameSinkManager()->surface_manager()->GarbageCollectSurfaces(); } void HardwareRenderer::DidReceiveCompositorFrameAck(
diff --git a/android_webview/browser/net/aw_network_delegate.cc b/android_webview/browser/net/aw_network_delegate.cc index 77bc59e5..4474ef0 100644 --- a/android_webview/browser/net/aw_network_delegate.cc +++ b/android_webview/browser/net/aw_network_delegate.cc
@@ -134,10 +134,9 @@ } bool AwNetworkDelegate::OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) { - return AwCookieAccessPolicy::GetInstance()->OnCanSetCookie(request, - cookie_line, + return AwCookieAccessPolicy::GetInstance()->OnCanSetCookie(request, cookie, options); }
diff --git a/android_webview/browser/net/aw_network_delegate.h b/android_webview/browser/net/aw_network_delegate.h index 2ebd620..a3f0d984 100644 --- a/android_webview/browser/net/aw_network_delegate.h +++ b/android_webview/browser/net/aw_network_delegate.h
@@ -56,7 +56,7 @@ bool OnCanGetCookies(const net::URLRequest& request, const net::CookieList& cookie_list) override; bool OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) override; bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& original_path,
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java b/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java index 39604ad..42594e5 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java +++ b/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
@@ -84,6 +84,7 @@ child.setHtmlInfo(child.newHtmlInfoBuilder("input") .addAttribute("name", field.mName) .addAttribute("type", field.mType) + .addAttribute("label", field.mLabel) .build()); switch (field.getControlType()) { case FormFieldData.TYPE_LIST:
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java index d15d1b1..b12718e 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
@@ -557,6 +557,7 @@ public void testBasicAutofill() throws Throwable { TestWebServer webServer = TestWebServer.start(); final String data = "<html><head></head><body><form action='a.html' name='formname'>" + + "<label>User Name:</label>" + "<input type='text' id='text1' name='username'" + " placeholder='placeholder@placeholder.com' autocomplete='username name'>" + "<input type='checkbox' id='checkbox1' name='showpassword'>" @@ -610,6 +611,7 @@ TestViewStructure.AwHtmlInfo htmlInfo0 = child0.getHtmlInfo(); assertEquals("text", htmlInfo0.getAttribute("type")); assertEquals("username", htmlInfo0.getAttribute("name")); + assertEquals("User Name:", htmlInfo0.getAttribute("label")); // Verify checkbox control filled correctly in ViewStructure. TestViewStructure child1 = viewStructure.getChild(1); @@ -619,6 +621,7 @@ TestViewStructure.AwHtmlInfo htmlInfo1 = child1.getHtmlInfo(); assertEquals("checkbox", htmlInfo1.getAttribute("type")); assertEquals("showpassword", htmlInfo1.getAttribute("name")); + assertEquals("", htmlInfo1.getAttribute("label")); // Verify select control filled correctly in ViewStructure. TestViewStructure child2 = viewStructure.getChild(2);
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 7796a0ff..335513e 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -377,6 +377,8 @@ "shelf/app_list_button.h", "shelf/app_list_shelf_item_delegate.cc", "shelf/app_list_shelf_item_delegate.h", + "shelf/assistant_overlay.cc", + "shelf/assistant_overlay.h", "shelf/ink_drop_button_listener.h", "shelf/login_shelf_view.cc", "shelf/login_shelf_view.h", @@ -422,8 +424,6 @@ "shelf/shelf_window_watcher.h", "shelf/shelf_window_watcher_item_delegate.cc", "shelf/shelf_window_watcher_item_delegate.h", - "shelf/voice_interaction_overlay.cc", - "shelf/voice_interaction_overlay.h", "shell.cc", "shell.h", "shell_delegate.h", @@ -999,7 +999,7 @@ defines = [ "ASH_IMPLEMENTATION" ] public_deps = [ - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//ash/resources", "//ash/resources/vector_icons", "//ash/strings", @@ -1136,7 +1136,7 @@ ":ash", ] deps = [ - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//base/third_party/dynamic_annotations", "//content/public/browser", @@ -1197,7 +1197,7 @@ deps = [ ":ash", ":test_support_without_content", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//base:i18n", "//components/user_manager", @@ -1233,7 +1233,7 @@ ":ash_shell_lib", ":ash_with_content", ":test_support_without_content", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base:i18n", "//chrome:packed_resources", "//chromeos", @@ -1274,7 +1274,7 @@ ":ash", ":ash_with_content", ":test_support_with_content", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//base/test:test_support", "//chromeos", @@ -1541,7 +1541,7 @@ ":ash", ":test_support_without_content", "//ash/autoclick/common:autoclick", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//ash/public/cpp:unit_tests", "//ash/resources", "//ash/resources/vector_icons", @@ -1625,7 +1625,7 @@ deps = [ ":test_support_without_content", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base/test:test_support", "//cc/base", "//mojo/edk/embedder:headers", @@ -1823,7 +1823,7 @@ ] deps = [ "//ash", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//ash/public/interfaces:test_interfaces", "//ash/resources", "//base", @@ -1980,7 +1980,7 @@ ":ash_service_resources", "//ash", "//ash:test_support_without_content", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//base/test:test_config", "//base/test:test_support",
diff --git a/ash/accessibility/accessibility_layer.cc b/ash/accessibility/accessibility_layer.cc index f830e08..ef2154f 100644 --- a/ash/accessibility/accessibility_layer.cc +++ b/ash/accessibility/accessibility_layer.cc
@@ -78,9 +78,6 @@ } } -void AccessibilityLayer::OnDelegatedFrameDamage( - const gfx::Rect& damage_rect_in_dip) {} - void AccessibilityLayer::OnDeviceScaleFactorChanged( float old_device_scale_factor, float new_device_scale_factor) {
diff --git a/ash/accessibility/accessibility_layer.h b/ash/accessibility/accessibility_layer.h index 8fcc686..e124a005 100644 --- a/ash/accessibility/accessibility_layer.h +++ b/ash/accessibility/accessibility_layer.h
@@ -84,7 +84,6 @@ private: // ui::LayerDelegate overrides: - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override;
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc index 6c2baf4..b0aa05c8 100644 --- a/ash/app_list/app_list_presenter_delegate_unittest.cc +++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -4,6 +4,7 @@ #include <memory> +#include "ash/app_list/model/app_list_view_state.h" #include "ash/app_list/test_app_list_presenter_impl.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/config.h" @@ -21,7 +22,6 @@ #include "base/macros.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_switches.h" -#include "ui/app_list/app_list_view_state.h" #include "ui/app_list/views/app_list_main_view.h" #include "ui/app_list/views/app_list_view.h" #include "ui/app_list/views/search_box_view.h"
diff --git a/ash/app_list/model/BUILD.gn b/ash/app_list/model/BUILD.gn new file mode 100644 index 0000000..015aad0 --- /dev/null +++ b/ash/app_list/model/BUILD.gn
@@ -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. + +component("app_list_model") { + sources = [ + "app_list_folder_item.cc", + "app_list_folder_item.h", + "app_list_item.cc", + "app_list_item.h", + "app_list_item_list.cc", + "app_list_item_list.h", + "app_list_item_list_observer.h", + "app_list_item_observer.h", + "app_list_model.cc", + "app_list_model.h", + "app_list_model_observer.h", + "app_list_view_state.h", + "folder_image.cc", + "folder_image.h", + "search/term_break_iterator.cc", + "search/term_break_iterator.h", + "search/tokenized_string.cc", + "search/tokenized_string.h", + "search/tokenized_string_char_iterator.cc", + "search/tokenized_string_char_iterator.h", + "search/tokenized_string_match.cc", + "search/tokenized_string_match.h", + "search_box_model.cc", + "search_box_model.h", + "search_box_model_observer.h", + "search_result.cc", + "search_result.h", + "search_result_observer.h", + ] + + defines = [ "APP_LIST_MODEL_IMPLEMENTATION" ] + + deps = [ + "//base:i18n", + "//cc/paint", + "//components/sync", + "//skia", + "//third_party/icu", + "//ui/base", + "//ui/gfx", + ] +}
diff --git a/ash/app_list/model/DEPS b/ash/app_list/model/DEPS new file mode 100644 index 0000000..5fb592e --- /dev/null +++ b/ash/app_list/model/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+components/sync", +]
diff --git a/ash/app_list/model/README.md b/ash/app_list/model/README.md new file mode 100644 index 0000000..d73546c --- /dev/null +++ b/ash/app_list/model/README.md
@@ -0,0 +1,19 @@ +# App List Model + +Design doc: go/move-applist + +## Introduction + +This directory holds all app list model classes. + +Currently the app list is running in the Chrome process but in the future it'll +be moved into Ash. Everything in //ui/app_list is being refactored and migrated +to //ash/app_list. + +During the migration we'll have build dependencies changed. The following paths +will depend on this since they're referring to the app list model: + +- //chrome/browser/extensions +- //chrome/browser/sync +- //chrome/browser/ui/app_list +- //ui/app_list
diff --git a/ui/app_list/app_list_folder_item.cc b/ash/app_list/model/app_list_folder_item.cc similarity index 95% rename from ui/app_list/app_list_folder_item.cc rename to ash/app_list/model/app_list_folder_item.cc index d8d320e3..f697677 100644 --- a/ui/app_list/app_list_folder_item.cc +++ b/ash/app_list/model/app_list_folder_item.cc
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/app_list/app_list_folder_item.h" +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item_list.h" #include "base/guid.h" -#include "ui/app_list/app_list_item_list.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/image/image_skia.h"
diff --git a/ui/app_list/app_list_folder_item.h b/ash/app_list/model/app_list_folder_item.h similarity index 78% rename from ui/app_list/app_list_folder_item.h rename to ash/app_list/model/app_list_folder_item.h index 464a45e..d138775c 100644 --- a/ui/app_list/app_list_folder_item.h +++ b/ash/app_list/model/app_list_folder_item.h
@@ -2,33 +2,33 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_APP_LIST_FOLDER_ITEM_H_ -#define UI_APP_LIST_APP_LIST_FOLDER_ITEM_H_ +#ifndef ASH_APP_LIST_MODEL_APP_LIST_FOLDER_ITEM_H_ +#define ASH_APP_LIST_MODEL_APP_LIST_FOLDER_ITEM_H_ #include <stddef.h> #include <string> #include <vector> +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_item_list_observer.h" +#include "ash/app_list/model/app_list_item_observer.h" +#include "ash/app_list/model/app_list_model_export.h" +#include "ash/app_list/model/folder_image.h" #include "base/macros.h" -#include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_item_list_observer.h" -#include "ui/app_list/app_list_item_observer.h" -#include "ui/app_list/folder_image.h" namespace gfx { class ImageSkia; class Rect; -} +} // namespace gfx namespace app_list { class AppListItemList; // AppListFolderItem implements the model/controller for folders. -class APP_LIST_EXPORT AppListFolderItem : public AppListItem, - public FolderImageObserver { +class APP_LIST_MODEL_EXPORT AppListFolderItem : public AppListItem, + public FolderImageObserver { public: // The folder type affects folder behavior. enum FolderType { @@ -53,7 +53,8 @@ // the same size of the top item icon. // The Rect returned is in the same coordinates of |folder_icon_bounds|. gfx::Rect GetTargetIconRectInFolderForItem( - AppListItem* item, const gfx::Rect& folder_icon_bounds); + AppListItem* item, + const gfx::Rect& folder_icon_bounds); AppListItemList* item_list() { return item_list_.get(); } const AppListItemList* item_list() const { return item_list_.get(); } @@ -91,4 +92,4 @@ } // namespace app_list -#endif // UI_APP_LIST_APP_LIST_FOLDER_ITEM_H_ +#endif // ASH_APP_LIST_MODEL_APP_LIST_FOLDER_ITEM_H_
diff --git a/ui/app_list/app_list_item.cc b/ash/app_list/model/app_list_item.cc similarity index 81% rename from ui/app_list/app_list_item.cc rename to ash/app_list/model/app_list_item.cc index 8606dd4..d78dc8fd 100644 --- a/ui/app_list/app_list_item.cc +++ b/ash/app_list/model/app_list_item.cc
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/app_list/app_list_item.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_item_observer.h" #include "base/logging.h" -#include "ui/app_list/app_list_item_observer.h" namespace app_list { @@ -13,8 +13,7 @@ : id_(id), highlighted_(false), is_installing_(false), - percent_downloaded_(-1) { -} + percent_downloaded_(-1) {} AppListItem::~AppListItem() { for (auto& observer : observers_) @@ -54,8 +53,7 @@ observers_.RemoveObserver(observer); } -void AppListItem::Activate(int event_flags) { -} +void AppListItem::Activate(int event_flags) {} const char* AppListItem::GetItemType() const { static const char* app_type = ""; @@ -75,17 +73,15 @@ } bool AppListItem::CompareForTest(const AppListItem* other) const { - return id_ == other->id_ && - folder_id_ == other->folder_id_ && - name_ == other->name_ && - short_name_ == other->short_name_ && - GetItemType() == other->GetItemType() && - position_.Equals(other->position_); + return id_ == other->id_ && folder_id_ == other->folder_id_ && + name_ == other->name_ && short_name_ == other->short_name_ && + GetItemType() == other->GetItemType() && + position_.Equals(other->position_); } std::string AppListItem::ToDebugString() const { - return id_.substr(0, 8) + " '" + name_ + "'" - + " [" + position_.ToDebugString() + "]"; + return id_.substr(0, 8) + " '" + name_ + "'" + " [" + + position_.ToDebugString() + "]"; } // Protected methods
diff --git a/ui/app_list/app_list_item.h b/ash/app_list/model/app_list_item.h similarity index 94% rename from ui/app_list/app_list_item.h rename to ash/app_list/model/app_list_item.h index 4f8d9ba..ce688d42 100644 --- a/ui/app_list/app_list_item.h +++ b/ash/app_list/model/app_list_item.h
@@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_APP_LIST_ITEM_H_ -#define UI_APP_LIST_APP_LIST_ITEM_H_ +#ifndef ASH_APP_LIST_MODEL_APP_LIST_ITEM_H_ +#define ASH_APP_LIST_MODEL_APP_LIST_ITEM_H_ #include <stddef.h> #include <string> +#include "ash/app_list/model/app_list_model_export.h" #include "base/macros.h" #include "base/observer_list.h" #include "components/sync/model/string_ordinal.h" -#include "ui/app_list/app_list_export.h" #include "ui/gfx/image/image_skia.h" class FastShowPickler; @@ -30,7 +30,7 @@ // AppListItem provides icon and title to be shown in a AppListItemView // and action to be executed when the AppListItemView is activated. -class APP_LIST_EXPORT AppListItem { +class APP_LIST_MODEL_EXPORT AppListItem { public: explicit AppListItem(const std::string& id); virtual ~AppListItem(); @@ -136,4 +136,4 @@ } // namespace app_list -#endif // UI_APP_LIST_APP_LIST_ITEM_H_ +#endif // ASH_APP_LIST_MODEL_APP_LIST_ITEM_H_
diff --git a/ui/app_list/app_list_item_list.cc b/ash/app_list/model/app_list_item_list.cc similarity index 97% rename from ui/app_list/app_list_item_list.cc rename to ash/app_list/model/app_list_item_list.cc index 2cb13fe7..421a113c 100644 --- a/ui/app_list/app_list_item_list.cc +++ b/ash/app_list/model/app_list_item_list.cc
@@ -2,18 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/app_list/app_list_item_list.h" +#include "ash/app_list/model/app_list_item_list.h" +#include "ash/app_list/model/app_list_item.h" #include "base/memory/ptr_util.h" -#include "ui/app_list/app_list_item.h" namespace app_list { -AppListItemList::AppListItemList() { -} +AppListItemList::AppListItemList() {} -AppListItemList::~AppListItemList() { -} +AppListItemList::~AppListItemList() {} void AppListItemList::AddObserver(AppListItemListObserver* observer) { observers_.AddObserver(observer);
diff --git a/ui/app_list/app_list_item_list.h b/ash/app_list/model/app_list_item_list.h similarity index 92% rename from ui/app_list/app_list_item_list.h rename to ash/app_list/model/app_list_item_list.h index 72ae543..0d6a04b7 100644 --- a/ui/app_list/app_list_item_list.h +++ b/ash/app_list/model/app_list_item_list.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 UI_APP_LIST_APP_LIST_ITEM_LIST_H_ -#define UI_APP_LIST_APP_LIST_ITEM_LIST_H_ +#ifndef ASH_APP_LIST_MODEL_APP_LIST_ITEM_LIST_H_ +#define ASH_APP_LIST_MODEL_APP_LIST_ITEM_LIST_H_ #include <stddef.h> @@ -11,11 +11,11 @@ #include <string> #include <vector> +#include "ash/app_list/model/app_list_item_list_observer.h" +#include "ash/app_list/model/app_list_model_export.h" #include "base/macros.h" #include "base/observer_list.h" #include "components/sync/model/string_ordinal.h" -#include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_item_list_observer.h" namespace app_list { @@ -24,7 +24,7 @@ // Class to manage items in the app list. Used both by AppListModel and // AppListFolderItem. Manages the position ordinal of items in the list, and // notifies observers when items in the list are added / deleted / moved. -class APP_LIST_EXPORT AppListItemList { +class APP_LIST_MODEL_EXPORT AppListItemList { public: AppListItemList(); virtual ~AppListItemList(); @@ -117,4 +117,4 @@ } // namespace app_list -#endif // UI_APP_LIST_APP_LIST_ITEM_LIST_H_ +#endif // ASH_APP_LIST_MODEL_APP_LIST_ITEM_LIST_H_
diff --git a/ui/app_list/app_list_item_list_observer.h b/ash/app_list/model/app_list_item_list_observer.h similarity index 79% rename from ui/app_list/app_list_item_list_observer.h rename to ash/app_list/model/app_list_item_list_observer.h index 7eb1d8a..77f7b059 100644 --- a/ui/app_list/app_list_item_list_observer.h +++ b/ash/app_list/model/app_list_item_list_observer.h
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_APP_LIST_ITEM_LIST_OBSERVER_H_ -#define UI_APP_LIST_APP_LIST_ITEM_LIST_OBSERVER_H_ +#ifndef ASH_APP_LIST_MODEL_APP_LIST_ITEM_LIST_OBSERVER_H_ +#define ASH_APP_LIST_MODEL_APP_LIST_ITEM_LIST_OBSERVER_H_ #include <stddef.h> -#include "ui/app_list/app_list_export.h" +#include "ash/app_list/model/app_list_model_export.h" namespace app_list { class AppListItem; -class APP_LIST_EXPORT AppListItemListObserver { +class APP_LIST_MODEL_EXPORT AppListItemListObserver { public: // Triggered after |item| has been added to the list at |index|. virtual void OnListItemAdded(size_t index, AppListItem* item) {} @@ -38,4 +38,4 @@ } // namespace app_list -#endif // UI_APP_LIST_APP_LIST_ITEM_LIST_OBSERVER_H_ +#endif // ASH_APP_LIST_MODEL_APP_LIST_ITEM_LIST_OBSERVER_H_
diff --git a/ui/app_list/app_list_item_observer.h b/ash/app_list/model/app_list_item_observer.h similarity index 73% rename from ui/app_list/app_list_item_observer.h rename to ash/app_list/model/app_list_item_observer.h index e74e127..8af214d 100644 --- a/ui/app_list/app_list_item_observer.h +++ b/ash/app_list/model/app_list_item_observer.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_APP_LIST_ITEM_OBSERVER_H_ -#define UI_APP_LIST_APP_LIST_ITEM_OBSERVER_H_ +#ifndef ASH_APP_LIST_MODEL_APP_LIST_ITEM_OBSERVER_H_ +#define ASH_APP_LIST_MODEL_APP_LIST_ITEM_OBSERVER_H_ -#include "ui/app_list/app_list_export.h" +#include "ash/app_list/model/app_list_model_export.h" namespace app_list { -class APP_LIST_EXPORT AppListItemObserver { +class APP_LIST_MODEL_EXPORT AppListItemObserver { public: // Invoked after item's icon is changed. virtual void ItemIconChanged() {} @@ -32,4 +32,4 @@ } // namespace app_list -#endif // UI_APP_LIST_APP_LIST_ITEM_OBSERVER_H_ +#endif // ASH_APP_LIST_MODEL_APP_LIST_ITEM_OBSERVER_H_
diff --git a/ui/app_list/app_list_model.cc b/ash/app_list/model/app_list_model.cc similarity index 97% rename from ui/app_list/app_list_model.cc rename to ash/app_list/model/app_list_model.cc index 402d6c26..70853b0e 100644 --- a/ui/app_list/app_list_model.cc +++ b/ash/app_list/model/app_list_model.cc
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/app_list/app_list_model.h" +#include "ash/app_list/model/app_list_model.h" #include <string> #include <utility> -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model_observer.h" -#include "ui/app_list/search_box_model.h" +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model_observer.h" +#include "ash/app_list/model/search_box_model.h" namespace app_list {
diff --git a/ui/app_list/app_list_model.h b/ash/app_list/model/app_list_model.h similarity index 94% rename from ui/app_list/app_list_model.h rename to ash/app_list/model/app_list_model.h index 7de5619..e1a3e7d8 100644 --- a/ui/app_list/app_list_model.h +++ b/ash/app_list/model/app_list_model.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 UI_APP_LIST_APP_LIST_MODEL_H_ -#define UI_APP_LIST_APP_LIST_MODEL_H_ +#ifndef ASH_APP_LIST_MODEL_APP_LIST_MODEL_H_ +#define ASH_APP_LIST_MODEL_APP_LIST_MODEL_H_ #include <stddef.h> @@ -11,13 +11,13 @@ #include <string> #include <vector> +#include "ash/app_list/model/app_list_item_list.h" +#include "ash/app_list/model/app_list_item_list_observer.h" +#include "ash/app_list/model/app_list_model_export.h" +#include "ash/app_list/model/app_list_view_state.h" +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "base/observer_list.h" -#include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_item_list.h" -#include "ui/app_list/app_list_item_list_observer.h" -#include "ui/app_list/app_list_view_state.h" -#include "ui/app_list/search_result.h" #include "ui/base/models/list_model.h" namespace app_list { @@ -35,7 +35,7 @@ // NOTE: Currently this class observes |top_level_item_list_|. The View code may // move entries in the item list directly (but can not add or remove them) and // the model needs to notify its observers when this occurs. -class APP_LIST_EXPORT AppListModel : public AppListItemListObserver { +class APP_LIST_MODEL_EXPORT AppListModel : public AppListItemListObserver { public: enum Status { STATUS_NORMAL, @@ -250,4 +250,4 @@ } // namespace app_list -#endif // UI_APP_LIST_APP_LIST_MODEL_H_ +#endif // ASH_APP_LIST_MODEL_APP_LIST_MODEL_H_
diff --git a/ash/app_list/model/app_list_model_export.h b/ash/app_list/model/app_list_model_export.h new file mode 100644 index 0000000..03e0b87 --- /dev/null +++ b/ash/app_list/model/app_list_model_export.h
@@ -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. + +#ifndef ASH_APP_LIST_MODEL_APP_LIST_MODEL_EXPORT_H_ +#define ASH_APP_LIST_MODEL_APP_LIST_MODEL_EXPORT_H_ + +// Defines APP_LIST_MODEL_EXPORT so that functionality implemented by the +// app_list_model module can be exported to consumers. + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(APP_LIST_MODEL_IMPLEMENTATION) +#define APP_LIST_MODEL_EXPORT __declspec(dllexport) +#else +#define APP_LIST_MODEL_EXPORT __declspec(dllimport) +#endif // defined(APP_LIST_MODEL_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(APP_LIST_MODEL_IMPLEMENTATION) +#define APP_LIST_MODEL_EXPORT __attribute__((visibility("default"))) +#else +#define APP_LIST_MODEL_EXPORT +#endif +#endif + +#else // defined(COMPONENT_BUILD) +#define APP_LIST_MODEL_EXPORT +#endif + +#endif // ASH_APP_LIST_MODEL_APP_LIST_MODEL_EXPORT_H_
diff --git a/ui/app_list/app_list_model_observer.h b/ash/app_list/model/app_list_model_observer.h similarity index 79% rename from ui/app_list/app_list_model_observer.h rename to ash/app_list/model/app_list_model_observer.h index 13953131..ed4ee8d 100644 --- a/ui/app_list/app_list_model_observer.h +++ b/ash/app_list/model/app_list_model_observer.h
@@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_APP_LIST_MODEL_OBSERVER_H_ -#define UI_APP_LIST_APP_LIST_MODEL_OBSERVER_H_ +#ifndef ASH_APP_LIST_MODEL_APP_LIST_MODEL_OBSERVER_H_ +#define ASH_APP_LIST_MODEL_APP_LIST_MODEL_OBSERVER_H_ -#include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_model.h" +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/app_list_model_export.h" namespace app_list { class AppListItem; -class APP_LIST_EXPORT AppListModelObserver { +class APP_LIST_MODEL_EXPORT AppListModelObserver { public: // Triggered after AppListModel's status has changed. virtual void OnAppListModelStatusChanged() {} @@ -42,4 +42,4 @@ } // namespace app_list -#endif // UI_APP_LIST_APP_LIST_MODEL_OBSERVER_H_ +#endif // ASH_APP_LIST_MODEL_APP_LIST_MODEL_OBSERVER_H_
diff --git a/ui/app_list/app_list_view_state.h b/ash/app_list/model/app_list_view_state.h similarity index 85% rename from ui/app_list/app_list_view_state.h rename to ash/app_list/model/app_list_view_state.h index 38c1111..0c64d4c 100644 --- a/ui/app_list/app_list_view_state.h +++ b/ash/app_list/model/app_list_view_state.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 UI_APP_LIST_APP_LIST_VIEW_STATE_H_ -#define UI_APP_LIST_APP_LIST_VIEW_STATE_H_ +#ifndef ASH_APP_LIST_MODEL_APP_LIST_VIEW_STATE_H_ +#define ASH_APP_LIST_MODEL_APP_LIST_VIEW_STATE_H_ namespace app_list { @@ -26,4 +26,4 @@ } // namespace app_list -#endif // UI_APP_LIST_APP_LIST_VIEW_STATE_H_ +#endif // ASH_APP_LIST_MODEL_APP_LIST_VIEW_STATE_H_
diff --git a/ui/app_list/folder_image.cc b/ash/app_list/model/folder_image.cc similarity index 97% rename from ui/app_list/folder_image.cc rename to ash/app_list/model/folder_image.cc index b3b34d791..9baf43d 100644 --- a/ui/app_list/folder_image.cc +++ b/ash/app_list/model/folder_image.cc
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/app_list/folder_image.h" +#include "ash/app_list/model/folder_image.h" #include <vector> +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_item_list.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_item_list.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/point.h" @@ -65,8 +65,7 @@ DCHECK(icons.size() <= FolderImage::kNumFolderTopItems); } -FolderImageSource::~FolderImageSource() { -} +FolderImageSource::~FolderImageSource() {} void FolderImageSource::DrawIcon(gfx::Canvas* canvas, const gfx::ImageSkia& icon,
diff --git a/ui/app_list/folder_image.h b/ash/app_list/model/folder_image.h similarity index 86% rename from ui/app_list/folder_image.h rename to ash/app_list/model/folder_image.h index d877b7d..21c533ea 100644 --- a/ui/app_list/folder_image.h +++ b/ash/app_list/model/folder_image.h
@@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_FOLDER_IMAGE_H_ -#define UI_APP_LIST_FOLDER_IMAGE_H_ +#ifndef ASH_APP_LIST_MODEL_FOLDER_IMAGE_H_ +#define ASH_APP_LIST_MODEL_FOLDER_IMAGE_H_ #include <stddef.h> #include <vector> +#include "ash/app_list/model/app_list_item_list_observer.h" +#include "ash/app_list/model/app_list_item_observer.h" +#include "ash/app_list/model/app_list_model_export.h" #include "base/observer_list.h" -#include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_item_list_observer.h" -#include "ui/app_list/app_list_item_observer.h" #include "ui/gfx/image/image_skia.h" namespace gfx { @@ -24,7 +24,7 @@ class AppListItem; class AppListItemList; -class APP_LIST_EXPORT FolderImageObserver { +class APP_LIST_MODEL_EXPORT FolderImageObserver { public: // Called when the folder icon has changed. virtual void OnFolderImageUpdated() {} @@ -36,8 +36,8 @@ // The icon for an app list folder, dynamically generated by drawing the // folder's items inside a circle. Automatically keeps itself up to date, and // notifies observers when it changes. -class APP_LIST_EXPORT FolderImage : public AppListItemListObserver, - public AppListItemObserver { +class APP_LIST_MODEL_EXPORT FolderImage : public AppListItemListObserver, + public AppListItemObserver { public: // Number of the top items in a folder, which are shown inside the folder icon // and animated when opening and closing a folder. @@ -106,4 +106,4 @@ } // namespace app_list -#endif // UI_APP_LIST_FOLDER_IMAGE_H_ +#endif // ASH_APP_LIST_MODEL_FOLDER_IMAGE_H_
diff --git a/ui/app_list/search/term_break_iterator.cc b/ash/app_list/model/search/term_break_iterator.cc similarity index 81% rename from ui/app_list/search/term_break_iterator.cc rename to ash/app_list/model/search/term_break_iterator.cc index 233a879..32ef60d 100644 --- a/ui/app_list/search/term_break_iterator.cc +++ b/ash/app_list/model/search/term_break_iterator.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 "ui/app_list/search/term_break_iterator.h" +#include "ash/app_list/model/search/term_break_iterator.h" #include "base/i18n/char_iterator.h" #include "base/logging.h" @@ -16,8 +16,7 @@ prev_(npos), pos_(0), iter_(new base::i18n::UTF16CharIterator(&word)), - state_(STATE_START) { -} + state_(STATE_START) {} TermBreakIterator::~TermBreakIterator() {} @@ -26,12 +25,12 @@ // Each col represents new state from input char. Cells with true value // represents a term boundary. const bool kBoundary[][STATE_LAST] = { - // START NUMBER UPPER LOWER CHAR - { false, false, false, false, false }, // START - { false, false, true, true, true }, // NUMBER - { false, true, false, false, true }, // UPPER - { false, true, true, false, true }, // LOWER - { false, true, true, true, false }, // CHAR + // START NUMBER UPPER LOWER CHAR + {false, false, false, false, false}, // START + {false, false, true, true, true}, // NUMBER + {false, true, false, false, true}, // UPPER + {false, true, true, false, true}, // LOWER + {false, true, true, true, false}, // CHAR }; while (iter_->Advance()) {
diff --git a/ui/app_list/search/term_break_iterator.h b/ash/app_list/model/search/term_break_iterator.h similarity index 84% rename from ui/app_list/search/term_break_iterator.h rename to ash/app_list/model/search/term_break_iterator.h index 714e50b5..2795b0a 100644 --- a/ui/app_list/search/term_break_iterator.h +++ b/ash/app_list/model/search/term_break_iterator.h
@@ -2,22 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_SEARCH_TERM_BREAK_ITERATOR_H_ -#define UI_APP_LIST_SEARCH_TERM_BREAK_ITERATOR_H_ +#ifndef ASH_APP_LIST_MODEL_SEARCH_TERM_BREAK_ITERATOR_H_ +#define ASH_APP_LIST_MODEL_SEARCH_TERM_BREAK_ITERATOR_H_ #include <stddef.h> #include <memory> +#include "ash/app_list/model/app_list_model_export.h" #include "base/macros.h" #include "base/strings/string16.h" -#include "ui/app_list/app_list_export.h" namespace base { namespace i18n { class UTF16CharIterator; } -} +} // namespace base namespace app_list { @@ -27,7 +27,7 @@ // e.g. // CamelCase -> Camel, Case // Python2.7 -> Python, 2.7 -class APP_LIST_EXPORT TermBreakIterator { +class APP_LIST_MODEL_EXPORT TermBreakIterator { public: // Note that |word| must out live this iterator. explicit TermBreakIterator(const base::string16& word); @@ -70,4 +70,4 @@ } // namespace app_list -#endif // UI_APP_LIST_SEARCH_TERM_BREAK_ITERATOR_H_ +#endif // ASH_APP_LIST_MODEL_SEARCH_TERM_BREAK_ITERATOR_H_
diff --git a/ui/app_list/search/tokenized_string.cc b/ash/app_list/model/search/tokenized_string.cc similarity index 80% rename from ui/app_list/search/tokenized_string.cc rename to ash/app_list/model/search/tokenized_string.cc index 887fe86..9634ce7e 100644 --- a/ui/app_list/search/tokenized_string.cc +++ b/ash/app_list/model/search/tokenized_string.cc
@@ -2,28 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/app_list/search/tokenized_string.h" +#include "ash/app_list/model/search/tokenized_string.h" #include <stddef.h> +#include "ash/app_list/model/search/term_break_iterator.h" #include "base/i18n/break_iterator.h" #include "base/i18n/case_conversion.h" #include "base/logging.h" -#include "ui/app_list/search/term_break_iterator.h" using base::i18n::BreakIterator; namespace app_list { -TokenizedString::TokenizedString(const base::string16& text) - : text_(text) { +TokenizedString::TokenizedString(const base::string16& text) : text_(text) { Tokenize(); } TokenizedString::~TokenizedString() {} void TokenizedString::Tokenize() { - BreakIterator break_iter(text_, BreakIterator::BREAK_WORD); + BreakIterator break_iter(text_, BreakIterator::BREAK_WORD); if (!break_iter.Init()) { NOTREACHED() << "BreakIterator init failed" << ", text=\"" << text_ << "\"";
diff --git a/ui/app_list/search/tokenized_string.h b/ash/app_list/model/search/tokenized_string.h similarity index 80% rename from ui/app_list/search/tokenized_string.h rename to ash/app_list/model/search/tokenized_string.h index 5eef1baf8..86884f1 100644 --- a/ui/app_list/search/tokenized_string.h +++ b/ash/app_list/model/search/tokenized_string.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_SEARCH_TOKENIZED_STRING_H_ -#define UI_APP_LIST_SEARCH_TOKENIZED_STRING_H_ +#ifndef ASH_APP_LIST_MODEL_SEARCH_TOKENIZED_STRING_H_ +#define ASH_APP_LIST_MODEL_SEARCH_TOKENIZED_STRING_H_ #include <vector> +#include "ash/app_list/model/app_list_model_export.h" #include "base/macros.h" #include "base/strings/string16.h" -#include "ui/app_list/app_list_export.h" #include "ui/gfx/range/range.h" namespace app_list { @@ -17,7 +17,7 @@ // TokenizedString takes a string and breaks it down into token words. It // first breaks using BreakIterator to get all the words. Then it breaks // the words again at camel case boundaries and alpha/number boundaries. -class APP_LIST_EXPORT TokenizedString { +class APP_LIST_MODEL_EXPORT TokenizedString { public: typedef std::vector<base::string16> Tokens; typedef std::vector<gfx::Range> Mappings; @@ -44,4 +44,4 @@ } // namespace app_list -#endif // UI_APP_LIST_SEARCH_TOKENIZED_STRING_H_ +#endif // ASH_APP_LIST_MODEL_SEARCH_TOKENIZED_STRING_H_
diff --git a/ui/app_list/search/tokenized_string_char_iterator.cc b/ash/app_list/model/search/tokenized_string_char_iterator.cc similarity index 88% rename from ui/app_list/search/tokenized_string_char_iterator.cc rename to ash/app_list/model/search/tokenized_string_char_iterator.cc index 766442b..1ed97e2 100644 --- a/ui/app_list/search/tokenized_string_char_iterator.cc +++ b/ash/app_list/model/search/tokenized_string_char_iterator.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 "ui/app_list/search/tokenized_string_char_iterator.h" +#include "ash/app_list/model/search/tokenized_string_char_iterator.h" #include "base/i18n/char_iterator.h" #include "base/logging.h" @@ -13,9 +13,7 @@ TokenizedStringCharIterator::State::State() : token_index(0u), char_index(0) {} TokenizedStringCharIterator::State::State(size_t token_index, int char_index) - : token_index(token_index), - char_index(char_index) { -} + : token_index(token_index), char_index(char_index) {} TokenizedStringCharIterator::TokenizedStringCharIterator( const TokenizedString& tokenized) @@ -52,8 +50,7 @@ int32_t TokenizedStringCharIterator::GetArrayPos() const { DCHECK(current_token_iter_); - return mappings_[current_token_].start() + - current_token_iter_->array_pos(); + return mappings_[current_token_].start() + current_token_iter_->array_pos(); } size_t TokenizedStringCharIterator::GetCharSize() const { @@ -64,8 +61,8 @@ return current_token_iter_ && current_token_iter_->char_pos() == 0; } -TokenizedStringCharIterator::State -TokenizedStringCharIterator::GetState() const { +TokenizedStringCharIterator::State TokenizedStringCharIterator::GetState() + const { return State(current_token_, current_token_iter_ ? current_token_iter_->char_pos() : 0); }
diff --git a/ui/app_list/search/tokenized_string_char_iterator.h b/ash/app_list/model/search/tokenized_string_char_iterator.h similarity index 82% rename from ui/app_list/search/tokenized_string_char_iterator.h rename to ash/app_list/model/search/tokenized_string_char_iterator.h index f2381439..2645240 100644 --- a/ui/app_list/search/tokenized_string_char_iterator.h +++ b/ash/app_list/model/search/tokenized_string_char_iterator.h
@@ -2,28 +2,28 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_SEARCH_TOKENIZED_STRING_CHAR_ITERATOR_H_ -#define UI_APP_LIST_SEARCH_TOKENIZED_STRING_CHAR_ITERATOR_H_ +#ifndef ASH_APP_LIST_MODEL_SEARCH_TOKENIZED_STRING_CHAR_ITERATOR_H_ +#define ASH_APP_LIST_MODEL_SEARCH_TOKENIZED_STRING_CHAR_ITERATOR_H_ #include <stddef.h> #include <stdint.h> #include <memory> +#include "ash/app_list/model/app_list_model_export.h" +#include "ash/app_list/model/search/tokenized_string.h" #include "base/macros.h" -#include "ui/app_list/app_list_export.h" -#include "ui/app_list/search/tokenized_string.h" namespace base { namespace i18n { class UTF16CharIterator; } -} +} // namespace base namespace app_list { // An UTF16 char iterator for a TokenizedString. -class APP_LIST_EXPORT TokenizedStringCharIterator { +class APP_LIST_MODEL_EXPORT TokenizedStringCharIterator { public: struct State { State(); @@ -78,4 +78,4 @@ } // namespace app_list -#endif // UI_APP_LIST_SEARCH_TOKENIZED_STRING_CHAR_ITERATOR_H_ +#endif // ASH_APP_LIST_MODEL_SEARCH_TOKENIZED_STRING_CHAR_ITERATOR_H_
diff --git a/ui/app_list/search/tokenized_string_match.cc b/ash/app_list/model/search/tokenized_string_match.cc similarity index 89% rename from ui/app_list/search/tokenized_string_match.cc rename to ash/app_list/model/search/tokenized_string_match.cc index 385bd0e..f9f290a 100644 --- a/ui/app_list/search/tokenized_string_match.cc +++ b/ash/app_list/model/search/tokenized_string_match.cc
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/app_list/search/tokenized_string_match.h" +#include "ash/app_list/model/search/tokenized_string_match.h" #include <stddef.h> #include <cmath> +#include "ash/app_list/model/search/tokenized_string_char_iterator.h" #include "base/i18n/string_search.h" #include "base/logging.h" #include "base/macros.h" -#include "ui/app_list/search/tokenized_string_char_iterator.h" namespace app_list { @@ -49,13 +49,11 @@ // a given text or as prefix of the acronyms of those text tokens. class PrefixMatcher { public: - PrefixMatcher(const TokenizedString& query, - const TokenizedString& text) + PrefixMatcher(const TokenizedString& query, const TokenizedString& text) : query_iter_(query), text_iter_(text), current_match_(gfx::Range::InvalidRange()), - current_relevance_(kNoMatchScore) { - } + current_relevance_(kNoMatchScore) {} // Invokes RunMatch to perform prefix match. Use |states_| as a stack to // perform DFS (depth first search) so that all possible matches are @@ -135,7 +133,7 @@ if (!current_match_.IsValid()) current_match_.set_start(text_iter_.GetArrayPos()); current_match_.set_end(text_iter_.GetArrayPos() + - text_iter_.GetCharSize()); + text_iter_.GetCharSize()); query_iter_.NextChar(); text_iter_.NextChar(); @@ -159,11 +157,8 @@ } void PushState() { - states_.push_back(State(current_relevance_, - current_match_, - current_hits_, - query_iter_, - text_iter_)); + states_.push_back(State(current_relevance_, current_match_, current_hits_, + query_iter_, text_iter_)); } void PopState() { @@ -193,8 +188,7 @@ } // namespace -TokenizedStringMatch::TokenizedStringMatch() - : relevance_(kNoMatchScore) {} +TokenizedStringMatch::TokenizedStringMatch() : relevance_(kNoMatchScore) {} TokenizedStringMatch::~TokenizedStringMatch() {} @@ -213,10 +207,9 @@ if (relevance_ == kNoMatchScore) { size_t substr_match_start = 0; size_t substr_match_length = 0; - if (base::i18n::StringSearchIgnoringCaseAndAccents(query.text(), - text.text(), - &substr_match_start, - &substr_match_length)) { + if (base::i18n::StringSearchIgnoringCaseAndAccents( + query.text(), text.text(), &substr_match_start, + &substr_match_length)) { relevance_ = kIsSubstringMultiplier * substr_match_length; hits_.push_back(gfx::Range(substr_match_start, substr_match_start + substr_match_length));
diff --git a/ui/app_list/search/tokenized_string_match.h b/ash/app_list/model/search/tokenized_string_match.h similarity index 84% rename from ui/app_list/search/tokenized_string_match.h rename to ash/app_list/model/search/tokenized_string_match.h index ffc5679..bd14c5a 100644 --- a/ui/app_list/search/tokenized_string_match.h +++ b/ash/app_list/model/search/tokenized_string_match.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_SEARCH_TOKENIZED_STRING_MATCH_H_ -#define UI_APP_LIST_SEARCH_TOKENIZED_STRING_MATCH_H_ +#ifndef ASH_APP_LIST_MODEL_SEARCH_TOKENIZED_STRING_MATCH_H_ +#define ASH_APP_LIST_MODEL_SEARCH_TOKENIZED_STRING_MATCH_H_ #include <vector> +#include "ash/app_list/model/app_list_model_export.h" #include "base/macros.h" #include "base/strings/string16.h" -#include "ui/app_list/app_list_export.h" #include "ui/gfx/range/range.h" namespace app_list { @@ -22,7 +22,7 @@ // of text. A relevance of zero means the two are completely different to each // other. The higher the relevance score, the better the two strings are // matched. Matched portions of text are stored as index ranges. -class APP_LIST_EXPORT TokenizedStringMatch { +class APP_LIST_MODEL_EXPORT TokenizedStringMatch { public: typedef std::vector<gfx::Range> Hits; @@ -51,4 +51,4 @@ } // namespace app_list -#endif // UI_APP_LIST_SEARCH_TOKENIZED_STRING_MATCH_H_ +#endif // ASH_APP_LIST_MODEL_SEARCH_TOKENIZED_STRING_MATCH_H_
diff --git a/ui/app_list/search_box_model.cc b/ash/app_list/model/search_box_model.cc similarity index 96% rename from ui/app_list/search_box_model.cc rename to ash/app_list/model/search_box_model.cc index ed43607..4f92c5f 100644 --- a/ui/app_list/search_box_model.cc +++ b/ash/app_list/model/search_box_model.cc
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/app_list/search_box_model.h" +#include "ash/app_list/model/search_box_model.h" #include <utility> +#include "ash/app_list/model/search_box_model_observer.h" #include "base/metrics/histogram_macros.h" -#include "ui/app_list/search_box_model_observer.h" namespace app_list {
diff --git a/ui/app_list/search_box_model.h b/ash/app_list/model/search_box_model.h similarity index 91% rename from ui/app_list/search_box_model.h rename to ash/app_list/model/search_box_model.h index 423b316..450698a 100644 --- a/ui/app_list/search_box_model.h +++ b/ash/app_list/model/search_box_model.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_SEARCH_BOX_MODEL_H_ -#define UI_APP_LIST_SEARCH_BOX_MODEL_H_ +#ifndef ASH_APP_LIST_MODEL_SEARCH_BOX_MODEL_H_ +#define ASH_APP_LIST_MODEL_SEARCH_BOX_MODEL_H_ +#include "ash/app_list/model/app_list_model_export.h" #include "base/macros.h" #include "base/observer_list.h" #include "base/strings/string16.h" -#include "ui/app_list/app_list_export.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/selection_model.h" @@ -21,10 +21,10 @@ // is used as query edit control's placeholder text and displayed when there is // no user text in the control. The selection model and the text represents the // text, cursor position and selected text in edit control. -class APP_LIST_EXPORT SearchBoxModel { +class APP_LIST_MODEL_EXPORT SearchBoxModel { public: // The properties of the speech button. - struct APP_LIST_EXPORT SpeechButtonProperty { + struct APP_LIST_MODEL_EXPORT SpeechButtonProperty { SpeechButtonProperty(const gfx::ImageSkia& on_icon, const base::string16& on_tooltip, const gfx::ImageSkia& off_icon, @@ -104,4 +104,4 @@ } // namespace app_list -#endif // UI_APP_LIST_SEARCH_BOX_MODEL_H_ +#endif // ASH_APP_LIST_MODEL_SEARCH_BOX_MODEL_H_
diff --git a/ui/app_list/search_box_model_observer.h b/ash/app_list/model/search_box_model_observer.h similarity index 70% rename from ui/app_list/search_box_model_observer.h rename to ash/app_list/model/search_box_model_observer.h index 9dfd2e8..ec54748 100644 --- a/ui/app_list/search_box_model_observer.h +++ b/ash/app_list/model/search_box_model_observer.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_SEARCH_BOX_MODEL_OBSERVER_H_ -#define UI_APP_LIST_SEARCH_BOX_MODEL_OBSERVER_H_ +#ifndef ASH_APP_LIST_MODEL_SEARCH_BOX_MODEL_OBSERVER_H_ +#define ASH_APP_LIST_MODEL_SEARCH_BOX_MODEL_OBSERVER_H_ -#include "ui/app_list/app_list_export.h" +#include "ash/app_list/model/app_list_model_export.h" namespace app_list { -class APP_LIST_EXPORT SearchBoxModelObserver { +class APP_LIST_MODEL_EXPORT SearchBoxModelObserver { public: // Invoked when the some properties of the speech recognition button is // changed. @@ -30,4 +30,4 @@ } // namespace app_list -#endif // UI_APP_LIST_SEARCH_BOX_MODEL_OBSERVER_H_ +#endif // ASH_APP_LIST_MODEL_SEARCH_BOX_MODEL_OBSERVER_H_
diff --git a/ui/app_list/search_result.cc b/ash/app_list/model/search_result.cc similarity index 94% rename from ui/app_list/search_result.cc rename to ash/app_list/model/search_result.cc index c8fcc19..48bc5733 100644 --- a/ui/app_list/search_result.cc +++ b/ash/app_list/model/search_result.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 "ui/app_list/search_result.h" +#include "ash/app_list/model/search_result.h" #include <map> -#include "ui/app_list/search/tokenized_string.h" -#include "ui/app_list/search/tokenized_string_match.h" -#include "ui/app_list/search_result_observer.h" +#include "ash/app_list/model/search/tokenized_string.h" +#include "ash/app_list/model/search/tokenized_string_match.h" +#include "ash/app_list/model/search_result_observer.h" namespace app_list {
diff --git a/ui/app_list/search_result.h b/ash/app_list/model/search_result.h similarity index 95% rename from ui/app_list/search_result.h rename to ash/app_list/model/search_result.h index 11bdd26..57399b5 100644 --- a/ui/app_list/search_result.h +++ b/ash/app_list/model/search_result.h
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_SEARCH_RESULT_H_ -#define UI_APP_LIST_SEARCH_RESULT_H_ +#ifndef ASH_APP_LIST_MODEL_SEARCH_RESULT_H_ +#define ASH_APP_LIST_MODEL_SEARCH_RESULT_H_ #include <stddef.h> #include <string> #include <vector> +#include "ash/app_list/model/app_list_model_export.h" #include "base/macros.h" #include "base/observer_list.h" #include "base/strings/string16.h" -#include "ui/app_list/app_list_export.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/range/range.h" @@ -34,7 +34,7 @@ // SearchResult consists of an icon, title text and details text. Title and // details text can have tagged ranges that are displayed differently from // default style. -class APP_LIST_EXPORT SearchResult { +class APP_LIST_MODEL_EXPORT SearchResult { public: // How the result should be displayed. Do not change the order of these as // they are used for metrics. @@ -60,7 +60,7 @@ }; // A tagged range in search result text. - struct APP_LIST_EXPORT Tag { + struct APP_LIST_MODEL_EXPORT Tag { // Similar to ACMatchClassification::Style, the style values are not // mutually exclusive. enum Style { @@ -83,7 +83,7 @@ // An action could be represented as an icon set or as a blue button with // a label. Icon set is chosen if label text is empty. Otherwise, a blue // button with the label text will be used. - struct APP_LIST_EXPORT Action { + struct APP_LIST_MODEL_EXPORT Action { Action(const gfx::ImageSkia& base_image, const gfx::ImageSkia& hover_image, const gfx::ImageSkia& pressed_image, @@ -260,4 +260,4 @@ } // namespace app_list -#endif // UI_APP_LIST_SEARCH_RESULT_H_ +#endif // ASH_APP_LIST_MODEL_SEARCH_RESULT_H_
diff --git a/ui/app_list/search_result_observer.h b/ash/app_list/model/search_result_observer.h similarity index 81% rename from ui/app_list/search_result_observer.h rename to ash/app_list/model/search_result_observer.h index 383c15d..2838eb4 100644 --- a/ui/app_list/search_result_observer.h +++ b/ash/app_list/model/search_result_observer.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_APP_LIST_SEARCH_RESULT_OBSERVER_H_ -#define UI_APP_LIST_SEARCH_RESULT_OBSERVER_H_ +#ifndef ASH_APP_LIST_MODEL_SEARCH_RESULT_OBSERVER_H_ +#define ASH_APP_LIST_MODEL_SEARCH_RESULT_OBSERVER_H_ -#include "ui/app_list/app_list_export.h" +#include "ash/app_list/model/app_list_model_export.h" namespace app_list { -class APP_LIST_EXPORT SearchResultObserver { +class APP_LIST_MODEL_EXPORT SearchResultObserver { public: // Invoked when the SearchResult's icon has changed. virtual void OnIconChanged() {} @@ -44,4 +44,4 @@ } // namespace app_list -#endif // UI_APP_LIST_SEARCH_RESULT_OBSERVER_H_ +#endif // ASH_APP_LIST_MODEL_SEARCH_RESULT_OBSERVER_H_
diff --git a/ash/autoclick/mus/BUILD.gn b/ash/autoclick/mus/BUILD.gn index c69bc11..b881bd5 100644 --- a/ash/autoclick/mus/BUILD.gn +++ b/ash/autoclick/mus/BUILD.gn
@@ -16,7 +16,7 @@ deps = [ "//ash/autoclick/common:autoclick", "//ash/autoclick/mus/public/interfaces", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//mash/public/interfaces", "//mojo/common",
diff --git a/ash/display/overscan_calibrator.cc b/ash/display/overscan_calibrator.cc index 4862dbc..edb41433 100644 --- a/ash/display/overscan_calibrator.cc +++ b/ash/display/overscan_calibrator.cc
@@ -142,9 +142,6 @@ DrawTriangle(center.x() + horizontal_offset, center.y(), -90, canvas); } -void OverscanCalibrator::OnDelegatedFrameDamage( - const gfx::Rect& damage_rect_in_dip) {} - void OverscanCalibrator::OnDeviceScaleFactorChanged( float old_device_scale_factor, float new_device_scale_factor) {
diff --git a/ash/display/overscan_calibrator.h b/ash/display/overscan_calibrator.h index 5f7eefd..e4e329fd 100644 --- a/ash/display/overscan_calibrator.h +++ b/ash/display/overscan_calibrator.h
@@ -44,7 +44,6 @@ private: // ui::LayerDelegate overrides: void OnPaintLayer(const ui::PaintContext& context) override; - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override;
diff --git a/ash/highlighter/highlighter_result_view.cc b/ash/highlighter/highlighter_result_view.cc index 40b142f..b5b56fe 100644 --- a/ash/highlighter/highlighter_result_view.cc +++ b/ash/highlighter/highlighter_result_view.cc
@@ -58,7 +58,6 @@ private: // ui::LayerDelegate: - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {} void OnPaintLayer(const ui::PaintContext& context) override;
diff --git a/ash/magnifier/partial_magnification_controller.cc b/ash/magnifier/partial_magnification_controller.cc index efcafc6..e9ad930 100644 --- a/ash/magnifier/partial_magnification_controller.cc +++ b/ash/magnifier/partial_magnification_controller.cc
@@ -126,8 +126,6 @@ recorder.canvas()->DrawCircle(rect.CenterPoint(), clipping_radius, flags); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} - void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override { // Redrawing will take care of scale factor change. @@ -196,8 +194,6 @@ border_flags); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} - void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {}
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index 4b6f9bce..0bd8246 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -5,7 +5,7 @@ import("//mojo/public/tools/bindings/mojom.gni") # C++ headers and sources that can be used outside ash. -component("ash_public_cpp") { +component("cpp") { sources = [ "accessibility_types.h", "app_types.h", @@ -81,6 +81,8 @@ allow_circular_includes_from = [ "//ash/public/interfaces:interfaces_internal" ] + + output_name = "ash_public_cpp" } # Using a test service because the traits need to pass handles around. Revisit @@ -105,7 +107,7 @@ ] deps = [ - ":ash_public_cpp", + ":cpp", ":test_interfaces", "//base", "//testing/gtest",
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn index 12c979d..60e07b21 100644 --- a/ash/public/interfaces/BUILD.gn +++ b/ash/public/interfaces/BUILD.gn
@@ -4,10 +4,10 @@ import("//mojo/public/tools/bindings/mojom.gni") -# Depend upon //ash/public/cpp:ash_public_cpp, which has a public_dep on this. -# The two targets must be bundled together as the typemaps depend upon -# //ash/public/cpp, and //ash/public/cpp needs to depend on this for generated -# code (such as enums and constants). +# Depend upon //ash/public/cpp, which has a public_dep on this. The two targets +# must be bundled together as the typemaps depend upon //ash/public/cpp, +# and //ash/public/cpp needs to depend on this for generated code (such as +# enums and constants). mojom("interfaces_internal") { visibility = [ "//ash/public/cpp:*" ]
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc index 93af957..9cf55d3 100644 --- a/ash/shelf/app_list_button.cc +++ b/ash/shelf/app_list_button.cc
@@ -11,11 +11,11 @@ #include "ash/public/cpp/shelf_types.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/session/session_controller.h" +#include "ash/shelf/assistant_overlay.h" #include "ash/shelf/ink_drop_button_listener.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_constants.h" #include "ash/shelf/shelf_view.h" -#include "ash/shelf/voice_interaction_overlay.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/tray/tray_popup_utils.h" @@ -157,14 +157,14 @@ case ui::ET_GESTURE_TAP: case ui::ET_GESTURE_TAP_CANCEL: if (UseVoiceInteractionStyle()) { - voice_interaction_overlay_->EndAnimation(); - voice_interaction_animation_delay_timer_->Stop(); + assistant_overlay_->EndAnimation(); + assistant_animation_delay_timer_->Stop(); } ImageButton::OnGestureEvent(event); return; case ui::ET_GESTURE_TAP_DOWN: if (UseVoiceInteractionStyle()) { - voice_interaction_animation_delay_timer_->Start( + assistant_animation_delay_timer_->Start( FROM_HERE, base::TimeDelta::FromMilliseconds( kVoiceInteractionAnimationDelayMs), @@ -180,7 +180,7 @@ base::RecordAction(base::UserMetricsAction( "VoiceInteraction.Started.AppListButtonLongPress")); Shell::Get()->app_list()->StartVoiceInteractionSession(); - voice_interaction_overlay_->BurstAnimation(); + assistant_overlay_->BurstAnimation(); event->SetHandled(); } else { ImageButton::OnGestureEvent(event); @@ -487,7 +487,7 @@ mojom::VoiceInteractionState state) { SchedulePaint(); - if (!voice_interaction_overlay_) + if (!assistant_overlay_) return; switch (state) { @@ -499,21 +499,20 @@ case mojom::VoiceInteractionState::NOT_READY: // If we are showing the bursting or waiting animation, no need to do // anything. Otherwise show the waiting animation now. - if (!voice_interaction_overlay_->IsBursting() && - !voice_interaction_overlay_->IsWaiting()) { - voice_interaction_overlay_->WaitingAnimation(); + if (!assistant_overlay_->IsBursting() && + !assistant_overlay_->IsWaiting()) { + assistant_overlay_->WaitingAnimation(); } break; case mojom::VoiceInteractionState::RUNNING: // we start hiding the animation if it is running. - if (voice_interaction_overlay_->IsBursting() || - voice_interaction_overlay_->IsWaiting()) { - voice_interaction_animation_hide_delay_timer_->Start( + if (assistant_overlay_->IsBursting() || assistant_overlay_->IsWaiting()) { + assistant_animation_hide_delay_timer_->Start( FROM_HERE, base::TimeDelta::FromMilliseconds( kVoiceInteractionAnimationHideDelayMs), - base::Bind(&VoiceInteractionOverlay::HideAnimation, - base::Unretained(voice_interaction_overlay_))); + base::Bind(&AssistantOverlay::HideAnimation, + base::Unretained(assistant_overlay_))); } voice_interaction_start_timestamp_ = base::TimeTicks::Now(); @@ -534,8 +533,7 @@ // Initialize voice interaction overlay when primary user session becomes // active. if (Shell::Get()->session_controller()->IsUserPrimary() && - !voice_interaction_overlay_ && - chromeos::switches::IsVoiceInteractionEnabled()) { + !assistant_overlay_ && chromeos::switches::IsVoiceInteractionEnabled()) { InitializeVoiceInteractionOverlay(); } } @@ -552,7 +550,7 @@ alignment == SHELF_ALIGNMENT_BOTTOM_LOCKED) && state == mojom::VoiceInteractionState::STOPPED && Shell::Get()->voice_interaction_controller()->setup_completed(); - voice_interaction_overlay_->StartAnimation(show_icon); + assistant_overlay_->StartAnimation(show_icon); } bool AppListButton::IsBackEvent(const gfx::Point& location) { @@ -600,7 +598,7 @@ bool setup_completed = controller->setup_completed(); bool is_feature_allowed = controller->allowed_state() == mojom::AssistantAllowedState::ALLOWED; - if (voice_interaction_overlay_ && is_feature_allowed && + if (assistant_overlay_ && is_feature_allowed && (settings_enabled || !setup_completed)) { return true; } @@ -608,12 +606,11 @@ } void AppListButton::InitializeVoiceInteractionOverlay() { - voice_interaction_overlay_ = new VoiceInteractionOverlay(this); - AddChildView(voice_interaction_overlay_); - voice_interaction_overlay_->SetVisible(false); - voice_interaction_animation_delay_timer_ = - std::make_unique<base::OneShotTimer>(); - voice_interaction_animation_hide_delay_timer_ = + assistant_overlay_ = new AssistantOverlay(this); + AddChildView(assistant_overlay_); + assistant_overlay_->SetVisible(false); + assistant_animation_delay_timer_ = std::make_unique<base::OneShotTimer>(); + assistant_animation_hide_delay_timer_ = std::make_unique<base::OneShotTimer>(); }
diff --git a/ash/shelf/app_list_button.h b/ash/shelf/app_list_button.h index 4edaba02..78895df 100644 --- a/ash/shelf/app_list_button.h +++ b/ash/shelf/app_list_button.h
@@ -23,7 +23,7 @@ class InkDropButtonListener; class Shelf; class ShelfView; -class VoiceInteractionOverlay; +class AssistantOverlay; // Button used for the AppList icon on the shelf. class ASH_EXPORT AppListButton : public views::ImageButton, @@ -117,10 +117,9 @@ Shelf* shelf_; // Owned by the view hierarchy. Null if the voice interaction is not enabled. - VoiceInteractionOverlay* voice_interaction_overlay_ = nullptr; - std::unique_ptr<base::OneShotTimer> voice_interaction_animation_delay_timer_; - std::unique_ptr<base::OneShotTimer> - voice_interaction_animation_hide_delay_timer_; + AssistantOverlay* assistant_overlay_ = nullptr; + std::unique_ptr<base::OneShotTimer> assistant_animation_delay_timer_; + std::unique_ptr<base::OneShotTimer> assistant_animation_hide_delay_timer_; base::TimeTicks voice_interaction_start_timestamp_; // Flag that gets set each time we receive a mouse or gesture event. It is
diff --git a/ash/shelf/voice_interaction_overlay.cc b/ash/shelf/assistant_overlay.cc similarity index 95% rename from ash/shelf/voice_interaction_overlay.cc rename to ash/shelf/assistant_overlay.cc index 0758a378..af2ada9 100644 --- a/ash/shelf/voice_interaction_overlay.cc +++ b/ash/shelf/assistant_overlay.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 "ash/shelf/voice_interaction_overlay.h" +#include "ash/shelf/assistant_overlay.h" #include <algorithm> #include <memory> @@ -114,11 +114,10 @@ } // namespace -class VoiceInteractionIcon : public ui::Layer, - public ui::CompositorAnimationObserver { +class AssistantIcon : public ui::Layer, public ui::CompositorAnimationObserver { public: - VoiceInteractionIcon() : Layer(ui::LAYER_NOT_DRAWN) { - set_name("VoiceInteractionOverlay:ICON_LAYER"); + AssistantIcon() : Layer(ui::LAYER_NOT_DRAWN) { + set_name("AssistantOverlay:ICON_LAYER"); SetBounds(gfx::Rect(0, 0, kIconInitSizeDip, kIconInitSizeDip)); SetFillsBoundsOpaquely(false); SetMasksToBounds(false); @@ -126,7 +125,7 @@ InitMoleculeShape(); } - ~VoiceInteractionIcon() override { StopAnimation(); } + ~AssistantIcon() override { StopAnimation(); } void StartAnimation() { ui::Compositor* compositor = GetCompositor(); @@ -225,13 +224,12 @@ ui::Compositor* animating_compositor_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(VoiceInteractionIcon); + DISALLOW_COPY_AND_ASSIGN(AssistantIcon); }; -class VoiceInteractionIconBackground : public ui::Layer, - public ui::LayerDelegate { +class AssistantIconBackground : public ui::Layer, public ui::LayerDelegate { public: - VoiceInteractionIconBackground() + AssistantIconBackground() : Layer(ui::LAYER_NOT_DRAWN), large_size_( gfx::Size(kBackgroundLargeWidthDip, kBackgroundLargeHeightDip)), @@ -244,7 +242,7 @@ rect_layer_delegate_(std::make_unique<views::RectangleLayerDelegate>( SK_ColorWHITE, gfx::SizeF(small_size_))) { - set_name("VoiceInteractionOverlay:BACKGROUND_LAYER"); + set_name("AssistantOverlay:BACKGROUND_LAYER"); SetBounds(gfx::Rect(0, 0, kBackgroundInitSizeDip, kBackgroundInitSizeDip)); SetFillsBoundsOpaquely(false); SetMasksToBounds(false); @@ -280,7 +278,7 @@ for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) AddPaintLayer(static_cast<PaintedShape>(i)); } - ~VoiceInteractionIconBackground() override{}; + ~AssistantIconBackground() override{}; void MoveLargeShadow(const gfx::PointF& new_center) { gfx::Transform transform; @@ -561,8 +559,6 @@ radius, flags); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} - void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {} @@ -594,17 +590,17 @@ // This layer shows the large rounded rectangle with shadow. std::unique_ptr<ui::Layer> large_shadow_layer_; - DISALLOW_COPY_AND_ASSIGN(VoiceInteractionIconBackground); + DISALLOW_COPY_AND_ASSIGN(AssistantIconBackground); }; -VoiceInteractionOverlay::VoiceInteractionOverlay(AppListButton* host_view) +AssistantOverlay::AssistantOverlay(AppListButton* host_view) : ripple_layer_(std::make_unique<ui::Layer>()), - icon_layer_(std::make_unique<VoiceInteractionIcon>()), - background_layer_(std::make_unique<VoiceInteractionIconBackground>()), + icon_layer_(std::make_unique<AssistantIcon>()), + background_layer_(std::make_unique<AssistantIconBackground>()), host_view_(host_view), circle_layer_delegate_(kRippleColor, kRippleCircleInitRadiusDip) { SetPaintToLayer(ui::LAYER_NOT_DRAWN); - layer()->set_name("VoiceInteractionOverlay:ROOT_LAYER"); + layer()->set_name("AssistantOverlay:ROOT_LAYER"); layer()->SetMasksToBounds(false); ripple_layer_->SetBounds(gfx::Rect(0, 0, kRippleCircleInitRadiusDip * 2, @@ -612,7 +608,7 @@ ripple_layer_->set_delegate(&circle_layer_delegate_); ripple_layer_->SetFillsBoundsOpaquely(false); ripple_layer_->SetMasksToBounds(true); - ripple_layer_->set_name("VoiceInteractionOverlay:PAINTED_LAYER"); + ripple_layer_->set_name("AssistantOverlay:PAINTED_LAYER"); layer()->Add(ripple_layer_.get()); layer()->Add(background_layer_.get()); @@ -620,9 +616,9 @@ layer()->Add(icon_layer_.get()); } -VoiceInteractionOverlay::~VoiceInteractionOverlay() {} +AssistantOverlay::~AssistantOverlay() {} -void VoiceInteractionOverlay::StartAnimation(bool show_icon) { +void AssistantOverlay::StartAnimation(bool show_icon) { animation_state_ = AnimationState::STARTING; show_icon_ = show_icon; SetVisible(true); @@ -734,7 +730,7 @@ } } -void VoiceInteractionOverlay::BurstAnimation() { +void AssistantOverlay::BurstAnimation() { animation_state_ = AnimationState::BURSTING; gfx::Point center = host_view_->GetAppListButtonCenterPoint(); @@ -805,7 +801,7 @@ nullptr); } -void VoiceInteractionOverlay::WaitingAnimation() { +void AssistantOverlay::WaitingAnimation() { // If we are already playing burst animation, it will end up at waiting state // anyway. No need to do anything. if (IsBursting()) @@ -864,7 +860,7 @@ } } -void VoiceInteractionOverlay::EndAnimation() { +void AssistantOverlay::EndAnimation() { if (IsBursting() || IsHidden()) { // Too late, user action already fired, we have to finish what's started. // Or the widget has already been hidden, no need to play the end animation. @@ -943,7 +939,7 @@ } } -void VoiceInteractionOverlay::HideAnimation() { +void AssistantOverlay::HideAnimation() { animation_state_ = AnimationState::HIDDEN; // Setup ripple animations.
diff --git a/ash/shelf/voice_interaction_overlay.h b/ash/shelf/assistant_overlay.h similarity index 68% rename from ash/shelf/voice_interaction_overlay.h rename to ash/shelf/assistant_overlay.h index 69abdd8b..5898693 100644 --- a/ash/shelf/voice_interaction_overlay.h +++ b/ash/shelf/assistant_overlay.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 ASH_SHELF_VOICE_INTERACTION_OVERLAY_H_ -#define ASH_SHELF_VOICE_INTERACTION_OVERLAY_H_ +#ifndef ASH_SHELF_ASSISTANT_OVERLAY_H_ +#define ASH_SHELF_ASSISTANT_OVERLAY_H_ #include <memory> @@ -16,13 +16,13 @@ namespace ash { class AppListButton; -class VoiceInteractionIconBackground; -class VoiceInteractionIcon; +class AssistantIconBackground; +class AssistantIcon; -class ASH_EXPORT VoiceInteractionOverlay : public views::View { +class ASH_EXPORT AssistantOverlay : public views::View { public: - explicit VoiceInteractionOverlay(AppListButton* host_view); - ~VoiceInteractionOverlay() override; + explicit AssistantOverlay(AppListButton* host_view); + ~AssistantOverlay() override; void StartAnimation(bool show_icon); void EndAnimation(); @@ -41,7 +41,7 @@ HIDDEN = 0, // Indicates currently playing the starting animation. STARTING, - // Indiates the current animation is in the bursting phase, which means no + // Indicates the current animation is in the bursting phase, which means no // turning back. BURSTING, // Indicates currently playing the waiting animation. @@ -49,8 +49,8 @@ }; std::unique_ptr<ui::Layer> ripple_layer_; - std::unique_ptr<VoiceInteractionIcon> icon_layer_; - std::unique_ptr<VoiceInteractionIconBackground> background_layer_; + std::unique_ptr<AssistantIcon> icon_layer_; + std::unique_ptr<AssistantIconBackground> background_layer_; AppListButton* host_view_; @@ -61,8 +61,8 @@ views::CircleLayerDelegate circle_layer_delegate_; - DISALLOW_COPY_AND_ASSIGN(VoiceInteractionOverlay); + DISALLOW_COPY_AND_ASSIGN(AssistantOverlay); }; } // namespace ash -#endif // ASH_SHELF_VOICE_INTERACTION_OVERLAY_H_ +#endif // ASH_SHELF_ASSISTANT_OVERLAY_H_
diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc index 8f1d2188e..759dde4 100644 --- a/ash/shell/app_list.cc +++ b/ash/shell/app_list.cc
@@ -7,6 +7,11 @@ #include <utility> #include <vector> +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_item_list.h" +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/search_box_model.h" +#include "ash/app_list/model/search_result.h" #include "ash/session/session_controller.h" #include "ash/shell.h" #include "ash/shell/example_factory.h" @@ -19,13 +24,8 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_item_list.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/presenter/app_list.h" -#include "ui/app_list/search_box_model.h" -#include "ui/app_list/search_result.h" #include "ui/app_list/speech_ui_model.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font_list.h"
diff --git a/ash/touch_hud/mus/BUILD.gn b/ash/touch_hud/mus/BUILD.gn index 8c82e8d..97d0989 100644 --- a/ash/touch_hud/mus/BUILD.gn +++ b/ash/touch_hud/mus/BUILD.gn
@@ -14,7 +14,7 @@ ] deps = [ - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//ash/touch_hud", "//base", "//mash/public/interfaces",
diff --git a/ash/utility/screenshot_controller.cc b/ash/utility/screenshot_controller.cc index 2a242320..b23b0a8 100644 --- a/ash/utility/screenshot_controller.cc +++ b/ash/utility/screenshot_controller.cc
@@ -132,8 +132,6 @@ recorder.canvas()->FillRect(region_, SK_ColorBLACK, SkBlendMode::kClear); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} - void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {}
diff --git a/ash/wayland/BUILD.gn b/ash/wayland/BUILD.gn index 2eba806..d9f3fe0 100644 --- a/ash/wayland/BUILD.gn +++ b/ash/wayland/BUILD.gn
@@ -11,7 +11,7 @@ ] deps = [ - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//components/exo", "//components/exo/wayland",
diff --git a/ash/wm/drag_window_resizer_unittest.cc b/ash/wm/drag_window_resizer_unittest.cc index 9d9475e..657f8e8 100644 --- a/ash/wm/drag_window_resizer_unittest.cc +++ b/ash/wm/drag_window_resizer_unittest.cc
@@ -48,7 +48,6 @@ void OnPaintLayer(const ui::PaintContext& context) override { paint_count_++; } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {}
diff --git a/ash/wm/workspace/multi_window_resize_controller_unittest.cc b/ash/wm/workspace/multi_window_resize_controller_unittest.cc index 0a5ff97..af102bb 100644 --- a/ash/wm/workspace/multi_window_resize_controller_unittest.cc +++ b/ash/wm/workspace/multi_window_resize_controller_unittest.cc
@@ -61,17 +61,6 @@ } protected: - aura::Window* CreateTestWindow(aura::WindowDelegate* delegate, - const gfx::Rect& bounds) { - aura::Window* window = new aura::Window(delegate); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - ParentWindowInPrimaryRootWindow(window); - window->SetBounds(bounds); - window->Show(); - return window; - } - void ShowNow() { resize_controller_->ShowNow(); } bool IsShowing() { return resize_controller_->IsShowing(); } @@ -108,12 +97,12 @@ // Assertions around moving mouse over 2 windows. TEST_F(MultiWindowResizeControllerTest, BasicTests) { aura::test::TestWindowDelegate delegate1; - std::unique_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); + std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate( + &delegate1, -1, gfx::Rect(0, 0, 100, 100))); delegate1.set_window_component(HTRIGHT); aura::test::TestWindowDelegate delegate2; - std::unique_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); + std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate( + &delegate2, -2, gfx::Rect(100, 0, 100, 100))); delegate2.set_window_component(HTRIGHT); ui::test::EventGenerator generator(w1->GetRootWindow()); generator.MoveMouseTo(w1->bounds().CenterPoint()); @@ -209,12 +198,12 @@ // Makes sure deleting a window hides. TEST_F(MultiWindowResizeControllerTest, DeleteWindow) { aura::test::TestWindowDelegate delegate1; - std::unique_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); + std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate( + &delegate1, -1, gfx::Rect(0, 0, 100, 100))); delegate1.set_window_component(HTRIGHT); aura::test::TestWindowDelegate delegate2; - std::unique_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); + std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate( + &delegate2, -2, gfx::Rect(100, 0, 100, 100))); delegate2.set_window_component(HTRIGHT); ui::test::EventGenerator generator(w1->GetRootWindow()); generator.MoveMouseTo(w1->bounds().CenterPoint()); @@ -248,12 +237,12 @@ // Tests resizing. TEST_F(MultiWindowResizeControllerTest, Drag) { aura::test::TestWindowDelegate delegate1; - std::unique_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); + std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate( + &delegate1, -1, gfx::Rect(0, 0, 100, 100))); delegate1.set_window_component(HTRIGHT); aura::test::TestWindowDelegate delegate2; - std::unique_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); + std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate( + &delegate2, -2, gfx::Rect(100, 0, 100, 100))); delegate2.set_window_component(HTRIGHT); ui::test::EventGenerator generator(w1->GetRootWindow()); generator.MoveMouseTo(w1->bounds().CenterPoint()); @@ -287,16 +276,16 @@ // Makes sure three windows are picked up. TEST_F(MultiWindowResizeControllerTest, Three) { aura::test::TestWindowDelegate delegate1; - std::unique_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); + std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate( + &delegate1, -1, gfx::Rect(0, 0, 100, 100))); delegate1.set_window_component(HTRIGHT); aura::test::TestWindowDelegate delegate2; - std::unique_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); + std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate( + &delegate2, -2, gfx::Rect(100, 0, 100, 100))); delegate2.set_window_component(HTRIGHT); aura::test::TestWindowDelegate delegate3; - std::unique_ptr<aura::Window> w3( - CreateTestWindow(&delegate3, gfx::Rect(200, 0, 100, 100))); + std::unique_ptr<aura::Window> w3(CreateTestWindowInShellWithDelegate( + &delegate3, -3, gfx::Rect(200, 0, 100, 100))); delegate3.set_window_component(HTRIGHT); ui::test::EventGenerator generator(w1->GetRootWindow()); @@ -327,12 +316,12 @@ // Tests that clicking outside of the resize handle dismisses it. TEST_F(MultiWindowResizeControllerTest, ClickOutside) { aura::test::TestWindowDelegate delegate1; - std::unique_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); + std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate( + &delegate1, -1, gfx::Rect(0, 0, 100, 100))); delegate1.set_window_component(HTRIGHT); aura::test::TestWindowDelegate delegate2; - std::unique_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); + std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate( + &delegate2, -2, gfx::Rect(100, 0, 100, 100))); delegate2.set_window_component(HTLEFT); ui::test::EventGenerator& generator(GetEventGenerator());
diff --git a/base/allocator/partition_allocator/address_space_randomization_unittest.cc b/base/allocator/partition_allocator/address_space_randomization_unittest.cc index 40a47e5..c8c1da4 100644 --- a/base/allocator/partition_allocator/address_space_randomization_unittest.cc +++ b/base/allocator/partition_allocator/address_space_randomization_unittest.cc
@@ -25,7 +25,8 @@ uintptr_t GetMask() { uintptr_t mask = internal::kASLRMask; #if defined(ARCH_CPU_64_BITS) -#if defined(OS_WIN) +// Sanitizers use their own kASLRMask constant. +#if defined(OS_WIN) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) if (!IsWindows8Point1OrGreater()) { mask = internal::kASLRMaskBefore8_10; }
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc index 8347760..00ad90e0 100644 --- a/base/allocator/partition_allocator/partition_alloc.cc +++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -174,21 +174,19 @@ PartitionRootBase::gOomHandlingFunction = oom_handling_function; } -void PartitionAllocInit(PartitionRoot* root, - size_t num_buckets, - size_t max_allocation) { - PartitionAllocBaseInit(root); +void PartitionRoot::Init(size_t num_buckets, size_t max_allocation) { + PartitionAllocBaseInit(this); - root->num_buckets = num_buckets; - root->max_allocation = max_allocation; + this->num_buckets = num_buckets; + this->max_allocation = max_allocation; size_t i; - for (i = 0; i < root->num_buckets; ++i) { - PartitionBucket* bucket = &root->buckets()[i]; + for (i = 0; i < this->num_buckets; ++i) { + PartitionBucket* bucket = &this->buckets()[i]; if (!i) bucket->slot_size = kAllocationGranularity; else bucket->slot_size = i << kBucketShift; - PartitionBucketInitBase(bucket, root); + PartitionBucketInitBase(bucket, this); } } @@ -1294,9 +1292,9 @@ } } -void PartitionPurgeMemory(PartitionRoot* root, int flags) { +void PartitionRoot::PurgeMemory(int flags) { if (flags & PartitionPurgeDecommitEmptyPages) - PartitionDecommitEmptyPages(root); + PartitionDecommitEmptyPages(this); // We don't currently do anything for PartitionPurgeDiscardUnusedSystemPages // here because that flag is only useful for allocations >= system page // size. We only have allocations that large inside generic partitions @@ -1480,14 +1478,13 @@ dumper->PartitionDumpTotals(partition_name, &stats); } -void PartitionDumpStats(PartitionRoot* partition, - const char* partition_name, - bool is_light_dump, - PartitionStatsDumper* dumper) { +void PartitionRoot::DumpStats(const char* partition_name, + bool is_light_dump, + PartitionStatsDumper* dumper) { PartitionMemoryStats stats = {0}; - stats.total_mmapped_bytes = partition->total_size_of_super_pages; - stats.total_committed_bytes = partition->total_size_of_committed_pages; - DCHECK(!partition->total_size_of_direct_mapped_pages); + stats.total_mmapped_bytes = this->total_size_of_super_pages; + stats.total_committed_bytes = this->total_size_of_committed_pages; + DCHECK(!this->total_size_of_direct_mapped_pages); static const size_t kMaxReportableBuckets = 4096 / sizeof(void*); std::unique_ptr<PartitionBucketMemoryStats[]> memory_stats; @@ -1495,12 +1492,12 @@ memory_stats = std::unique_ptr<PartitionBucketMemoryStats[]>( new PartitionBucketMemoryStats[kMaxReportableBuckets]); - const size_t partitionNumBuckets = partition->num_buckets; + const size_t partitionNumBuckets = this->num_buckets; DCHECK(partitionNumBuckets <= kMaxReportableBuckets); for (size_t i = 0; i < partitionNumBuckets; ++i) { PartitionBucketMemoryStats bucket_stats = {0}; - PartitionDumpBucketStats(&bucket_stats, &partition->buckets()[i]); + PartitionDumpBucketStats(&bucket_stats, &this->buckets()[i]); if (bucket_stats.is_valid) { stats.total_resident_bytes += bucket_stats.resident_bytes; stats.total_active_bytes += bucket_stats.active_bytes;
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h index 2ce8a92..f004a12 100644 --- a/base/allocator/partition_allocator/partition_alloc.h +++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -6,7 +6,7 @@ #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_H_ // DESCRIPTION -// partitionAlloc() / PartitionAllocGeneric() and PartitionFree() / +// PartitionRoot::Alloc() / PartitionAllocGeneric() and PartitionFree() / // PartitionFreeGeneric() are approximately analagous to malloc() and free(). // // The main difference is that a PartitionRoot / PartitionRootGeneric object @@ -225,6 +225,7 @@ 0x13, 0x37, 0xF0, 0x05, 0xBA, 0x11, 0xAB, 0x1E}; #endif +class PartitionStatsDumper; struct PartitionBucket; struct PartitionRootBase; @@ -327,6 +328,16 @@ static void (*gOomHandlingFunction)(); }; +enum PartitionPurgeFlags { + // Decommitting the ring list of empty pages is reasonably fast. + PartitionPurgeDecommitEmptyPages = 1 << 0, + // Discarding unused system pages is slower, because it involves walking all + // freelists in all active partition pages of all buckets >= system page + // size. It often frees a similar amount of memory to decommitting the empty + // pages, though. + PartitionPurgeDiscardUnusedSystemPages = 1 << 1, +}; + // Never instantiate a PartitionRoot directly, instead use PartitionAlloc. struct BASE_EXPORT PartitionRoot : public PartitionRootBase { PartitionRoot(); @@ -341,6 +352,16 @@ ALWAYS_INLINE const PartitionBucket* buckets() const { return reinterpret_cast<const PartitionBucket*>(this + 1); } + + void Init(size_t num_buckets, size_t max_allocation); + + ALWAYS_INLINE void* Alloc(size_t size, const char* type_name); + + void PurgeMemory(int flags); + + void DumpStats(const char* partition_name, + bool is_light_dump, + PartitionStatsDumper* dumper); }; // Never instantiate a PartitionRootGeneric directly, instead use @@ -415,22 +436,8 @@ }; BASE_EXPORT void PartitionAllocGlobalInit(void (*oom_handling_function)()); -BASE_EXPORT void PartitionAllocInit(PartitionRoot*, - size_t num_buckets, - size_t max_allocation); BASE_EXPORT void PartitionAllocGenericInit(PartitionRootGeneric*); -enum PartitionPurgeFlags { - // Decommitting the ring list of empty pages is reasonably fast. - PartitionPurgeDecommitEmptyPages = 1 << 0, - // Discarding unused system pages is slower, because it involves walking all - // freelists in all active partition pages of all buckets >= system page - // size. It often frees a similar amount of memory to decommitting the empty - // pages, though. - PartitionPurgeDiscardUnusedSystemPages = 1 << 1, -}; - -BASE_EXPORT void PartitionPurgeMemory(PartitionRoot*, int); BASE_EXPORT void PartitionPurgeMemoryGeneric(PartitionRootGeneric*, int); BASE_EXPORT NOINLINE void* PartitionAllocSlowPath(PartitionRootBase*, @@ -443,10 +450,6 @@ size_t, const char* type_name); -BASE_EXPORT void PartitionDumpStats(PartitionRoot*, - const char* partition_name, - bool is_light_dump, - PartitionStatsDumper*); BASE_EXPORT void PartitionDumpStatsGeneric(PartitionRootGeneric*, const char* partition_name, bool is_light_dump, @@ -725,9 +728,7 @@ return ret; } -ALWAYS_INLINE void* PartitionAlloc(PartitionRoot* root, - size_t size, - const char* type_name) { +ALWAYS_INLINE void* PartitionRoot::Alloc(size_t size, const char* type_name) { #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) void* result = malloc(size); CHECK(result); @@ -735,12 +736,12 @@ #else size_t requested_size = size; size = PartitionCookieSizeAdjustAdd(size); - DCHECK(root->initialized); + DCHECK(this->initialized); size_t index = size >> kBucketShift; - DCHECK(index < root->num_buckets); + DCHECK(index < this->num_buckets); DCHECK(size == index << kBucketShift); - PartitionBucket* bucket = &root->buckets()[index]; - void* result = PartitionBucketAlloc(root, 0, size, bucket); + PartitionBucket* bucket = &this->buckets()[index]; + void* result = PartitionBucketAlloc(this, 0, size, bucket); PartitionAllocHooks::AllocationHookIfEnabled(result, requested_size, type_name); return result; @@ -919,9 +920,7 @@ ~SizeSpecificPartitionAllocator() = default; static const size_t kMaxAllocation = N - kAllocationGranularity; static const size_t kNumBuckets = N / kAllocationGranularity; - void init() { - PartitionAllocInit(&partition_root_, kNumBuckets, kMaxAllocation); - } + void init() { partition_root_.Init(kNumBuckets, kMaxAllocation); } ALWAYS_INLINE PartitionRoot* root() { return &partition_root_; } private:
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc index 16a1638..20b9837 100644 --- a/base/allocator/partition_allocator/partition_alloc_unittest.cc +++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -122,7 +122,7 @@ void* last = nullptr; size_t i; for (i = 0; i < num_slots; ++i) { - void* ptr = PartitionAlloc(allocator.root(), size, type_name); + void* ptr = allocator.root()->Alloc(size, type_name); EXPECT_TRUE(ptr); if (!i) first = PartitionCookieFreePointerAdjust(ptr); @@ -149,7 +149,7 @@ DCHECK(!bucket->active_pages_head->num_allocated_slots); for (size_t i = 0; i < kMaxFreeableSpans; ++i) { - void* ptr = PartitionAlloc(allocator.root(), size, type_name); + void* ptr = allocator.root()->Alloc(size, type_name); EXPECT_EQ(1, bucket->active_pages_head->num_allocated_slots); PartitionFree(ptr); EXPECT_EQ(0, bucket->active_pages_head->num_allocated_slots); @@ -383,7 +383,7 @@ EXPECT_EQ(seedPage, bucket->active_pages_head); EXPECT_EQ(nullptr, bucket->active_pages_head->next_page); - void* ptr = PartitionAlloc(allocator.root(), kTestAllocSize, type_name); + void* ptr = allocator.root()->Alloc(kTestAllocSize, type_name); EXPECT_TRUE(ptr); EXPECT_EQ(kPointerOffset, reinterpret_cast<size_t>(ptr) & kPartitionPageOffsetMask); @@ -401,9 +401,9 @@ // Test multiple allocations, and freelist handling. TEST_F(PartitionAllocTest, MultiAlloc) { char* ptr1 = reinterpret_cast<char*>( - PartitionAlloc(allocator.root(), kTestAllocSize, type_name)); + allocator.root()->Alloc(kTestAllocSize, type_name)); char* ptr2 = reinterpret_cast<char*>( - PartitionAlloc(allocator.root(), kTestAllocSize, type_name)); + allocator.root()->Alloc(kTestAllocSize, type_name)); EXPECT_TRUE(ptr1); EXPECT_TRUE(ptr2); ptrdiff_t diff = ptr2 - ptr1; @@ -412,19 +412,19 @@ // Check that we re-use the just-freed slot. PartitionFree(ptr2); ptr2 = reinterpret_cast<char*>( - PartitionAlloc(allocator.root(), kTestAllocSize, type_name)); + allocator.root()->Alloc(kTestAllocSize, type_name)); EXPECT_TRUE(ptr2); diff = ptr2 - ptr1; EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff); PartitionFree(ptr1); ptr1 = reinterpret_cast<char*>( - PartitionAlloc(allocator.root(), kTestAllocSize, type_name)); + allocator.root()->Alloc(kTestAllocSize, type_name)); EXPECT_TRUE(ptr1); diff = ptr2 - ptr1; EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff); char* ptr3 = reinterpret_cast<char*>( - PartitionAlloc(allocator.root(), kTestAllocSize, type_name)); + allocator.root()->Alloc(kTestAllocSize, type_name)); EXPECT_TRUE(ptr3); diff = ptr3 - ptr1; EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize * 2), diff); @@ -491,7 +491,7 @@ reinterpret_cast<char*>(PartitionPageToPointer(page1)) + kPointerOffset; PartitionFree(ptr); EXPECT_EQ(page1, bucket->active_pages_head); - (void)PartitionAlloc(allocator.root(), kTestAllocSize, type_name); + (void)allocator.root()->Alloc(kTestAllocSize, type_name); EXPECT_EQ(page1, bucket->active_pages_head); EXPECT_EQ(page2, bucket->active_pages_head->next_page); @@ -508,7 +508,7 @@ // Trying to allocate at this time should cause us to cycle around to page2 // and find the recently freed slot. char* newPtr = reinterpret_cast<char*>( - PartitionAlloc(allocator.root(), kTestAllocSize, type_name)); + allocator.root()->Alloc(kTestAllocSize, type_name)); EXPECT_EQ(ptr, newPtr); EXPECT_EQ(page2, bucket->active_pages_head); EXPECT_EQ(page3, page2->next_page); @@ -519,7 +519,7 @@ PartitionFree(ptr); // This allocation should be satisfied by page1. newPtr = reinterpret_cast<char*>( - PartitionAlloc(allocator.root(), kTestAllocSize, type_name)); + allocator.root()->Alloc(kTestAllocSize, type_name)); EXPECT_EQ(ptr, newPtr); EXPECT_EQ(page1, bucket->active_pages_head); EXPECT_EQ(page2, page1->next_page); @@ -530,7 +530,7 @@ // Allocating whilst in this state exposed a bug, so keep the test. ptr = reinterpret_cast<char*>( - PartitionAlloc(allocator.root(), kTestAllocSize, type_name)); + allocator.root()->Alloc(kTestAllocSize, type_name)); PartitionFree(ptr); } @@ -946,7 +946,7 @@ PartitionBucket* bucket = &allocator.root()->buckets()[bucket_index]; EXPECT_EQ(nullptr, bucket->empty_pages_head); - void* ptr = PartitionAlloc(allocator.root(), big_size, type_name); + void* ptr = allocator.root()->Alloc(big_size, type_name); EXPECT_TRUE(ptr); PartitionPage* page = @@ -962,25 +962,25 @@ EXPECT_EQ(1, page->num_allocated_slots); EXPECT_EQ(2, page->num_unprovisioned_slots); - void* ptr2 = PartitionAlloc(allocator.root(), big_size, type_name); + void* ptr2 = allocator.root()->Alloc(big_size, type_name); EXPECT_TRUE(ptr2); EXPECT_FALSE(page->freelist_head); EXPECT_EQ(2, page->num_allocated_slots); EXPECT_EQ(2, page->num_unprovisioned_slots); - void* ptr3 = PartitionAlloc(allocator.root(), big_size, type_name); + void* ptr3 = allocator.root()->Alloc(big_size, type_name); EXPECT_TRUE(ptr3); EXPECT_TRUE(page->freelist_head); EXPECT_EQ(3, page->num_allocated_slots); EXPECT_EQ(0, page->num_unprovisioned_slots); - void* ptr4 = PartitionAlloc(allocator.root(), big_size, type_name); + void* ptr4 = allocator.root()->Alloc(big_size, type_name); EXPECT_TRUE(ptr4); EXPECT_FALSE(page->freelist_head); EXPECT_EQ(4, page->num_allocated_slots); EXPECT_EQ(0, page->num_unprovisioned_slots); - void* ptr5 = PartitionAlloc(allocator.root(), big_size, type_name); + void* ptr5 = allocator.root()->Alloc(big_size, type_name); EXPECT_TRUE(ptr5); PartitionPage* page2 = @@ -989,8 +989,8 @@ // Churn things a little whilst there's a partial page freelist. PartitionFree(ptr); - ptr = PartitionAlloc(allocator.root(), big_size, type_name); - void* ptr6 = PartitionAlloc(allocator.root(), big_size, type_name); + ptr = allocator.root()->Alloc(big_size, type_name); + void* ptr6 = allocator.root()->Alloc(big_size, type_name); PartitionFree(ptr); PartitionFree(ptr2); @@ -1010,7 +1010,7 @@ bucket = &allocator.root()->buckets()[bucket_index]; EXPECT_EQ(nullptr, bucket->empty_pages_head); - ptr = PartitionAlloc(allocator.root(), mediumSize, type_name); + ptr = allocator.root()->Alloc(mediumSize, type_name); EXPECT_TRUE(ptr); page = PartitionPointerToPage(PartitionCookieFreePointerAdjust(ptr)); EXPECT_EQ(1, page->num_allocated_slots); @@ -1028,7 +1028,7 @@ bucket = &allocator.root()->buckets()[bucket_index]; EXPECT_EQ(nullptr, bucket->empty_pages_head); - ptr = PartitionAlloc(allocator.root(), smallSize, type_name); + ptr = allocator.root()->Alloc(smallSize, type_name); EXPECT_TRUE(ptr); page = PartitionPointerToPage(PartitionCookieFreePointerAdjust(ptr)); EXPECT_EQ(1, page->num_allocated_slots); @@ -1047,7 +1047,7 @@ bucket = &allocator.root()->buckets()[bucket_index]; EXPECT_EQ(nullptr, bucket->empty_pages_head); - ptr = PartitionAlloc(allocator.root(), verySmallSize, type_name); + ptr = allocator.root()->Alloc(verySmallSize, type_name); EXPECT_TRUE(ptr); page = PartitionPointerToPage(PartitionCookieFreePointerAdjust(ptr)); EXPECT_EQ(1, page->num_allocated_slots); @@ -1098,7 +1098,7 @@ // Grab two full pages and a non-full page. PartitionPage* page1 = GetFullPage(kTestAllocSize); PartitionPage* page2 = GetFullPage(kTestAllocSize); - void* ptr = PartitionAlloc(allocator.root(), kTestAllocSize, type_name); + void* ptr = allocator.root()->Alloc(kTestAllocSize, type_name); EXPECT_TRUE(ptr); EXPECT_NE(page1, bucket->active_pages_head); EXPECT_NE(page2, bucket->active_pages_head); @@ -1116,8 +1116,8 @@ // If we perform two allocations from the same bucket now, we expect to // refill both the nearly full pages. - (void)PartitionAlloc(allocator.root(), kTestAllocSize, type_name); - (void)PartitionAlloc(allocator.root(), kTestAllocSize, type_name); + (void)allocator.root()->Alloc(kTestAllocSize, type_name); + (void)allocator.root()->Alloc(kTestAllocSize, type_name); EXPECT_EQ(1, page->num_allocated_slots); FreeFullPage(page2); @@ -1236,7 +1236,7 @@ size_t bucket_index = (big_size + kExtraAllocSize) >> kBucketShift; PartitionBucket* bucket = &allocator.root()->buckets()[bucket_index]; - void* ptr = PartitionAlloc(allocator.root(), big_size, type_name); + void* ptr = allocator.root()->Alloc(big_size, type_name); EXPECT_TRUE(ptr); PartitionPage* page = PartitionPointerToPage(PartitionCookieFreePointerAdjust(ptr)); @@ -1263,14 +1263,14 @@ // Check that an allocation works ok whilst in this state (a free'd page // as the active pages head). - ptr = PartitionAlloc(allocator.root(), big_size, type_name); + ptr = allocator.root()->Alloc(big_size, type_name); EXPECT_FALSE(bucket->empty_pages_head); PartitionFree(ptr); // Also check that a page that is bouncing immediately between empty and // used does not get freed. for (size_t i = 0; i < kMaxFreeableSpans * 2; ++i) { - ptr = PartitionAlloc(allocator.root(), big_size, type_name); + ptr = allocator.root()->Alloc(big_size, type_name); EXPECT_TRUE(page->freelist_head); PartitionFree(ptr); EXPECT_TRUE(page->freelist_head); @@ -1482,10 +1482,10 @@ // crashing and return non-zero values when memory is allocated. TEST_F(PartitionAllocTest, DumpMemoryStats) { { - void* ptr = PartitionAlloc(allocator.root(), kTestAllocSize, type_name); + void* ptr = allocator.root()->Alloc(kTestAllocSize, type_name); MockPartitionStatsDumper mockStatsDumper; - PartitionDumpStats(allocator.root(), "mock_allocator", - false /* detailed dump */, &mockStatsDumper); + allocator.root()->DumpStats("mock_allocator", false /* detailed dump */, + &mockStatsDumper); EXPECT_TRUE(mockStatsDumper.IsMemoryAllocationRecorded()); PartitionFree(ptr); }
diff --git a/base/memory/protected_memory.h b/base/memory/protected_memory.h index 3413460..7ae5fda 100644 --- a/base/memory/protected_memory.h +++ b/base/memory/protected_memory.h
@@ -26,8 +26,13 @@ // Define the section read-only __asm__(".section protected_memory, \"a\"\n\t"); #define PROTECTED_MEMORY_SECTION __attribute__((section("protected_memory"))) -extern char __start_protected_memory; -extern char __stop_protected_memory; + +// Explicitly mark these variables hidden so the symbols are local to the +// currently built component. Otherwise they are created with global (external) +// linkage and component builds would break because a single pair of these +// symbols would override the rest. +__attribute__((visibility("hidden"))) extern char __start_protected_memory; +__attribute__((visibility("hidden"))) extern char __stop_protected_memory; #elif defined(OS_MACOSX) && !defined(OS_IOS) // The segment the section is in is defined read-only with a linker flag in
diff --git a/build/android/adb_gdb b/build/android/adb_gdb index a3ee4e9..c8d223d6 100755 --- a/build/android/adb_gdb +++ b/build/android/adb_gdb
@@ -704,6 +704,7 @@ # Allow several concurrent debugging sessions APP_DATA_DIR=$(adb_shell run-as $PACKAGE_NAME /system/bin/sh -c pwd) +fail_panic "Failed to run-as $PACKAGE_NAME, is the app debuggable?" TARGET_GDBSERVER="$APP_DATA_DIR/gdbserver-adb-gdb-$TMP_ID" TMP_TARGET_GDBSERVER=/data/local/tmp/gdbserver-adb-gdb-$TMP_ID
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py index ecd280e..5be45e5 100644 --- a/build/android/gyp/util/build_utils.py +++ b/build/android/gyp/util/build_utils.py
@@ -30,9 +30,10 @@ COLORAMA_ROOT = os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party', 'colorama', 'src') -# aapt should ignore OWNERS files in addition the default ignore pattern. -AAPT_IGNORE_PATTERN = ('!OWNERS:!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:' + - '!CVS:!thumbs.db::!*~:!*.d.stamp') +# aapt should ignore OWNERS and python files in addition the default ignore +# pattern. +AAPT_IGNORE_PATTERN = ('!OWNERS:!*.py:!*.pyc:!.svn:!.git:!.ds_store:!*.scc:' + + '.*:<dir>_*:!CVS:!thumbs.db::!*~:!*.d.stamp') HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0) _HERMETIC_FILE_ATTR = (0644 << 16L)
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py index 2a4826a3..16e9969 100644 --- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py +++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -446,18 +446,20 @@ with self._env.output_manager.ArchivedTempfile( stream_name, 'logcat') as logcat_file: - with logcat_monitor.LogcatMonitor( - device.adb, - filter_specs=local_device_environment.LOGCAT_FILTERS, - output_file=logcat_file.name, - transform_func=self._test_instance.MaybeDeobfuscateLines) as logmon: - with _LogTestEndpoints(device, test_name): - with contextlib_ext.Optional( - trace_event.trace(test_name), - self._env.trace_output): - output = device.StartInstrumentation( - target, raw=True, extras=extras, timeout=timeout, retries=0) - logmon.Close() + try: + with logcat_monitor.LogcatMonitor( + device.adb, + filter_specs=local_device_environment.LOGCAT_FILTERS, + output_file=logcat_file.name, + transform_func=self._test_instance.MaybeDeobfuscateLines) as logmon: + with _LogTestEndpoints(device, test_name): + with contextlib_ext.Optional( + trace_event.trace(test_name), + self._env.trace_output): + output = device.StartInstrumentation( + target, raw=True, extras=extras, timeout=timeout, retries=0) + finally: + logmon.Close() if logcat_file.Link(): logging.info('Logcat saved to %s', logcat_file.Link())
diff --git a/build/android/pylib/local/device/local_device_test_run.py b/build/android/pylib/local/device/local_device_test_run.py index 85c13b7d..21ab0465 100644 --- a/build/android/pylib/local/device/local_device_test_run.py +++ b/build/android/pylib/local/device/local_device_test_run.py
@@ -77,6 +77,18 @@ else: raise Exception( 'Unexpected result type: %s' % type(result).__name__) + except device_errors.CommandTimeoutError: + if isinstance(test, list): + results.AddResults( + base_test_result.BaseTestResult( + self._GetUniqueTestName(t), + base_test_result.ResultType.TIMEOUT) + for t in test) + else: + results.AddResult( + base_test_result.BaseTestResult( + self._GetUniqueTestName(test), + base_test_result.ResultType.TIMEOUT)) except Exception as e: # pylint: disable=broad-except if isinstance(tests, test_collection.TestCollection): rerun = test
diff --git a/build/android/pylib/results/json_results.py b/build/android/pylib/results/json_results.py index 19fc60f..d9f441f 100644 --- a/build/android/pylib/results/json_results.py +++ b/build/android/pylib/results/json_results.py
@@ -124,7 +124,8 @@ } -def GenerateJsonResultsFile(test_run_result, file_path, global_tags=None): +def GenerateJsonResultsFile(test_run_result, file_path, global_tags=None, + **kwargs): """Write |test_run_result| to JSON. This emulates the format of the JSON emitted by @@ -136,7 +137,8 @@ """ with open(file_path, 'w') as json_result_file: json_result_file.write(json.dumps( - GenerateResultsDict(test_run_result, global_tags=global_tags))) + GenerateResultsDict(test_run_result, global_tags=global_tags), + **kwargs)) def ParseResultsFromJson(json_results):
diff --git a/build/android/test_runner.py b/build/android/test_runner.py index 6daa33c..01081e6 100755 --- a/build/android/test_runner.py +++ b/build/android/test_runner.py
@@ -821,7 +821,8 @@ finally: json_results.GenerateJsonResultsFile( all_raw_results, json_file.name, - global_tags=list(global_results_tags)) + global_tags=list(global_results_tags), + indent=2) @contextlib.contextmanager def upload_logcats_file():
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index b3335d9..48ed140 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn
@@ -524,6 +524,7 @@ "//build/config/compiler:default_optimization", "//build/config/compiler:default_stack_frames", "//build/config/compiler:default_symbols", + "//build/config/compiler:no_exceptions", "//build/config/compiler:no_rtti", "//build/config/compiler:runtime_library", "//build/config/coverage:default_coverage", @@ -545,7 +546,6 @@ } if (is_posix) { - default_compiler_configs += [ "//build/config/gcc:no_exceptions" ] if (current_os != "aix") { default_compiler_configs += [ "//build/config/gcc:symbol_visibility_hidden" ]
diff --git a/build/config/angle_temp.gni b/build/config/angle_temp.gni index 991f06a..a9d45f2 100644 --- a/build/config/angle_temp.gni +++ b/build/config/angle_temp.gni
@@ -5,5 +5,5 @@ declare_args() { # This is a placeholder to enable a transation for ANGLE's build. # TOOD(jmadill): Remove this once transition is complete. - is_temp_angle = false + is_temp_angle = true }
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 62d2cf13..a6ba4ea6 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -1239,6 +1239,14 @@ # in -Wall but gcc does, and it gives false positives. cflags += [ "-Wno-maybe-uninitialized" ] cflags += [ "-Wno-deprecated-declarations" ] + + # GCC assumes 'this' is never nullptr and optimizes away code + # like "if (this == nullptr) ...": [1]. However, some Chromium + # code relies on these types of null pointer checks [2], so + # disable this optimization. + # [1] https://gcc.gnu.org/gcc-6/porting_to.html#this-cannot-be-null + # [2] https://crbug.com/784492#c13 + cflags += [ "-fno-delete-null-pointer-checks" ] } } @@ -1463,6 +1471,31 @@ } } +# exceptions ------------------------------------------------------------------- +# +# Allows turning Exceptions on or off. + +config("exceptions") { + if (is_win) { + # Enables exceptions in the STL. + defines = [ "_HAS_EXCEPTIONS=1" ] + cflags_cc = [ "/EHsc" ] + } else { + cflags_cc = [ "-fexceptions" ] + cflags_objcc = cflags_cc + } +} + +config("no_exceptions") { + if (is_win) { + # Disables exceptions in the STL. + defines = [ "_HAS_EXCEPTIONS=0" ] + } else { + cflags_cc = [ "-fno-exceptions" ] + cflags_objcc = cflags_cc + } +} + # Warnings --------------------------------------------------------------------- # This will generate warnings when using Clang if code generates exit-time
diff --git a/build/config/gcc/BUILD.gn b/build/config/gcc/BUILD.gn index 4d00a9f..0f4493f 100644 --- a/build/config/gcc/BUILD.gn +++ b/build/config/gcc/BUILD.gn
@@ -138,8 +138,3 @@ ] } } - -config("no_exceptions") { - cflags_cc = [ "-fno-exceptions" ] - cflags_objcc = cflags_cc -}
diff --git a/build/config/linux/pangocairo/BUILD.gn b/build/config/linux/pangocairo/BUILD.gn index d53a6558..ddcc754bb 100644 --- a/build/config/linux/pangocairo/BUILD.gn +++ b/build/config/linux/pangocairo/BUILD.gn
@@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/buildflag_header.gni") import("//build/config/linux/pangocairo/pangocairo.gni") import("//build/config/linux/pkg_config.gni") @@ -18,8 +17,3 @@ ] } } - -buildflag_header("features") { - header = "features.h" - flags = [ "USE_PANGOCAIRO=$use_pangocairo" ] -}
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn index a4e95a3..d289619 100644 --- a/build/config/sanitizers/BUILD.gn +++ b/build/config/sanitizers/BUILD.gn
@@ -266,12 +266,7 @@ "-gcolumn-info", ] - # Disable frame pointer elimination for better stack traces. - if (is_posix) { - cflags += [ "-fno-omit-frame-pointer" ] - } else { - cflags += [ "/Oy-" ] - } + # Frame pointers are controlled in //build/config/compiler:default_stack_frames } }
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index 402ce9bc..bc762f5 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn
@@ -192,7 +192,6 @@ "__STD_C", "_CRT_RAND_S", "_CRT_SECURE_NO_DEPRECATE", - "_HAS_EXCEPTIONS=0", "_SCL_SECURE_NO_DEPRECATE", ]
diff --git a/build/download_nacl_toolchains.py b/build/download_nacl_toolchains.py index cccecce..ea9e0cda 100755 --- a/build/download_nacl_toolchains.py +++ b/build/download_nacl_toolchains.py
@@ -52,9 +52,7 @@ if 'target_arch=arm' not in os.environ.get('GYP_DEFINES', ''): args = ['--exclude', 'nacl_arm_newlib'] + args - package_version.main(args) - - return 0 + return package_version.main(args) if __name__ == '__main__':
diff --git a/build/linux/sysroot_scripts/install-sysroot.py b/build/linux/sysroot_scripts/install-sysroot.py index fe01daa6..2a7918bb 100755 --- a/build/linux/sysroot_scripts/install-sysroot.py +++ b/build/linux/sysroot_scripts/install-sysroot.py
@@ -39,7 +39,7 @@ URL_PREFIX = 'https://commondatastorage.googleapis.com' URL_PATH = 'chrome-linux-sysroot/toolchain' -VALID_ARCHS = ('arm', 'arm64', 'i386', 'amd64', 'mips') +VALID_ARCHS = ('arm', 'arm64', 'i386', 'amd64', 'mips', 'mips64el') class Error(Exception): @@ -72,6 +72,8 @@ return 'arm64' if detected_host_arch == 'mips': return 'mips' + if detected_host_arch == 'mips64': + return 'mips64el' if detected_host_arch == 'ppc': return 'ppc' if detected_host_arch == 's390': @@ -101,6 +103,8 @@ return 'arm64' if target_arch == 'mipsel': return 'mips' + if target_arch == 'mips64el': + return 'mips64el' return None
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc index e431eb7..be1830a 100644 --- a/build/sanitizers/tsan_suppressions.cc +++ b/build/sanitizers/tsan_suppressions.cc
@@ -119,10 +119,6 @@ // http://crbug.com/310851 "race:net::ProxyResolverV8Tracing::Job::~Job\n" - // http://crbug.com/327330 - "race:PrepareTextureMailbox\n" - "race:cc::LayerTreeHost::PaintLayerContents\n" - // http://crbug.com/476529 "deadlock:cc::VideoLayerImpl::WillDraw\n"
diff --git a/build/secondary/third_party/crashpad/OWNERS b/build/secondary/third_party/crashpad/OWNERS deleted file mode 100644 index 93e31e5..0000000 --- a/build/secondary/third_party/crashpad/OWNERS +++ /dev/null
@@ -1,5 +0,0 @@ -mark@chromium.org -rsesek@chromium.org -scottmg@chromium.org - -# TEAM: crashpad-dev@chromium.org
diff --git a/build/secondary/third_party/crashpad/crashpad/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/BUILD.gn deleted file mode 100644 index efbfee6a..0000000 --- a/build/secondary/third_party/crashpad/crashpad/BUILD.gn +++ /dev/null
@@ -1,21 +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("//testing/test.gni") - -config("crashpad_config") { - include_dirs = [ "//third_party/crashpad/crashpad" ] -} - -test("crashpad_tests") { - deps = [ - "client:client_test", - "handler:handler_test", - "minidump:minidump_test", - "snapshot:snapshot_test", - "test:gmock_main", - "test:test_test", - "util:util_test", - ] -}
diff --git a/build/secondary/third_party/crashpad/crashpad/third_party/apple_cctools/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/third_party/apple_cctools/BUILD.gn deleted file mode 100644 index c0250564..0000000 --- a/build/secondary/third_party/crashpad/crashpad/third_party/apple_cctools/BUILD.gn +++ /dev/null
@@ -1,15 +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. - -config("apple_cctools_config") { - include_dirs = [ "../.." ] -} - -source_set("apple_cctools") { - sources = [ - "cctools/include/mach-o/getsect.h", - "cctools/libmacho/getsecbyname.c", - ] - public_configs = [ ":apple_cctools_config" ] -}
diff --git a/build/secondary/third_party/crashpad/crashpad/third_party/getopt/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/third_party/getopt/BUILD.gn deleted file mode 100644 index 3edcfda7..0000000 --- a/build/secondary/third_party/crashpad/crashpad/third_party/getopt/BUILD.gn +++ /dev/null
@@ -1,10 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("getopt") { - sources = [ - "getopt.cc", - "getopt.h", - ] -}
diff --git a/build/secondary/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn deleted file mode 100644 index 5710805..0000000 --- a/build/secondary/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn +++ /dev/null
@@ -1,14 +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. - -config("zlib_config") { - defines = [ "CRASHPAD_ZLIB_SOURCE_CHROMIUM" ] -} - -group("zlib") { - public_configs = [ ":zlib_config" ] - public_deps = [ - "//third_party/zlib:zlib", - ] -}
diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc index 403b781e..935ef9a 100644 --- a/cc/layers/texture_layer.cc +++ b/cc/layers/texture_layer.cc
@@ -34,7 +34,7 @@ } void TextureLayer::ClearTexture() { - SetTextureMailbox(viz::TextureMailbox(), nullptr); + SetTransferableResource(viz::TransferableResource(), nullptr); } std::unique_ptr<LayerImpl> TextureLayer::CreateLayerImpl( @@ -99,24 +99,22 @@ SetNeedsCommit(); } -void TextureLayer::SetTextureMailboxInternal( - const viz::TextureMailbox& mailbox, +void TextureLayer::SetTransferableResourceInternal( + const viz::TransferableResource& resource, std::unique_ptr<viz::SingleReleaseCallback> release_callback, - bool requires_commit, - bool allow_mailbox_reuse) { - DCHECK(!mailbox.IsValid() || !holder_ref_ || - !mailbox.Equals(holder_ref_->holder()->mailbox()) || - allow_mailbox_reuse); - DCHECK_EQ(mailbox.IsValid(), !!release_callback); + bool requires_commit) { + DCHECK(resource.mailbox_holder.mailbox.IsZero() || !holder_ref_ || + resource != holder_ref_->holder()->resource()); + DCHECK_EQ(resource.mailbox_holder.mailbox.IsZero(), !release_callback); // If we never commited the mailbox, we need to release it here. - if (mailbox.IsValid()) { - holder_ref_ = - TextureMailboxHolder::Create(mailbox, std::move(release_callback)); + if (!resource.mailbox_holder.mailbox.IsZero()) { + holder_ref_ = TransferableResourceHolder::Create( + resource, std::move(release_callback)); } else { holder_ref_ = nullptr; } - needs_set_mailbox_ = true; + needs_set_resource_ = true; // If we are within a commit, no need to do it again immediately after. if (requires_commit) SetNeedsCommit(); @@ -129,13 +127,12 @@ SetNextCommitWaitsForActivation(); } -void TextureLayer::SetTextureMailbox( - const viz::TextureMailbox& mailbox, +void TextureLayer::SetTransferableResource( + const viz::TransferableResource& resource, std::unique_ptr<viz::SingleReleaseCallback> release_callback) { bool requires_commit = true; - bool allow_mailbox_reuse = false; - SetTextureMailboxInternal(mailbox, std::move(release_callback), - requires_commit, allow_mailbox_reuse); + SetTransferableResourceInternal(resource, std::move(release_callback), + requires_commit); } void TextureLayer::SetNeedsDisplayRect(const gfx::Rect& dirty_rect) { @@ -152,7 +149,7 @@ // we will need to set the mailbox again on a new TextureLayerImpl the next // time we push. if (!host && holder_ref_) { - needs_set_mailbox_ = true; + needs_set_resource_ = true; // The active frame needs to be replaced and the mailbox returned before the // commit is called complete. SetNextCommitWaitsForActivation(); @@ -167,21 +164,20 @@ bool TextureLayer::Update() { bool updated = Layer::Update(); if (client_) { - viz::TextureMailbox mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; - if (client_->PrepareTextureMailbox(&mailbox, &release_callback)) { + if (client_->PrepareTransferableResource(&resource, &release_callback)) { // Already within a commit, no need to do another one immediately. bool requires_commit = false; - bool allow_mailbox_reuse = false; - SetTextureMailboxInternal(mailbox, std::move(release_callback), - requires_commit, allow_mailbox_reuse); + SetTransferableResourceInternal(resource, std::move(release_callback), + requires_commit); updated = true; } } - // SetTextureMailbox could be called externally and the same mailbox used for - // different textures. Such callers notify this layer that the texture has - // changed by calling SetNeedsDisplay, so check for that here. + // SetTransferableResource could be called externally and the same mailbox + // used for different textures. Such callers notify this layer that the + // texture has changed by calling SetNeedsDisplay, so check for that here. return updated || !update_rect().IsEmpty(); } @@ -201,54 +197,54 @@ texture_layer->SetVertexOpacity(vertex_opacity_); texture_layer->SetPremultipliedAlpha(premultiplied_alpha_); texture_layer->SetBlendBackgroundColor(blend_background_color_); - if (needs_set_mailbox_) { - viz::TextureMailbox texture_mailbox; + if (needs_set_resource_) { + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; if (holder_ref_) { - TextureMailboxHolder* holder = holder_ref_->holder(); - texture_mailbox = holder->mailbox(); + TransferableResourceHolder* holder = holder_ref_->holder(); + resource = holder->resource(); release_callback = holder->GetCallbackForImplThread( layer_tree_host()->GetTaskRunnerProvider()->MainThreadTaskRunner()); } - texture_layer->SetTextureMailbox(texture_mailbox, - std::move(release_callback)); - needs_set_mailbox_ = false; + texture_layer->SetTransferableResource(resource, + std::move(release_callback)); + needs_set_resource_ = false; } } -TextureLayer::TextureMailboxHolder::MainThreadReference::MainThreadReference( - TextureMailboxHolder* holder) +TextureLayer::TransferableResourceHolder::MainThreadReference:: + MainThreadReference(TransferableResourceHolder* holder) : holder_(holder) { holder_->InternalAddRef(); } -TextureLayer::TextureMailboxHolder::MainThreadReference:: +TextureLayer::TransferableResourceHolder::MainThreadReference:: ~MainThreadReference() { holder_->InternalRelease(); } -TextureLayer::TextureMailboxHolder::TextureMailboxHolder( - const viz::TextureMailbox& mailbox, +TextureLayer::TransferableResourceHolder::TransferableResourceHolder( + const viz::TransferableResource& resource, std::unique_ptr<viz::SingleReleaseCallback> release_callback) : internal_references_(0), - mailbox_(mailbox), + resource_(resource), release_callback_(std::move(release_callback)), - sync_token_(mailbox.sync_token()), + sync_token_(resource.mailbox_holder.sync_token), is_lost_(false) {} -TextureLayer::TextureMailboxHolder::~TextureMailboxHolder() { +TextureLayer::TransferableResourceHolder::~TransferableResourceHolder() { DCHECK_EQ(0u, internal_references_); } -std::unique_ptr<TextureLayer::TextureMailboxHolder::MainThreadReference> -TextureLayer::TextureMailboxHolder::Create( - const viz::TextureMailbox& mailbox, +std::unique_ptr<TextureLayer::TransferableResourceHolder::MainThreadReference> +TextureLayer::TransferableResourceHolder::Create( + const viz::TransferableResource& resource, std::unique_ptr<viz::SingleReleaseCallback> release_callback) { return std::make_unique<MainThreadReference>( - new TextureMailboxHolder(mailbox, std::move(release_callback))); + new TransferableResourceHolder(resource, std::move(release_callback))); } -void TextureLayer::TextureMailboxHolder::Return( +void TextureLayer::TransferableResourceHolder::Return( const gpu::SyncToken& sync_token, bool is_lost) { base::AutoLock lock(arguments_lock_); @@ -257,37 +253,38 @@ } std::unique_ptr<viz::SingleReleaseCallback> -TextureLayer::TextureMailboxHolder::GetCallbackForImplThread( +TextureLayer::TransferableResourceHolder::GetCallbackForImplThread( scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner) { // We can't call GetCallbackForImplThread if we released the main thread // reference. DCHECK_GT(internal_references_, 0u); InternalAddRef(); return viz::SingleReleaseCallback::Create( - base::Bind(&TextureMailboxHolder::ReturnAndReleaseOnImplThread, this, - std::move(main_thread_task_runner))); + base::Bind(&TransferableResourceHolder::ReturnAndReleaseOnImplThread, + this, std::move(main_thread_task_runner))); } -void TextureLayer::TextureMailboxHolder::InternalAddRef() { +void TextureLayer::TransferableResourceHolder::InternalAddRef() { ++internal_references_; } -void TextureLayer::TextureMailboxHolder::InternalRelease() { +void TextureLayer::TransferableResourceHolder::InternalRelease() { DCHECK(main_thread_checker_.CalledOnValidThread()); if (!--internal_references_) { release_callback_->Run(sync_token_, is_lost_); - mailbox_ = viz::TextureMailbox(); + resource_ = viz::TransferableResource(); release_callback_ = nullptr; } } -void TextureLayer::TextureMailboxHolder::ReturnAndReleaseOnImplThread( +void TextureLayer::TransferableResourceHolder::ReturnAndReleaseOnImplThread( const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner, const gpu::SyncToken& sync_token, bool is_lost) { Return(sync_token, is_lost); main_thread_task_runner->PostTask( - FROM_HERE, base::Bind(&TextureMailboxHolder::InternalRelease, this)); + FROM_HERE, + base::Bind(&TransferableResourceHolder::InternalRelease, this)); } } // namespace cc
diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h index 0b3cc40..ae19b371 100644 --- a/cc/layers/texture_layer.h +++ b/cc/layers/texture_layer.h
@@ -13,7 +13,7 @@ #include "base/threading/thread_checker.h" #include "cc/cc_export.h" #include "cc/layers/layer.h" -#include "components/viz/common/quads/texture_mailbox.h" +#include "components/viz/common/resources/transferable_resource.h" namespace gpu { struct SyncToken; @@ -30,21 +30,21 @@ // A Layer containing a the rendered output of a plugin instance. class CC_EXPORT TextureLayer : public Layer { public: - class CC_EXPORT TextureMailboxHolder - : public base::RefCountedThreadSafe<TextureMailboxHolder> { + class CC_EXPORT TransferableResourceHolder + : public base::RefCountedThreadSafe<TransferableResourceHolder> { public: class CC_EXPORT MainThreadReference { public: - explicit MainThreadReference(TextureMailboxHolder* holder); + explicit MainThreadReference(TransferableResourceHolder* holder); ~MainThreadReference(); - TextureMailboxHolder* holder() { return holder_.get(); } + TransferableResourceHolder* holder() { return holder_.get(); } private: - scoped_refptr<TextureMailboxHolder> holder_; + scoped_refptr<TransferableResourceHolder> holder_; DISALLOW_COPY_AND_ASSIGN(MainThreadReference); }; - const viz::TextureMailbox& mailbox() const { return mailbox_; } + const viz::TransferableResource& resource() const { return resource_; } void Return(const gpu::SyncToken& sync_token, bool is_lost); // Gets a viz::ReleaseCallback that can be called from another thread. Note: @@ -57,15 +57,15 @@ // Protected visiblity so only TextureLayer and unit tests can create these. static std::unique_ptr<MainThreadReference> Create( - const viz::TextureMailbox& mailbox, + const viz::TransferableResource& resource, std::unique_ptr<viz::SingleReleaseCallback> release_callback); - virtual ~TextureMailboxHolder(); + virtual ~TransferableResourceHolder(); private: - friend class base::RefCountedThreadSafe<TextureMailboxHolder>; + friend class base::RefCountedThreadSafe<TransferableResourceHolder>; friend class MainThreadReference; - explicit TextureMailboxHolder( - const viz::TextureMailbox& mailbox, + explicit TransferableResourceHolder( + const viz::TransferableResource& resource, std::unique_ptr<viz::SingleReleaseCallback> release_callback); void InternalAddRef(); @@ -78,7 +78,7 @@ // These members are only accessed on the main thread, or on the impl thread // during commit where the main thread is blocked. unsigned internal_references_; - viz::TextureMailbox mailbox_; + viz::TransferableResource resource_; std::unique_ptr<viz::SingleReleaseCallback> release_callback_; // This lock guards the sync_token_ and is_lost_ fields because they can be @@ -89,7 +89,7 @@ gpu::SyncToken sync_token_; bool is_lost_; base::ThreadChecker main_thread_checker_; - DISALLOW_COPY_AND_ASSIGN(TextureMailboxHolder); + DISALLOW_COPY_AND_ASSIGN(TransferableResourceHolder); }; // Used when mailbox names are specified instead of texture IDs. @@ -132,8 +132,8 @@ void SetBlendBackgroundColor(bool blend); // Code path for plugins which supply their own mailbox. - void SetTextureMailbox( - const viz::TextureMailbox& mailbox, + void SetTransferableResource( + const viz::TransferableResource& resource, std::unique_ptr<viz::SingleReleaseCallback> release_callback); void SetNeedsDisplayRect(const gfx::Rect& dirty_rect) override; @@ -149,11 +149,10 @@ bool HasDrawableContent() const override; private: - void SetTextureMailboxInternal( - const viz::TextureMailbox& mailbox, + void SetTransferableResourceInternal( + const viz::TransferableResource& resource, std::unique_ptr<viz::SingleReleaseCallback> release_callback, - bool requires_commit, - bool allow_mailbox_reuse); + bool requires_commit); TextureLayerClient* client_; @@ -166,8 +165,8 @@ bool premultiplied_alpha_ = true; bool blend_background_color_ = false; - std::unique_ptr<TextureMailboxHolder::MainThreadReference> holder_ref_; - bool needs_set_mailbox_ = false; + std::unique_ptr<TransferableResourceHolder::MainThreadReference> holder_ref_; + bool needs_set_resource_ = false; DISALLOW_COPY_AND_ASSIGN(TextureLayer); };
diff --git a/cc/layers/texture_layer_client.h b/cc/layers/texture_layer_client.h index 8fe8d96..a535d50 100644 --- a/cc/layers/texture_layer_client.h +++ b/cc/layers/texture_layer_client.h
@@ -8,7 +8,7 @@ #include "components/viz/common/resources/single_release_callback.h" namespace viz { -class TextureMailbox; +struct TransferableResource; } namespace cc { @@ -18,8 +18,8 @@ // Returns true and provides a mailbox if a new frame is available. // Returns false if no new data is available // and the old mailbox is to be reused. - virtual bool PrepareTextureMailbox( - viz::TextureMailbox* mailbox, + virtual bool PrepareTransferableResource( + viz::TransferableResource* transferable_resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback) = 0; protected:
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc index 57f9fd5..cb8c3cf 100644 --- a/cc/layers/texture_layer_impl.cc +++ b/cc/layers/texture_layer_impl.cc
@@ -22,16 +22,18 @@ TextureLayerImpl::TextureLayerImpl(LayerTreeImpl* tree_impl, int id) : LayerImpl(tree_impl, id) {} -TextureLayerImpl::~TextureLayerImpl() { FreeTextureMailbox(); } +TextureLayerImpl::~TextureLayerImpl() { + FreeTransferableResource(); +} -void TextureLayerImpl::SetTextureMailbox( - const viz::TextureMailbox& mailbox, +void TextureLayerImpl::SetTransferableResource( + const viz::TransferableResource& resource, std::unique_ptr<viz::SingleReleaseCallback> release_callback) { - DCHECK_EQ(mailbox.IsValid(), !!release_callback); - FreeTextureMailbox(); - texture_mailbox_ = mailbox; + DCHECK_EQ(resource.mailbox_holder.mailbox.IsZero(), !release_callback); + FreeTransferableResource(); + transferable_resource_ = resource; release_callback_ = std::move(release_callback); - own_mailbox_ = true; + own_resource_ = true; SetNeedsPushProperties(); } @@ -54,10 +56,10 @@ texture_layer->SetPremultipliedAlpha(premultiplied_alpha_); texture_layer->SetBlendBackgroundColor(blend_background_color_); texture_layer->SetNearestNeighbor(nearest_neighbor_); - if (own_mailbox_) { - texture_layer->SetTextureMailbox(texture_mailbox_, - std::move(release_callback_)); - own_mailbox_ = false; + if (own_resource_) { + texture_layer->SetTransferableResource(transferable_resource_, + std::move(release_callback_)); + own_resource_ = false; } } @@ -69,30 +71,31 @@ // compositing but the client thinks it is in software, or vice versa. These // should only happen transiently, and should resolve when the client hears // about the mode switch. - if (draw_mode == DRAW_MODE_HARDWARE && !texture_mailbox_.IsTexture()) { + if (draw_mode == DRAW_MODE_HARDWARE && transferable_resource_.is_software) { DLOG(ERROR) << "Gpu compositor has software resource in TextureLayer"; return false; } - if (draw_mode == DRAW_MODE_SOFTWARE && !texture_mailbox_.IsSharedMemory()) { + if (draw_mode == DRAW_MODE_SOFTWARE && !transferable_resource_.is_software) { DLOG(ERROR) << "Software compositor has gpu resource in TextureLayer"; return false; } - if (own_mailbox_) { - DCHECK(!external_texture_resource_); - external_texture_resource_ = - resource_provider->CreateResourceFromTextureMailbox( - texture_mailbox_, std::move(release_callback_)); - own_mailbox_ = false; + if (own_resource_) { + DCHECK(!resource_id_); + if (!transferable_resource_.mailbox_holder.mailbox.IsZero()) { + resource_id_ = resource_provider->ImportResource( + transferable_resource_, std::move(release_callback_)); + DCHECK(resource_id_); + } + own_resource_ = false; } - return external_texture_resource_ && - LayerImpl::WillDraw(draw_mode, resource_provider); + return resource_id_ && LayerImpl::WillDraw(draw_mode, resource_provider); } void TextureLayerImpl::AppendQuads(viz::RenderPass* render_pass, AppendQuadsData* append_quads_data) { - DCHECK(external_texture_resource_); + DCHECK(resource_id_); SkColor bg_color = blend_background_color_ ? background_color() : SK_ColorTRANSPARENT; @@ -120,10 +123,10 @@ auto* quad = render_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>(); quad->SetNew(shared_quad_state, quad_rect, visible_quad_rect, needs_blending, - external_texture_resource_, premultiplied_alpha_, uv_top_left_, + resource_id_, premultiplied_alpha_, uv_top_left_, uv_bottom_right_, bg_color, vertex_opacity_, flipped_, nearest_neighbor_, false); - quad->set_resource_size_in_pixels(texture_mailbox_.size_in_pixels()); + quad->set_resource_size_in_pixels(transferable_resource_.size); ValidateQuadResources(quad); } @@ -138,8 +141,8 @@ } void TextureLayerImpl::ReleaseResources() { - FreeTextureMailbox(); - external_texture_resource_ = 0; + FreeTransferableResource(); + resource_id_ = 0; } void TextureLayerImpl::SetPremultipliedAlpha(bool premultiplied_alpha) { @@ -187,19 +190,20 @@ return "cc::TextureLayerImpl"; } -void TextureLayerImpl::FreeTextureMailbox() { - if (own_mailbox_) { - DCHECK(!external_texture_resource_); - if (release_callback_) - release_callback_->Run(texture_mailbox_.sync_token(), false); - texture_mailbox_ = viz::TextureMailbox(); +void TextureLayerImpl::FreeTransferableResource() { + if (own_resource_) { + DCHECK(!resource_id_); + if (release_callback_) { + // We didn't use the resource, so don't need to return a SyncToken. + release_callback_->Run(gpu::SyncToken(), false); + } + transferable_resource_ = viz::TransferableResource(); release_callback_ = nullptr; - } else if (external_texture_resource_) { - DCHECK(!own_mailbox_); - ResourceProvider* resource_provider = - layer_tree_impl()->resource_provider(); - resource_provider->DeleteResource(external_texture_resource_); - external_texture_resource_ = 0; + } else if (resource_id_) { + DCHECK(!own_resource_); + auto* resource_provider = layer_tree_impl()->resource_provider(); + resource_provider->RemoveImportedResource(resource_id_); + resource_id_ = 0; } }
diff --git a/cc/layers/texture_layer_impl.h b/cc/layers/texture_layer_impl.h index 17a86f21..d688902 100644 --- a/cc/layers/texture_layer_impl.h +++ b/cc/layers/texture_layer_impl.h
@@ -12,7 +12,7 @@ #include "base/memory/ptr_util.h" #include "cc/cc_export.h" #include "cc/layers/layer_impl.h" -#include "components/viz/common/quads/texture_mailbox.h" +#include "components/viz/common/resources/transferable_resource.h" namespace viz { class SingleReleaseCallback; @@ -56,17 +56,16 @@ // 0--3 void SetVertexOpacity(const float vertex_opacity[4]); - void SetTextureMailbox( - const viz::TextureMailbox& mailbox, + void SetTransferableResource( + const viz::TransferableResource& resource, std::unique_ptr<viz::SingleReleaseCallback> release_callback); private: TextureLayerImpl(LayerTreeImpl* tree_impl, int id); const char* LayerTypeAsString() const override; - void FreeTextureMailbox(); + void FreeTransferableResource(); - viz::ResourceId external_texture_resource_ = 0; bool premultiplied_alpha_ = true; bool blend_background_color_ = false; bool flipped_ = true; @@ -75,9 +74,18 @@ gfx::PointF uv_bottom_right_ = gfx::PointF(1.f, 1.f); float vertex_opacity_[4] = {1.f, 1.f, 1.f, 1.f}; - viz::TextureMailbox texture_mailbox_; + // True while the |transferable_resource_| is owned by this layer, and + // becomes false once it is passed to another layer or to the + // LayerTreeResourceProvider, at which point we get back a |resource_id_|. + bool own_resource_ = false; + // A TransferableResource from the layer's client that will be given + // to the display compositor. + viz::TransferableResource transferable_resource_; + // Local ResourceId for the TransferableResource, to be used with the + // compositor's LayerTreeResourceProvider in order to refer to the + // TransferableResource given to it. + viz::ResourceId resource_id_ = 0; std::unique_ptr<viz::SingleReleaseCallback> release_callback_; - bool own_mailbox_ = false; DISALLOW_COPY_AND_ASSIGN(TextureLayerImpl); };
diff --git a/cc/layers/texture_layer_impl_unittest.cc b/cc/layers/texture_layer_impl_unittest.cc index e95f5575..86157245 100644 --- a/cc/layers/texture_layer_impl_unittest.cc +++ b/cc/layers/texture_layer_impl_unittest.cc
@@ -52,23 +52,21 @@ LayerTestCommon::LayerImplTest impl; + auto* gl = impl.layer_tree_frame_sink()->context_provider()->ContextGL(); + gpu::Mailbox mailbox; - impl.layer_tree_frame_sink() - ->context_provider() - ->ContextGL() - ->GenMailboxCHROMIUM(mailbox.name); - viz::TextureMailbox texture_mailbox( - mailbox, + gl->GenMailboxCHROMIUM(mailbox.name); + auto resource = viz::TransferableResource::MakeGL( + std::move(mailbox), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(gpu::CommandBufferNamespace::GPU_IO, 0x123, - gpu::CommandBufferId::FromUnsafeValue(0x234), 0x456), - GL_TEXTURE_2D); + gpu::CommandBufferId::FromUnsafeValue(0x234), 0x456)); TextureLayerImpl* texture_layer_impl = impl.AddChildToRoot<TextureLayerImpl>(); texture_layer_impl->SetBounds(layer_size); texture_layer_impl->SetDrawsContent(true); - texture_layer_impl->SetTextureMailbox( - texture_mailbox, + texture_layer_impl->SetTransferableResource( + resource, viz::SingleReleaseCallback::Create(base::Bind(&IgnoreCallback))); impl.CalcDrawProps(viewport_size); @@ -115,26 +113,25 @@ gfx::Size layer_size(1000, 1000); gfx::Size viewport_size(1000, 1000); - gpu::Mailbox mailbox; - impl.layer_tree_frame_sink() - ->context_provider() - ->ContextGL() - ->GenMailboxCHROMIUM(mailbox.name); - viz::TextureMailbox texture_mailbox( - mailbox, + auto* gl = impl.layer_tree_frame_sink()->context_provider()->ContextGL(); + + viz::TransferableResource resource; + resource.is_software = false; + gl->GenMailboxCHROMIUM(resource.mailbox_holder.mailbox.name); + resource.mailbox_holder.sync_token = gpu::SyncToken(gpu::CommandBufferNamespace::GPU_IO, 0x123, - gpu::CommandBufferId::FromUnsafeValue(0x234), 0x456), - GL_TEXTURE_2D); + gpu::CommandBufferId::FromUnsafeValue(0x234), 0x456); + resource.mailbox_holder.texture_target = GL_TEXTURE_2D; TextureLayerImpl* texture_layer_impl = impl.AddChildToRoot<TextureLayerImpl>(); texture_layer_impl->SetBounds(layer_size); texture_layer_impl->SetDrawsContent(true); - texture_layer_impl->SetTextureMailbox( - texture_mailbox, viz::SingleReleaseCallback::Create(base::Bind( - [](bool* released, const gpu::SyncToken& sync_token, - bool lost) { *released = true; }, - base::Unretained(&released)))); + texture_layer_impl->SetTransferableResource( + resource, viz::SingleReleaseCallback::Create(base::Bind( + [](bool* released, const gpu::SyncToken& sync_token, + bool lost) { *released = true; }, + base::Unretained(&released)))); impl.CalcDrawProps(viewport_size);
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc index 3c879a74..921d6c2 100644 --- a/cc/layers/texture_layer_unittest.cc +++ b/cc/layers/texture_layer_unittest.cc
@@ -39,6 +39,7 @@ #include "cc/trees/single_thread_proxy.h" #include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/resources/returned_resource.h" +#include "components/viz/common/resources/transferable_resource.h" #include "components/viz/test/test_layer_tree_frame_sink.h" #include "gpu/GLES2/gl2extchromium.h" #include "testing/gmock/include/gmock/gmock.h" @@ -93,38 +94,7 @@ StubLayerTreeHostSingleThreadClient single_thread_client_; }; -class FakeTextureLayerClient : public TextureLayerClient { - public: - FakeTextureLayerClient() : mailbox_changed_(true) {} - - bool PrepareTextureMailbox( - viz::TextureMailbox* mailbox, - std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override { - if (!mailbox_changed_) - return false; - - *mailbox = mailbox_; - *release_callback = std::move(release_callback_); - mailbox_changed_ = false; - return true; - } - - void set_mailbox( - const viz::TextureMailbox& mailbox, - std::unique_ptr<viz::SingleReleaseCallback> release_callback) { - mailbox_ = mailbox; - release_callback_ = std::move(release_callback); - mailbox_changed_ = true; - } - - private: - viz::TextureMailbox mailbox_; - std::unique_ptr<viz::SingleReleaseCallback> release_callback_; - bool mailbox_changed_; - DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient); -}; - -class MockMailboxCallback { +class MockReleaseCallback { public: MOCK_METHOD3(Release, void(const gpu::Mailbox& mailbox, @@ -136,8 +106,8 @@ bool lost_resource)); }; -struct CommonMailboxObjects { - explicit CommonMailboxObjects(viz::SharedBitmapManager* manager) +struct CommonResourceObjects { + explicit CommonResourceObjects(viz::SharedBitmapManager* manager) : mailbox_name1_(MailboxFromChar('1')), mailbox_name2_(MailboxFromChar('2')), sync_token1_(gpu::CommandBufferNamespace::GPU_IO, @@ -148,25 +118,26 @@ 123, gpu::CommandBufferId::FromUnsafeValue(0x234), 2) { - release_mailbox1_ = base::Bind(&MockMailboxCallback::Release, - base::Unretained(&mock_callback_), - mailbox_name1_); - release_mailbox2_ = base::Bind(&MockMailboxCallback::Release, - base::Unretained(&mock_callback_), - mailbox_name2_); + release_callback1_ = + base::Bind(&MockReleaseCallback::Release, + base::Unretained(&mock_callback_), mailbox_name1_); + release_callback2_ = + base::Bind(&MockReleaseCallback::Release, + base::Unretained(&mock_callback_), mailbox_name2_); const uint32_t arbitrary_target1 = GL_TEXTURE_2D; const uint32_t arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES; - mailbox1_ = - viz::TextureMailbox(mailbox_name1_, sync_token1_, arbitrary_target1); - mailbox2_ = - viz::TextureMailbox(mailbox_name2_, sync_token2_, arbitrary_target2); + resource1_ = viz::TransferableResource::MakeGL( + mailbox_name1_, GL_LINEAR, arbitrary_target1, sync_token1_); + resource2_ = viz::TransferableResource::MakeGL( + mailbox_name2_, GL_LINEAR, arbitrary_target2, sync_token2_); gfx::Size size(128, 128); shared_bitmap_ = manager->AllocateSharedBitmap(size); DCHECK(shared_bitmap_); - release_mailbox3_ = - base::Bind(&MockMailboxCallback::Release2, + release_callback3_ = + base::Bind(&MockReleaseCallback::Release2, base::Unretained(&mock_callback_), shared_bitmap_.get()); - mailbox3_ = viz::TextureMailbox(shared_bitmap_.get(), size); + resource3_ = viz::TransferableResource::MakeSoftware( + shared_bitmap_->id(), shared_bitmap_->sequence_number(), size); } using RepeatingReleaseCallback = @@ -175,16 +146,16 @@ gpu::Mailbox mailbox_name1_; gpu::Mailbox mailbox_name2_; - MockMailboxCallback mock_callback_; - RepeatingReleaseCallback release_mailbox1_; - RepeatingReleaseCallback release_mailbox2_; - RepeatingReleaseCallback release_mailbox3_; - viz::TextureMailbox mailbox1_; - viz::TextureMailbox mailbox2_; - viz::TextureMailbox mailbox3_; + MockReleaseCallback mock_callback_; + RepeatingReleaseCallback release_callback1_; + RepeatingReleaseCallback release_callback2_; + RepeatingReleaseCallback release_callback3_; gpu::SyncToken sync_token1_; gpu::SyncToken sync_token2_; std::unique_ptr<viz::SharedBitmap> shared_bitmap_; + viz::TransferableResource resource1_; + viz::TransferableResource resource2_; + viz::TransferableResource resource3_; }; class TextureLayerTest : public testing::Test { @@ -222,7 +193,7 @@ TestTaskGraphRunner task_graph_runner_; std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink_; FakeLayerTreeHostImpl host_impl_; - CommonMailboxObjects test_data_; + CommonResourceObjects test_data_; }; TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) { @@ -242,15 +213,15 @@ EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true)); } -class TestMailboxHolder : public TextureLayer::TextureMailboxHolder { +class TestMailboxHolder : public TextureLayer::TransferableResourceHolder { public: - using TextureLayer::TextureMailboxHolder::Create; + using TextureLayer::TransferableResourceHolder::Create; protected: ~TestMailboxHolder() override {} }; -class TextureLayerWithMailboxTest : public TextureLayerTest { +class TextureLayerWithResourceTest : public TextureLayerTest { protected: void TearDown() override { Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); @@ -262,7 +233,7 @@ } }; -TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) { +TEST_F(TextureLayerWithResourceTest, ReplaceMailboxOnMainThreadBeforeCommit) { scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(nullptr); ASSERT_TRUE(test_layer.get()); @@ -272,9 +243,9 @@ Mock::VerifyAndClearExpectations(layer_tree_host_.get()); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); - test_layer->SetTextureMailbox( - test_data_.mailbox1_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_)); + test_layer->SetTransferableResource( + test_data_.resource1_, + viz::SingleReleaseCallback::Create(test_data_.release_callback1_)); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); @@ -282,9 +253,9 @@ test_data_.mock_callback_, Release(test_data_.mailbox_name1_, test_data_.sync_token1_, false)) .Times(1); - test_layer->SetTextureMailbox( - test_data_.mailbox2_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox2_)); + test_layer->SetTransferableResource( + test_data_.resource2_, + viz::SingleReleaseCallback::Create(test_data_.release_callback2_)); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); @@ -293,14 +264,14 @@ test_data_.mock_callback_, Release(test_data_.mailbox_name2_, test_data_.sync_token2_, false)) .Times(1); - test_layer->SetTextureMailbox(viz::TextureMailbox(), nullptr); + test_layer->ClearTexture(); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); - test_layer->SetTextureMailbox( - test_data_.mailbox3_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox3_)); + test_layer->SetTransferableResource( + test_data_.resource3_, + viz::SingleReleaseCallback::Create(test_data_.release_callback3_)); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); @@ -308,15 +279,15 @@ EXPECT_CALL(test_data_.mock_callback_, Release2(test_data_.shared_bitmap_.get(), _, false)) .Times(1); - test_layer->SetTextureMailbox(viz::TextureMailbox(), nullptr); + test_layer->ClearTexture(); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); // Test destructor. EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); - test_layer->SetTextureMailbox( - test_data_.mailbox1_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_)); + test_layer->SetTransferableResource( + test_data_.resource1_, + viz::SingleReleaseCallback::Create(test_data_.release_callback1_)); } class TextureLayerMailboxHolderTest : public TextureLayerTest { @@ -337,8 +308,8 @@ void CreateMainRef() { main_ref_ = TestMailboxHolder::Create( - test_data_.mailbox1_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_)); + test_data_.resource1_, + viz::SingleReleaseCallback::Create(test_data_.release_callback1_)); } void ReleaseMainRef() { main_ref_ = nullptr; } @@ -395,8 +366,8 @@ EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); - // The main thread ref is the last one, so the mailbox is released back to the - // embedder, with the last sync point provided by the impl trees. + // The main thread ref is the last one, so the resource is released back to + // the embedder, with the last sync point provided by the impl trees. EXPECT_CALL(test_data_.mock_callback_, Release(test_data_.mailbox_name1_, SyncTokenFromUInt(200), false)) .Times(1); @@ -451,7 +422,7 @@ EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); - // The second impl reference is destroyed last, causing the mailbox to be + // The second impl reference is destroyed last, causing the resource to be // released back to the embedder with the last sync point from the impl tree. EXPECT_CALL(test_data_.mock_callback_, Release(test_data_.mailbox_name1_, SyncTokenFromUInt(200), true)) @@ -505,7 +476,7 @@ EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); - // The second impl reference is destroyed last, causing the mailbox to be + // The second impl reference is destroyed last, causing the resource to be // released back to the embedder with the last sync point from the impl tree. EXPECT_CALL(test_data_.mock_callback_, Release(test_data_.mailbox_name1_, SyncTokenFromUInt(100), true)) @@ -518,8 +489,6 @@ class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest { public: - TextureLayerImplWithMailboxThreadedCallback() = default; - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, @@ -540,8 +509,8 @@ ++test_case_; switch (test_case_) { case 1: - // Case #1: change mailbox before the commit. The old mailbox should be - // released immediately. + // Case #1: change resource before the commit. The old resource should + // be released immediately. SetMailbox('2'); EXPECT_EQ(1, callback_count_); PostSetNeedsCommitToMainThread(); @@ -550,8 +519,8 @@ pending_callback_ = false; break; case 2: - // Case #2: change mailbox after the commit (and draw), where the - // layer draws. The old mailbox should be released during the next + // Case #2: change resource after the commit (and draw), where the + // layer draws. The old resource should be released during the next // commit. SetMailbox('3'); EXPECT_EQ(1, callback_count_); @@ -561,20 +530,20 @@ break; case 3: EXPECT_EQ(2, callback_count_); - // Case #3: change mailbox when the layer doesn't draw. The old - // mailbox should be released during the next commit. + // Case #3: change resource when the layer doesn't draw. The old + // resource should be released during the next commit. layer_->SetBounds(gfx::Size()); SetMailbox('4'); break; case 4: EXPECT_EQ(3, callback_count_); - // Case #4: release mailbox that was committed but never drawn. The - // old mailbox should be released during the next commit. - layer_->SetTextureMailbox(viz::TextureMailbox(), nullptr); + // Case #4: release resource that was committed but never drawn. The + // old resource should be released during the next commit. + layer_->ClearTexture(); break; case 5: EXPECT_EQ(4, callback_count_); - // Restore a mailbox for the next step. + // Restore a resource for the next step. SetMailbox('5'); // Cases 6 and 7 do not rely on callbacks to advance. @@ -582,16 +551,16 @@ break; case 6: // Case #5: remove layer from tree. Callback should *not* be called, the - // mailbox is returned to the main thread. + // resource is returned to the main thread. EXPECT_EQ(4, callback_count_); layer_->RemoveFromParent(); break; case 7: EXPECT_EQ(4, callback_count_); - // Resetting the mailbox will call the callback now, before another + // Resetting the resource will call the callback now, before another // commit is needed, as the ReleaseCallback is already in flight from // RemoveFromParent(). - layer_->SetTextureMailbox(viz::TextureMailbox(), nullptr); + layer_->ClearTexture(); pending_callback_ = true; frame_number_ = layer_tree_host()->SourceFrameNumber(); break; @@ -626,13 +595,12 @@ viz::SingleReleaseCallback::Create(base::Bind( &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback, base::Unretained(this), mailbox_char)); - layer_->SetTextureMailbox( - viz::TextureMailbox( - MailboxFromChar(mailbox_char), - SyncTokenFromUInt(static_cast<uint32_t>(mailbox_char)), - GL_TEXTURE_2D), - std::move(callback)); - // Damage the layer so we send a new frame with the new mailbox to the + + auto resource = viz::TransferableResource::MakeGL( + MailboxFromChar(mailbox_char), GL_LINEAR, GL_TEXTURE_2D, + SyncTokenFromUInt(static_cast<uint32_t>(mailbox_char))); + layer_->SetTransferableResource(resource, std::move(callback)); + // Damage the layer so we send a new frame with the new resource to the // Display compositor. layer_->SetNeedsDisplay(); } @@ -704,9 +672,9 @@ viz::SingleReleaseCallback::Create(base::Bind( &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback, base::Unretained(this), sync_token)); - layer_->SetTextureMailbox(viz::TextureMailbox(MailboxFromChar(mailbox_char), - sync_token, GL_TEXTURE_2D), - std::move(callback)); + auto resource = viz::TransferableResource::MakeGL( + MailboxFromChar(mailbox_char), GL_LINEAR, GL_TEXTURE_2D, sync_token); + layer_->SetTransferableResource(resource, std::move(callback)); } void BeginTest() override { @@ -779,7 +747,7 @@ SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerMailboxIsActivatedDuringCommit); -class TextureLayerImplWithMailboxTest : public TextureLayerTest { +class TextureLayerImplWithResourceTest : public TextureLayerTest { protected: void SetUp() override { TextureLayerTest::SetUp(); @@ -802,10 +770,9 @@ // Test conditions for results of TextureLayerImpl::WillDraw under // different configurations of different mailbox, texture_id, and draw_mode. -TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) { - EXPECT_CALL( - test_data_.mock_callback_, - Release(test_data_.mailbox_name1_, test_data_.sync_token1_, false)) +TEST_F(TextureLayerImplWithResourceTest, TestWillDraw) { + EXPECT_CALL(test_data_.mock_callback_, + Release(test_data_.mailbox_name1_, gpu::SyncToken(), false)) .Times(AnyNumber()); EXPECT_CALL( test_data_.mock_callback_, @@ -815,16 +782,16 @@ { std::unique_ptr<TextureLayerImpl> impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1); - impl_layer->SetTextureMailbox( - test_data_.mailbox1_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_)); + impl_layer->SetTransferableResource( + test_data_.resource1_, + viz::SingleReleaseCallback::Create(test_data_.release_callback1_)); EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE)); } { std::unique_ptr<TextureLayerImpl> impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1); - impl_layer->SetTextureMailbox(viz::TextureMailbox(), nullptr); + impl_layer->SetTransferableResource(viz::TransferableResource(), nullptr); EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE)); } @@ -832,16 +799,16 @@ { std::unique_ptr<TextureLayerImpl> impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1); - impl_layer->SetTextureMailbox( - test_data_.mailbox1_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_)); + impl_layer->SetTransferableResource( + test_data_.resource1_, + viz::SingleReleaseCallback::Create(test_data_.release_callback1_)); EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE)); } { std::unique_ptr<TextureLayerImpl> impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1); - impl_layer->SetTextureMailbox(viz::TextureMailbox(), nullptr); + impl_layer->SetTransferableResource(viz::TransferableResource(), nullptr); EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE)); } @@ -849,9 +816,9 @@ // Software resource. std::unique_ptr<TextureLayerImpl> impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1); - impl_layer->SetTextureMailbox( - test_data_.mailbox3_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox3_)); + impl_layer->SetTransferableResource( + test_data_.resource3_, + viz::SingleReleaseCallback::Create(test_data_.release_callback3_)); EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE)); } @@ -859,14 +826,14 @@ { std::unique_ptr<TextureLayerImpl> impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1); - impl_layer->SetTextureMailbox( - test_data_.mailbox1_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_)); + impl_layer->SetTransferableResource( + test_data_.resource1_, + viz::SingleReleaseCallback::Create(test_data_.release_callback1_)); EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE)); } } -TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) { +TEST_F(TextureLayerImplWithResourceTest, TestImplLayerCallbacks) { host_impl_.CreatePendingTree(); std::unique_ptr<TextureLayerImpl> pending_layer; pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1); @@ -876,18 +843,18 @@ pending_layer->CreateLayerImpl(host_impl_.active_tree())); ASSERT_TRUE(active_layer); - pending_layer->SetTextureMailbox( - test_data_.mailbox1_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_)); + pending_layer->SetTransferableResource( + test_data_.resource1_, + viz::SingleReleaseCallback::Create(test_data_.release_callback1_)); - // Test multiple commits without an activation. - EXPECT_CALL( - test_data_.mock_callback_, - Release(test_data_.mailbox_name1_, test_data_.sync_token1_, false)) + // Test multiple commits without an activation. The resource wasn't used so no + // sync token is returned. + EXPECT_CALL(test_data_.mock_callback_, + Release(test_data_.mailbox_name1_, gpu::SyncToken(), false)) .Times(1); - pending_layer->SetTextureMailbox( - test_data_.mailbox2_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox2_)); + pending_layer->SetTransferableResource( + test_data_.resource2_, + viz::SingleReleaseCallback::Create(test_data_.release_callback2_)); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); // Test callback after activation. @@ -895,9 +862,9 @@ active_layer->DidBecomeActive(); EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); - pending_layer->SetTextureMailbox( - test_data_.mailbox1_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_)); + pending_layer->SetTransferableResource( + test_data_.resource1_, + viz::SingleReleaseCallback::Create(test_data_.release_callback1_)); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); EXPECT_CALL(test_data_.mock_callback_, @@ -911,22 +878,21 @@ EXPECT_CALL(test_data_.mock_callback_, Release(test_data_.mailbox_name1_, _, false)) .Times(1); - pending_layer->SetTextureMailbox(viz::TextureMailbox(), nullptr); + pending_layer->SetTransferableResource(viz::TransferableResource(), nullptr); pending_layer->PushPropertiesTo(active_layer.get()); active_layer->DidBecomeActive(); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); - // Test destructor. - EXPECT_CALL( - test_data_.mock_callback_, - Release(test_data_.mailbox_name1_, test_data_.sync_token1_, false)) + // Test destructor. The resource wasn't used so no sync token is returned. + EXPECT_CALL(test_data_.mock_callback_, + Release(test_data_.mailbox_name1_, gpu::SyncToken(), false)) .Times(1); - pending_layer->SetTextureMailbox( - test_data_.mailbox1_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_)); + pending_layer->SetTransferableResource( + test_data_.resource1_, + viz::SingleReleaseCallback::Create(test_data_.release_callback1_)); } -TEST_F(TextureLayerImplWithMailboxTest, +TEST_F(TextureLayerImplWithResourceTest, TestDestructorCallbackOnCreatedResource) { std::unique_ptr<TextureLayerImpl> impl_layer; impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1); @@ -935,39 +901,14 @@ EXPECT_CALL(test_data_.mock_callback_, Release(test_data_.mailbox_name1_, _, false)) .Times(1); - impl_layer->SetTextureMailbox( - test_data_.mailbox1_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_)); + impl_layer->SetTransferableResource( + test_data_.resource1_, + viz::SingleReleaseCallback::Create(test_data_.release_callback1_)); impl_layer->DidBecomeActive(); EXPECT_TRUE(impl_layer->WillDraw( DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider())); impl_layer->DidDraw(host_impl_.active_tree()->resource_provider()); - impl_layer->SetTextureMailbox(viz::TextureMailbox(), nullptr); -} - -TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) { - LayerTreeResourceProvider* provider = - host_impl_.active_tree()->resource_provider(); - viz::ResourceId id = provider->CreateResourceFromTextureMailbox( - test_data_.mailbox1_, - viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_)); - provider->AllocateForTesting(id); - - // Transfer some resources to the parent. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(id); - std::vector<viz::TransferableResource> list; - provider->PrepareSendToParent(resource_ids_to_transfer, &list); - EXPECT_TRUE(provider->InUseByConsumer(id)); - EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); - provider->DeleteResource(id); - Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); - EXPECT_CALL(test_data_.mock_callback_, - Release(test_data_.mailbox_name1_, _, false)) - .Times(1); - std::vector<viz::ReturnedResource> returned = - viz::TransferableResource::ReturnResources(list); - provider->ReceiveReturnsFromParent(returned); + impl_layer->SetTransferableResource(viz::TransferableResource(), nullptr); } // Checks that TextureLayer::Update does not cause an extra commit when setting @@ -977,24 +918,25 @@ public TextureLayerClient { public: // TextureLayerClient implementation. - bool PrepareTextureMailbox( - viz::TextureMailbox* texture_mailbox, + bool PrepareTransferableResource( + viz::TransferableResource* resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override { if (layer_tree_host()->SourceFrameNumber() == 1) { - // Once this has been committed, the mailbox will be released. - *texture_mailbox = viz::TextureMailbox(); + // Once this has been committed, the resource will be released. + *resource = viz::TransferableResource(); return true; } - *texture_mailbox = viz::TextureMailbox( - MailboxFromChar('1'), SyncTokenFromUInt(0x123), GL_TEXTURE_2D); + *resource = viz::TransferableResource::MakeGL(MailboxFromChar('1'), + GL_LINEAR, GL_TEXTURE_2D, + SyncTokenFromUInt(0x123)); *release_callback = viz::SingleReleaseCallback::Create( - base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased, + base::Bind(&TextureLayerNoExtraCommitForMailboxTest::ResourceReleased, base::Unretained(this))); return true; } - void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource) { + void ResourceReleased(const gpu::SyncToken& sync_token, bool lost_resource) { EXPECT_TRUE(sync_token.HasData()); EndTest(); } @@ -1047,36 +989,35 @@ public TextureLayerClient { public: TextureLayerChangeInvisibleMailboxTest() - : mailbox_changed_(true), - mailbox_returned_(0), + : resource_changed_(true), + resource_(MakeResource('1')), + resource_returned_(0), prepare_called_(0), - commit_count_(0) { - mailbox_ = MakeMailbox('1'); - } + commit_count_(0) {} // TextureLayerClient implementation. - bool PrepareTextureMailbox( - viz::TextureMailbox* mailbox, + bool PrepareTransferableResource( + viz::TransferableResource* resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override { ++prepare_called_; - if (!mailbox_changed_) + if (!resource_changed_) return false; - *mailbox = mailbox_; + *resource = resource_; *release_callback = viz::SingleReleaseCallback::Create( - base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased, + base::Bind(&TextureLayerChangeInvisibleMailboxTest::ResourceReleased, base::Unretained(this))); return true; } - viz::TextureMailbox MakeMailbox(char name) { - return viz::TextureMailbox(MailboxFromChar(name), - SyncTokenFromUInt(static_cast<uint32_t>(name)), - GL_TEXTURE_2D); + viz::TransferableResource MakeResource(char name) { + return viz::TransferableResource::MakeGL( + MailboxFromChar(name), GL_LINEAR, GL_TEXTURE_2D, + SyncTokenFromUInt(static_cast<uint32_t>(name))); } - void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource) { + void ResourceReleased(const gpu::SyncToken& sync_token, bool lost_resource) { EXPECT_TRUE(sync_token.HasData()); - ++mailbox_returned_; + ++resource_returned_; } void SetupTree() override { @@ -1119,8 +1060,8 @@ // Layer shouldn't have been updated. EXPECT_EQ(1, prepare_called_); // Change the texture. - mailbox_ = MakeMailbox('2'); - mailbox_changed_ = true; + resource_ = MakeResource('2'); + resource_changed_ = true; texture_layer_->SetNeedsDisplay(); // Force a change to make sure we draw a frame. solid_layer_->SetBackgroundColor(SK_ColorGRAY); @@ -1128,20 +1069,20 @@ case 3: // Layer shouldn't have been updated. EXPECT_EQ(1, prepare_called_); - // So the old mailbox isn't returned yet. - EXPECT_EQ(0, mailbox_returned_); + // So the old resource isn't returned yet. + EXPECT_EQ(0, resource_returned_); // Make layer visible again. parent_layer_->SetOpacity(0.9f); break; case 4: // Layer should have been updated. EXPECT_EQ(2, prepare_called_); - // So the old mailbox should have been returned already. - EXPECT_EQ(1, mailbox_returned_); + // So the old resource should have been returned already. + EXPECT_EQ(1, resource_returned_); texture_layer_->ClearClient(); break; case 5: - EXPECT_EQ(2, mailbox_returned_); + EXPECT_EQ(2, resource_returned_); EndTest(); break; default: @@ -1158,9 +1099,9 @@ scoped_refptr<TextureLayer> texture_layer_; // Used on the main thread. - bool mailbox_changed_; - viz::TextureMailbox mailbox_; - int mailbox_returned_; + bool resource_changed_; + viz::TransferableResource resource_; + int resource_returned_; int prepare_called_; int commit_count_; }; @@ -1168,25 +1109,25 @@ SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest); // Test that TextureLayerImpl::ReleaseResources can be called which releases -// the mailbox back to TextureLayerClient. +// the resource back to TextureLayerClient. class TextureLayerReleaseResourcesBase : public LayerTreeTest, public TextureLayerClient { public: // TextureLayerClient implementation. - bool PrepareTextureMailbox( - viz::TextureMailbox* mailbox, + bool PrepareTransferableResource( + viz::TransferableResource* resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override { - *mailbox = viz::TextureMailbox(MailboxFromChar('1'), SyncTokenFromUInt(1), - GL_TEXTURE_2D); + *resource = viz::TransferableResource::MakeGL( + MailboxFromChar('1'), GL_LINEAR, GL_TEXTURE_2D, SyncTokenFromUInt(1)); *release_callback = viz::SingleReleaseCallback::Create( - base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased, + base::Bind(&TextureLayerReleaseResourcesBase::ResourceReleased, base::Unretained(this))); return true; } - void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource) { - mailbox_released_ = true; + void ResourceReleased(const gpu::SyncToken& sync_token, bool lost_resource) { + resource_released_ = true; } void SetupTree() override { @@ -1202,19 +1143,19 @@ } void BeginTest() override { - mailbox_released_ = false; + resource_released_ = false; PostSetNeedsCommitToMainThread(); } void DidCommitAndDrawFrame() override { EndTest(); } - void AfterTest() override { EXPECT_TRUE(mailbox_released_); } + void AfterTest() override { EXPECT_TRUE(resource_released_); } protected: int texture_layer_id_; private: - bool mailbox_released_; + bool resource_released_; }; class TextureLayerReleaseResourcesAfterCommit @@ -1239,7 +1180,7 @@ SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate); -class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest { +class TextureLayerWithResourceMainThreadDeleted : public LayerTreeTest { public: void ReleaseCallback(const gpu::SyncToken& sync_token, bool lost_resource) { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); @@ -1252,14 +1193,12 @@ EXPECT_EQ(true, main_thread_.CalledOnValidThread()); std::unique_ptr<viz::SingleReleaseCallback> callback = viz::SingleReleaseCallback::Create(base::Bind( - &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback, + &TextureLayerWithResourceMainThreadDeleted::ReleaseCallback, base::Unretained(this))); - layer_->SetTextureMailbox( - viz::TextureMailbox( - MailboxFromChar(mailbox_char), - SyncTokenFromUInt(static_cast<uint32_t>(mailbox_char)), - GL_TEXTURE_2D), - std::move(callback)); + auto resource = viz::TransferableResource::MakeGL( + MailboxFromChar(mailbox_char), GL_LINEAR, GL_TEXTURE_2D, + SyncTokenFromUInt(static_cast<uint32_t>(mailbox_char))); + layer_->SetTransferableResource(resource, std::move(callback)); } void SetupTree() override { @@ -1281,7 +1220,7 @@ callback_count_ = 0; - // Set the mailbox on the main thread. + // Set the resource on the main thread. SetMailbox('1'); EXPECT_EQ(0, callback_count_); @@ -1291,7 +1230,7 @@ void DidCommitAndDrawFrame() override { switch (layer_tree_host()->SourceFrameNumber()) { case 1: - // Delete the TextureLayer on the main thread while the mailbox is in + // Delete the TextureLayer on the main thread while the resource is in // the impl tree. layer_->RemoveFromParent(); layer_ = nullptr; @@ -1308,9 +1247,9 @@ scoped_refptr<TextureLayer> layer_; }; -SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerWithMailboxMainThreadDeleted); +SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerWithResourceMainThreadDeleted); -class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest { +class TextureLayerWithResourceImplThreadDeleted : public LayerTreeTest { public: void ReleaseCallback(const gpu::SyncToken& sync_token, bool lost_resource) { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); @@ -1323,14 +1262,12 @@ EXPECT_EQ(true, main_thread_.CalledOnValidThread()); std::unique_ptr<viz::SingleReleaseCallback> callback = viz::SingleReleaseCallback::Create(base::Bind( - &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback, + &TextureLayerWithResourceImplThreadDeleted::ReleaseCallback, base::Unretained(this))); - layer_->SetTextureMailbox( - viz::TextureMailbox( - MailboxFromChar(mailbox_char), - SyncTokenFromUInt(static_cast<uint32_t>(mailbox_char)), - GL_TEXTURE_2D), - std::move(callback)); + auto resource = viz::TransferableResource::MakeGL( + MailboxFromChar(mailbox_char), GL_LINEAR, GL_TEXTURE_2D, + SyncTokenFromUInt(static_cast<uint32_t>(mailbox_char))); + layer_->SetTransferableResource(resource, std::move(callback)); } void SetupTree() override { @@ -1352,7 +1289,7 @@ callback_count_ = 0; - // Set the mailbox on the main thread. + // Set the resource on the main thread. SetMailbox('1'); EXPECT_EQ(0, callback_count_); @@ -1362,7 +1299,7 @@ void DidCommitAndDrawFrame() override { switch (layer_tree_host()->SourceFrameNumber()) { case 1: - // Remove the TextureLayer on the main thread while the mailbox is in + // Remove the TextureLayer on the main thread while the resource is in // the impl tree, but don't delete the TextureLayer until after the impl // tree side is deleted. layer_->RemoveFromParent(); @@ -1382,7 +1319,7 @@ scoped_refptr<TextureLayer> layer_; }; -SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerWithMailboxImplThreadDeleted); +SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerWithResourceImplThreadDeleted); } // namespace } // namespace cc
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn index c604daed..c2f3510 100644 --- a/cc/paint/BUILD.gn +++ b/cc/paint/BUILD.gn
@@ -20,7 +20,6 @@ "image_id.h", "image_provider.cc", "image_provider.h", - "paint_canvas.cc", "paint_canvas.h", "paint_export.h", "paint_flags.cc",
diff --git a/cc/paint/oop_pixeltest.cc b/cc/paint/oop_pixeltest.cc index 1edbef6..6c73d50 100644 --- a/cc/paint/oop_pixeltest.cc +++ b/cc/paint/oop_pixeltest.cc
@@ -82,16 +82,16 @@ float post_scale = 1.f; }; - std::vector<SkColor> Raster(scoped_refptr<DisplayItemList> display_item_list, - const gfx::Size& playback_size) { + SkBitmap Raster(scoped_refptr<DisplayItemList> display_item_list, + const gfx::Size& playback_size) { RasterOptions options; options.bitmap_rect = gfx::Rect(playback_size); options.playback_rect = gfx::Rect(playback_size); return Raster(display_item_list, options); } - std::vector<SkColor> Raster(scoped_refptr<DisplayItemList> display_item_list, - const RasterOptions& options) { + SkBitmap Raster(scoped_refptr<DisplayItemList> display_item_list, + const RasterOptions& options) { gpu::gles2::GLES2Interface* gl = context_->GetImplementation(); GLuint texture_id; GLuint fbo_id; @@ -136,19 +136,28 @@ gl->DeleteTextures(1, &texture_id); gl->DeleteFramebuffers(1, &fbo_id); - std::vector<SkColor> colors; + // Swizzle rgba->bgra if needed. + std::vector<SkPMColor> colors; colors.reserve(width * height); for (int h = 0; h < height; ++h) { for (int w = 0; w < width; ++w) { int i = (h * width + w) * 4; - colors.push_back( - SkColorSetARGB(data[i + 3], data[i + 0], data[i + 1], data[i + 2])); + colors.push_back(SkPreMultiplyARGB(data[i + 3], data[i + 0], + data[i + 1], data[i + 2])); } } - return colors; + + SkBitmap bitmap; + bitmap.allocN32Pixels(width, height); + SkPixmap pixmap(SkImageInfo::MakeN32Premul(options.bitmap_rect.width(), + options.bitmap_rect.height()), + colors.data(), + options.bitmap_rect.width() * sizeof(SkColor)); + bitmap.writePixels(pixmap); + return bitmap; } - std::vector<SkColor> RasterExpectedBitmap( + SkBitmap RasterExpectedBitmap( scoped_refptr<DisplayItemList> display_item_list, const gfx::Size& playback_size) { RasterOptions options; @@ -157,7 +166,7 @@ return RasterExpectedBitmap(display_item_list, options); } - std::vector<SkColor> RasterExpectedBitmap( + SkBitmap RasterExpectedBitmap( scoped_refptr<DisplayItemList> display_item_list, const RasterOptions& options) { // Generate bitmap via the "in process" raster path. This verifies @@ -218,44 +227,17 @@ bool success = surface->readPixels(bitmap, 0, 0); CHECK(success); EXPECT_EQ(gl->GetError(), static_cast<unsigned>(GL_NO_ERROR)); - - int width = options.bitmap_rect.width(); - int height = options.bitmap_rect.height(); - EXPECT_EQ(width, bitmap.width()); - EXPECT_EQ(height, bitmap.height()); - - std::vector<SkColor> colors; - colors.reserve(width * height); - for (int h = 0; h < height; ++h) { - for (int w = 0; w < width; ++w) { - colors.push_back(bitmap.getColor(w, h)); - } - } - return colors; + return bitmap; } - void ExpectEquals(const gfx::Size& size, - std::vector<SkColor>* actual, - std::vector<SkColor>* expected) { - size_t expected_size = size.width() * size.height(); - ASSERT_EQ(expected->size(), expected_size); - if (*actual == *expected) + void ExpectEquals(SkBitmap actual, SkBitmap expected) { + EXPECT_EQ(actual.dimensions(), expected.dimensions()); + auto expected_url = GetPNGDataUrl(expected); + auto actual_url = GetPNGDataUrl(actual); + if (actual_url == expected_url) return; - - ASSERT_EQ(actual->size(), expected_size); - - SkBitmap expected_bitmap; - expected_bitmap.installPixels( - SkImageInfo::MakeN32Premul(size.width(), size.height()), - expected->data(), size.width() * sizeof(SkColor)); - - SkBitmap actual_bitmap; - actual_bitmap.installPixels( - SkImageInfo::MakeN32Premul(size.width(), size.height()), actual->data(), - size.width() * sizeof(SkColor)); - - ADD_FAILURE() << "\nExpected: " << GetPNGDataUrl(expected_bitmap) - << "\nActual: " << GetPNGDataUrl(actual_bitmap); + ADD_FAILURE() << "\nExpected: " << expected_url + << "\nActual: " << actual_url; } private: @@ -274,9 +256,13 @@ display_item_list->Finalize(); auto actual = Raster(std::move(display_item_list), rect.size()); - std::vector<SkColor> expected(rect.width() * rect.height(), - SkColorSetARGB(255, 0, 0, 255)); - ExpectEquals(rect.size(), &actual, &expected); + std::vector<SkPMColor> expected_pixels(rect.width() * rect.height(), + SkPreMultiplyARGB(255, 0, 0, 255)); + SkBitmap expected; + expected.installPixels( + SkImageInfo::MakeN32Premul(rect.width(), rect.height()), + expected_pixels.data(), rect.width() * sizeof(SkColor)); + ExpectEquals(actual, expected); } TEST_F(OopPixelTest, DrawRect) { @@ -306,18 +292,22 @@ // Expected colors are 5x5 rects of // BLUE GREEN // CYAN RED - std::vector<SkColor> expected(rect.width() * rect.height()); + std::vector<SkPMColor> expected_pixels(rect.width() * rect.height()); for (int h = 0; h < rect.height(); ++h) { - auto start = expected.begin() + h * rect.width(); - SkColor left_color = - h < 5 ? input[0].second.getColor() : input[2].second.getColor(); - SkColor right_color = - h < 5 ? input[1].second.getColor() : input[3].second.getColor(); + auto start = expected_pixels.begin() + h * rect.width(); + SkPMColor left_color = SkPreMultiplyColor( + h < 5 ? input[0].second.getColor() : input[2].second.getColor()); + SkPMColor right_color = SkPreMultiplyColor( + h < 5 ? input[1].second.getColor() : input[3].second.getColor()); std::fill(start, start + 5, left_color); std::fill(start + 5, start + 10, right_color); } - ExpectEquals(rect.size(), &actual, &expected); + SkBitmap expected; + expected.installPixels( + SkImageInfo::MakeN32Premul(rect.width(), rect.height()), + expected_pixels.data(), rect.width() * sizeof(SkPMColor)); + ExpectEquals(actual, expected); } // Test various bitmap and playback rects in the raster options, to verify @@ -349,7 +339,7 @@ auto actual = Raster(display_item_list, options); auto expected = RasterExpectedBitmap(display_item_list, options); - ExpectEquals(options.bitmap_rect.size(), &actual, &expected); + ExpectEquals(actual, expected); } } @@ -380,7 +370,7 @@ auto actual = Raster(display_item_list, options); auto expected = RasterExpectedBitmap(display_item_list, options); - ExpectEquals(options.bitmap_rect.size(), &actual, &expected); + ExpectEquals(actual, expected); } TEST_F(OopPixelTest, DrawRectQueryMiddleOfDisplayList) { @@ -412,7 +402,7 @@ auto actual = Raster(display_item_list, options); auto expected = RasterExpectedBitmap(display_item_list, options); - ExpectEquals(options.bitmap_rect.size(), &actual, &expected); + ExpectEquals(actual, expected); } } // namespace
diff --git a/cc/paint/paint_canvas.cc b/cc/paint/paint_canvas.cc deleted file mode 100644 index a49b2b4..0000000 --- a/cc/paint/paint_canvas.cc +++ /dev/null
@@ -1,36 +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 "cc/paint/paint_canvas.h" - -#include "base/memory/ptr_util.h" -#include "cc/paint/paint_record.h" -#include "cc/paint/paint_recorder.h" -#include "third_party/skia/include/core/SkAnnotation.h" -#include "third_party/skia/include/core/SkMetaData.h" - -#if defined(OS_MACOSX) -namespace { -const char kIsPreviewMetafileKey[] = "CrIsPreviewMetafile"; -} -#endif - -namespace cc { - -#if defined(OS_MACOSX) -void SetIsPreviewMetafile(PaintCanvas* canvas, bool is_preview) { - SkMetaData& meta = canvas->getMetaData(); - meta.setBool(kIsPreviewMetafileKey, is_preview); -} - -bool IsPreviewMetafile(PaintCanvas* canvas) { - bool value; - SkMetaData& meta = canvas->getMetaData(); - if (!meta.findBool(kIsPreviewMetafileKey, &value)) - value = false; - return value; -} -#endif - -} // namespace cc
diff --git a/cc/paint/paint_canvas.h b/cc/paint/paint_canvas.h index e62fee07e..0b1c1619 100644 --- a/cc/paint/paint_canvas.h +++ b/cc/paint/paint_canvas.h
@@ -195,13 +195,6 @@ int save_count_ = 0; }; -// Following routines are used in print preview workflow to mark the -// preview metafile. -#if defined(OS_MACOSX) -CC_PAINT_EXPORT void SetIsPreviewMetafile(PaintCanvas* canvas, bool is_preview); -CC_PAINT_EXPORT bool IsPreviewMetafile(PaintCanvas* canvas); -#endif - } // namespace cc #endif // CC_PAINT_PAINT_CANVAS_H_
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc index 25ca3a3..f397127 100644 --- a/cc/paint/paint_image.cc +++ b/cc/paint/paint_image.cc
@@ -142,6 +142,13 @@ return SkISize::Make(width(), height()); } +SkImageInfo PaintImage::CreateDecodeImageInfo(const SkISize& size, + SkColorType color_type) const { + DCHECK(GetSupportedDecodeSize(size) == size); + return SkImageInfo::Make(size.width(), size.height(), color_type, + kPremul_SkAlphaType); +} + bool PaintImage::Decode(void* memory, SkImageInfo* info, sk_sp<SkColorSpace> color_space,
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h index 5bc445b..1e32f87 100644 --- a/cc/paint/paint_image.h +++ b/cc/paint/paint_image.h
@@ -116,6 +116,11 @@ // GetSupportedDecodeSize(size). SkISize GetSupportedDecodeSize(const SkISize& requested_size) const; + // Returns SkImageInfo that should be used to decode this image to the given + // size and color type. The size must be supported. + SkImageInfo CreateDecodeImageInfo(const SkISize& size, + SkColorType color_type) const; + // Decode the image into the given memory for the given SkImageInfo. // - Size in |info| must be supported. // - The amount of memory allocated must be at least
diff --git a/cc/resources/display_resource_provider.cc b/cc/resources/display_resource_provider.cc index 3d13953..439e689 100644 --- a/cc/resources/display_resource_provider.cc +++ b/cc/resources/display_resource_provider.cc
@@ -162,6 +162,7 @@ to_return.reserve(unused.size()); std::vector<viz::ReturnedResource*> need_synchronization_resources; std::vector<GLbyte*> unverified_sync_tokens; + std::vector<size_t> to_return_indices_unverified; GLES2Interface* gl = ContextGL(); @@ -222,8 +223,10 @@ need_synchronization_resources.push_back(&to_return.back()); } else if (returned.sync_token.HasData() && !returned.sync_token.verified_flush()) { - // Before returning any sync tokens, they must be verified. - unverified_sync_tokens.push_back(returned.sync_token.GetData()); + // Before returning any sync tokens, they must be verified. Store an + // index into |to_return| instead of a pointer as vectors may realloc + // and move their data. + to_return_indices_unverified.push_back(to_return.size() - 1); } } @@ -232,6 +235,9 @@ DeleteResourceInternal(it, style); } + for (size_t i : to_return_indices_unverified) + unverified_sync_tokens.push_back(to_return[i].sync_token.GetData()); + gpu::SyncToken new_sync_token; if (!need_synchronization_resources.empty()) { DCHECK(child_info->needs_sync_tokens);
diff --git a/cc/resources/layer_tree_resource_provider.cc b/cc/resources/layer_tree_resource_provider.cc index 6303503..cdf8b5eb 100644 --- a/cc/resources/layer_tree_resource_provider.cc +++ b/cc/resources/layer_tree_resource_provider.cc
@@ -67,63 +67,6 @@ } } -viz::ResourceId LayerTreeResourceProvider::CreateResourceFromTextureMailbox( - const viz::TextureMailbox& mailbox, - std::unique_ptr<viz::SingleReleaseCallback> release_callback, - bool read_lock_fences_enabled, - gfx::BufferFormat buffer_format) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - // Just store the information. Mailbox will be consumed in - // DisplayResourceProvider::LockForRead(). - viz::ResourceId id = next_id_++; - DCHECK(mailbox.IsValid()); - viz::internal::Resource* resource = InsertResource( - id, viz::internal::Resource( - mailbox.size_in_pixels(), viz::internal::Resource::EXTERNAL, - viz::ResourceTextureHint::kDefault, - mailbox.IsTexture() ? viz::ResourceType::kTexture - : viz::ResourceType::kBitmap, - viz::RGBA_8888, mailbox.color_space())); - if (mailbox.IsTexture()) { - GLenum filter = mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR; - resource->filter = filter; - resource->original_filter = filter; - resource->min_filter = filter; - resource->target = mailbox.target(); - resource->UpdateSyncToken(mailbox.sync_token()); - } else { - DCHECK(mailbox.IsSharedMemory()); - resource->SetSharedBitmap(mailbox.shared_bitmap()); - } - resource->allocated = true; - resource->mailbox = mailbox.mailbox(); - resource->release_callback = - base::Bind(&viz::SingleReleaseCallback::Run, - base::Owned(release_callback.release())); - resource->read_lock_fences_enabled = read_lock_fences_enabled; - resource->buffer_format = buffer_format; - resource->is_overlay_candidate = mailbox.is_overlay_candidate(); - resource->color_space = mailbox.color_space(); - - return id; -} - -viz::ResourceId LayerTreeResourceProvider::CreateResourceFromTextureMailbox( - const viz::TextureMailbox& mailbox, - std::unique_ptr<viz::SingleReleaseCallback> release_callback, - bool read_lock_fences_enabled) { - return CreateResourceFromTextureMailbox(mailbox, std::move(release_callback), - read_lock_fences_enabled, - gfx::BufferFormat::RGBA_8888); -} - -viz::ResourceId LayerTreeResourceProvider::CreateResourceFromTextureMailbox( - const viz::TextureMailbox& mailbox, - std::unique_ptr<viz::SingleReleaseCallback> release_callback) { - return CreateResourceFromTextureMailbox(mailbox, std::move(release_callback), - false); -} - gpu::SyncToken LayerTreeResourceProvider::GetSyncTokenForResources( const ResourceIdArray& resource_ids) { gpu::SyncToken latest_sync_token;
diff --git a/cc/resources/layer_tree_resource_provider.h b/cc/resources/layer_tree_resource_provider.h index d46969a..08e33e17 100644 --- a/cc/resources/layer_tree_resource_provider.h +++ b/cc/resources/layer_tree_resource_provider.h
@@ -25,22 +25,6 @@ const viz::ResourceSettings& resource_settings); ~LayerTreeResourceProvider() override; - // Wraps an external texture mailbox into a GL resource. - viz::ResourceId CreateResourceFromTextureMailbox( - const viz::TextureMailbox& mailbox, - std::unique_ptr<viz::SingleReleaseCallback> release_callback); - - viz::ResourceId CreateResourceFromTextureMailbox( - const viz::TextureMailbox& mailbox, - std::unique_ptr<viz::SingleReleaseCallback> release_callback, - bool read_lock_fences_enabled); - - viz::ResourceId CreateResourceFromTextureMailbox( - const viz::TextureMailbox& mailbox, - std::unique_ptr<viz::SingleReleaseCallback> release_callback, - bool read_lock_fences_enabled, - gfx::BufferFormat buffer_format); - // Gets the most recent sync token from the indicated resources. gpu::SyncToken GetSyncTokenForResources(const ResourceIdArray& resource_ids);
diff --git a/cc/resources/layer_tree_resource_provider_unittest.cc b/cc/resources/layer_tree_resource_provider_unittest.cc index 2075837..3478b55c 100644 --- a/cc/resources/layer_tree_resource_provider_unittest.cc +++ b/cc/resources/layer_tree_resource_provider_unittest.cc
@@ -103,18 +103,6 @@ provider().RemoveImportedResource(id); } -TEST_P(LayerTreeResourceProviderTest, TransferableResourceNotLostOnShutdown) { - MockReleaseCallback release; - viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); - provider().ImportResource( - tran, viz::SingleReleaseCallback::Create(base::Bind( - &MockReleaseCallback::Released, base::Unretained(&release)))); - - // On shutdown the TransferableResource is not lost if not exported. - EXPECT_CALL(release, Released(_, false)); - Shutdown(); -} - TEST_P(LayerTreeResourceProviderTest, TransferableResourceSendToParent) { MockReleaseCallback release; viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index f0df2aed..aea9471 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -473,31 +473,6 @@ if (!lost_resource && resource->origin == viz::internal::Resource::INTERNAL) WaitSyncTokenInternal(resource); - if (resource->origin == viz::internal::Resource::EXTERNAL) { - gpu::SyncToken sync_token = resource->sync_token(); - if (resource->is_gpu_resource_type()) { - DCHECK(!resource->mailbox.IsZero()); - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - if (resource->gl_id) { - DCHECK_NE(viz::internal::Resource::NEEDS_WAIT, - resource->synchronization_state()); - gl->DeleteTextures(1, &resource->gl_id); - resource->gl_id = 0; - if (!lost_resource) { - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); - gl->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); - } - } - } else { - DCHECK(resource->shared_bitmap); - resource->shared_bitmap = nullptr; - resource->pixels = nullptr; - } - std::move(resource->release_callback).Run(sync_token, lost_resource); - } - if (resource->image_id) { DCHECK_EQ(resource->origin, viz::internal::Resource::INTERNAL); GLES2Interface* gl = ContextGL(); @@ -513,7 +488,6 @@ } if (resource->owned_shared_bitmap) { - DCHECK_NE(resource->origin, viz::internal::Resource::EXTERNAL); DCHECK_EQ(viz::ResourceType::kBitmap, resource->type); resource->shared_bitmap = nullptr; resource->pixels = nullptr; @@ -521,7 +495,6 @@ } if (resource->gpu_memory_buffer) { - DCHECK_NE(resource->origin, viz::internal::Resource::EXTERNAL); DCHECK_EQ(viz::ResourceType::kGpuMemoryBuffer, resource->type); resource->gpu_memory_buffer = nullptr; }
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h index f15bdc9..605f88b5 100644 --- a/cc/resources/resource_provider.h +++ b/cc/resources/resource_provider.h
@@ -93,7 +93,7 @@ bool IsSoftware() const { return !compositor_context_provider_; } - void DidLoseVulkanContextProvider() { lost_context_provider_ = true; } + void DidLoseContextProvider() { lost_context_provider_ = true; } int max_texture_size() const { return settings_.max_texture_size; } viz::ResourceFormat best_texture_format() const { @@ -318,6 +318,7 @@ size_t CountPromotionHintRequestsForTesting(); #endif + // TODO(danakj): Move to DisplayResourceProvider. void WaitSyncToken(viz::ResourceId id); static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl);
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc index 2a78cc53..dd85f137 100644 --- a/cc/resources/resource_provider_unittest.cc +++ b/cc/resources/resource_provider_unittest.cc
@@ -67,11 +67,6 @@ *release_lost_resource = lost_resource; } -static void SharedBitmapReleaseCallback( - std::unique_ptr<viz::SharedBitmap> bitmap, - const gpu::SyncToken& sync_token, - bool lost_resource) {} - static void ReleaseSharedBitmapCallback( std::unique_ptr<viz::SharedBitmap> shared_bitmap, bool* release_called, @@ -417,13 +412,16 @@ class ResourceProviderTest : public testing::TestWithParam<viz::ResourceType> { public: explicit ResourceProviderTest(bool child_needs_sync_token) - : shared_data_(ContextSharedData::Create()) { + : child_needs_sync_token_(child_needs_sync_token), + shared_data_(ContextSharedData::Create()) { switch (GetParam()) { case viz::ResourceType::kGpuMemoryBuffer: case viz::ResourceType::kTexture: { auto context3d(ResourceProviderContext::Create(shared_data_.get())); context3d_ = context3d.get(); context_provider_ = TestContextProvider::Create(std::move(context3d)); + context_provider_->UnboundTestContext3d() + ->set_support_texture_format_bgra8888(true); context_provider_->BindToCurrentThread(); auto child_context_owned = @@ -431,6 +429,8 @@ child_context_ = child_context_owned.get(); child_context_provider_ = TestContextProvider::Create(std::move(child_context_owned)); + child_context_provider_->UnboundTestContext3d() + ->set_support_texture_format_bgra8888(true); child_context_provider_->BindToCurrentThread(); break; } @@ -444,18 +444,22 @@ child_gpu_memory_buffer_manager_ = gpu_memory_buffer_manager_->CreateClientGpuMemoryBufferManager(); - viz::ResourceSettings resource_settings = CreateResourceSettings(); resource_provider_ = std::make_unique<DisplayResourceProvider>( context_provider_.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), resource_settings); - child_resource_provider_ = std::make_unique<LayerTreeResourceProvider>( - child_context_provider_.get(), shared_bitmap_manager_.get(), - child_gpu_memory_buffer_manager_.get(), child_needs_sync_token, - resource_settings); + gpu_memory_buffer_manager_.get(), CreateResourceSettings()); + + MakeChildResourceProvider(); } ResourceProviderTest() : ResourceProviderTest(true) {} + void MakeChildResourceProvider() { + child_resource_provider_ = std::make_unique<LayerTreeResourceProvider>( + child_context_provider_.get(), shared_bitmap_manager_.get(), + child_gpu_memory_buffer_manager_.get(), child_needs_sync_token_, + CreateResourceSettings()); + } + static void CollectResources( std::vector<viz::ReturnedResource>* array, const std::vector<viz::ReturnedResource>& returned) { @@ -495,8 +499,9 @@ viz::SingleReleaseCallback::Create(base::Bind( ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), release_called, release_sync_token, lost_resource)); - return child_resource_provider_->CreateResourceFromTextureMailbox( - viz::TextureMailbox(gpu_mailbox, *sync_token, GL_TEXTURE_2D), + return child_resource_provider_->ImportResource( + viz::TransferableResource::MakeGL(gpu_mailbox, GL_LINEAR, + GL_TEXTURE_2D, *sync_token), std::move(callback)); } else { gfx::Size size(64, 64); @@ -508,12 +513,38 @@ viz::SingleReleaseCallback::Create(base::Bind( ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), release_called, release_sync_token, lost_resource)); - return child_resource_provider_->CreateResourceFromTextureMailbox( - viz::TextureMailbox(shared_bitmap_ptr, size), std::move(callback)); + return child_resource_provider_->ImportResource( + viz::TransferableResource::MakeSoftware( + shared_bitmap_ptr->id(), shared_bitmap_ptr->sequence_number(), + size), + std::move(callback)); } } + viz::ResourceId MakeGpuResourceAndSendToDisplay( + char c, + GLuint filter, + GLuint target, + const gpu::SyncToken& sync_token, + DisplayResourceProvider* resource_provider) { + ReturnCallback return_callback = + base::Bind([](const std::vector<viz::ReturnedResource>&) {}); + + int child = resource_provider->CreateChild(return_callback); + + gpu::Mailbox gpu_mailbox; + gpu_mailbox.name[0] = c; + gpu_mailbox.name[1] = 0; + auto resource = viz::TransferableResource::MakeGL(gpu_mailbox, GL_LINEAR, + target, sync_token); + resource.id = 11; + resource_provider->ReceiveFromChild(child, {resource}); + auto& map = resource_provider->GetChildToParentMap(child); + return map.find(resource.id)->second; + } + protected: + bool child_needs_sync_token_; std::unique_ptr<ContextSharedData> shared_data_; ResourceProviderContext* context3d_ = nullptr; ResourceProviderContext* child_context_ = nullptr; @@ -599,7 +630,9 @@ if (GetParam() != viz::ResourceType::kTexture) return; gfx::Size size(1, 1); - viz::ResourceFormat format = viz::RGBA_8888; + // Use some non-default format to detect when defaults aren't changed + // correctly. + viz::ResourceFormat format = viz::BGRA_8888; size_t pixel_size = TextureSizeBytes(size, format); ASSERT_EQ(4U, pixel_size); @@ -623,26 +656,6 @@ EXPECT_TRUE(lock.GetGpuMemoryBuffer()); } - GLuint external_texture_id = child_context_->createExternalTexture(); - - gpu::Mailbox external_mailbox; - child_context_->genMailboxCHROMIUM(external_mailbox.name); - child_context_->produceTextureDirectCHROMIUM( - external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name); - gpu::SyncToken external_sync_token; - child_context_->genSyncToken(child_context_->insertFenceSync(), - external_sync_token.GetData()); - EXPECT_TRUE(external_sync_token.HasData()); - - gfx::ColorSpace color_space4 = gfx::ColorSpace::CreateXYZD50(); - viz::TextureMailbox id4_mailbox(external_mailbox, external_sync_token, - GL_TEXTURE_EXTERNAL_OES); - id4_mailbox.set_color_space(color_space4); - viz::ResourceId id4 = - child_resource_provider_->CreateResourceFromTextureMailbox( - id4_mailbox, viz::SingleReleaseCallback::Create( - base::Bind(&EmptyReleaseCallback))); - std::vector<viz::ReturnedResource> returned_to_child; int child_id = resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); @@ -652,12 +665,11 @@ resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); resource_ids_to_transfer.push_back(id3); - resource_ids_to_transfer.push_back(id4); std::vector<viz::TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); - ASSERT_EQ(4u, list.size()); + ASSERT_EQ(3u, list.size()); EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); EXPECT_EQ(list[0].mailbox_holder.sync_token, @@ -665,19 +677,18 @@ EXPECT_TRUE(list[2].mailbox_holder.sync_token.HasData()); EXPECT_EQ(list[0].mailbox_holder.sync_token, list[2].mailbox_holder.sync_token); - EXPECT_EQ(external_sync_token, list[3].mailbox_holder.sync_token); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].mailbox_holder.texture_target); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].mailbox_holder.texture_target); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[2].mailbox_holder.texture_target); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), - list[3].mailbox_holder.texture_target); + EXPECT_EQ(list[0].buffer_format, gfx::BufferFormat::RGBA_8888); + EXPECT_EQ(list[1].buffer_format, gfx::BufferFormat::RGBA_8888); + EXPECT_EQ(list[2].buffer_format, gfx::BufferFormat::BGRA_8888); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4)); resource_provider_->ReceiveFromChild(child_id, list); EXPECT_NE(list[0].mailbox_holder.sync_token, context3d_->last_waited_sync_token()); @@ -697,23 +708,19 @@ resource_ids_to_receive.insert(id1); resource_ids_to_receive.insert(id2); resource_ids_to_receive.insert(id3); - resource_ids_to_receive.insert(id4); resource_provider_->DeclareUsedResourcesFromChild(child_id, resource_ids_to_receive); - EXPECT_EQ(4u, resource_provider_->num_resources()); + EXPECT_EQ(3u, resource_provider_->num_resources()); viz::ResourceId mapped_id1 = resource_map[id1]; viz::ResourceId mapped_id2 = resource_map[id2]; viz::ResourceId mapped_id3 = resource_map[id3]; - viz::ResourceId mapped_id4 = resource_map[id4]; EXPECT_NE(0u, mapped_id1); EXPECT_NE(0u, mapped_id2); EXPECT_NE(0u, mapped_id3); - EXPECT_NE(0u, mapped_id4); EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id1)); EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id2)); EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id3)); - EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id4)); uint8_t result[4] = { 0 }; GetResourcePixels( @@ -727,18 +734,12 @@ EXPECT_FALSE(resource_provider_->IsOverlayCandidate(mapped_id1)); EXPECT_FALSE(resource_provider_->IsOverlayCandidate(mapped_id2)); EXPECT_TRUE(resource_provider_->IsOverlayCandidate(mapped_id3)); - EXPECT_FALSE(resource_provider_->IsOverlayCandidate(mapped_id4)); { resource_provider_->WaitSyncToken(mapped_id1); DisplayResourceProvider::ScopedReadLockGL lock1(resource_provider_.get(), mapped_id1); EXPECT_TRUE(lock1.color_space() == color_space1); - - resource_provider_->WaitSyncToken(mapped_id4); - DisplayResourceProvider::ScopedReadLockGL lock4(resource_provider_.get(), - mapped_id4); - EXPECT_TRUE(lock4.color_space() == color_space4); } { @@ -761,6 +762,9 @@ list[1].mailbox_holder.texture_target); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[2].mailbox_holder.texture_target); + EXPECT_EQ(list[0].buffer_format, gfx::BufferFormat::RGBA_8888); + EXPECT_EQ(list[1].buffer_format, gfx::BufferFormat::RGBA_8888); + EXPECT_EQ(list[2].buffer_format, gfx::BufferFormat::BGRA_8888); std::vector<viz::ReturnedResource> returned = viz::TransferableResource::ReturnResources(list); child_resource_provider_->ReceiveReturnsFromParent(returned); @@ -778,22 +782,19 @@ viz::ResourceIdSet no_resources; resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); - ASSERT_EQ(4u, returned_to_child.size()); + ASSERT_EQ(3u, returned_to_child.size()); EXPECT_TRUE(returned_to_child[0].sync_token.HasData()); EXPECT_TRUE(returned_to_child[1].sync_token.HasData()); EXPECT_TRUE(returned_to_child[2].sync_token.HasData()); - EXPECT_TRUE(returned_to_child[3].sync_token.HasData()); EXPECT_FALSE(returned_to_child[0].lost); EXPECT_FALSE(returned_to_child[1].lost); EXPECT_FALSE(returned_to_child[2].lost); - EXPECT_FALSE(returned_to_child[3].lost); child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); returned_to_child.clear(); } EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1)); EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2)); EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3)); - EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4)); { child_resource_provider_->WaitSyncToken(id1); @@ -815,56 +816,47 @@ resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); resource_ids_to_transfer.push_back(id3); - resource_ids_to_transfer.push_back(id4); std::vector<viz::TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); - ASSERT_EQ(4u, list.size()); + ASSERT_EQ(3u, list.size()); EXPECT_EQ(id1, list[0].id); EXPECT_EQ(id2, list[1].id); EXPECT_EQ(id3, list[2].id); - EXPECT_EQ(id4, list[3].id); EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData()); EXPECT_TRUE(list[2].mailbox_holder.sync_token.HasData()); - EXPECT_TRUE(list[3].mailbox_holder.sync_token.HasData()); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].mailbox_holder.texture_target); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].mailbox_holder.texture_target); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[2].mailbox_holder.texture_target); - EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), - list[3].mailbox_holder.texture_target); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4)); resource_provider_->ReceiveFromChild(child_id, list); viz::ResourceIdSet resource_ids_to_receive; resource_ids_to_receive.insert(id1); resource_ids_to_receive.insert(id2); resource_ids_to_receive.insert(id3); - resource_ids_to_receive.insert(id4); resource_provider_->DeclareUsedResourcesFromChild(child_id, resource_ids_to_receive); } EXPECT_EQ(0u, returned_to_child.size()); - EXPECT_EQ(4u, resource_provider_->num_resources()); + EXPECT_EQ(3u, resource_provider_->num_resources()); resource_provider_->DestroyChild(child_id); EXPECT_EQ(0u, resource_provider_->num_resources()); - ASSERT_EQ(4u, returned_to_child.size()); + ASSERT_EQ(3u, returned_to_child.size()); EXPECT_TRUE(returned_to_child[0].sync_token.HasData()); EXPECT_TRUE(returned_to_child[1].sync_token.HasData()); EXPECT_TRUE(returned_to_child[2].sync_token.HasData()); - EXPECT_TRUE(returned_to_child[3].sync_token.HasData()); EXPECT_FALSE(returned_to_child[0].lost); EXPECT_FALSE(returned_to_child[1].lost); EXPECT_FALSE(returned_to_child[2].lost); - EXPECT_FALSE(returned_to_child[3].lost); } #if defined(OS_ANDROID) @@ -1004,12 +996,11 @@ child_context_->genSyncToken(child_context_->insertFenceSync(), external_sync_token.GetData()); EXPECT_TRUE(external_sync_token.HasData()); - viz::ResourceId id3 = - child_resource_provider_->CreateResourceFromTextureMailbox( - viz::TextureMailbox(external_mailbox, external_sync_token, - GL_TEXTURE_EXTERNAL_OES), - viz::SingleReleaseCallback::Create( - base::Bind(&EmptyReleaseCallback))); + viz::ResourceId id3 = child_resource_provider_->ImportResource( + viz::TransferableResource::MakeGL(external_mailbox, GL_LINEAR, + GL_TEXTURE_EXTERNAL_OES, + external_sync_token), + viz::SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback))); std::vector<viz::ReturnedResource> returned_to_child; int child_id = @@ -1385,7 +1376,7 @@ EXPECT_EQ(0u, returned_to_child.size()); EXPECT_EQ(2u, resource_provider_->num_resources()); - resource_provider_->DidLoseVulkanContextProvider(); + resource_provider_->DidLoseContextProvider(); resource_provider_ = nullptr; EXPECT_EQ(2u, returned_to_child.size()); @@ -1413,15 +1404,6 @@ uint8_t data2[4] = { 5, 5, 5, 5 }; child_resource_provider_->CopyToResource(id2, data2, size); - std::unique_ptr<viz::SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap( - shared_bitmap_manager_.get(), gfx::Size(1, 1), 0)); - viz::SharedBitmap* shared_bitmap_ptr = shared_bitmap.get(); - viz::ResourceId id3 = - child_resource_provider_->CreateResourceFromTextureMailbox( - viz::TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)), - viz::SingleReleaseCallback::Create(base::Bind( - &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap)))); - std::vector<viz::ReturnedResource> returned_to_child; int child_id = resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); @@ -1430,39 +1412,32 @@ ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); - resource_ids_to_transfer.push_back(id3); std::vector<viz::TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); - ASSERT_EQ(3u, list.size()); + ASSERT_EQ(2u, list.size()); EXPECT_FALSE(list[0].mailbox_holder.sync_token.HasData()); EXPECT_FALSE(list[1].mailbox_holder.sync_token.HasData()); - EXPECT_FALSE(list[2].mailbox_holder.sync_token.HasData()); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); resource_provider_->ReceiveFromChild(child_id, list); viz::ResourceIdSet resource_ids_to_receive; resource_ids_to_receive.insert(id1); resource_ids_to_receive.insert(id2); - resource_ids_to_receive.insert(id3); resource_provider_->DeclareUsedResourcesFromChild(child_id, resource_ids_to_receive); } - EXPECT_EQ(3u, resource_provider_->num_resources()); + EXPECT_EQ(2u, resource_provider_->num_resources()); ResourceProvider::ResourceIdMap resource_map = resource_provider_->GetChildToParentMap(child_id); viz::ResourceId mapped_id1 = resource_map[id1]; viz::ResourceId mapped_id2 = resource_map[id2]; - viz::ResourceId mapped_id3 = resource_map[id3]; EXPECT_NE(0u, mapped_id1); EXPECT_NE(0u, mapped_id2); - EXPECT_NE(0u, mapped_id3); EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id1)); EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id2)); - EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id3)); uint8_t result[4] = { 0 }; GetResourcePixels( @@ -1502,27 +1477,23 @@ viz::ResourceIdSet no_resources; resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); - ASSERT_EQ(3u, returned_to_child.size()); + ASSERT_EQ(2u, returned_to_child.size()); EXPECT_FALSE(returned_to_child[0].sync_token.HasData()); EXPECT_FALSE(returned_to_child[1].sync_token.HasData()); - EXPECT_FALSE(returned_to_child[2].sync_token.HasData()); std::set<viz::ResourceId> expected_ids; expected_ids.insert(id1); expected_ids.insert(id2); - expected_ids.insert(id3); std::set<viz::ResourceId> returned_ids; - for (unsigned i = 0; i < 3; i++) + for (unsigned i = 0; i < returned_to_child.size(); i++) returned_ids.insert(returned_to_child[i].id); EXPECT_EQ(expected_ids, returned_ids); EXPECT_FALSE(returned_to_child[0].lost); EXPECT_FALSE(returned_to_child[1].lost); - EXPECT_FALSE(returned_to_child[2].lost); child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); returned_to_child.clear(); } EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1)); EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2)); - EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3)); { ResourceProvider::ScopedWriteLockSoftware lock( @@ -1545,48 +1516,41 @@ ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); - resource_ids_to_transfer.push_back(id3); std::vector<viz::TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); - ASSERT_EQ(3u, list.size()); + ASSERT_EQ(2u, list.size()); EXPECT_EQ(id1, list[0].id); EXPECT_EQ(id2, list[1].id); - EXPECT_EQ(id3, list[2].id); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); - EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); resource_provider_->ReceiveFromChild(child_id, list); viz::ResourceIdSet resource_ids_to_receive; resource_ids_to_receive.insert(id1); resource_ids_to_receive.insert(id2); - resource_ids_to_receive.insert(id3); resource_provider_->DeclareUsedResourcesFromChild(child_id, resource_ids_to_receive); } EXPECT_EQ(0u, returned_to_child.size()); - EXPECT_EQ(3u, resource_provider_->num_resources()); + EXPECT_EQ(2u, resource_provider_->num_resources()); resource_provider_->DestroyChild(child_id); EXPECT_EQ(0u, resource_provider_->num_resources()); - ASSERT_EQ(3u, returned_to_child.size()); + ASSERT_EQ(2u, returned_to_child.size()); EXPECT_FALSE(returned_to_child[0].sync_token.HasData()); EXPECT_FALSE(returned_to_child[1].sync_token.HasData()); - EXPECT_FALSE(returned_to_child[2].sync_token.HasData()); std::set<viz::ResourceId> expected_ids; expected_ids.insert(id1); expected_ids.insert(id2); - expected_ids.insert(id3); std::set<viz::ResourceId> returned_ids; - for (unsigned i = 0; i < 3; i++) + for (unsigned i = 0; i < returned_to_child.size(); i++) returned_ids.insert(returned_to_child[i].id); EXPECT_EQ(expected_ids, returned_ids); EXPECT_FALSE(returned_to_child[0].lost); EXPECT_FALSE(returned_to_child[1].lost); - EXPECT_FALSE(returned_to_child[2].lost); } TEST_P(ResourceProviderTest, TransferGLToSoftware) { @@ -2023,10 +1987,10 @@ bool lost_resource = false; viz::ReleaseCallback callback = base::Bind(ReleaseCallback, &release_sync_token, &lost_resource); - viz::ResourceId resource = - child_resource_provider_->CreateResourceFromTextureMailbox( - viz::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D), - viz::SingleReleaseCallback::Create(std::move(callback))); + viz::ResourceId resource = child_resource_provider_->ImportResource( + viz::TransferableResource::MakeGL(mailbox, GL_LINEAR, GL_TEXTURE_2D, + sync_token), + viz::SingleReleaseCallback::Create(std::move(callback))); EXPECT_EQ(1u, context()->NumTextures()); EXPECT_FALSE(release_sync_token.HasData()); { @@ -2067,7 +2031,7 @@ EXPECT_EQ(1u, context()->NumTextures()); EXPECT_FALSE(release_sync_token.HasData()); - child_resource_provider_->DeleteResource(resource); + child_resource_provider_->RemoveImportedResource(resource); EXPECT_LE(list[0].mailbox_holder.sync_token.release_count(), release_sync_token.release_count()); EXPECT_FALSE(lost_resource); @@ -2079,8 +2043,9 @@ EXPECT_LT(0u, sync_token.release_count()); release_sync_token.Clear(); callback = base::Bind(ReleaseCallback, &release_sync_token, &lost_resource); - resource = child_resource_provider_->CreateResourceFromTextureMailbox( - viz::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D), + resource = child_resource_provider_->ImportResource( + viz::TransferableResource::MakeGL(mailbox, GL_LINEAR, GL_TEXTURE_2D, + sync_token), viz::SingleReleaseCallback::Create(std::move(callback))); EXPECT_EQ(1u, context()->NumTextures()); EXPECT_FALSE(release_sync_token.HasData()); @@ -2115,7 +2080,7 @@ EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); // Delete the resource, which shouldn't do anything. - child_resource_provider_->DeleteResource(resource); + child_resource_provider_->RemoveImportedResource(resource); EXPECT_EQ(1u, context()->NumTextures()); EXPECT_FALSE(release_sync_token.HasData()); @@ -2164,7 +2129,7 @@ } // Lose the output surface in the parent. - resource_provider_->DidLoseVulkanContextProvider(); + resource_provider_->DidLoseContextProvider(); { EXPECT_EQ(0u, returned_to_child.size()); @@ -2218,7 +2183,7 @@ } // Lose the output surface in the parent. - resource_provider_->DidLoseVulkanContextProvider(); + resource_provider_->DidLoseContextProvider(); { EXPECT_EQ(0u, returned_to_child.size()); @@ -2238,85 +2203,84 @@ // Delete the resource in the child. Expect the resource to be lost if it's // a GL texture. - child_resource_provider_->DeleteResource(resource); + child_resource_provider_->RemoveImportedResource(resource); EXPECT_EQ(lost_resource, GetParam() == viz::ResourceType::kTexture); } TEST_P(ResourceProviderTest, Shutdown) { - gpu::SyncToken release_sync_token; - bool lost_resource = false; - bool release_called = false; - gpu::SyncToken sync_token; - CreateChildMailbox(&release_sync_token, &lost_resource, &release_called, - &sync_token); + enum Cases { + // If not exported, the resource is returned not lost, and doesn't need a + // sync token. + kShutdownWithoutExport = 0, + // If exported and not returned, the resource is lost, and doesn't need/have + // a sync token to give. + kShutdownAfterExport, + // If exported and returned, the resource is not lost. + kShutdownAfterExportAndReturn, + // If returned as lost, then the resource must report lost on shutdown too. + kShutdownAfterExportAndReturnWithLostResource, + // If the context is lost, it doesn't affect imported resources as they are + // just weak references. + kShutdownAfterContextLossWithoutExport, + // If the context is lost, it doesn't affect imported resources as they are + // just weak references. + kShutdownAfterContextLossAfterExportAndReturn, + kNumCases, + }; - EXPECT_FALSE(release_sync_token.HasData()); - EXPECT_FALSE(lost_resource); + for (int i = 0; i < kNumCases; ++i) { + auto c = static_cast<Cases>(i); + SCOPED_TRACE(c); - child_resource_provider_ = nullptr; + gpu::SyncToken release_sync_token; + bool lost_resource = false; + bool release_called = false; + gpu::SyncToken sync_token; + viz::ResourceId id = CreateChildMailbox(&release_sync_token, &lost_resource, + &release_called, &sync_token); - if (GetParam() == viz::ResourceType::kTexture) { - EXPECT_LE(sync_token.release_count(), release_sync_token.release_count()); + if (i == kShutdownAfterExport || i == kShutdownAfterExportAndReturn || + i == kShutdownAfterExportAndReturnWithLostResource || + i == kShutdownAfterContextLossAfterExportAndReturn) { + std::vector<viz::TransferableResource> send_list; + child_resource_provider_->PrepareSendToParent({id}, &send_list); + } + + if (i == kShutdownAfterExportAndReturn || + i == kShutdownAfterExportAndReturnWithLostResource || + i == kShutdownAfterContextLossAfterExportAndReturn) { + viz::ReturnedResource r; + r.id = id; + r.sync_token = sync_token; + r.count = 1; + r.lost = (i == kShutdownAfterExportAndReturnWithLostResource); + child_resource_provider_->ReceiveReturnsFromParent({r}); + } + + EXPECT_FALSE(release_sync_token.HasData()); + EXPECT_FALSE(lost_resource); + + // Shutdown! + child_resource_provider_ = nullptr; + + // If the resource was exported and returned, then it should come with a + // sync token. + if (GetParam() == viz::ResourceType::kTexture && + (i == kShutdownAfterExportAndReturn || + i == kShutdownAfterExportAndReturnWithLostResource || + i == kShutdownAfterContextLossAfterExportAndReturn)) { + EXPECT_LE(sync_token.release_count(), release_sync_token.release_count()); + } + + // We always get the ReleaseCallback called. + EXPECT_TRUE(release_called); + bool expect_lost = i == kShutdownAfterExport || + i == kShutdownAfterExportAndReturnWithLostResource; + EXPECT_EQ(expect_lost, lost_resource); + + // Recreate it for the next case. + MakeChildResourceProvider(); } - EXPECT_TRUE(release_called); - EXPECT_FALSE(lost_resource); -} - -TEST_P(ResourceProviderTest, ShutdownWithExportedResource) { - gpu::SyncToken release_sync_token; - bool lost_resource = false; - bool release_called = false; - gpu::SyncToken sync_token; - viz::ResourceId resource = CreateChildMailbox( - &release_sync_token, &lost_resource, &release_called, &sync_token); - - // Transfer the resource, so we can't release it properly on shutdown. - ResourceProvider::ResourceIdArray resource_ids_to_transfer; - resource_ids_to_transfer.push_back(resource); - std::vector<viz::TransferableResource> list; - child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, - &list); - - EXPECT_FALSE(release_sync_token.HasData()); - EXPECT_FALSE(lost_resource); - - child_resource_provider_ = nullptr; - - // Since the resource is in the parent, the child considers it lost. - EXPECT_TRUE(lost_resource); -} - -TEST_P(ResourceProviderTest, LostContext) { - // viz::TextureMailbox callbacks only exist for GL textures for now. - if (GetParam() != viz::ResourceType::kTexture) - return; - unsigned texture = context()->createTexture(); - context()->bindTexture(GL_TEXTURE_2D, texture); - gpu::Mailbox mailbox; - context()->genMailboxCHROMIUM(mailbox.name); - context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name); - gpu::SyncToken sync_token; - context()->genSyncToken(context()->insertFenceSync(), sync_token.GetData()); - - EXPECT_TRUE(sync_token.HasData()); - - gpu::SyncToken release_sync_token; - bool lost_resource = false; - std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create( - base::Bind(&ReleaseCallback, &release_sync_token, &lost_resource)); - child_resource_provider_->CreateResourceFromTextureMailbox( - viz::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D), - std::move(callback)); - - EXPECT_FALSE(release_sync_token.HasData()); - EXPECT_FALSE(lost_resource); - - child_resource_provider_->DidLoseVulkanContextProvider(); - child_resource_provider_ = nullptr; - - EXPECT_LE(sync_token.release_count(), release_sync_token.release_count()); - EXPECT_TRUE(lost_resource); } TEST_P(ResourceProviderTest, ScopedSampler) { @@ -2525,7 +2489,7 @@ } } -TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) { +TEST_P(ResourceProviderTest, ImportedResource_SharedMemory) { if (GetParam() != viz::ResourceType::kBitmap) return; @@ -2547,11 +2511,11 @@ std::unique_ptr<viz::SingleReleaseCallback> callback = viz::SingleReleaseCallback::Create( base::Bind(&ReleaseCallback, &release_sync_token, &lost_resource)); - viz::TextureMailbox mailbox(shared_bitmap.get(), size); + auto resource = viz::TransferableResource::MakeSoftware( + shared_bitmap->id(), shared_bitmap->sequence_number(), size); viz::ResourceId resource_id = - child_resource_provider->CreateResourceFromTextureMailbox( - mailbox, std::move(callback)); + child_resource_provider->ImportResource(resource, std::move(callback)); EXPECT_NE(0u, resource_id); // Transfer resources to the parent. @@ -2588,12 +2552,12 @@ EXPECT_EQ(1u, returned_to_child.size()); child_resource_provider->ReceiveReturnsFromParent(returned_to_child); - child_resource_provider->DeleteResource(resource_id); + child_resource_provider->RemoveImportedResource(resource_id); EXPECT_FALSE(release_sync_token.HasData()); EXPECT_FALSE(lost_resource); } -class ResourceProviderTestTextureMailboxGLFilters +class ResourceProviderTestImportedResourceGLFilters : public ResourceProviderTest { public: static void RunTest( @@ -2642,12 +2606,12 @@ viz::SingleReleaseCallback::Create( base::Bind(&ReleaseCallback, &release_sync_token, &lost_resource)); - viz::TextureMailbox mailbox(gpu_mailbox, sync_token, target); - mailbox.set_nearest_neighbor(mailbox_nearest_neighbor); + GLuint filter = mailbox_nearest_neighbor ? GL_NEAREST : GL_LINEAR; + auto resource = viz::TransferableResource::MakeGL(gpu_mailbox, filter, + target, sync_token); viz::ResourceId resource_id = - child_resource_provider->CreateResourceFromTextureMailbox( - mailbox, std::move(callback)); + child_resource_provider->ImportResource(resource, std::move(callback)); EXPECT_NE(0u, resource_id); EXPECT_EQ(current_fence_sync, child_context->GetNextFenceSync()); @@ -2719,61 +2683,53 @@ EXPECT_EQ(1u, returned_to_child.size()); child_resource_provider->ReceiveReturnsFromParent(returned_to_child); - child_resource_provider->DeleteResource(resource_id); + child_resource_provider->RemoveImportedResource(resource_id); EXPECT_TRUE(release_sync_token.HasData()); EXPECT_FALSE(lost_resource); } }; -TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToLinear) { +TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_LinearToLinear) { // Mailboxing is only supported for GL textures. if (GetParam() != viz::ResourceType::kTexture) return; - ResourceProviderTestTextureMailboxGLFilters::RunTest( - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - false, + ResourceProviderTestImportedResourceGLFilters::RunTest( + shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), false, GL_LINEAR); } -TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToNearest) { +TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_NearestToNearest) { // Mailboxing is only supported for GL textures. if (GetParam() != viz::ResourceType::kTexture) return; - ResourceProviderTestTextureMailboxGLFilters::RunTest( - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - true, + ResourceProviderTestImportedResourceGLFilters::RunTest( + shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), true, GL_NEAREST); } -TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToLinear) { +TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_NearestToLinear) { // Mailboxing is only supported for GL textures. if (GetParam() != viz::ResourceType::kTexture) return; - ResourceProviderTestTextureMailboxGLFilters::RunTest( - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - true, + ResourceProviderTestImportedResourceGLFilters::RunTest( + shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), true, GL_LINEAR); } -TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToNearest) { +TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_LinearToNearest) { // Mailboxing is only supported for GL textures. if (GetParam() != viz::ResourceType::kTexture) return; - ResourceProviderTestTextureMailboxGLFilters::RunTest( - shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), - false, + ResourceProviderTestImportedResourceGLFilters::RunTest( + shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), false, GL_NEAREST); } -TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { +TEST_P(ResourceProviderTest, ImportedResource_GLTextureExternalOES) { // Mailboxing is only supported for GL textures. if (GetParam() != viz::ResourceType::kTexture) return; @@ -2813,11 +2769,11 @@ std::unique_ptr<viz::SingleReleaseCallback> callback = viz::SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)); - viz::TextureMailbox mailbox(gpu_mailbox, sync_token, target); + auto resource = viz::TransferableResource::MakeGL(gpu_mailbox, GL_LINEAR, + target, sync_token); viz::ResourceId resource_id = - child_resource_provider->CreateResourceFromTextureMailbox( - mailbox, std::move(callback)); + child_resource_provider->ImportResource(resource, std::move(callback)); EXPECT_NE(0u, resource_id); EXPECT_EQ(current_fence_sync, child_context->GetNextFenceSync()); @@ -2879,11 +2835,10 @@ EXPECT_EQ(1u, returned_to_child.size()); child_resource_provider->ReceiveReturnsFromParent(returned_to_child); - child_resource_provider->DeleteResource(resource_id); + child_resource_provider->RemoveImportedResource(resource_id); } -TEST_P(ResourceProviderTest, - TextureMailbox_WaitSyncTokenIfNeeded_WithSyncToken) { +TEST_P(ResourceProviderTest, WaitSyncTokenIfNeeded_ResourceFromChild) { // Mailboxing is only supported for GL textures. if (GetParam() != viz::ResourceType::kTexture) return; @@ -2893,10 +2848,9 @@ auto context_provider = TestContextProvider::Create(std::move(context_owned)); context_provider->BindToCurrentThread(); - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( + auto resource_provider = std::make_unique<DisplayResourceProvider>( context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); + gpu_memory_buffer_manager_.get(), CreateResourceSettings()); gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, gpu::CommandBufferId::FromUnsafeValue(0x12), 0x34); @@ -2908,15 +2862,65 @@ EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); - gpu::Mailbox gpu_mailbox; - memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); - std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)); + // Receive a resource from the child. + std::vector<viz::ReturnedResource> returned; + ReturnCallback return_callback = base::Bind( + [](std::vector<viz::ReturnedResource>* out, + const std::vector<viz::ReturnedResource>& in) { + *out = std::move(in); + }, + &returned); + int child = resource_provider->CreateChild(return_callback); - viz::TextureMailbox mailbox(gpu_mailbox, sync_token, target); + // Send a bunch of resources, to make sure things work when there's more than + // one resource, and to make vectors reallocate and such. + for (int i = 0; i < 100; ++i) { + gpu::Mailbox gpu_mailbox; + memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); + auto resource = viz::TransferableResource::MakeGL(gpu_mailbox, GL_LINEAR, + target, sync_token); + resource.id = i; + resource_provider->ReceiveFromChild(child, {resource}); + auto& map = resource_provider->GetChildToParentMap(child); + EXPECT_EQ(i + 1u, map.size()); + } - viz::ResourceId id = resource_provider->CreateResourceFromTextureMailbox( - mailbox, std::move(callback)); + EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); + resource_provider.reset(); + // Returned resources don't have InsertFenceSyncCHROMIUM() called. + EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); + + // The returned resource has a verified sync token. + ASSERT_EQ(returned.size(), 100u); + for (viz::ReturnedResource& r : returned) + EXPECT_TRUE(r.sync_token.verified_flush()); +} + +TEST_P(ResourceProviderTest, WaitSyncTokenIfNeeded_WithSyncToken) { + // Mailboxing is only supported for GL textures. + if (GetParam() != viz::ResourceType::kTexture) + return; + + auto context_owned(std::make_unique<TextureStateTrackingContext>()); + TextureStateTrackingContext* context = context_owned.get(); + auto context_provider = TestContextProvider::Create(std::move(context_owned)); + context_provider->BindToCurrentThread(); + + auto resource_provider = std::make_unique<DisplayResourceProvider>( + context_provider.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), CreateResourceSettings()); + + gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, + gpu::CommandBufferId::FromUnsafeValue(0x12), 0x34); + const GLuint64 current_fence_sync = context->GetNextFenceSync(); + + EXPECT_CALL(*context, bindTexture(_, _)).Times(0); + EXPECT_CALL(*context, waitSyncToken(_)).Times(0); + EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); + EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); + + viz::ResourceId id = MakeGpuResourceAndSendToDisplay( + 'a', GL_LINEAR, GL_TEXTURE_2D, sync_token, resource_provider.get()); EXPECT_NE(0u, id); EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); @@ -2935,7 +2939,8 @@ } } -TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncTokenIfNeeded_NoSyncToken) { +TEST_P(ResourceProviderTest, + ImportedResource_WaitSyncTokenIfNeeded_NoSyncToken) { // Mailboxing is only supported for GL textures. if (GetParam() != viz::ResourceType::kTexture) return; @@ -2945,31 +2950,23 @@ auto context_provider = TestContextProvider::Create(std::move(context_owned)); context_provider->BindToCurrentThread(); - auto resource_provider(std::make_unique<LayerTreeResourceProvider>( + auto resource_provider = std::make_unique<DisplayResourceProvider>( context_provider.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired, - CreateResourceSettings())); + gpu_memory_buffer_manager_.get(), CreateResourceSettings()); gpu::SyncToken sync_token; const GLuint64 current_fence_sync = context->GetNextFenceSync(); - unsigned target = GL_TEXTURE_2D; EXPECT_CALL(*context, bindTexture(_, _)).Times(0); EXPECT_CALL(*context, waitSyncToken(_)).Times(0); EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); - gpu::Mailbox gpu_mailbox; - memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); - std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)); + viz::ResourceId id = MakeGpuResourceAndSendToDisplay( + 'h', GL_LINEAR, GL_TEXTURE_2D, sync_token, resource_provider.get()); - viz::TextureMailbox mailbox(gpu_mailbox, sync_token, target); - - viz::ResourceId id = resource_provider->CreateResourceFromTextureMailbox( - mailbox, std::move(callback)); - EXPECT_NE(0u, id); EXPECT_EQ(current_fence_sync, context->GetNextFenceSync()); + EXPECT_NE(0u, id); Mock::VerifyAndClearExpectations(context); @@ -2981,7 +2978,7 @@ } } -TEST_P(ResourceProviderTest, TextureMailbox_PrepareSendToParent_NoSyncToken) { +TEST_P(ResourceProviderTest, ImportedResource_PrepareSendToParent_NoSyncToken) { // Mailboxing is only supported for GL textures. if (GetParam() != viz::ResourceType::kTexture) return; @@ -3001,14 +2998,14 @@ EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); - viz::TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), - GL_TEXTURE_2D); + auto resource = viz::TransferableResource::MakeGL( + gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken()); std::unique_ptr<viz::SingleReleaseCallback> callback = viz::SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)); - viz::ResourceId id = resource_provider->CreateResourceFromTextureMailbox( - mailbox, std::move(callback)); + viz::ResourceId id = + resource_provider->ImportResource(resource, std::move(callback)); EXPECT_NE(0u, id); Mock::VerifyAndClearExpectations(context);
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc index b8879d6..5370cab 100644 --- a/cc/test/layer_tree_pixel_test.cc +++ b/cc/test/layer_tree_pixel_test.cc
@@ -139,7 +139,7 @@ // Drop TextureMailboxes on the main thread so that they can be cleaned up and // the pending callbacks will fire. for (size_t i = 0; i < texture_layers_.size(); ++i) { - texture_layers_[i]->SetTextureMailbox(viz::TextureMailbox(), nullptr); + texture_layers_[i]->ClearTexture(); } TryEndTest();
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index c6c8332..8dd61405 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc
@@ -40,6 +40,85 @@ #include "ui/gfx/geometry/size_conversions.h" namespace cc { +namespace { + +class SynchronousLayerTreeFrameSink : public viz::TestLayerTreeFrameSink { + public: + SynchronousLayerTreeFrameSink( + scoped_refptr<viz::ContextProvider> compositor_context_provider, + scoped_refptr<viz::ContextProvider> worker_context_provider, + viz::SharedBitmapManager* shared_bitmap_manager, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + const viz::RendererSettings& renderer_settings, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + double refresh_rate) + : viz::TestLayerTreeFrameSink(std::move(compositor_context_provider), + std::move(worker_context_provider), + shared_bitmap_manager, + gpu_memory_buffer_manager, + renderer_settings, + task_runner, + false, + false, + refresh_rate), + task_runner_(std::move(task_runner)), + weak_factory_(this) {} + ~SynchronousLayerTreeFrameSink() override = default; + + void set_viewport(const gfx::Rect& viewport) { viewport_ = viewport; } + + bool BindToClient(LayerTreeFrameSinkClient* client) override { + if (!viz::TestLayerTreeFrameSink::BindToClient(client)) + return false; + client_ = client; + return true; + } + void DetachFromClient() override { + client_ = nullptr; + weak_factory_.InvalidateWeakPtrs(); + viz::TestLayerTreeFrameSink::DetachFromClient(); + } + void Invalidate() override { + if (frame_request_pending_) + return; + frame_request_pending_ = true; + InvalidateIfPossible(); + } + void SubmitCompositorFrame(viz::CompositorFrame frame) override { + frame_ack_pending_ = true; + viz::TestLayerTreeFrameSink::SubmitCompositorFrame(std::move(frame)); + } + void DidReceiveCompositorFrameAck( + const std::vector<viz::ReturnedResource>& resources) override { + DCHECK(frame_ack_pending_); + frame_ack_pending_ = false; + viz::TestLayerTreeFrameSink::DidReceiveCompositorFrameAck(resources); + InvalidateIfPossible(); + } + + private: + void InvalidateIfPossible() { + if (!frame_request_pending_ || frame_ack_pending_) + return; + task_runner_->PostTask( + FROM_HERE, + base::Bind(&SynchronousLayerTreeFrameSink::DispatchInvalidation, + weak_factory_.GetWeakPtr())); + } + void DispatchInvalidation() { + frame_request_pending_ = false; + client_->OnDraw(gfx::Transform(SkMatrix::I()), viewport_, false); + } + + bool frame_request_pending_ = false; + bool frame_ack_pending_ = false; + LayerTreeFrameSinkClient* client_ = nullptr; + gfx::Rect viewport_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + base::WeakPtrFactory<SynchronousLayerTreeFrameSink> weak_factory_; +}; + +} // namespace void CreateVirtualViewportLayers(Layer* root_layer, scoped_refptr<Layer> outer_scroll_layer, @@ -897,6 +976,17 @@ bool synchronous_composite = !HasImplThread() && !layer_tree_host()->GetSettings().single_thread_proxy_scheduler; + + DCHECK( + !synchronous_composite || + !layer_tree_host()->GetSettings().using_synchronous_renderer_compositor); + if (layer_tree_host()->GetSettings().using_synchronous_renderer_compositor) { + return std::make_unique<SynchronousLayerTreeFrameSink>( + compositor_context_provider, std::move(worker_context_provider), + shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings, + impl_task_runner_, refresh_rate); + } + return std::make_unique<viz::TestLayerTreeFrameSink>( compositor_context_provider, std::move(worker_context_provider), shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings,
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc index 94a5bb0..4dbe2bd4 100644 --- a/cc/test/render_pass_test_utils.cc +++ b/cc/test/render_pass_test_utils.cc
@@ -16,6 +16,7 @@ #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/quads/tile_draw_quad.h" #include "components/viz/common/quads/yuv_video_draw_quad.h" +#include "components/viz/common/resources/transferable_resource.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "ui/gfx/geometry/rect.h" @@ -167,12 +168,10 @@ memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); std::unique_ptr<viz::SingleReleaseCallback> callback = viz::SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)); - viz::TextureMailbox mailbox(gpu_mailbox, kSyncTokenForMailboxTextureQuad, - target); + auto transfer_resource = viz::TransferableResource::MakeGL( + gpu_mailbox, GL_LINEAR, target, kSyncTokenForMailboxTextureQuad); viz::ResourceId resource8 = - resource_provider->CreateResourceFromTextureMailbox(mailbox, - std::move(callback)); - resource_provider->AllocateForTesting(resource8); + resource_provider->ImportResource(transfer_resource, std::move(callback)); viz::SharedQuadState* shared_state = to_pass->CreateAndAppendSharedQuadState(); @@ -208,12 +207,12 @@ gfx::PointF(1.f, 1.f), SK_ColorTRANSPARENT, vertex_opacity, false, false, false); - auto* mailbox_texture_quad = + auto* external_resource_texture_quad = to_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>(); - mailbox_texture_quad->SetNew(shared_state, rect, visible_rect, needs_blending, - resource8, false, gfx::PointF(0.f, 0.f), - gfx::PointF(1.f, 1.f), SK_ColorTRANSPARENT, - vertex_opacity, false, false, false); + external_resource_texture_quad->SetNew( + shared_state, rect, visible_rect, needs_blending, resource8, false, + gfx::PointF(0.f, 0.f), gfx::PointF(1.f, 1.f), SK_ColorTRANSPARENT, + vertex_opacity, false, false, false); auto* scaled_tile_quad = to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>(); @@ -325,12 +324,10 @@ memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); std::unique_ptr<viz::SingleReleaseCallback> callback = viz::SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)); - viz::TextureMailbox mailbox(gpu_mailbox, kSyncTokenForMailboxTextureQuad, - target); - viz::ResourceId resource8 = - child_resource_provider->CreateResourceFromTextureMailbox( - mailbox, std::move(callback)); - child_resource_provider->AllocateForTesting(resource8); + auto transfer_resource = viz::TransferableResource::MakeGL( + gpu_mailbox, GL_LINEAR, target, kSyncTokenForMailboxTextureQuad); + viz::ResourceId resource8 = child_resource_provider->ImportResource( + transfer_resource, std::move(callback)); // Transfer resource to the parent. ResourceProvider::ResourceIdArray resource_ids_to_transfer; @@ -412,12 +409,12 @@ gfx::PointF(1.f, 1.f), SK_ColorTRANSPARENT, vertex_opacity, false, false, false); - viz::TextureDrawQuad* mailbox_texture_quad = + viz::TextureDrawQuad* external_resource_texture_quad = to_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>(); - mailbox_texture_quad->SetNew(shared_state, rect, visible_rect, needs_blending, - mapped_resource8, false, gfx::PointF(0.f, 0.f), - gfx::PointF(1.f, 1.f), SK_ColorTRANSPARENT, - vertex_opacity, false, false, false); + external_resource_texture_quad->SetNew( + shared_state, rect, visible_rect, needs_blending, mapped_resource8, false, + gfx::PointF(0.f, 0.f), gfx::PointF(1.f, 1.f), SK_ColorTRANSPARENT, + vertex_opacity, false, false, false); viz::TileDrawQuad* scaled_tile_quad = to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc index 8ccc1535..84b16fe 100644 --- a/cc/test/test_web_graphics_context_3d.cc +++ b/cc/test/test_web_graphics_context_3d.cc
@@ -609,7 +609,9 @@ GLsizei width, GLsizei height, GLenum internalformat) { - DCHECK(internalformat == GL_RGB || internalformat == GL_RGBA); + DCHECK(internalformat == GL_RGB || internalformat == GL_RGBA || + (test_capabilities_.texture_format_bgra8888 && + internalformat == GL_BGRA_EXT)); GLuint image_id = NextImageId(); base::AutoLock lock(namespace_->lock); std::unordered_set<unsigned>& images = namespace_->images; @@ -632,7 +634,9 @@ GLsizei height, GLenum internalformat, GLenum usage) { - DCHECK(internalformat == GL_RGB || internalformat == GL_RGBA); + DCHECK(internalformat == GL_RGB || internalformat == GL_RGBA || + (test_capabilities_.texture_format_bgra8888 && + internalformat == GL_BGRA_EXT)); GLuint image_id = NextImageId(); base::AutoLock lock(namespace_->lock); std::unordered_set<unsigned>& images = namespace_->images;
diff --git a/cc/tiles/software_image_decode_cache.cc b/cc/tiles/software_image_decode_cache.cc index 62764ad1f..c83246c 100644 --- a/cc/tiles/software_image_decode_cache.cc +++ b/cc/tiles/software_image_decode_cache.cc
@@ -53,7 +53,7 @@ const int kMinDimensionToSubrect = 4 * 1024; const float kMemoryRatioToSubrect = 0.5f; -// Tracing ID sequence for use in CacheEntry. +// Tracing ID sequence for use in DecodedImage. base::AtomicSequenceNumber g_next_tracing_id_; class AutoRemoveKeyFromTaskMap { @@ -73,17 +73,35 @@ const SoftwareImageDecodeCache::ImageKey& key_; }; +class AutoDrawWithImageFinished { + public: + AutoDrawWithImageFinished(SoftwareImageDecodeCache* cache, + const DrawImage& draw_image, + const DecodedDrawImage& decoded_draw_image) + : cache_(cache), + draw_image_(draw_image), + decoded_draw_image_(decoded_draw_image) {} + ~AutoDrawWithImageFinished() { + cache_->DrawWithImageFinished(draw_image_, decoded_draw_image_); + } + + private: + SoftwareImageDecodeCache* cache_; + const DrawImage& draw_image_; + const DecodedDrawImage& decoded_draw_image_; +}; + class ImageDecodeTaskImpl : public TileTask { public: ImageDecodeTaskImpl(SoftwareImageDecodeCache* cache, const SoftwareImageDecodeCache::ImageKey& image_key, - const PaintImage& paint_image, + const DrawImage& image, SoftwareImageDecodeCache::DecodeTaskType task_type, const ImageDecodeCache::TracingInfo& tracing_info) : TileTask(true), cache_(cache), image_key_(image_key), - paint_image_(paint_image), + image_(image), task_type_(task_type), tracing_info_(tracing_info) {} @@ -93,15 +111,15 @@ "software", "source_prepare_tiles_id", tracing_info_.prepare_tiles_id); devtools_instrumentation::ScopedImageDecodeTask image_decode_task( - paint_image_.GetSkImage().get(), + image_.paint_image().GetSkImage().get(), devtools_instrumentation::ScopedImageDecodeTask::kSoftware, ImageDecodeCache::ToScopedTaskType(tracing_info_.task_type)); - cache_->DecodeImageInTask(image_key_, paint_image_, task_type_); + cache_->DecodeImage(image_key_, image_, task_type_); } // Overridden from TileTask: void OnTaskCompleted() override { - cache_->OnImageDecodeTaskCompleted(image_key_, task_type_); + cache_->RemovePendingTask(image_key_, task_type_); } protected: @@ -110,7 +128,7 @@ private: SoftwareImageDecodeCache* cache_; SoftwareImageDecodeCache::ImageKey image_key_; - PaintImage paint_image_; + DrawImage image_; SoftwareImageDecodeCache::DecodeTaskType task_type_; const ImageDecodeCache::TracingInfo tracing_info_; @@ -138,9 +156,10 @@ return std::min(key.filter_quality(), kLow_SkFilterQuality); } -SkImageInfo CreateImageInfo(const SkISize& size, SkColorType color_type) { - return SkImageInfo::Make(size.width(), size.height(), color_type, - kPremul_SkAlphaType); +SkImageInfo CreateImageInfo(size_t width, + size_t height, + SkColorType color_type) { + return SkImageInfo::Make(width, height, color_type, kPremul_SkAlphaType); } void RecordLockExistingCachedImageHistogram(TilePriority::PriorityBin bin, @@ -169,19 +188,13 @@ return gfx::Rect(x, y, right - x, bottom - y); } -std::unique_ptr<base::DiscardableMemory> AllocateDiscardable( - const SkImageInfo& info) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "AllocateDiscardable"); - return base::DiscardableMemoryAllocator::GetInstance() - ->AllocateLockedDiscardableMemory(info.minRowBytes() * info.height()); -} - } // namespace SoftwareImageDecodeCache::SoftwareImageDecodeCache( SkColorType color_type, size_t locked_memory_limit_bytes) : decoded_images_(ImageMRUCache::NO_AUTO_EVICT), + at_raster_decoded_images_(ImageMRUCache::NO_AUTO_EVICT), locked_images_budget_(locked_memory_limit_bytes), color_type_(color_type), max_items_in_cache_(kNormalMaxItemsInCache) { @@ -197,6 +210,10 @@ } SoftwareImageDecodeCache::~SoftwareImageDecodeCache() { + // Debugging crbug.com/650234 + CHECK_EQ(0u, decoded_images_ref_counts_.size()); + CHECK_EQ(0u, at_raster_decoded_images_ref_counts_.size()); + // It is safe to unregister, even if we didn't register in the constructor. base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( this); @@ -236,377 +253,597 @@ const DrawImage& image, const TracingInfo& tracing_info, DecodeTaskType task_type) { + // If the image already exists or if we're going to create a task for it, then + // we'll likely need to ref this image (the exception is if we're prerolling + // the image only). That means the image is or will be in the cache. When the + // ref goes to 0, it will be unpinned but will remain in the cache. If the + // image does not fit into the budget, then we don't ref this image, since it + // will be decoded at raster time which is when it will be temporarily put in + // the cache. ImageKey key = ImageKey::FromDrawImage(image, color_type_); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), - "SoftwareImageDecodeCache::GetTaskForImageAndRefInternal", "key", + "SoftwareImageDecodeCache::GetTaskForImageAndRef", "key", key.ToString()); // If the target size is empty, we can skip this image during draw (and thus // we don't need to decode it or ref it). - if (key.target_size().IsEmpty()) + if (key.target_size().IsEmpty()) { return TaskResult(false); + } base::AutoLock lock(lock_); + // If we already have the image in cache, then we can return it. + auto decoded_it = decoded_images_.Get(key); bool new_image_fits_in_memory = locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes(); + if (decoded_it != decoded_images_.end()) { + bool image_was_locked = decoded_it->second->is_locked(); + if (image_was_locked || + (new_image_fits_in_memory && decoded_it->second->Lock())) { + RefImage(key); - // Get or generate the cache entry. - auto decoded_it = decoded_images_.Get(key); - CacheEntry* cache_entry = nullptr; - if (decoded_it == decoded_images_.end()) { - // There is no reason to create a new entry if we know it won't fit anyway. - if (!new_image_fits_in_memory) - return TaskResult(false); - cache_entry = AddCacheEntry(key); - if (task_type == DecodeTaskType::USE_OUT_OF_RASTER_TASKS) - cache_entry->mark_out_of_raster(); - } else { - cache_entry = decoded_it->second.get(); - } - DCHECK(cache_entry); - - if (!cache_entry->is_budgeted) { - if (!new_image_fits_in_memory) { - // We don't need to ref anything here because this image will be at - // raster. - return TaskResult(false); + // If the image wasn't locked, then we just succeeded in locking it. + if (!image_was_locked) { + RecordLockExistingCachedImageHistogram(tracing_info.requesting_tile_bin, + true); + } + return TaskResult(true); } - AddBudgetForImage(key, cache_entry); + + // If the image fits in memory, then we at least tried to lock it and + // failed. This means that it's not valid anymore. + if (new_image_fits_in_memory) { + RecordLockExistingCachedImageHistogram(tracing_info.requesting_tile_bin, + false); + CleanupDecodedImagesCache(key, decoded_it); + } } - DCHECK(cache_entry->is_budgeted); - // The rest of the code will return either true or a task, so we should ref - // the image once now for the raster to unref. - ++cache_entry->ref_count; - - // If we already have a locked entry, then we can just use that. Otherwise - // we'll have to create a task. - if (cache_entry->is_locked) - return TaskResult(true); - - scoped_refptr<TileTask>& task = - task_type == DecodeTaskType::USE_IN_RASTER_TASKS - ? cache_entry->in_raster_task - : cache_entry->out_of_raster_task; - if (!task) { - // Ref image once for the task. - ++cache_entry->ref_count; - task = base::MakeRefCounted<ImageDecodeTaskImpl>( - this, key, image.paint_image(), task_type, tracing_info); + DCHECK(task_type == DecodeTaskType::USE_IN_RASTER_TASKS || + task_type == DecodeTaskType::USE_OUT_OF_RASTER_TASKS); + // If the task exists, return it. Note that if we always need to create a new + // task, then just set |existing_task| to reference the passed in task (which + // is set to nullptr above). + scoped_refptr<TileTask>& existing_task = + (task_type == DecodeTaskType::USE_IN_RASTER_TASKS) + ? pending_in_raster_image_tasks_[key] + : pending_out_of_raster_image_tasks_[key]; + if (existing_task) { + RefImage(key); + return TaskResult(existing_task); } - return TaskResult(task); + + // At this point, we have to create a new image/task, so we need to abort if + // it doesn't fit into memory and there are currently no raster tasks that + // would have already accounted for memory. The latter part is possible if + // there's a running raster task that could not be canceled, and still has a + // ref to the image that is now being reffed for the new schedule. + if (!new_image_fits_in_memory && (decoded_images_ref_counts_.find(key) == + decoded_images_ref_counts_.end())) { + return TaskResult(false); + } + + // Actually create the task. RefImage will account for memory on the first + // ref. + RefImage(key); + existing_task = base::MakeRefCounted<ImageDecodeTaskImpl>( + this, key, image, task_type, tracing_info); + return TaskResult(existing_task); } -void SoftwareImageDecodeCache::AddBudgetForImage(const ImageKey& key, - CacheEntry* entry) { +void SoftwareImageDecodeCache::RefImage(const ImageKey& key) { TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), - "SoftwareImageDecodeCache::AddBudgetForImage", "key", - key.ToString()); + "SoftwareImageDecodeCache::RefImage", "key", key.ToString()); lock_.AssertAcquired(); - - DCHECK(!entry->is_budgeted); - DCHECK_GE(locked_images_budget_.AvailableMemoryBytes(), key.locked_bytes()); - locked_images_budget_.AddUsage(key.locked_bytes()); - entry->is_budgeted = true; -} - -void SoftwareImageDecodeCache::RemoveBudgetForImage(const ImageKey& key, - CacheEntry* entry) { - TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), - "SoftwareImageDecodeCache::RemoveBudgetForImage", "key", - key.ToString()); - lock_.AssertAcquired(); - - DCHECK(entry->is_budgeted); - locked_images_budget_.SubtractUsage(key.locked_bytes()); - entry->is_budgeted = false; + int ref = ++decoded_images_ref_counts_[key]; + if (ref == 1) { + DCHECK_GE(locked_images_budget_.AvailableMemoryBytes(), key.locked_bytes()); + locked_images_budget_.AddUsage(key.locked_bytes()); + } } void SoftwareImageDecodeCache::UnrefImage(const DrawImage& image) { + // When we unref the image, there are several situations we need to consider: + // 1. The ref did not reach 0, which means we have to keep the image locked. + // 2. The ref reached 0, we should unlock it. + // 2a. The image isn't in the locked cache because we didn't get to decode + // it yet (or failed to decode it). + // 2b. Unlock the image but keep it in list. const ImageKey& key = ImageKey::FromDrawImage(image, color_type_); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "SoftwareImageDecodeCache::UnrefImage", "key", key.ToString()); base::AutoLock lock(lock_); - UnrefImage(key); -} + auto ref_count_it = decoded_images_ref_counts_.find(key); + DCHECK(ref_count_it != decoded_images_ref_counts_.end()); -void SoftwareImageDecodeCache::UnrefImage(const ImageKey& key) { - lock_.AssertAcquired(); - auto decoded_image_it = decoded_images_.Peek(key); - DCHECK(decoded_image_it != decoded_images_.end()); - auto* entry = decoded_image_it->second.get(); - DCHECK_GT(entry->ref_count, 0); - if (--entry->ref_count == 0) { - if (entry->is_budgeted) - RemoveBudgetForImage(key, entry); - if (entry->is_locked) - entry->Unlock(); + --ref_count_it->second; + if (ref_count_it->second == 0) { + decoded_images_ref_counts_.erase(ref_count_it); + locked_images_budget_.SubtractUsage(key.locked_bytes()); + + auto decoded_image_it = decoded_images_.Peek(key); + // If we've never decoded the image before ref reached 0, then we wouldn't + // have it in our cache. This would happen if we canceled tasks. + if (decoded_image_it == decoded_images_.end()) + return; + DCHECK(decoded_image_it->second->is_locked()); + decoded_image_it->second->Unlock(); } } -void SoftwareImageDecodeCache::DecodeImageInTask(const ImageKey& key, - const PaintImage& paint_image, - DecodeTaskType task_type) { - TRACE_EVENT1("cc", "SoftwareImageDecodeCache::DecodeImageInTask", "key", +void SoftwareImageDecodeCache::DecodeImage(const ImageKey& key, + const DrawImage& image, + DecodeTaskType task_type) { + TRACE_EVENT1("cc", "SoftwareImageDecodeCache::DecodeImage", "key", key.ToString()); base::AutoLock lock(lock_); + AutoRemoveKeyFromTaskMap remove_key_from_task_map( + (task_type == DecodeTaskType::USE_IN_RASTER_TASKS) + ? &pending_in_raster_image_tasks_ + : &pending_out_of_raster_image_tasks_, + key); + + // We could have finished all of the raster tasks (cancelled) while the task + // was just starting to run. Since this task already started running, it + // wasn't cancelled. So, if the ref count for the image is 0 then we can just + // abort. + if (decoded_images_ref_counts_.find(key) == + decoded_images_ref_counts_.end()) { + return; + } auto image_it = decoded_images_.Peek(key); - DCHECK(image_it != decoded_images_.end()); - auto* cache_entry = image_it->second.get(); - // These two checks must be true because we're running this from a task, which - // means that we've budgeted this entry when we got the task and the ref count - // is also held by the task (released in OnTaskCompleted). - DCHECK_GT(cache_entry->ref_count, 0); - DCHECK(cache_entry->is_budgeted); + if (image_it != decoded_images_.end()) { + if (image_it->second->is_locked() || image_it->second->Lock()) + return; + CleanupDecodedImagesCache(key, image_it); + } - DecodeImageIfNecessary(key, paint_image, cache_entry); - DCHECK(cache_entry->decode_failed || cache_entry->is_locked); + std::unique_ptr<DecodedImage> decoded_image; + { + base::AutoUnlock unlock(lock_); + decoded_image = DecodeImageInternal(key, image); + } + + // Abort if we failed to decode the image. + if (!decoded_image) + return; + + // At this point, it could have been the case that this image was decoded in + // place by an already running raster task from a previous schedule. If that's + // the case, then it would have already been placed into the cache (possibly + // locked). Remove it if that was the case. + image_it = decoded_images_.Peek(key); + if (image_it != decoded_images_.end()) { + if (image_it->second->is_locked() || image_it->second->Lock()) { + // Make sure to unlock the decode we did in this function. + decoded_image->Unlock(); + return; + } + CleanupDecodedImagesCache(key, image_it); + } + + // We could have finished all of the raster tasks (cancelled) while this image + // decode task was running, which means that we now have a locked image but no + // ref counts. Unlock it immediately in this case. + if (decoded_images_ref_counts_.find(key) == + decoded_images_ref_counts_.end()) { + decoded_image->Unlock(); + } + + if (task_type == DecodeTaskType::USE_OUT_OF_RASTER_TASKS) + decoded_image->mark_out_of_raster(); + RecordImageMipLevelUMA( MipMapUtil::GetLevelForSize(key.src_rect().size(), key.target_size())); + + CacheDecodedImages(key, std::move(decoded_image)); } -void SoftwareImageDecodeCache::DecodeImageIfNecessary( - const ImageKey& key, - const PaintImage& paint_image, - CacheEntry* entry) { +std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> +SoftwareImageDecodeCache::DecodeImageInternal(const ImageKey& key, + const DrawImage& draw_image) { TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), - "SoftwareImageDecodeCache::DecodeImageIfNecessary", "key", + "SoftwareImageDecodeCache::DecodeImageInternal", "key", key.ToString()); - lock_.AssertAcquired(); - DCHECK_GT(entry->ref_count, 0); - - if (key.target_size().IsEmpty()) - entry->decode_failed = true; - - if (entry->decode_failed) - return; - - if (entry->memory) { - if (entry->is_locked) - return; - - bool lock_succeeded = entry->Lock(); - // TODO(vmpstr): Deprecate the prepaint split, since it doesn't matter. - RecordLockExistingCachedImageHistogram(TilePriority::NOW, lock_succeeded); - - if (lock_succeeded) - return; - entry->memory = nullptr; - } - - const SkIRect full_size_rect = - SkIRect::MakeWH(paint_image.width(), paint_image.height()); - const bool need_subset = - (gfx::RectToSkIRect(key.src_rect()) != full_size_rect); - const SkIRect target_size_rect = - SkIRect::MakeWH(key.target_size().width(), key.target_size().height()); - - std::unique_ptr<CacheEntry> local_cache_entry; - // If this is a full size, unsubrected image, we will definitely need to do - // a decode. - if (!need_subset && target_size_rect == full_size_rect) { - base::AutoUnlock release(lock_); - local_cache_entry = DoDecodeImage(key, paint_image); - } else { - // Use the full image decode to generate a scaled/subrected decode. - // TODO(vmpstr): Change this part to find a good candidate first other - // than the full decode. Also this part needs to handle decode to scale. - base::Optional<ImageKey> candidate_key; - auto image_keys_it = frame_key_to_image_keys_.find(key.frame_key()); - // We know that we must have at least our own |entry| in this list, so it - // won't be empty. - DCHECK(image_keys_it != frame_key_to_image_keys_.end()); - - auto& available_keys = image_keys_it->second; - std::sort(available_keys.begin(), available_keys.end(), - [](const ImageKey& one, const ImageKey& two) { - // Return true if |one| scale is less than |two| scale. - return one.target_size().width() < two.target_size().width() && - one.target_size().height() < two.target_size().height(); - }); - for (auto& available_key : available_keys) { - // Only consider keys coming from the same src rect, since otherwise the - // resulting image was extracted using a different src. Only consider keys - if (available_key.src_rect() != key.src_rect()) - continue; - - // that are at least as big as the required |key|. - if (available_key.target_size().width() < key.target_size().width() || - available_key.target_size().height() < key.target_size().height()) { - continue; - } - auto image_it = decoded_images_.Peek(available_key); - DCHECK(image_it != decoded_images_.end()); - auto* available_entry = image_it->second.get(); - if (available_entry->is_locked || available_entry->Lock()) { - candidate_key.emplace(available_key); - break; - } - } - - if (!candidate_key) { - DrawImage candidate_draw_image( - paint_image, full_size_rect, kNone_SkFilterQuality, SkMatrix::I(), - key.frame_key().frame_index(), key.target_color_space()); - candidate_key.emplace( - ImageKey::FromDrawImage(candidate_draw_image, color_type_)); - } - - auto decoded_draw_image = - GetDecodedImageForDrawInternal(*candidate_key, paint_image); - - if (!decoded_draw_image.image()) { - local_cache_entry = nullptr; - } else { - base::AutoUnlock release(lock_); - local_cache_entry = - GenerateCacheEntryFromCandidate(key, decoded_draw_image); - } - - // Unref to balance the GetDecodedImageForDrawInternal() call. - UnrefImage(*candidate_key); - } - - if (!local_cache_entry) { - entry->decode_failed = true; - return; - } - - // Just in case someone else did this already, just unlock our work. - // TODO(vmpstr): It's possible to have a pending decode state where the - // thread would just block on a cv and wait for that decode to finish - // instead of actually doing the work. - if (entry->memory) { - // This would have to be locked because we hold a ref count on the entry. So - // if someone ever populated the entry with memory, they would not be able - // to unlock it. - DCHECK(entry->is_locked); - // Unlock our local memory though. - local_cache_entry->Unlock(); - } else { - local_cache_entry->MoveImageMemoryTo(entry); - DCHECK(entry->is_locked); - } -} - -std::unique_ptr<SoftwareImageDecodeCache::CacheEntry> -SoftwareImageDecodeCache::DoDecodeImage(const ImageKey& key, - const PaintImage& paint_image) { - SkISize target_size = - SkISize::Make(key.target_size().width(), key.target_size().height()); - DCHECK(target_size == paint_image.GetSupportedDecodeSize(target_size)); - - SkImageInfo target_info = CreateImageInfo(target_size, color_type_); - std::unique_ptr<base::DiscardableMemory> target_pixels = - AllocateDiscardable(target_info); - DCHECK(target_pixels); - - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), - "SoftwareImageDecodeCache::DoDecodeImage - " - "decode"); - DCHECK(!key.should_use_subrect()); - bool result = paint_image.Decode(target_pixels->data(), &target_info, - key.target_color_space().ToSkColorSpace(), - key.frame_key().frame_index()); - if (!result) { - target_pixels->Unlock(); + const PaintImage& paint_image = draw_image.paint_image(); + if (!paint_image) return nullptr; - } - return std::make_unique<CacheEntry>(target_info, std::move(target_pixels), - SkSize::Make(0, 0)); -} -std::unique_ptr<SoftwareImageDecodeCache::CacheEntry> -SoftwareImageDecodeCache::GenerateCacheEntryFromCandidate( - const ImageKey& key, - const DecodedDrawImage& candidate_image) { - SkISize target_size = + // Special case subrect into a special function. + if (key.should_use_subrect()) + return GetSubrectImageDecode(key, paint_image); + + // There are two cases where we can use the exact size image decode: + // - If we we're using full image (no subset) and we can decode natively to + // that scale, or + // - If we're not doing a scale at all (which is supported by all decoders and + // subsetting is handled in the draw calls). + // TODO(vmpstr): See if we can subrect the result of decoded to scale. + SkIRect full_size_rect = + SkIRect::MakeWH(paint_image.width(), paint_image.height()); + bool need_subset = (gfx::RectToSkIRect(key.src_rect()) != full_size_rect); + SkISize exact_size = SkISize::Make(key.target_size().width(), key.target_size().height()); - SkImageInfo target_info = CreateImageInfo(target_size, color_type_); - std::unique_ptr<base::DiscardableMemory> target_pixels = - AllocateDiscardable(target_info); - DCHECK(target_pixels); - - if (key.should_use_subrect()) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), - "SoftwareImageDecodeCache::GenerateCacheEntryFromCandidate - " - "subrect"); - bool result = candidate_image.image()->readPixels( - target_info, target_pixels->data(), target_info.minRowBytes(), - key.src_rect().x(), key.src_rect().y(), SkImage::kDisallow_CachingHint); - // We have a decoded image, and we're reading into already allocated memory. - // This should never fail. - DCHECK(result); - return std::make_unique<CacheEntry>( - target_info.makeColorSpace(candidate_image.image()->refColorSpace()), - std::move(target_pixels), - SkSize::Make(-key.src_rect().x(), -key.src_rect().y())); + // TODO(vmpstr): If an image of a bigger size is already decoded and is + // lock-able then it might be faster to just scale that instead of redecoding + // to exact scale. We need to profile this. + if ((!need_subset && + exact_size == paint_image.GetSupportedDecodeSize(exact_size)) || + SkIRect::MakeSize(exact_size) == full_size_rect) { + return GetExactSizeImageDecode(key, paint_image); } - - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), - "SoftwareImageDecodeCache::GenerateCacheEntryFromCandidate - " - "scale"); - SkPixmap decoded_pixmap; - bool result = candidate_image.image()->peekPixels(&decoded_pixmap); - result = result && decoded_pixmap.extractSubset( - &decoded_pixmap, gfx::RectToSkIRect(key.src_rect())); - DCHECK(result) << key.ToString(); - - SkPixmap target_pixmap(target_info, target_pixels->data(), - target_info.minRowBytes()); - result = decoded_pixmap.scalePixels(target_pixmap, key.filter_quality()); - DCHECK(result) << key.ToString(); - return std::make_unique<CacheEntry>( - target_info.makeColorSpace(candidate_image.image()->refColorSpace()), - std::move(target_pixels), - SkSize::Make(-key.src_rect().x(), -key.src_rect().y())); + return GetScaledImageDecode(key, paint_image); } DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDraw( const DrawImage& draw_image) { - base::AutoLock hold(lock_); - return GetDecodedImageForDrawInternal( - ImageKey::FromDrawImage(draw_image, color_type_), - draw_image.paint_image()); + ImageKey key = ImageKey::FromDrawImage(draw_image, color_type_); + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "SoftwareImageDecodeCache::GetDecodedImageForDraw", "key", + key.ToString()); + // If the target size is empty, we can skip this image draw. + if (key.target_size().IsEmpty()) + return DecodedDrawImage(nullptr, kNone_SkFilterQuality); + + return GetDecodedImageForDrawInternal(key, draw_image); } DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDrawInternal( const ImageKey& key, - const PaintImage& paint_image) { + const DrawImage& draw_image) { TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "SoftwareImageDecodeCache::GetDecodedImageForDrawInternal", "key", key.ToString()); - lock_.AssertAcquired(); - auto decoded_it = decoded_images_.Get(key); - CacheEntry* cache_entry = nullptr; - if (decoded_it == decoded_images_.end()) - cache_entry = AddCacheEntry(key); - else - cache_entry = decoded_it->second.get(); + base::AutoLock lock(lock_); + auto decoded_images_it = decoded_images_.Get(key); + // If we found the image and it's locked, then return it. If it's not locked, + // erase it from the cache since it might be put into the at-raster cache. + std::unique_ptr<DecodedImage> scoped_decoded_image; + DecodedImage* decoded_image = nullptr; + if (decoded_images_it != decoded_images_.end()) { + decoded_image = decoded_images_it->second.get(); + if (decoded_image->is_locked()) { + RefImage(key); + decoded_image->mark_used(); + return DecodedDrawImage( + decoded_image->image(), decoded_image->src_rect_offset(), + GetScaleAdjustment(key), GetDecodedFilterQuality(key)); + } else { + scoped_decoded_image = std::move(decoded_images_it->second); + CleanupDecodedImagesCache(key, decoded_images_it); + } + } - // We'll definitely ref this cache entry and use it. - ++cache_entry->ref_count; - cache_entry->mark_used(); + // See if another thread already decoded this image at raster time. If so, we + // can just use that result directly. + auto at_raster_images_it = at_raster_decoded_images_.Get(key); + if (at_raster_images_it != at_raster_decoded_images_.end()) { + DCHECK(at_raster_images_it->second->is_locked()); + RefAtRasterImage(key); + DecodedImage* at_raster_decoded_image = at_raster_images_it->second.get(); + at_raster_decoded_image->mark_used(); + auto decoded_draw_image = + DecodedDrawImage(at_raster_decoded_image->image(), + at_raster_decoded_image->src_rect_offset(), + GetScaleAdjustment(key), GetDecodedFilterQuality(key)); + decoded_draw_image.set_at_raster_decode(true); + return decoded_draw_image; + } - DecodeImageIfNecessary(key, paint_image, cache_entry); + // Now we know that we don't have a locked image, and we seem to be the first + // thread encountering this image (that might not be true, since other threads + // might be decoding it already). This means that we need to decode the image + // assuming we can't lock the one we found in the cache. + bool check_at_raster_cache = false; + if (!decoded_image || !decoded_image->Lock()) { + // Note that we have to release the lock, since this lock is also accessed + // on the compositor thread. This means holding on to the lock might stall + // the compositor thread for the duration of the decode! + base::AutoUnlock unlock(lock_); + scoped_decoded_image = DecodeImageInternal(key, draw_image); + decoded_image = scoped_decoded_image.get(); + + // Skip the image if we couldn't decode it. + if (!decoded_image) + return DecodedDrawImage(nullptr, kNone_SkFilterQuality); + check_at_raster_cache = true; + } + + DCHECK(decoded_image == scoped_decoded_image.get()); + + // While we unlocked the lock, it could be the case that another thread + // already decoded this already and put it in the at-raster cache. Look it up + // first. + if (check_at_raster_cache) { + at_raster_images_it = at_raster_decoded_images_.Get(key); + if (at_raster_images_it != at_raster_decoded_images_.end()) { + // We have to drop our decode, since the one in the cache is being used by + // another thread. + decoded_image->Unlock(); + decoded_image = at_raster_images_it->second.get(); + scoped_decoded_image = nullptr; + } + } + + // If we really are the first ones, or if the other thread already unlocked + // the image, then put our work into at-raster time cache. + if (scoped_decoded_image) + at_raster_decoded_images_.Put(key, std::move(scoped_decoded_image)); + + DCHECK(decoded_image); + DCHECK(decoded_image->is_locked()); + RefAtRasterImage(key); + decoded_image->mark_used(); auto decoded_draw_image = - DecodedDrawImage(cache_entry->image(), cache_entry->src_rect_offset(), + DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(), GetScaleAdjustment(key), GetDecodedFilterQuality(key)); - decoded_draw_image.set_at_raster_decode(!cache_entry->is_budgeted); + decoded_draw_image.set_at_raster_decode(true); return decoded_draw_image; } +std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> +SoftwareImageDecodeCache::GetExactSizeImageDecode( + const ImageKey& key, + const PaintImage& paint_image) { + SkISize decode_size = + SkISize::Make(key.target_size().width(), key.target_size().height()); + DCHECK(decode_size == paint_image.GetSupportedDecodeSize(decode_size)); + + SkImageInfo decoded_info = + paint_image.CreateDecodeImageInfo(decode_size, color_type_); + + std::unique_ptr<base::DiscardableMemory> decoded_pixels; + { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "SoftwareImageDecodeCache::GetOriginalSizeImageDecode - " + "allocate decoded pixels"); + decoded_pixels = + base::DiscardableMemoryAllocator::GetInstance() + ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() * + decoded_info.height()); + } + { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "SoftwareImageDecodeCache::GetOriginalSizeImageDecode - " + "decode"); + bool result = paint_image.Decode(decoded_pixels->data(), &decoded_info, + key.target_color_space().ToSkColorSpace(), + key.frame_key().frame_index()); + if (!result) { + decoded_pixels->Unlock(); + return nullptr; + } + } + + return std::make_unique<DecodedImage>(decoded_info, std::move(decoded_pixels), + SkSize::Make(0, 0)); +} + +std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> +SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key, + const PaintImage& image) { + // Construct a key to use in GetDecodedImageForDrawInternal(). + // This allows us to reuse an image in any cache if available. + // This uses the original sized image, since when we're subrecting, there is + // no scale. + // TODO(vmpstr): This doesn't have to be true, but the Key generation makes it + // so. We could also subrect scaled images. + SkIRect exact_size_rect = SkIRect::MakeWH(image.width(), image.height()); + DrawImage exact_size_draw_image(image, exact_size_rect, kNone_SkFilterQuality, + SkMatrix::I(), key.frame_key().frame_index(), + key.target_color_space()); + ImageKey exact_size_key = + ImageKey::FromDrawImage(exact_size_draw_image, color_type_); + +// Sanity checks. +#if DCHECK_IS_ON() + SkISize exact_target_size = + SkISize::Make(exact_size_key.target_size().width(), + exact_size_key.target_size().height()); + DCHECK(image.GetSupportedDecodeSize(exact_target_size) == exact_target_size); + DCHECK(!exact_size_key.should_use_subrect()); +#endif + + auto decoded_draw_image = + GetDecodedImageForDrawInternal(exact_size_key, exact_size_draw_image); + AutoDrawWithImageFinished auto_finish_draw(this, exact_size_draw_image, + decoded_draw_image); + if (!decoded_draw_image.image()) + return nullptr; + + DCHECK(SkColorSpace::Equals(decoded_draw_image.image()->colorSpace(), + key.target_color_space().ToSkColorSpace().get())); + SkImageInfo subrect_info = CreateImageInfo( + key.target_size().width(), key.target_size().height(), color_type_); + std::unique_ptr<base::DiscardableMemory> subrect_pixels; + { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "SoftwareImageDecodeCache::GetSubrectImageDecode - " + "allocate subrect pixels"); + // TODO(vmpstr): This is using checked math to diagnose a problem reported + // in crbug.com/662217. If this is causing crashes, then it should be fixed + // elsewhere by skipping images that are too large. + base::CheckedNumeric<size_t> byte_size = subrect_info.minRowBytes(); + byte_size *= subrect_info.height(); + subrect_pixels = + base::DiscardableMemoryAllocator::GetInstance() + ->AllocateLockedDiscardableMemory(byte_size.ValueOrDie()); + } + { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "SoftwareImageDecodeCache::GetSubrectImageDecode - " + "read pixels"); + bool result = decoded_draw_image.image()->readPixels( + subrect_info, subrect_pixels->data(), subrect_info.minRowBytes(), + key.src_rect().x(), key.src_rect().y(), SkImage::kDisallow_CachingHint); + // We have a decoded image, and we're reading into already allocated memory. + // This should never fail. + DCHECK(result); + } + + return std::make_unique<DecodedImage>( + subrect_info.makeColorSpace(decoded_draw_image.image()->refColorSpace()), + std::move(subrect_pixels), + SkSize::Make(-key.src_rect().x(), -key.src_rect().y())); +} + +std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> +SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key, + const PaintImage& image) { + // Construct a key to use in GetDecodedImageForDrawInternal(). + // This allows us to reuse an image in any cache if available. + // TODO(vmpstr): If we're using a subrect, then we need to decode the original + // image and subset it since the subset might be strict. If we plumb whether + // the subrect is strict or not, we can loosen this condition. + SkIRect full_size_rect = SkIRect::MakeWH(image.width(), image.height()); + bool need_subset = (gfx::RectToSkIRect(key.src_rect()) != full_size_rect); + SkIRect exact_size_rect = + need_subset + ? full_size_rect + : SkIRect::MakeSize(image.GetSupportedDecodeSize(SkISize::Make( + key.target_size().width(), key.target_size().height()))); + + DrawImage exact_size_draw_image(image, exact_size_rect, kNone_SkFilterQuality, + SkMatrix::I(), key.frame_key().frame_index(), + key.target_color_space()); + ImageKey exact_size_key = + ImageKey::FromDrawImage(exact_size_draw_image, color_type_); + +// Sanity checks. +#if DCHECK_IS_ON() + SkISize exact_target_size = + SkISize::Make(exact_size_key.target_size().width(), + exact_size_key.target_size().height()); + DCHECK(image.GetSupportedDecodeSize(exact_target_size) == exact_target_size); + DCHECK(!need_subset || exact_size_key.target_size() == + gfx::Size(image.width(), image.height())); + DCHECK(!exact_size_key.should_use_subrect()); +#endif + + auto decoded_draw_image = + GetDecodedImageForDrawInternal(exact_size_key, exact_size_draw_image); + AutoDrawWithImageFinished auto_finish_draw(this, exact_size_draw_image, + decoded_draw_image); + if (!decoded_draw_image.image()) + return nullptr; + + SkPixmap decoded_pixmap; + bool result = decoded_draw_image.image()->peekPixels(&decoded_pixmap); + DCHECK(result) << key.ToString(); + if (need_subset) { + result = decoded_pixmap.extractSubset(&decoded_pixmap, + gfx::RectToSkIRect(key.src_rect())); + DCHECK(result) << key.ToString(); + } + + DCHECK(!key.target_size().IsEmpty()); + DCHECK(SkColorSpace::Equals(decoded_draw_image.image()->colorSpace(), + key.target_color_space().ToSkColorSpace().get())); + SkImageInfo scaled_info = CreateImageInfo( + key.target_size().width(), key.target_size().height(), color_type_); + std::unique_ptr<base::DiscardableMemory> scaled_pixels; + { + TRACE_EVENT0( + TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "SoftwareImageDecodeCache::ScaleImage - allocate scaled pixels"); + scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() + ->AllocateLockedDiscardableMemory( + scaled_info.minRowBytes() * scaled_info.height()); + } + SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), + scaled_info.minRowBytes()); + DCHECK(key.filter_quality() == kMedium_SkFilterQuality); + { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "SoftwareImageDecodeCache::ScaleImage - scale pixels"); + bool result = + decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); + DCHECK(result) << key.ToString(); + } + + return std::make_unique<DecodedImage>( + scaled_info.makeColorSpace(decoded_draw_image.image()->refColorSpace()), + std::move(scaled_pixels), + SkSize::Make(-key.src_rect().x(), -key.src_rect().y())); +} + void SoftwareImageDecodeCache::DrawWithImageFinished( const DrawImage& image, const DecodedDrawImage& decoded_image) { TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "SoftwareImageDecodeCache::DrawWithImageFinished", "key", ImageKey::FromDrawImage(image, color_type_).ToString()); - UnrefImage(image); + ImageKey key = ImageKey::FromDrawImage(image, color_type_); + if (!decoded_image.image()) + return; + + if (decoded_image.is_at_raster_decode()) + UnrefAtRasterImage(key); + else + UnrefImage(image); +} + +void SoftwareImageDecodeCache::RefAtRasterImage(const ImageKey& key) { + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "SoftwareImageDecodeCache::RefAtRasterImage", "key", + key.ToString()); + DCHECK(at_raster_decoded_images_.Peek(key) != + at_raster_decoded_images_.end()); + ++at_raster_decoded_images_ref_counts_[key]; +} + +void SoftwareImageDecodeCache::UnrefAtRasterImage(const ImageKey& key) { + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "SoftwareImageDecodeCache::UnrefAtRasterImage", "key", + key.ToString()); + base::AutoLock lock(lock_); + + auto ref_it = at_raster_decoded_images_ref_counts_.find(key); + DCHECK(ref_it != at_raster_decoded_images_ref_counts_.end()); + --ref_it->second; + if (ref_it->second == 0) { + at_raster_decoded_images_ref_counts_.erase(ref_it); + auto at_raster_image_it = at_raster_decoded_images_.Peek(key); + DCHECK(at_raster_image_it != at_raster_decoded_images_.end()); + + // The ref for our image reached 0 and it's still locked. We need to figure + // out what the best thing to do with the image. There are several + // situations: + // 1. The image is not in the main cache and... + // 1a. ... its ref count is 0: unlock our image and put it in the main + // cache. + // 1b. ... ref count is not 0: keep the image locked and put it in the + // main cache. + // 2. The image is in the main cache... + // 2a. ... and is locked: unlock our image and discard it + // 2b. ... and is unlocked and... + // 2b1. ... its ref count is 0: unlock our image and replace the + // existing one with ours. + // 2b2. ... its ref count is not 0: this shouldn't be possible. + auto image_it = decoded_images_.Peek(key); + if (image_it == decoded_images_.end()) { + if (decoded_images_ref_counts_.find(key) == + decoded_images_ref_counts_.end()) { + at_raster_image_it->second->Unlock(); + } + CacheDecodedImages(key, std::move(at_raster_image_it->second)); + } else if (image_it->second->is_locked()) { + at_raster_image_it->second->Unlock(); + } else { + DCHECK(decoded_images_ref_counts_.find(key) == + decoded_images_ref_counts_.end()); + at_raster_image_it->second->Unlock(); + // Access decoded_images_ directly here to avoid deletion and entry + // of same key in ImageKey vector of decoded_images_unique_ids_. + decoded_images_.Erase(image_it); + decoded_images_.Put(key, std::move(at_raster_image_it->second)); + } + at_raster_decoded_images_.Erase(at_raster_image_it); + } } void SoftwareImageDecodeCache::ReduceCacheUsageUntilWithinLimit(size_t limit) { @@ -614,23 +851,17 @@ "SoftwareImageDecodeCache::ReduceCacheUsageUntilWithinLimit"); lifetime_max_items_in_cache_ = std::max(lifetime_max_items_in_cache_, decoded_images_.size()); + size_t num_to_remove = + (decoded_images_.size() > limit) ? (decoded_images_.size() - limit) : 0; for (auto it = decoded_images_.rbegin(); - decoded_images_.size() > limit && it != decoded_images_.rend();) { - if (it->second->ref_count != 0) { + num_to_remove != 0 && it != decoded_images_.rend();) { + if (it->second->is_locked()) { ++it; continue; } - const ImageKey& key = it->first; - auto vector_it = frame_key_to_image_keys_.find(key.frame_key()); - auto item_it = - std::find(vector_it->second.begin(), vector_it->second.end(), key); - DCHECK(item_it != vector_it->second.end()); - vector_it->second.erase(item_it); - if (vector_it->second.empty()) - frame_key_to_image_keys_.erase(vector_it); - it = decoded_images_.Erase(it); + --num_to_remove; } } @@ -656,37 +887,29 @@ if (it == frame_key_to_image_keys_.end()) return; - for (auto key_it = it->second.begin(); key_it != it->second.end();) { + for (auto key = it->second.begin(); key != it->second.end(); ++key) { // This iterates over the ImageKey vector for the given skimage_id, // and deletes all entries from decoded_images_ corresponding to the // skimage_id. - auto image_it = decoded_images_.Peek(*key_it); - // TODO(sohanjg): Find an optimized way to cleanup locked images. - if (image_it != decoded_images_.end() && image_it->second->ref_count == 0) { + auto image_it = decoded_images_.Peek(*key); + // TODO(sohanjg) :Find an optimized way to cleanup locked images. + if (image_it != decoded_images_.end() && !image_it->second->is_locked()) decoded_images_.Erase(image_it); - key_it = it->second.erase(key_it); - } else { - ++key_it; - } } - if (it->second.empty()) - frame_key_to_image_keys_.erase(it); + frame_key_to_image_keys_.erase(it); } -void SoftwareImageDecodeCache::OnImageDecodeTaskCompleted( - const ImageKey& key, - DecodeTaskType task_type) { - base::AutoLock hold(lock_); - - auto image_it = decoded_images_.Peek(key); - DCHECK(image_it != decoded_images_.end()); - CacheEntry* cache_entry = image_it->second.get(); - auto& task = task_type == DecodeTaskType::USE_IN_RASTER_TASKS - ? cache_entry->in_raster_task - : cache_entry->out_of_raster_task; - task = nullptr; - - UnrefImage(key); +void SoftwareImageDecodeCache::RemovePendingTask(const ImageKey& key, + DecodeTaskType task_type) { + base::AutoLock lock(lock_); + switch (task_type) { + case DecodeTaskType::USE_IN_RASTER_TASKS: + pending_in_raster_image_tasks_.erase(key); + break; + case DecodeTaskType::USE_OUT_OF_RASTER_TASKS: + pending_out_of_raster_image_tasks_.erase(key); + break; + } } bool SoftwareImageDecodeCache::OnMemoryDump( @@ -701,37 +924,40 @@ dump->AddScalar("locked_size", MemoryAllocatorDump::kUnitsBytes, locked_images_budget_.GetCurrentUsageSafe()); } else { - for (const auto& image_pair : decoded_images_) { - int image_id = static_cast<int>(image_pair.first.frame_key().hash()); - CacheEntry* entry = image_pair.second.get(); - DCHECK(entry); - // We might not have memory for this cache entry, depending on where int - // he CacheEntry lifecycle we are. If we don't have memory, then we don't - // have to record it in the dump. - if (!entry->memory) - continue; - - std::string dump_name = base::StringPrintf( - "cc/image_memory/cache_0x%" PRIXPTR "/%s/image_%" PRIu64 "_id_%d", - reinterpret_cast<uintptr_t>(this), - entry->is_budgeted ? "budgeted" : "at_raster", entry->tracing_id(), - image_id); - // CreateMemoryAllocatorDump will automatically add tracking values for - // the total size. We also add a "locked_size" below. - MemoryAllocatorDump* dump = - entry->memory->CreateMemoryAllocatorDump(dump_name.c_str(), pmd); - DCHECK(dump); - size_t locked_bytes = - entry->is_locked ? image_pair.first.locked_bytes() : 0u; - dump->AddScalar("locked_size", MemoryAllocatorDump::kUnitsBytes, - locked_bytes); - } + // Dump each of our caches. + DumpImageMemoryForCache(decoded_images_, "cached", pmd); + DumpImageMemoryForCache(at_raster_decoded_images_, "at_raster", pmd); } // Memory dump can't fail, always return true. return true; } +void SoftwareImageDecodeCache::DumpImageMemoryForCache( + const ImageMRUCache& cache, + const char* cache_name, + base::trace_event::ProcessMemoryDump* pmd) const { + lock_.AssertAcquired(); + + for (const auto& image_pair : cache) { + int image_id = static_cast<int>(image_pair.first.frame_key().hash()); + std::string dump_name = base::StringPrintf( + "cc/image_memory/cache_0x%" PRIXPTR "/%s/image_%" PRIu64 "_id_%d", + reinterpret_cast<uintptr_t>(this), cache_name, + image_pair.second->tracing_id(), image_id); + // CreateMemoryAllocatorDump will automatically add tracking values for the + // total size. We also add a "locked_size" below. + MemoryAllocatorDump* dump = + image_pair.second->memory()->CreateMemoryAllocatorDump( + dump_name.c_str(), pmd); + DCHECK(dump); + size_t locked_bytes = + image_pair.second->is_locked() ? image_pair.first.locked_bytes() : 0u; + dump->AddScalar("locked_size", MemoryAllocatorDump::kUnitsBytes, + locked_bytes); + } +} + // SoftwareImageDecodeCacheKey ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image, SkColorType color_type) { @@ -882,26 +1108,23 @@ return str.str(); } -// CacheEntry -SoftwareImageDecodeCache::CacheEntry::CacheEntry() - : tracing_id_(g_next_tracing_id_.GetNext()) {} -SoftwareImageDecodeCache::CacheEntry::CacheEntry( +// DecodedImage +SoftwareImageDecodeCache::DecodedImage::DecodedImage( const SkImageInfo& info, - std::unique_ptr<base::DiscardableMemory> in_memory, + std::unique_ptr<base::DiscardableMemory> memory, const SkSize& src_rect_offset) - : is_locked(true), - memory(std::move(in_memory)), + : locked_(true), image_info_(info), + memory_(std::move(memory)), src_rect_offset_(src_rect_offset), tracing_id_(g_next_tracing_id_.GetNext()) { - DCHECK(memory); - SkPixmap pixmap(image_info_, memory->data(), image_info_.minRowBytes()); + SkPixmap pixmap(image_info_, memory_->data(), image_info_.minRowBytes()); image_ = SkImage::MakeFromRaster( pixmap, [](const void* pixels, void* context) {}, nullptr); } -SoftwareImageDecodeCache::CacheEntry::~CacheEntry() { - DCHECK(!is_locked); +SoftwareImageDecodeCache::DecodedImage::~DecodedImage() { + DCHECK(!locked_); // lock_count | used | last lock failed | result state // ===========+=======+==================+================== // 1 | false | false | WASTED @@ -947,44 +1170,22 @@ usage_stats_.first_lock_wasted); } -void SoftwareImageDecodeCache::CacheEntry::MoveImageMemoryTo( - CacheEntry* entry) { - DCHECK(!is_budgeted); - DCHECK_EQ(ref_count, 0); - - // Copy/move most things except budgeted and ref counts. - entry->decode_failed = decode_failed; - entry->is_locked = is_locked; - is_locked = false; - - entry->memory = std::move(memory); - entry->image_info_ = std::move(image_info_); - entry->src_rect_offset_ = std::move(src_rect_offset_); - entry->image_ = std::move(image_); -} - -bool SoftwareImageDecodeCache::CacheEntry::Lock() { - if (!memory) - return false; - - DCHECK(!is_locked); - bool success = memory->Lock(); +bool SoftwareImageDecodeCache::DecodedImage::Lock() { + DCHECK(!locked_); + bool success = memory_->Lock(); if (!success) { usage_stats_.last_lock_failed = true; return false; } - is_locked = true; + locked_ = true; ++usage_stats_.lock_count; return true; } -void SoftwareImageDecodeCache::CacheEntry::Unlock() { - if (!memory) - return; - - DCHECK(is_locked); - memory->Unlock(); - is_locked = false; +void SoftwareImageDecodeCache::DecodedImage::Unlock() { + DCHECK(locked_); + memory_->Unlock(); + locked_ = false; if (usage_stats_.lock_count == 1) usage_stats_.first_lock_wasted = !usage_stats_.used; } @@ -1040,12 +1241,31 @@ ReduceCacheUsageUntilWithinLimit(0); } -SoftwareImageDecodeCache::CacheEntry* SoftwareImageDecodeCache::AddCacheEntry( - const ImageKey& key) { +void SoftwareImageDecodeCache::CleanupDecodedImagesCache( + const ImageKey& key, + ImageMRUCache::iterator it) { + lock_.AssertAcquired(); + auto vector_it = frame_key_to_image_keys_.find(key.frame_key()); + + // TODO(sohanjg): Check if we can DCHECK here. + if (vector_it != frame_key_to_image_keys_.end()) { + auto iter = + std::find(vector_it->second.begin(), vector_it->second.end(), key); + DCHECK(iter != vector_it->second.end()); + vector_it->second.erase(iter); + if (vector_it->second.empty()) + frame_key_to_image_keys_.erase(vector_it); + } + + decoded_images_.Erase(it); +} + +void SoftwareImageDecodeCache::CacheDecodedImages( + const ImageKey& key, + std::unique_ptr<DecodedImage> decoded_image) { lock_.AssertAcquired(); frame_key_to_image_keys_[key.frame_key()].push_back(key); - auto it = decoded_images_.Put(key, std::make_unique<CacheEntry>()); - return it->second.get(); + decoded_images_.Put(key, std::move(decoded_image)); } } // namespace cc
diff --git a/cc/tiles/software_image_decode_cache.h b/cc/tiles/software_image_decode_cache.h index 7ac4d1f..120df10 100644 --- a/cc/tiles/software_image_decode_cache.h +++ b/cc/tiles/software_image_decode_cache.h
@@ -142,12 +142,11 @@ // Decode the given image and store it in the cache. This is only called by an // image decode task from a worker thread. - void DecodeImageInTask(const ImageKey& key, - const PaintImage& paint_image, - DecodeTaskType task_type); + void DecodeImage(const ImageKey& key, + const DrawImage& image, + DecodeTaskType task_type); - void OnImageDecodeTaskCompleted(const ImageKey& key, - DecodeTaskType task_type); + void RemovePendingTask(const ImageKey& key, DecodeTaskType task_type); // MemoryDumpProvider overrides. bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, @@ -156,30 +155,29 @@ size_t GetNumCacheEntriesForTesting() const { return decoded_images_.size(); } private: - // CacheEntry is a convenience storage for discardable memory. It can also + // DecodedImage is a convenience storage for discardable memory. It can also // construct an image out of SkImageInfo and stored discardable memory. - class CacheEntry { + class DecodedImage { public: - CacheEntry(); - CacheEntry(const SkImageInfo& info, - std::unique_ptr<base::DiscardableMemory> memory, - const SkSize& src_rect_offset); - ~CacheEntry(); + DecodedImage(const SkImageInfo& info, + std::unique_ptr<base::DiscardableMemory> memory, + const SkSize& src_rect_offset); + ~DecodedImage(); - void MoveImageMemoryTo(CacheEntry* entry); - - sk_sp<SkImage> image() const { - if (!memory) - return nullptr; - DCHECK(is_locked); + const sk_sp<SkImage>& image() const { + DCHECK(locked_); return image_; } + const SkSize& src_rect_offset() const { return src_rect_offset_; } + bool is_locked() const { return locked_; } bool Lock(); void Unlock(); - // An ID which uniquely identifies this CacheEntry within the image decode + const base::DiscardableMemory* memory() const { return memory_.get(); } + + // An ID which uniquely identifies this DecodedImage within the image decode // cache. Used in memory tracing. uint64_t tracing_id() const { return tracing_id_; } // Mark this image as being used in either a draw or as a source for a @@ -188,21 +186,6 @@ void mark_used() { usage_stats_.used = true; } void mark_out_of_raster() { usage_stats_.first_lock_out_of_raster = true; } - // Since this is an inner class, we expose these variables publicly for - // simplicity. - // TODO(vmpstr): A good simple clean-up would be to rethink this class - // and its interactions to instead expose a few functions which would also - // facilitate easier DCHECKs. - int ref_count = 0; - bool decode_failed = false; - bool is_locked = false; - bool is_budgeted = false; - - scoped_refptr<TileTask> in_raster_task; - scoped_refptr<TileTask> out_of_raster_task; - - std::unique_ptr<base::DiscardableMemory> memory; - private: struct UsageStats { // We can only create a decoded image in a locked state, so the initial @@ -214,7 +197,9 @@ bool first_lock_out_of_raster = false; }; + bool locked_; SkImageInfo image_info_; + std::unique_ptr<base::DiscardableMemory> memory_; sk_sp<SkImage> image_; SkSize src_rect_offset_; uint64_t tracing_id_; @@ -240,22 +225,62 @@ }; using ImageMRUCache = base:: - HashingMRUCache<ImageKey, std::unique_ptr<CacheEntry>, ImageKeyHash>; + HashingMRUCache<ImageKey, std::unique_ptr<DecodedImage>, ImageKeyHash>; + + // Looks for the key in the cache and returns true if it was found and was + // successfully locked (or if it was already locked). Note that if this + // function returns true, then a ref count is increased for the image. + bool LockDecodedImageIfPossibleAndRef(const ImageKey& key); // Actually decode the image. Note that this function can (and should) be // called with no lock acquired, since it can do a lot of work. Note that it // can also return nullptr to indicate the decode failed. - std::unique_ptr<CacheEntry> DecodeImageInternal(const ImageKey& key, + std::unique_ptr<DecodedImage> DecodeImageInternal( + const ImageKey& key, + const DrawImage& draw_image); + + // Get the decoded draw image for the given key and draw_image. Note that this + // function has to be called with no lock acquired, since it will acquire its + // own locks and might call DecodeImageInternal above. Also note that this + // function will use the provided key, even if + // ImageKey::FromDrawImage(draw_image) would return a different key. + // Note that when used internally, we still require that + // DrawWithImageFinished() is called afterwards. + DecodedDrawImage GetDecodedImageForDrawInternal(const ImageKey& key, const DrawImage& draw_image); - // Get the decoded draw image for the given key and paint_image. Note that - // this function has to be called with no lock acquired, since it will acquire - // its own locks and might call DecodeImageInternal above. Note that - // when used internally, we still require that DrawWithImageFinished() is - // called afterwards. - DecodedDrawImage GetDecodedImageForDrawInternal( + // GetExactSizeImageDecode is called by DecodeImageInternal when the + // quality does not scale the image. Like DecodeImageInternal, it should be + // called with no lock acquired and it returns nullptr if the decoding failed. + std::unique_ptr<DecodedImage> GetExactSizeImageDecode( const ImageKey& key, - const PaintImage& paint_image); + const PaintImage& image); + + // GetSubrectImageDecode is similar to GetExactSizeImageDecode in that the + // image is decoded to exact scale. However, we extract a subrect (copy it + // out) and only return this subrect in order to cache a smaller amount of + // memory. Note that this uses GetExactSizeImageDecode to get the initial + // data, which ensures that we cache an unlocked version of the original image + // in case we need to extract multiple subrects (as would be the case in an + // atlas). + std::unique_ptr<DecodedImage> GetSubrectImageDecode(const ImageKey& key, + const PaintImage& image); + + // GetScaledImageDecode is called by DecodeImageInternal when the quality + // requires the image be scaled. Like DecodeImageInternal, it should be + // called with no lock acquired and it returns nullptr if the decoding or + // scaling failed. + std::unique_ptr<DecodedImage> GetScaledImageDecode(const ImageKey& key, + const PaintImage& image); + + void RefImage(const ImageKey& key); + void RefAtRasterImage(const ImageKey& key); + void UnrefAtRasterImage(const ImageKey& key); + + // Helper function which dumps all images in a specific ImageMRUCache. + void DumpImageMemoryForCache(const ImageMRUCache& cache, + const char* cache_name, + base::trace_event::ProcessMemoryDump* pmd) const; // Removes unlocked decoded images until the number of decoded images is // reduced within the given limit. @@ -271,21 +296,10 @@ const TracingInfo& tracing_info, DecodeTaskType type); - CacheEntry* AddCacheEntry(const ImageKey& key); - - void DecodeImageIfNecessary(const ImageKey& key, - const PaintImage& paint_image, - CacheEntry* cache_entry); - void AddBudgetForImage(const ImageKey& key, CacheEntry* entry); - void RemoveBudgetForImage(const ImageKey& key, CacheEntry* entry); - - std::unique_ptr<CacheEntry> DoDecodeImage(const ImageKey& key, - const PaintImage& image); - std::unique_ptr<CacheEntry> GenerateCacheEntryFromCandidate( - const ImageKey& key, - const DecodedDrawImage& candidate); - - void UnrefImage(const ImageKey& key); + void CacheDecodedImages(const ImageKey& key, + std::unique_ptr<DecodedImage> decoded_image); + void CleanupDecodedImagesCache(const ImageKey& key, + ImageMRUCache::iterator it); std::unordered_map<ImageKey, scoped_refptr<TileTask>, ImageKeyHash> pending_in_raster_image_tasks_; @@ -300,6 +314,7 @@ // Decoded images and ref counts (predecode path). ImageMRUCache decoded_images_; + std::unordered_map<ImageKey, int, ImageKeyHash> decoded_images_ref_counts_; // A map of PaintImage::FrameKey to the ImageKeys for cached decodes of this // PaintImage. @@ -308,6 +323,11 @@ PaintImage::FrameKeyHash> frame_key_to_image_keys_; + // Decoded image and ref counts (at-raster decode path). + ImageMRUCache at_raster_decoded_images_; + std::unordered_map<ImageKey, int, ImageKeyHash> + at_raster_decoded_images_ref_counts_; + MemoryBudget locked_images_budget_; SkColorType color_type_;
diff --git a/cc/tiles/software_image_decode_cache_unittest.cc b/cc/tiles/software_image_decode_cache_unittest.cc index 24f8ade..c5e0ff91 100644 --- a/cc/tiles/software_image_decode_cache_unittest.cc +++ b/cc/tiles/software_image_decode_cache_unittest.cc
@@ -654,36 +654,6 @@ cache.UnrefImage(draw_image); } -TEST(SoftwareImageDecodeCacheTest, GetTaskForImageProcessUnrefCancel) { - TestSoftwareImageDecodeCache cache; - PaintImage paint_image = CreatePaintImage(100, 100); - bool is_decomposable = true; - SkFilterQuality quality = kHigh_SkFilterQuality; - - DrawImage draw_image( - paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()), - quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - ImageDecodeCache::TaskResult result = - cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result.need_unref); - EXPECT_TRUE(result.task); - - TestTileTaskRunner::ProcessTask(result.task.get()); - cache.UnrefImage(draw_image); - - result = - cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result.need_unref); - EXPECT_TRUE(result.task); - - TestTileTaskRunner::CancelTask(result.task.get()); - TestTileTaskRunner::CompleteTask(result.task.get()); - // This is expected to pass instead of DCHECKing since we're reducing the ref - // for an image which isn't locked to begin with. - cache.UnrefImage(draw_image); -} - TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentQuality) { TestSoftwareImageDecodeCache cache; PaintImage paint_image = CreatePaintImage(100, 100); @@ -1112,6 +1082,97 @@ cache.DrawWithImageFinished(draw_image, another_decoded_draw_image); } +TEST(SoftwareImageDecodeCacheTest, + GetDecodedImageForDrawAtRasterDecodeDoesNotPreventTasks) { + TestSoftwareImageDecodeCache cache; + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + PaintImage paint_image = CreatePaintImage(100, 100); + DrawImage draw_image( + paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()), + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + PaintImage::kDefaultFrameIndex, DefaultColorSpace()); + + DecodedDrawImage decoded_draw_image = + cache.GetDecodedImageForDraw(draw_image); + EXPECT_TRUE(decoded_draw_image.image()); + EXPECT_EQ(50, decoded_draw_image.image()->width()); + EXPECT_EQ(50, decoded_draw_image.image()->height()); + EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width()); + EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height()); + EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality()); + EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity()); + EXPECT_TRUE(decoded_draw_image.is_at_raster_decode()); + + ImageDecodeCache::TaskResult result = + cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo()); + EXPECT_TRUE(result.need_unref); + EXPECT_TRUE(result.task); + + TestTileTaskRunner::ProcessTask(result.task.get()); + + DecodedDrawImage another_decoded_draw_image = + cache.GetDecodedImageForDraw(draw_image); + // This should get the new decoded/locked image, not the one we're using at + // raster. + // TODO(vmpstr): We can possibly optimize this so that the decode simply moves + // the image to the right spot. + EXPECT_NE(decoded_draw_image.image()->uniqueID(), + another_decoded_draw_image.image()->uniqueID()); + EXPECT_FALSE(another_decoded_draw_image.is_at_raster_decode()); + + cache.DrawWithImageFinished(draw_image, decoded_draw_image); + cache.DrawWithImageFinished(draw_image, another_decoded_draw_image); + cache.UnrefImage(draw_image); +} + +TEST(SoftwareImageDecodeCacheTest, + GetDecodedImageForDrawAtRasterDecodeIsUsedForLockedCache) { + TestSoftwareImageDecodeCache cache; + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + PaintImage paint_image = CreatePaintImage(100, 100); + DrawImage draw_image( + paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()), + quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + PaintImage::kDefaultFrameIndex, DefaultColorSpace()); + + DecodedDrawImage decoded_draw_image = + cache.GetDecodedImageForDraw(draw_image); + EXPECT_TRUE(decoded_draw_image.image()); + EXPECT_EQ(50, decoded_draw_image.image()->width()); + EXPECT_EQ(50, decoded_draw_image.image()->height()); + EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width()); + EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height()); + EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality()); + EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity()); + EXPECT_TRUE(decoded_draw_image.is_at_raster_decode()); + + ImageDecodeCache::TaskResult result = + cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo()); + EXPECT_TRUE(result.need_unref); + EXPECT_TRUE(result.task); + + // If we finish the draw here, then we will use it for the locked decode + // instead of decoding again. + cache.DrawWithImageFinished(draw_image, decoded_draw_image); + + TestTileTaskRunner::ProcessTask(result.task.get()); + + DecodedDrawImage another_decoded_draw_image = + cache.GetDecodedImageForDraw(draw_image); + // This should get the decoded/locked image which we originally decoded at + // raster time, since it's now in the locked cache. + EXPECT_EQ(decoded_draw_image.image()->uniqueID(), + another_decoded_draw_image.image()->uniqueID()); + EXPECT_FALSE(another_decoded_draw_image.is_at_raster_decode()); + + cache.DrawWithImageFinished(draw_image, another_decoded_draw_image); + cache.UnrefImage(draw_image); +} + TEST(SoftwareImageDecodeCacheTest, ZeroSizedImagesAreSkipped) { TestSoftwareImageDecodeCache cache; bool is_decomposable = true; @@ -1577,18 +1638,20 @@ std::vector<PaintImage::FrameKey> frame_keys; for (int i = 0; i < 10; ++i) { - SCOPED_TRACE(i); PaintImage paint_image = CreatePaintImage(100, 100); DrawImage draw_image( paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), PaintImage::kDefaultFrameIndex, DefaultColorSpace()); frame_keys.push_back(draw_image.frame_key()); + DecodedDrawImage decoded_draw_image = + cache.GetDecodedImageForDraw(draw_image); ImageDecodeCache::TaskResult result = cache.GetTaskForImageAndRef( draw_image, ImageDecodeCache::TracingInfo()); EXPECT_TRUE(result.need_unref); EXPECT_TRUE(result.task); TestTileTaskRunner::ProcessTask(result.task.get()); + cache.DrawWithImageFinished(draw_image, decoded_draw_image); cache.UnrefImage(draw_image); } @@ -1655,314 +1718,5 @@ cache.DrawWithImageFinished(subset_draw_image, decoded_image); } -TEST(SoftwareImageDecodeCacheTest, UseClosestAvailableDecode) { - TestSoftwareImageDecodeCache cache; - bool is_decomposable = true; - SkFilterQuality quality = kMedium_SkFilterQuality; - PaintImage paint_image = CreatePaintImage(512, 512); - SkIRect src_rect = SkIRect::MakeWH(paint_image.width(), paint_image.height()); - - // Populate a 0.5 scale image in the cache. - DrawImage draw_image_50( - paint_image, src_rect, quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - ImageDecodeCache::TaskResult result_50 = cache.GetTaskForImageAndRef( - draw_image_50, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result_50.task); - EXPECT_TRUE(result_50.need_unref); - - TestTileTaskRunner::ProcessTask(result_50.task.get()); - // Clear all (unlocked) images from the cache. - cache.ClearCache(); - - // Verify that we indeed have a cached item at that scale. - { - DecodedDrawImage decoded = cache.GetDecodedImageForDraw(draw_image_50); - EXPECT_EQ(256, decoded.image()->width()); - EXPECT_EQ(256, decoded.image()->height()); - EXPECT_FALSE(decoded.is_at_raster_decode()); - cache.DrawWithImageFinished(draw_image_50, decoded); - } - - // At this point we should only have one image in the cache. - EXPECT_EQ(1u, cache.GetNumCacheEntriesForTesting()); - - // Get a task for 0.125 scale, which should use the 0.5 scale decode and scale - // it 4x. - DrawImage draw_image_125( - paint_image, src_rect, quality, - CreateMatrix(SkSize::Make(0.125f, 0.125f), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - ImageDecodeCache::TaskResult result_125 = cache.GetTaskForImageAndRef( - draw_image_125, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result_125.task); - EXPECT_TRUE(result_125.need_unref); - - TestTileTaskRunner::ProcessTask(result_125.task.get()); - - // Note that we don't clear the cache, since there should be no transient - // entries, just the locked ones. - // Verify that the draw image is at the right scale. - { - DecodedDrawImage decoded = cache.GetDecodedImageForDraw(draw_image_125); - EXPECT_EQ(64, decoded.image()->width()); - EXPECT_EQ(64, decoded.image()->height()); - EXPECT_FALSE(decoded.is_at_raster_decode()); - cache.DrawWithImageFinished(draw_image_125, decoded); - } - - // Now we should only have 2 images in the cache (0.5 and 0.125 scales). - EXPECT_EQ(2u, cache.GetNumCacheEntriesForTesting()); - - // Clean up. - cache.UnrefImage(draw_image_50); - cache.UnrefImage(draw_image_125); -} - -TEST(SoftwareImageDecodeCacheTest, UseClosestAvailableDecodeAtRaster) { - TestSoftwareImageDecodeCache cache; - bool is_decomposable = true; - SkFilterQuality quality = kMedium_SkFilterQuality; - PaintImage paint_image = CreatePaintImage(512, 512); - SkIRect src_rect = SkIRect::MakeWH(paint_image.width(), paint_image.height()); - - // Populate a 0.5 scale image in the cache. - DrawImage draw_image_50( - paint_image, src_rect, quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - ImageDecodeCache::TaskResult result_50 = cache.GetTaskForImageAndRef( - draw_image_50, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result_50.task); - EXPECT_TRUE(result_50.need_unref); - - TestTileTaskRunner::ProcessTask(result_50.task.get()); - // Clear all (unlocked) images from the cache. - cache.ClearCache(); - - // Verify that we indeed have a cached item at that scale. - { - DecodedDrawImage decoded = cache.GetDecodedImageForDraw(draw_image_50); - EXPECT_EQ(256, decoded.image()->width()); - EXPECT_EQ(256, decoded.image()->height()); - EXPECT_FALSE(decoded.is_at_raster_decode()); - cache.DrawWithImageFinished(draw_image_50, decoded); - } - - // At this point we should only have one image in the cache. - EXPECT_EQ(1u, cache.GetNumCacheEntriesForTesting()); - - // Get a task for 0.125 scale, which should use the 0.5 scale decode and scale - // it 4x. - DrawImage draw_image_125( - paint_image, src_rect, quality, - CreateMatrix(SkSize::Make(0.125f, 0.125f), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - - // Verify that the draw image at raster is at the right scale. - { - DecodedDrawImage decoded = cache.GetDecodedImageForDraw(draw_image_125); - EXPECT_EQ(64, decoded.image()->width()); - EXPECT_EQ(64, decoded.image()->height()); - EXPECT_TRUE(decoded.is_at_raster_decode()); - cache.DrawWithImageFinished(draw_image_125, decoded); - } - - // Now we should only have 2 images in the cache (0.5 and 0.125 scales). - EXPECT_EQ(2u, cache.GetNumCacheEntriesForTesting()); - - // Clean up. - cache.UnrefImage(draw_image_50); -} - -TEST(SoftwareImageDecodeCacheTest, UseClosestAvailableDecodeNotSmaller) { - TestSoftwareImageDecodeCache cache; - bool is_decomposable = true; - SkFilterQuality quality = kMedium_SkFilterQuality; - PaintImage paint_image = CreatePaintImage(512, 512); - SkIRect src_rect = SkIRect::MakeWH(paint_image.width(), paint_image.height()); - - // Populate a 0.25 scale image in the cache. - DrawImage draw_image_25( - paint_image, src_rect, quality, - CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - ImageDecodeCache::TaskResult result_25 = cache.GetTaskForImageAndRef( - draw_image_25, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result_25.task); - EXPECT_TRUE(result_25.need_unref); - - TestTileTaskRunner::ProcessTask(result_25.task.get()); - // Clear all (unlocked) images from the cache. - cache.ClearCache(); - - // Verify that we indeed have a cached item at that scale. - { - DecodedDrawImage decoded = cache.GetDecodedImageForDraw(draw_image_25); - EXPECT_EQ(128, decoded.image()->width()); - EXPECT_EQ(128, decoded.image()->height()); - EXPECT_FALSE(decoded.is_at_raster_decode()); - cache.DrawWithImageFinished(draw_image_25, decoded); - } - - // At this point we should only have one image in the cache. - EXPECT_EQ(1u, cache.GetNumCacheEntriesForTesting()); - - // Get a task for 0.5 scale, which can't use the 0.125 scale, so it would - // generate a 1.0 scale first and use that. - DrawImage draw_image_50( - paint_image, src_rect, quality, - CreateMatrix(SkSize::Make(0.50, 0.50), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - ImageDecodeCache::TaskResult result_50 = cache.GetTaskForImageAndRef( - draw_image_50, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result_50.task); - EXPECT_TRUE(result_50.need_unref); - - TestTileTaskRunner::ProcessTask(result_50.task.get()); - - // Verify that the draw image at raster is at the right scale. - { - DecodedDrawImage decoded = cache.GetDecodedImageForDraw(draw_image_50); - EXPECT_EQ(256, decoded.image()->width()); - EXPECT_EQ(256, decoded.image()->height()); - EXPECT_FALSE(decoded.is_at_raster_decode()); - cache.DrawWithImageFinished(draw_image_50, decoded); - } - - // Now we should only have 3 images in the cache (1.0, 0.5 and 0.25 scales). - EXPECT_EQ(3u, cache.GetNumCacheEntriesForTesting()); - - // Clean up. - cache.UnrefImage(draw_image_25); - cache.UnrefImage(draw_image_50); -} - -TEST(SoftwareImageDecodeCacheTest, - UseClosestAvailableDecodeNotSmallerAtRaster) { - TestSoftwareImageDecodeCache cache; - bool is_decomposable = true; - SkFilterQuality quality = kMedium_SkFilterQuality; - PaintImage paint_image = CreatePaintImage(512, 512); - SkIRect src_rect = SkIRect::MakeWH(paint_image.width(), paint_image.height()); - - // Populate a 0.25 scale image in the cache. - DrawImage draw_image_25( - paint_image, src_rect, quality, - CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - ImageDecodeCache::TaskResult result_25 = cache.GetTaskForImageAndRef( - draw_image_25, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result_25.task); - EXPECT_TRUE(result_25.need_unref); - - TestTileTaskRunner::ProcessTask(result_25.task.get()); - // Clear all (unlocked) images from the cache. - cache.ClearCache(); - - // Verify that we indeed have a cached item at that scale. - { - DecodedDrawImage decoded = cache.GetDecodedImageForDraw(draw_image_25); - EXPECT_EQ(128, decoded.image()->width()); - EXPECT_EQ(128, decoded.image()->height()); - EXPECT_FALSE(decoded.is_at_raster_decode()); - cache.DrawWithImageFinished(draw_image_25, decoded); - } - - // At this point we should only have one image in the cache. - EXPECT_EQ(1u, cache.GetNumCacheEntriesForTesting()); - - // Get a task for 0.5 scale, which can't use the 0.125 scale, so it would - // generate a 1.0 scale first and use that. - DrawImage draw_image_50( - paint_image, src_rect, quality, - CreateMatrix(SkSize::Make(0.50, 0.50), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - - // Verify that the draw image at raster is at the right scale. - { - DecodedDrawImage decoded = cache.GetDecodedImageForDraw(draw_image_50); - EXPECT_EQ(256, decoded.image()->width()); - EXPECT_EQ(256, decoded.image()->height()); - EXPECT_TRUE(decoded.is_at_raster_decode()); - cache.DrawWithImageFinished(draw_image_50, decoded); - } - - // Now we should only have 3 images in the cache (1.0, 0.5 and 0.25 scales). - EXPECT_EQ(3u, cache.GetNumCacheEntriesForTesting()); - - // Clean up. - cache.UnrefImage(draw_image_25); -} - -TEST(SoftwareImageDecodeCache, UseClosestAvailableDecodeWithTheSameSrc) { - TestSoftwareImageDecodeCache cache; - bool is_decomposable = true; - SkFilterQuality quality = kMedium_SkFilterQuality; - PaintImage paint_image = CreatePaintImage(512, 512); - SkIRect full_src_rect = - SkIRect::MakeWH(paint_image.width(), paint_image.height()); - SkIRect decoded_src_rect = SkIRect::MakeXYWH(1, 1, paint_image.width() - 2, - paint_image.height() - 2); - - // Populate a 0.5f scale image in the cache with a non-full src rect. - DrawImage draw_image_50( - paint_image, decoded_src_rect, quality, - CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - ImageDecodeCache::TaskResult result_50 = cache.GetTaskForImageAndRef( - draw_image_50, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result_50.task); - EXPECT_TRUE(result_50.need_unref); - - TestTileTaskRunner::ProcessTask(result_50.task.get()); - // Clear all (unlocked) images from the cache. - cache.ClearCache(); - - // Verify that we indeed have a cached item at that scale. - { - DecodedDrawImage decoded = cache.GetDecodedImageForDraw(draw_image_50); - // Note the subrect is reflected in the size. - EXPECT_EQ(255, decoded.image()->width()); - EXPECT_EQ(255, decoded.image()->height()); - EXPECT_FALSE(decoded.is_at_raster_decode()); - cache.DrawWithImageFinished(draw_image_50, decoded); - } - - // At this point we should only have one image in the cache. - EXPECT_EQ(1u, cache.GetNumCacheEntriesForTesting()); - - // Get a task for 0.25 scale, which can't use the 0.5f scale, since it was - // generated a different src rect. It would generate a 1.0 scale first with a - // full src rect and use that. - DrawImage draw_image_25( - paint_image, full_src_rect, quality, - CreateMatrix(SkSize::Make(0.25, 0.25), is_decomposable), - PaintImage::kDefaultFrameIndex, DefaultColorSpace()); - ImageDecodeCache::TaskResult result_25 = cache.GetTaskForImageAndRef( - draw_image_25, ImageDecodeCache::TracingInfo()); - EXPECT_TRUE(result_25.task); - EXPECT_TRUE(result_25.need_unref); - - TestTileTaskRunner::ProcessTask(result_25.task.get()); - - // Verify that the draw image at raster is at the right scale. - { - DecodedDrawImage decoded = cache.GetDecodedImageForDraw(draw_image_25); - EXPECT_EQ(128, decoded.image()->width()); - EXPECT_EQ(128, decoded.image()->height()); - EXPECT_FALSE(decoded.is_at_raster_decode()); - cache.DrawWithImageFinished(draw_image_25, decoded); - } - - // Now we should only have 3 images in the cache (1.0, 0.5, and 0.25 scales). - EXPECT_EQ(3u, cache.GetNumCacheEntriesForTesting()); - - // Clean up. - cache.UnrefImage(draw_image_50); - cache.UnrefImage(draw_image_25); -} - } // namespace } // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 1f4d74e..60d23a2 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -643,8 +643,6 @@ gfx::PointF device_viewport_point = gfx::ScalePoint( gfx::PointF(viewport_point), active_tree_->device_scale_factor()); - // Now determine if there are actually any handlers at that point. - // TODO(rbyers): Consider also honoring touch-action (crbug.com/347272). LayerImpl* layer_impl_with_touch_handler = active_tree_->FindLayerThatIsHitByPointInTouchHandlerRegion( device_viewport_point); @@ -656,8 +654,23 @@ } if (out_touch_action) { + gfx::Transform layer_screen_space_transform = + layer_impl_with_touch_handler->ScreenSpaceTransform(); + gfx::Transform inverse_layer_screen_space( + gfx::Transform::kSkipInitialization); + bool can_be_inversed = + layer_screen_space_transform.GetInverse(&inverse_layer_screen_space); + // Getting here indicates that |layer_impl_with_touch_handler| is non-null, + // which means that the |hit| in FindClosestMatchingLayer() is true, which + // indicates that the inverse is available. + DCHECK(can_be_inversed); + bool clipped = false; + gfx::Point3F planar_point = MathUtil::ProjectPoint3D( + inverse_layer_screen_space, device_viewport_point, &clipped); + gfx::PointF hit_test_point_in_layer_space = + gfx::PointF(planar_point.x(), planar_point.y()); const auto& region = layer_impl_with_touch_handler->touch_action_region(); - gfx::Point point = gfx::ToRoundedPoint(device_viewport_point); + gfx::Point point = gfx::ToRoundedPoint(hit_test_point_in_layer_space); *out_touch_action = region.GetWhiteListedTouchAction(point); } @@ -2127,7 +2140,7 @@ void LayerTreeHostImpl::DidLoseLayerTreeFrameSink() { if (resource_provider_) - resource_provider_->DidLoseVulkanContextProvider(); + resource_provider_->DidLoseContextProvider(); has_valid_layer_tree_frame_sink_ = false; client_->DidLoseLayerTreeFrameSinkOnImplThread(); }
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 1341dc0..063668d4 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -603,6 +603,60 @@ host_impl_ = nullptr; } + void WhiteListedTouchActionTestHelper(float device_scale_factor, + float page_scale_factor) { + LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(200, 200)); + host_impl_->SetViewportSize(gfx::Size(100, 100)); + DrawFrame(); + LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing(); + + // Just hard code some random number, we care about the actual page scale + // factor on the active tree. + float min_page_scale_factor = 0.1f; + float max_page_scale_factor = 5.0f; + host_impl_->active_tree()->PushPageScaleFromMainThread( + page_scale_factor, min_page_scale_factor, max_page_scale_factor); + host_impl_->active_tree()->SetDeviceScaleFactor(device_scale_factor); + + std::unique_ptr<LayerImpl> child_layer = + LayerImpl::Create(host_impl_->active_tree(), 6); + LayerImpl* child = child_layer.get(); + child_layer->SetDrawsContent(true); + child_layer->SetPosition(gfx::PointF(0, 0)); + child_layer->SetBounds(gfx::Size(25, 25)); + scroll->test_properties()->AddChild(std::move(child_layer)); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + TouchActionRegion root_touch_action_region; + root_touch_action_region.Union(kTouchActionPanX, gfx::Rect(0, 0, 50, 50)); + root->SetTouchActionRegion(root_touch_action_region); + TouchActionRegion child_touch_action_region; + child_touch_action_region.Union(kTouchActionPanLeft, + gfx::Rect(0, 0, 25, 25)); + child->SetTouchActionRegion(child_touch_action_region); + + TouchAction touch_action = kTouchActionAuto; + host_impl_->EventListenerTypeForTouchStartOrMoveAt(gfx::Point(10, 10), + &touch_action); + EXPECT_EQ(kTouchActionPanLeft, touch_action); + touch_action = kTouchActionAuto; + host_impl_->EventListenerTypeForTouchStartOrMoveAt(gfx::Point(30, 30), + &touch_action); + EXPECT_EQ(kTouchActionPanX, touch_action); + + TouchActionRegion new_child_region; + new_child_region.Union(kTouchActionPanY, gfx::Rect(0, 0, 25, 25)); + child->SetTouchActionRegion(new_child_region); + touch_action = kTouchActionAuto; + host_impl_->EventListenerTypeForTouchStartOrMoveAt(gfx::Point(10, 10), + &touch_action); + EXPECT_EQ(kTouchActionPanY, touch_action); + touch_action = kTouchActionAuto; + host_impl_->EventListenerTypeForTouchStartOrMoveAt(gfx::Point(30, 30), + &touch_action); + EXPECT_EQ(kTouchActionPanX, touch_action); + } + void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor); void pinch_zoom_pan_viewport_test(float device_scale_factor); void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor); @@ -13134,5 +13188,21 @@ EXPECT_FALSE(host_impl_->NeedUpdateGpuRasterizationStatusForTesting()); } +TEST_F(LayerTreeHostImplTest, WhiteListedTouchActionTest1) { + WhiteListedTouchActionTestHelper(1.0f, 1.0f); +} + +TEST_F(LayerTreeHostImplTest, WhiteListedTouchActionTest2) { + WhiteListedTouchActionTestHelper(1.0f, 0.789f); +} + +TEST_F(LayerTreeHostImplTest, WhiteListedTouchActionTest3) { + WhiteListedTouchActionTestHelper(2.345f, 1.0f); +} + +TEST_F(LayerTreeHostImplTest, WhiteListedTouchActionTest4) { + WhiteListedTouchActionTestHelper(2.654f, 0.678f); +} + } // namespace } // namespace cc
diff --git a/cc/trees/layer_tree_host_perftest.cc b/cc/trees/layer_tree_host_perftest.cc index ad70557..c30afeb6 100644 --- a/cc/trees/layer_tree_host_perftest.cc +++ b/cc/trees/layer_tree_host_perftest.cc
@@ -324,10 +324,11 @@ gpu::CommandBufferId::FromUnsafeValue(1), next_fence_sync_); next_sync_token.SetVerifyFlush(); - viz::TextureMailbox mailbox(gpu_mailbox, next_sync_token, GL_TEXTURE_2D); + viz::TransferableResource resource = viz::TransferableResource::MakeGL( + gpu_mailbox, GL_LINEAR, GL_TEXTURE_2D, next_sync_token); next_fence_sync_++; - tab_contents_->SetTextureMailbox(mailbox, std::move(callback)); + tab_contents_->SetTransferableResource(resource, std::move(callback)); ++sent_mailboxes_count_; tab_contents_->SetNeedsDisplay(); } @@ -348,7 +349,7 @@ } void CleanUpAndEndTestOnMainThread() { - tab_contents_->SetTextureMailbox(viz::TextureMailbox(), nullptr); + tab_contents_->ClearTexture(); // ReleaseMailbox will end the test when we get the last mailbox back. }
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index baf15ae..608d266 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -8131,6 +8131,17 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestImageAnimation); +class LayerTreeHostTestImageAnimationSynchronousScheduling + : public LayerTreeHostTestImageAnimation { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + LayerTreeHostTestImageAnimation::InitializeSettings(settings); + settings->using_synchronous_renderer_compositor = true; + } +}; + +MULTI_THREAD_TEST_F(LayerTreeHostTestImageAnimationSynchronousScheduling); + class LayerTreeHostTestImageDecodingHints : public LayerTreeHostTest { public: void BeginTest() override { PostSetNeedsCommitToMainThread(); }
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc index ef9db115..cf734f1 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -916,11 +916,12 @@ TextureLayer::CreateForMailbox(nullptr); texture->SetBounds(gfx::Size(10, 10)); texture->SetIsDrawable(true); - texture->SetTextureMailbox( - viz::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D), - viz::SingleReleaseCallback::Create( - base::Bind(&LayerTreeHostContextTestDontUseLostResources:: - EmptyReleaseCallback))); + auto resource = viz::TransferableResource::MakeGL( + mailbox, GL_LINEAR, GL_TEXTURE_2D, sync_token); + texture->SetTransferableResource( + resource, viz::SingleReleaseCallback::Create( + base::Bind(&LayerTreeHostContextTestDontUseLostResources:: + EmptyReleaseCallback))); root->AddChild(texture); scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client_);
diff --git a/chrome/VERSION b/chrome/VERSION index 234cae5..14139287 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=64 MINOR=0 -BUILD=3274 +BUILD=3275 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index aa7e04b..bf2e946 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -727,39 +727,68 @@ variables = chrome_sync_shell_jinja_variables } -shared_library("libchrome") { +# This template contains common code for both libchrome and libchromefortest. +# The former is used in chrome_public_apk. The latter is used in +# chrome_public_apk_for_test. The distinction is necessary because the latter +# requires additional native sources for JNI shims only used by tests. +template("chrome_shared_library") { + shared_library(target_name) { + forward_variables_from(invoker, "*") + + deps += [ + "//build/config:exe_and_shlib_deps", + "//chrome:chrome_android_core", + ] + + if (enable_vr) { + # Ensure libgvr static library appears before gcc library in linking order. + # See https://crbug.com/704305 for details. + libs = [ "//third_party/gvr-android-sdk/libgvr_shim_static_${current_cpu}.a" ] + } + + if (use_order_profiling) { + deps += [ "//tools/cygprofile" ] + } + + # See crbug.com/705088, crbug.com/717815. + if (target_cpu == "arm" && (is_asan || use_order_profiling)) { + ldflags = [ "-Wl,--long-plt" ] + } + + if (chromium_linker_supported && use_lld) { + configs += [ "//build/config/android:lld_pack_relocations" ] + } + + public_configs = extra_chrome_shared_library_configs + deps += extra_chrome_shared_library_deps + } +} + +chrome_shared_library("libchrome") { sources = [ "../app/android/chrome_main_delegate_android_initializer.cc", "../browser/android/chrome_entry_point.cc", ] deps = [ ":chrome_jni_registration($default_toolchain)", - "//build/config:exe_and_shlib_deps", - "//chrome:chrome_android_core", ] +} - if (enable_vr) { - # Ensure libgvr static library appears before gcc library in linking order. - # See https://crbug.com/704305 for details. - libs = - [ "//third_party/gvr-android-sdk/libgvr_shim_static_${current_cpu}.a" ] - } - - if (use_order_profiling) { - deps += [ "//tools/cygprofile" ] - } - - # See crbug.com/705088, crbug.com/717815. - if (target_cpu == "arm" && (is_asan || use_order_profiling)) { - ldflags = [ "-Wl,--long-plt" ] - } - - if (chromium_linker_supported && use_lld) { - configs += [ "//build/config/android:lld_pack_relocations" ] - } - - public_configs = extra_chrome_shared_library_configs - deps += extra_chrome_shared_library_deps +chrome_shared_library("libchromefortest") { + testonly = true + sources = [ + "../app/android/chrome_main_delegate_android_initializer.cc", + "../browser/android/chrome_entry_point_for_test.cc", + "../browser/profiling_host/profiling_test_driver.cc", + "../browser/profiling_host/profiling_test_driver.h", + "../browser/profiling_host/test_android_shim.cc", + "../browser/profiling_host/test_android_shim.h", + ] + deps = [ + ":chrome_jni_for_test_registration($default_toolchain)", + "//base/test:test_support", + "//chrome/browser/profiling_host:jni_headers", + ] } # Ensure that .pak files are built only once (build them in the default @@ -772,6 +801,13 @@ exception_files = jni_exception_files } + generate_jni_registration("chrome_jni_for_test_registration") { + testonly = true + target = ":chrome_public_apk_for_test" + output = "$root_gen_dir/chrome/browser/android/${target_name}.h" + exception_files = jni_exception_files + } + generate_jni_registration("chrome_sync_shell_jni_registration") { testonly = true target = ":chrome_sync_shell_apk" @@ -996,6 +1032,17 @@ shared_libraries = [ ":libchrome" ] } +chrome_public_apk_tmpl_shared("chrome_public_apk_for_test") { + testonly = true + android_manifest = chrome_public_android_manifest + android_manifest_dep = ":chrome_public_android_manifest" + apk_name = "ChromePublicForTest" + shared_libraries = [ ":libchromefortest" ] + deps = [ + "//chrome/browser/profiling_host:profiling_host_java_test_support", + ] +} + chrome_public_apk_tmpl_shared("chrome_modern_public_apk") { android_manifest = chrome_modern_public_android_manifest android_manifest_dep = ":chrome_modern_public_android_manifest" @@ -1090,7 +1137,7 @@ instrumentation_test_apk("chrome_public_test_apk") { apk_name = "ChromePublicTest" - apk_under_test = ":chrome_public_apk" + apk_under_test = ":chrome_public_apk_for_test" android_manifest = chrome_public_test_apk_manifest android_manifest_dep = ":chrome_public_test_apk_manifest" @@ -1099,6 +1146,7 @@ "//chrome/android/webapk/libs/runtime_library:runtime_library_javatests", "//chrome/android/webapk/shell_apk:shell_apk_javatests", "//chrome/android/webapk/shell_apk:webapk_javatests", + "//chrome/browser/profiling_host:profiling_host_javatests", "//third_party/android_support_test_runner:runner_java", ] additional_apks = [
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index ef70b0f..a621bab12 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -461,6 +461,7 @@ <activity android:name="org.chromium.chrome.browser.firstrun.FirstRunActivity" android:theme="@style/FirstRunTheme" {% block first_run_activity_common %} + android:label="@string/fre_activity_label" android:launchMode="singleInstance" android:excludeFromRecents="true" android:autoRemoveFromRecents="true"
diff --git a/chrome/android/java/res/PRESUBMIT.py b/chrome/android/java/res/PRESUBMIT.py new file mode 100644 index 0000000..38a313a --- /dev/null +++ b/chrome/android/java/res/PRESUBMIT.py
@@ -0,0 +1,139 @@ +# 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. + +"""Presubmit script for Android xml code. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into depot_tools. + +This presubmit checks for the following: + - Colors are defined as RRGGBB or AARRGGBB + - No (A)RGB values are referenced outside colors.xml + - No duplicate (A)RGB values are referenced in colors.xml +""" + +from collections import defaultdict +import re + +COLOR_PATTERN = re.compile(r'(>|")(#[0-9A-Fa-f]+)(<|")') +VALID_COLOR_PATTERN = re.compile( + r'^#([0-9A-F][0-9A-E]|[0-9A-E][0-9A-F])?[0-9A-F]{6}$') + + +def CheckChangeOnUpload(input_api, output_api): + return _CommonChecks(input_api, output_api) + + +def CheckChangeOnCommit(input_api, output_api): + return _CommonChecks(input_api, output_api) + + +def _CommonChecks(input_api, output_api): + """Checks common to both upload and commit.""" + result = [] + result.extend(_CheckColorFormat(input_api, output_api)) + result.extend(_CheckColorReferences(input_api, output_api)) + result.extend(_CheckDuplicateColors(input_api, output_api)) + # Add more checks here + return result + + +def _CheckColorFormat(input_api, output_api): + """Checks color (A)RGB values are of format either RRGGBB or AARRGGBB.""" + errors = [] + for f in input_api.AffectedFiles(include_deletes=False): + if not f.LocalPath().endswith('.xml'): + continue + # Ingnore vector drawable xmls + contents = input_api.ReadFile(f) + if '<vector' in contents: + continue + for line_number, line in f.ChangedContents(): + color = COLOR_PATTERN.search(line) + if color and not VALID_COLOR_PATTERN.match(color.group(2)): + errors.append( + ' %s:%d\n \t%s' % (f.LocalPath(), line_number, line.strip())) + if errors: + return [output_api.PresubmitError( + ''' + Android Color Reference Check failed: + Your new code added (A)RGB values for colors that are not well + formatted, listed below. + + This is banned, please define colors in format of #RRGGBB for opaque + colors or #AARRGGBB for translucent colors. Note that they should be + defined in chrome/android/java/res/values/colors.xml. + + See https://crbug.com/775198 for more information. + ''', + errors)] + return [] + + +def _CheckColorReferences(input_api, output_api): + """Checks no (A)RGB values are defined outside colors.xml.""" + errors = [] + for f in input_api.AffectedFiles(include_deletes=False): + if (not f.LocalPath().endswith('.xml') or + f.LocalPath().endswith('/colors.xml')): + continue + # Ingnore vector drawable xmls + contents = input_api.ReadFile(f) + if '<vector' in contents: + continue + for line_number, line in f.ChangedContents(): + if COLOR_PATTERN.search(line): + errors.append( + ' %s:%d\n \t%s' % (f.LocalPath(), line_number, line.strip())) + if errors: + return [output_api.PresubmitError( + ''' + Android Color Reference Check failed: + Your new code added new color references that are not color resources from + chrome/android/java/res/values/colors.xml, listed below. + + This is banned, please use the existing color resources or create a new + color resource in colors.xml, and reference the color by @color/.... + + See https://crbug.com/775198 for more information. + ''', + errors)] + return [] + + +def _CheckDuplicateColors(input_api, output_api): + """Checks colors defined by (A)RGB values in colors.xml are unique.""" + errors = [] + for f in input_api.AffectedFiles(include_deletes=False): + if not f.LocalPath().endswith('/colors.xml'): + continue + colors = defaultdict(int) + contents = input_api.ReadFile(f) + # Get count for each color defined. + for line in contents.splitlines(False): + color = COLOR_PATTERN.search(line) + if color: + colors[color.group(2)] += 1 + + # Check duplicates in changed contents. + for line_number, line in f.ChangedContents(): + color = COLOR_PATTERN.search(line) + if color and colors[color.group(2)] > 1: + errors.append( + ' %s:%d\n \t%s' % (f.LocalPath(), line_number, line.strip())) + if errors: + return [output_api.PresubmitError( + ''' + Android Duplicate Color Declaration Check failed: + Your new code added new colors by (A)RGB values that are already defined in + chrome/android/java/res/values/colors.xml, listed below. + + This is banned, please reference the existing color resource from colors.xml + using @color/... and if needed, give the existing color resource a more + general name (e.g. google_grey_100). + + See https://crbug.com/775198 for more information. + ''', + errors)] + return []
diff --git a/chrome/android/java/res/PRESUBMIT_test.py b/chrome/android/java/res/PRESUBMIT_test.py new file mode 100755 index 0000000..5f0a9e5 --- /dev/null +++ b/chrome/android/java/res/PRESUBMIT_test.py
@@ -0,0 +1,129 @@ +#!/usr/bin/env python +# 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 os +import sys +import unittest + +import PRESUBMIT + +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname( + os.path.dirname(os.path.abspath(__file__))))))) +from PRESUBMIT_test_mocks import MockFile, MockInputApi, MockOutputApi + + +class ColorFormatTest(unittest.TestCase): + + def testColorFormatIgnoredFile(self): + lines = ['<color name="color1">#61000000</color>', + '<color name="color2">#FFFFFF</color>', + '<color name="color3">#CCC</color>'] + mock_input_api = MockInputApi() + mock_input_api.files = [MockFile('chrome/path/test.java', lines)] + errors = PRESUBMIT._CheckColorFormat(mock_input_api, MockOutputApi()) + self.assertEqual(0, len(errors)) + + def testColorFormatTooShort(self): + lines = ['<color name="color1">#61000000</color>', + '<color name="color2">#FFFFFF</color>', + '<color name="color3">#CCC</color>'] + mock_input_api = MockInputApi() + mock_input_api.files = [MockFile('chrome/path/test.xml', lines)] + errors = PRESUBMIT._CheckColorFormat(mock_input_api, MockOutputApi()) + self.assertEqual(1, len(errors)) + self.assertEqual(1, len(errors[0].items)) + self.assertEqual(' chrome/path/test.xml:3', + errors[0].items[0].splitlines()[0]) + + def testColorInvalidAlphaValue(self): + lines = ['<color name="color1">#61000000</color>', + '<color name="color2">#FEFFFFFF</color>', + '<color name="color3">#FFCCCCCC</color>'] + mock_input_api = MockInputApi() + mock_input_api.files = [MockFile('chrome/path/test.xml', lines)] + errors = PRESUBMIT._CheckColorFormat(mock_input_api, MockOutputApi()) + self.assertEqual(1, len(errors)) + self.assertEqual(1, len(errors[0].items)) + self.assertEqual(' chrome/path/test.xml:3', + errors[0].items[0].splitlines()[0]) + + def testColorFormatLowerCase(self): + lines = ['<color name="color1">#61000000</color>', + '<color name="color2">#EFFFFFFF</color>', + '<color name="color3">#CcCcCC</color>'] + mock_input_api = MockInputApi() + mock_input_api.files = [MockFile('chrome/path/test.xml', lines)] + errors = PRESUBMIT._CheckColorFormat(mock_input_api, MockOutputApi()) + self.assertEqual(1, len(errors)) + self.assertEqual(1, len(errors[0].items)) + self.assertEqual(' chrome/path/test.xml:3', + errors[0].items[0].splitlines()[0]) + + +class ColorReferencesTest(unittest.TestCase): + + def testVectorDrawbleIgnored(self): + lines = ['<vector', + 'tools:targetApi="21"', + 'android:fillColor="#CCCCCC">', + '</vector>'] + mock_input_api = MockInputApi() + mock_input_api.files = [MockFile('chrome/path/test.xml', lines)] + errors = PRESUBMIT._CheckColorReferences(mock_input_api, MockOutputApi()) + self.assertEqual(0, len(errors)) + + def testInvalidReference(self): + lines = ['<TextView', + 'android:textColor="#FFFFFF" />'] + mock_input_api = MockInputApi() + mock_input_api.files = [MockFile('chrome/path/test.xml', lines)] + errors = PRESUBMIT._CheckColorReferences(mock_input_api, MockOutputApi()) + self.assertEqual(1, len(errors)) + self.assertEqual(1, len(errors[0].items)) + self.assertEqual(' chrome/path/test.xml:2', + errors[0].items[0].splitlines()[0]) + + def testValidReference(self): + lines = ['<TextView', + 'android:textColor="@color/color1" />'] + mock_input_api = MockInputApi() + mock_input_api.files = [MockFile('chrome/path/test.xml', lines)] + errors = PRESUBMIT._CheckColorReferences(mock_input_api, MockOutputApi()) + self.assertEqual(0, len(errors)) + + def testValidReferenceInColorResources(self): + lines = ['<color name="color1">#61000000</color>'] + mock_input_api = MockInputApi() + mock_input_api.files = [MockFile('chrome/path/colors.xml', lines)] + errors = PRESUBMIT._CheckColorReferences(mock_input_api, MockOutputApi()) + self.assertEqual(0, len(errors)) + + +class DuplicateColorsTest(unittest.TestCase): + + def testFailure(self): + lines = ['<color name="color1">#61000000</color>', + '<color name="color2">#61000000</color>'] + mock_input_api = MockInputApi() + mock_input_api.files = [MockFile('chrome/path/colors.xml', lines)] + errors = PRESUBMIT._CheckDuplicateColors(mock_input_api, MockOutputApi()) + self.assertEqual(1, len(errors)) + self.assertEqual(2, len(errors[0].items)) + self.assertEqual(' chrome/path/colors.xml:1', + errors[0].items[0].splitlines()[0]) + self.assertEqual(' chrome/path/colors.xml:2', + errors[0].items[1].splitlines()[0]) + + def testSucess(self): + lines = ['<color name="color1">#61000000</color>', + '<color name="color1">#FFFFFF</color>'] + mock_input_api = MockInputApi() + mock_input_api.files = [MockFile('chrome/path/colors.xml', lines)] + errors = PRESUBMIT._CheckDuplicateColors(mock_input_api, MockOutputApi()) + self.assertEqual(0, len(errors)) + + +if __name__ == '__main__': + unittest.main()
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index 3197fe4..5519a801 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -6,43 +6,44 @@ <resources> <!-- Common colors --> <color name="default_text_color">@color/black_alpha_87</color> - <color name="default_primary_color">#f2f2f2</color> + <color name="default_primary_color">#F2F2F2</color> <color name="light_normal_color">#5A5A5A</color> - <color name="light_active_color">#4285F4</color> - <color name="input_underline_error_color">#d32f2f</color> + <color name="light_active_color">@color/google_blue_500</color> + <color name="input_underline_error_color">#D32F2F</color> <color name="explanation_text_color">#909090</color> <color name="text_highlight_color">#C6DAFC</color> <color name="dark_action_bar_color">#263238</color> <color name="descriptive_text_color">#646464</color> - <color name="error_text_color">#c53929</color> + <color name="error_text_color">@color/google_red_700</color> <color name="google_blue_grey_500">#607D8B</color> - <color name="google_red_700">#c53929</color> - <color name="google_green_700">#0b8043</color> - <color name="google_grey_100">#f5f5f5</color> - <color name="google_grey_200">#eeeeee</color> - <color name="google_grey_300">#e0e0e0</color> - <color name="google_grey_400">#bdbdbd</color> + <color name="google_red_700">#C53929</color> + <color name="google_green_700">#0B8043</color> + <color name="google_grey_50">#FAFAFA</color> + <color name="google_grey_100">#F5F5F5</color> + <color name="google_grey_200">#EEEEEE</color> + <color name="google_grey_300">#E0E0E0</color> + <color name="google_grey_400">#BDBDBD</color> <color name="google_grey_500">#9E9E9E</color> <color name="google_grey_600">#757575</color> <color name="grey_alpha_90">#E6505050</color> - <color name="toolbar_shadow_color">#1d000000</color> - <color name="white_alpha_50">#80ffffff</color> - <color name="white_alpha_54">#8Affffff</color> - <color name="white_alpha_90">#E6FFFFFF</color> + <color name="black_alpha_11">#1D000000</color> + <color name="white_alpha_50">#80FFFFFF</color> + <color name="white_alpha_54">#8AFFFFFF</color> <color name="black_alpha_65">#A6000000</color> - <color name="light_grey">#ccc</color> - <color name="modal_dialog_scrim_color">#7f000000</color> + <color name="white_alpha_90">#E6FFFFFF</color> + <color name="light_grey">#CCCCCC</color> + <color name="modal_dialog_scrim_color">#7F000000</color> <color name="modern_grey_300">#DFE1E5</color> <color name="modern_light_grey">#F1F3F4</color> <!-- New list of common text colors --> <color name="black_alpha_20">#33000000</color> - <color name="black_alpha_30">#4d000000</color> + <color name="black_alpha_30">#4D000000</color> <color name="black_alpha_40">#66000000</color> <!-- Infobar colors --> - <color name="infobar_accent_blue">#4285f4</color> + <color name="infobar_accent_blue">@color/google_blue_500</color> <color name="infobar_descriptive_text_color">@color/black_alpha_54</color> <!-- Snackbar colors --> @@ -51,7 +52,7 @@ <!-- Tab Switcher Colors --> <color name="tab_switcher_background">#14181C</color> <color name="accessibility_tab_switcher_list_item">#252525</color> - <color name="accessibility_close_undo_text">#3adaff</color> + <color name="accessibility_close_undo_text">#3ADAFF</color> <color name="tab_back">#F1F1F1</color> <color name="tab_back_incognito">#4F4F4F</color> @@ -64,26 +65,26 @@ <!-- URL Emphasizer colors --> <color name="url_emphasis_non_emphasized_text">#80333333</color> - <color name="url_emphasis_light_non_emphasized_text">#80ffffff</color> + <color name="url_emphasis_light_non_emphasized_text">@color/white_alpha_50</color> <color name="url_emphasis_domain_and_registry">#333333</color> - <color name="url_emphasis_light_domain_and_registry">#ffffff</color> + <color name="url_emphasis_light_domain_and_registry">@android:color/white</color> <color name="url_emphasis_default_text">@color/black_alpha_87</color> <!--suppress UnusedResources --> - <color name="url_emphasis_light_default_text">#ffffff</color> + <color name="url_emphasis_light_default_text">@android:color/white</color> <!-- Omnibox Suggestion colors --> - <color name="suggestion_url_dark">#4285f4</color> - <color name="suggestion_url_light">#5595fe</color> + <color name="suggestion_url_dark">@color/google_blue_500</color> + <color name="suggestion_url_light">#5595FE</color> <color name="answers_description_text_negative">@color/google_red_700</color> <color name="answers_description_text_positive">@color/google_green_700</color> - <color name="answers_answer_text">#8a8a8a</color> + <color name="answers_answer_text">#8A8A8A</color> <!-- Distilled Page Prefs colors --> <color name="distilled_page_prefs_selected">#999999</color> - <color name="distilled_page_prefs_unselected">#ffffff</color> + <color name="distilled_page_prefs_unselected">@android:color/white</color> <!-- Password generation popup colors --> - <color name="password_generation_divider_color">#e5e5e5</color> + <color name="password_generation_divider_color">#E5E5E5</color> <!-- Preferences Colors --> <color name="pref_accent_color">@color/light_active_color</color> @@ -91,25 +92,25 @@ <!-- Data Saver Colors --> <color name="data_reduction_compressed_color">@color/pref_accent_color</color> <color name="data_reduction_original_color">#E1E1E1</color> - <color name="data_reduction_chart_background_color">#FAFAFA</color> + <color name="data_reduction_chart_background_color">@color/google_grey_50</color> <color name="data_reduction_breakdown_text_color">#212121</color> <color name="data_reduction_breakdown_light_text_color">#737373</color> <!-- Compositor Tab Title Colors --> <color name="compositor_tab_title_bar_text">@color/black_alpha_87</color> - <color name="compositor_tab_title_bar_text_incognito">#FFFFFFFF</color> + <color name="compositor_tab_title_bar_text_incognito">@android:color/white</color> <!-- Account Signin Colors --> <!-- As in dimens.xml, signin uses values from the First Run Experience --> - <color name="signin_head_background">#fff</color> - <color name="signin_body_background">#fafafa</color> + <color name="signin_head_background">@android:color/white</color> + <color name="signin_body_background">@color/google_grey_50</color> <!-- Sad Tab colors --> <color name="sad_tab_body_text_color">#646464</color> <!-- NTP and Home sheet colors. Also used on the bookmarks and recent tabs pages. --> - <color name="ntp_bg">#f2f2f2</color> - <color name="ntp_bg_incognito">#222</color> + <color name="ntp_bg">@color/default_primary_color</color> + <color name="ntp_bg_incognito">#222222</color> <color name="ntp_search_box_hint">@color/black_alpha_54</color> <color name="ntp_list_header_subtext">#969696</color> <color name="snippets_publisher_name_color">#646464</color> @@ -120,21 +121,21 @@ <color name="suggestions_offline_badge_tint">@color/google_blue_500</color> <!-- Incognito NTP Colors. --> - <color name="incognito_text">#b3ffffff</color> + <color name="incognito_text">#B3FFFFFF</color> <color name="incognito_emphasis">@android:color/white</color> - <color name="incognito_header">#ccffffff</color> - <color name="incognito_ntp_learn_more_link">#03a9f4</color> - <color name="incognito_ntp_header">#d2d2d2</color> + <color name="incognito_header">#CCFFFFFF</color> + <color name="incognito_ntp_learn_more_link">#03A9F4</color> + <color name="incognito_ntp_header">#D2D2D2</color> <!-- Contextual Search colors --> - <color name="contextual_search_promo_background_color">#EEEEEE</color> + <color name="contextual_search_promo_background_color">@color/google_grey_200</color> <color name="contextual_search_promo_border_color">#C2C2C2</color> <!-- Progress Bar colors --> <color name="progress_bar_foreground">@color/light_active_color</color> <color name="progress_bar_foreground_white">@android:color/white</color> <color name="progress_bar_secondary">@color/google_grey_600</color> - <color name="progress_bar_background">#3d4386f7</color> + <color name="progress_bar_background">#3D4386F7</color> <color name="progress_bar_background_white">@color/black_alpha_30</color> <!-- Theme colors. Also used for toolbar background --> @@ -146,36 +147,36 @@ <!-- LocationBar colors --> <color name="locationbar_dark_hint_text">@color/black_alpha_54</color> <color name="locationbar_light_hint_text">@color/white_alpha_70</color> - <color name="locationbar_light_selection_color">#cc5595fe</color> + <color name="locationbar_light_selection_color">#CC5595FE</color> <color name="locationbar_status_color">@color/black_alpha_54</color> - <color name="locationbar_status_color_light">#ffffff</color> - <color name="locationbar_status_separator_color">#3d000000</color> - <color name="locationbar_status_separator_color_light">#3dffffff</color> - <color name="omnibox_focused_fading_background_color">#a6000000</color> + <color name="locationbar_status_color_light">@android:color/white</color> + <color name="locationbar_status_separator_color">#3D000000</color> + <color name="locationbar_status_separator_color_light">#3DFFFFFF</color> + <color name="omnibox_focused_fading_background_color">@color/black_alpha_65</color> <!-- Find in Page colors --> - <color name="find_result_bar_background_color">#bfffffff</color> - <color name="find_result_bar_background_border_color">#bf666666</color> - <color name="find_result_bar_result_color">#ffde43</color> - <color name="find_result_bar_result_border_color">#c9af35</color> - <color name="find_result_bar_active_color">#ff9632</color> - <color name="find_result_bar_active_border_color">#c37e3b</color> - <color name="find_in_page_query_white_color">#ffffff</color> - <color name="find_in_page_failed_results_status_color">#db4437</color> + <color name="find_result_bar_background_color">#BFFFFFFF</color> + <color name="find_result_bar_background_border_color">#BF666666</color> + <color name="find_result_bar_result_color">#FFDE43</color> + <color name="find_result_bar_result_border_color">#C9AF35</color> + <color name="find_result_bar_active_color">#FF9632</color> + <color name="find_result_bar_active_border_color">#C37E3B</color> + <color name="find_in_page_query_white_color">@android:color/white</color> + <color name="find_in_page_failed_results_status_color">#DB4437</color> <!-- App Background Colors --> - <color name="light_background_color">#FFFFFF</color> - <color name="resizing_background_color">#FFFFFF</color> + <color name="light_background_color">@android:color/white</color> + <color name="resizing_background_color">@android:color/white</color> <!-- WebappActivity colors --> - <color name="webapp_default_bg">#fafafa</color> - <color name="webapp_splash_title_light">#ffffff</color> + <color name="webapp_default_bg">@color/google_grey_50</color> + <color name="webapp_splash_title_light">@android:color/white</color> <!-- Bookmark UI colors --> <color name="bookmark_detail_section">#7C7B79</color> <!-- Favicon colors --> - <color name="default_favicon_background_color">#ff787878</color> + <color name="default_favicon_background_color">#787878</color> <!-- Photo Picker colors --> <color name="photo_picker_tile_bg_color">@color/google_grey_200</color> @@ -184,25 +185,26 @@ <color name="photo_picker_special_tile_disabled_color">@color/google_grey_400</color> <!-- Bookmark widget colors --> - <color name="bookmark_widget_pressed_highlight">#1D000000</color> + <color name="bookmark_widget_pressed_highlight">@color/black_alpha_11</color> <!-- Physical Web diagnostics colors --> - <color name="physical_web_diags_success_color">#00933b</color> - <color name="physical_web_diags_failure_color">#f90101</color> - <color name="physical_web_diags_indeterminate_color">#f2b50f</color> + <color name="physical_web_diags_success_color">#00933B</color> + <color name="physical_web_diags_failure_color">#F90101</color> + <color name="physical_web_diags_indeterminate_color">#F2B50F</color> <!-- Payments UI colors --> - <color name="payments_section_edit_background">#f5f5f5</color> - <color name="payments_section_chevron">#b2b2b2</color> - <color name="payments_section_separator">#e0e0e0</color> + <color name="payments_section_edit_background">@color/google_grey_100</color> + <color name="payments_section_chevron">#B2B2B2</color> + <color name="payments_section_separator">@color/google_grey_300</color> <!-- Translate Infobar colors --> - <color name="translate_overflow_menu_divider_color">#e0e0e0</color> + <color name="translate_overflow_menu_divider_color">@color/google_grey_300</color> <!-- Other colors --> <color name="media_viewer_bg">#000000</color> - <color name="image_viewer_bg">#0e0e0e</color> - <color name="modern_toolbar_bg">#E6FFFFFF</color> + <color name="image_viewer_bg">#0E0E0E</color> + <color name="modern_toolbar_bg">@color/white_alpha_90</color> <color name="google_blue_500_alpha_38_opaque">#B7D1FB</color> + <color name="toolbar_shadow_color">@color/black_alpha_11</color> </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java index 1243e4d..5687b00a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java
@@ -14,7 +14,6 @@ import android.text.TextUtils; import org.chromium.base.ApplicationStatus; -import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; @@ -28,20 +27,17 @@ import org.chromium.chrome.browser.notifications.NotificationConstants; import org.chromium.chrome.browser.notifications.NotificationUmaTracker; import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions; +import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; -import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl; -import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabModelSelectorMetadata; -import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabPersistentStoreObserver; +import org.chromium.chrome.browser.tabmodel.TabModelObserver; import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.common.Referrer; import org.chromium.ui.widget.Toast; import java.lang.ref.WeakReference; -import java.util.HashSet; -import java.util.List; -import java.util.Set; /** * The foreground service responsible for creating notifications for Browser Actions and keep the @@ -75,12 +71,11 @@ private static int sTitleResId; - private static Set<Integer> sPendingTabIds = new HashSet<Integer>(); - private static int sPendingCreatedUrlNum; + private static int sLoadingUrlNum; - private BrowserActionsTabModelSelector mBrowserActionsSelector; - private TabModelSelectorImpl mTabbedModeTabModelSelector; - private TabPersistentStoreObserver mObserver; + private BrowserActionsTabModelSelector mSelector; + + private TabModelObserver mObserver; @Override public IBinder onBind(Intent intent) { @@ -100,77 +95,74 @@ @Override public int onStartCommand(Intent intent, int flags, int startId) { if (TextUtils.equals(intent.getAction(), ACTION_TAB_CREATION_START)) { - createNotification(false); + sendBrowserActionsNotification(Tab.INVALID_TAB_ID); - String url = IntentUtils.safeGetStringExtra(intent, EXTRA_LINK_URL); + String linkUrl = IntentUtils.safeGetStringExtra(intent, EXTRA_LINK_URL); String sourcePackageName = IntentUtils.safeGetStringExtra(intent, EXTRA_SOURCE_PACKAGE_NAME); - openTabInBackground(url, sourcePackageName); - Toast.makeText(this, R.string.browser_actions_open_in_background_toast_message, + Context context = ContextUtils.getApplicationContext(); + int tabId = openTabInBackground(linkUrl, sourcePackageName); + updateTabIdForNotification(tabId); + if (tabId != Tab.INVALID_TAB_ID) { + finishTabCreation(); + } + Toast.makeText(context, R.string.browser_actions_open_in_background_toast_message, Toast.LENGTH_SHORT) .show(); updateNumTabCreatedInBackground(); NotificationUmaTracker.getInstance().onNotificationShown( NotificationUmaTracker.BROWSER_ACTIONS, ChannelDefinitions.CHANNEL_ID_BROWSER); } else if (TextUtils.equals(intent.getAction(), ACTION_TAB_CREATION_CHROME_DISPLAYED)) { - clearPendingStatus(); - removeObserver(); + setLoadingUrlNum(0); + if (mSelector != null) { + mSelector.getModel(false).removeObserver(mObserver); + } stopForeground(true); } // The service will not be restarted if Chrome get killed. return START_NOT_STICKY; } - private static void clearPendingStatus() { - sPendingTabIds.clear(); - sPendingCreatedUrlNum = 0; + private static void setLoadingUrlNum(int num) { + sLoadingUrlNum = num; } - private void createNotification(boolean isUpdate) { - sendBrowserActionsNotification(isUpdate); - if (isUpdate) { - ContextUtils.getAppSharedPreferences() - .edit() - .putBoolean(PREF_HAS_BROWSER_ACTIONS_NOTIFICATION, true) - .apply(); - } + private void updateTabIdForNotification(int tabId) { + sendBrowserActionsNotification(tabId); + ContextUtils.getAppSharedPreferences() + .edit() + .putBoolean(PREF_HAS_BROWSER_ACTIONS_NOTIFICATION, true) + .apply(); } - private void backgroundServiceIfNecessary() { - if (sPendingTabIds.isEmpty() && sPendingCreatedUrlNum == 0) { - stopForeground(false); - removeObserver(); - } - } - - private void removeObserver() { - if (mObserver == null) return; - if (mBrowserActionsSelector != null) { - mBrowserActionsSelector.removeTabPersistentStoreObserver(mObserver); - } - if (mTabbedModeTabModelSelector != null) { - mTabbedModeTabModelSelector.removeTabPersistentStoreObserver(mObserver); + private void finishTabCreation() { + if (sLoadingUrlNum > 0) { + sLoadingUrlNum--; + if (sLoadingUrlNum == 0) { + stopForeground(false); + if (mSelector != null) { + mSelector.getModel(false).removeObserver(mObserver); + } + } } } @VisibleForTesting static boolean isBackgroundService() { - return sPendingTabIds.isEmpty() && sPendingCreatedUrlNum == 0; + return sLoadingUrlNum == 0; } - private void openTabInBackground(String linkUrl, String sourcePackageName) { + private int openTabInBackground(String linkUrl, String sourcePackageName) { Referrer referrer = IntentHandler.constructValidReferrerForAuthority(sourcePackageName); LoadUrlParams loadUrlParams = new LoadUrlParams(linkUrl); loadUrlParams.setReferrer(referrer); Tab tab = launchTabInRunningTabbedActivity(loadUrlParams); if (tab != null) { - int tabId = tab.getId(); - assert tabId != Tab.INVALID_TAB_ID; - sPendingTabIds.add(tabId); - createNotification(true); - return; + sLoadingUrlNum++; + return tab.getId(); } launchTabInBrowserActionsModel(loadUrlParams); + return Tab.INVALID_TAB_ID; } private Tab launchTabInRunningTabbedActivity(LoadUrlParams loadUrlParams) { @@ -180,61 +172,48 @@ ChromeTabbedActivity activity = (ChromeTabbedActivity) ref.get(); if (activity == null) continue; if (activity.getTabModelSelector() != null) { - mTabbedModeTabModelSelector = (TabModelSelectorImpl) activity.getTabModelSelector(); - mTabbedModeTabModelSelector.addTabPersistentStoreObserver( - getTabPersistentStoreObserver()); - Tab tab = mTabbedModeTabModelSelector.openNewTab( + Tab tab = activity.getTabModelSelector().openNewTab( loadUrlParams, TabLaunchType.FROM_BROWSER_ACTIONS, null, false); assert tab != null; + // TODO(ltian): need to listen to the observer from PersistenceStore when TabState + // is saved to disk. See crbug.com/766349. + tab.addObserver(new EmptyTabObserver() { + @Override + public void onPageLoadFinished(Tab tab) { + finishTabCreation(); + tab.removeObserver(this); + } + }); return tab; } } return null; } - private TabPersistentStoreObserver getTabPersistentStoreObserver() { + private void launchTabInBrowserActionsModel(LoadUrlParams loadUrlParams) { + mSelector = BrowserActionsTabModelSelector.getInstance(); + sLoadingUrlNum++; if (mObserver == null) { - mObserver = new TabPersistentStoreObserver() { + mObserver = new EmptyTabModelObserver() { @Override - public void onMetadataSavedAsynchronously( - TabModelSelectorMetadata modelSelectorMetadata) { - removeSavedTabs(modelSelectorMetadata.normalModelMetadata.ids); - backgroundServiceIfNecessary(); + public void didAddTab(Tab tab, TabLaunchType type) { + assert mSelector != null; + if (!mSelector.isTabStateInitialized()) return; + assert tab != null; + finishTabCreation(); } }; } - return mObserver; + mSelector.getModel(false).addObserver(mObserver); + mSelector.openNewTab(loadUrlParams); } - private void launchTabInBrowserActionsModel(LoadUrlParams loadUrlParams) { - mBrowserActionsSelector = BrowserActionsTabModelSelector.getInstance(); - mBrowserActionsSelector.addTabPersistentStoreObserver(getTabPersistentStoreObserver()); - Callback<Integer> tabCreatedCallback = new Callback<Integer>() { - @Override - public void onResult(Integer tabId) { - // Service has been changed to background by opening Chrome so nothing needs to - // update. - if (sPendingCreatedUrlNum == 0) return; - sPendingCreatedUrlNum--; - if (tabId != Tab.INVALID_TAB_ID) sPendingTabIds.add(tabId); - backgroundServiceIfNecessary(); - createNotification(true); - } - }; - sPendingCreatedUrlNum++; - mBrowserActionsSelector.openNewTab(loadUrlParams, tabCreatedCallback); - } - - private void removeSavedTabs(List<Integer> savedTabIds) { - for (Integer tabId : savedTabIds) sPendingTabIds.remove(tabId); - } - - private void sendBrowserActionsNotification(boolean isUpdate) { - ChromeNotificationBuilder builder = createNotificationBuilder(isUpdate); + private void sendBrowserActionsNotification(int tabId) { + ChromeNotificationBuilder builder = createNotificationBuilder(tabId); startForeground(NotificationConstants.NOTIFICATION_ID_BROWSER_ACTIONS, builder.build()); } - private ChromeNotificationBuilder createNotificationBuilder(boolean isUpdate) { + private ChromeNotificationBuilder createNotificationBuilder(int tabId) { ChromeNotificationBuilder builder = NotificationBuilderFactory .createChromeNotificationBuilder( @@ -243,38 +222,30 @@ .setLocalOnly(true) .setAutoCancel(true) .setContentText(this.getString(R.string.browser_actions_notification_text)); - sTitleResId = getNotificationTitleId(isUpdate); + if (hasBrowserActionsNotification()) { + sTitleResId = R.string.browser_actions_multi_links_open_notification_title; + } else { + sTitleResId = R.string.browser_actions_single_link_open_notification_title; + RecordUserAction.record("BrowserActions.TabOpenedNotificationCreated"); + } builder.setContentTitle(this.getString(sTitleResId)); - sNotificationIntent = buildNotificationIntent(isUpdate); + sNotificationIntent = buildNotificationIntent(tabId); PendingIntent notifyPendingIntent = PendingIntent.getActivity( this, 0, sNotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(notifyPendingIntent); return builder; } - private int getNotificationTitleId(boolean isUpdate) { - if (isUpdate) { - assert sTitleResId != 0; - } else if (hasBrowserActionsNotification()) { - sTitleResId = R.string.browser_actions_multi_links_open_notification_title; - } else { - sTitleResId = R.string.browser_actions_single_link_open_notification_title; - } - return sTitleResId; - } - - /** - * TODO(ltian:) fix ChromeTabbedActivity.processUrlViewIntent to handle Intent after browser - * actions tab merging and use Tab.createBringTabToFrontIntent to create Intent for single url. - */ - private Intent buildNotificationIntent(boolean isUpdate) { - Intent intent; + private Intent buildNotificationIntent(int tabId) { boolean multipleUrls = hasBrowserActionsNotification(); - intent = new Intent(this, ChromeLauncherActivity.class); - IntentHandler.addTrustedIntentExtras(intent); - if (isUpdate) { - intent.putExtra(EXTRA_IS_SINGLE_URL, !multipleUrls); + Intent intent; + if (!multipleUrls && tabId != Tab.INVALID_TAB_ID) { + intent = Tab.createBringTabToFrontIntent(tabId); + } else { + intent = new Intent(this, ChromeLauncherActivity.class); + IntentHandler.addTrustedIntentExtras(intent); } + intent.putExtra(EXTRA_IS_SINGLE_URL, !multipleUrls); return intent; } @@ -300,7 +271,7 @@ public static void onTabbedModeForegrounded() { // If Chrome is shown, force the foreground service to be killed so notification bound to it // will be dismissed. - if (!sPendingTabIds.isEmpty() || sPendingCreatedUrlNum > 0) { + if (sLoadingUrlNum != 0) { Context context = ContextUtils.getApplicationContext(); Intent intent = new Intent(context, BrowserActionsService.class); intent.setAction(ACTION_TAB_CREATION_CHROME_DISPLAYED);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java index 2280d62..350eb2b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java
@@ -6,7 +6,6 @@ import android.os.AsyncTask; -import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.browseractions.BrowserActionsTabCreatorManager.BrowserActionsTabCreator; @@ -127,12 +126,11 @@ /** * Creates a new Tab with given url in Browser Actions tab model. * @param loadUrlParams The url params to be opened. - * @param tabCreatedCallback The {@link Callback} to run when tab is created. */ - public void openNewTab(LoadUrlParams loadUrlParams, Callback<Integer> tabCreatedCallback) { + public void openNewTab(LoadUrlParams loadUrlParams) { // If tab model is restored, directly create a new tab. if (isTabStateInitialized()) { - createNewTab(loadUrlParams, tabCreatedCallback); + createNewTab(loadUrlParams); return; } if (mTabCreationRunnable == null) { @@ -140,7 +138,7 @@ @Override public void run() { for (int i = 0; i < mPendingUrls.size(); i++) { - createNewTab(mPendingUrls.get(i), tabCreatedCallback); + createNewTab(mPendingUrls.get(i)); } mPendingUrls.clear(); } @@ -158,9 +156,8 @@ mPendingUrls.add(loadUrlParams); } - private void createNewTab(LoadUrlParams params, Callback<Integer> tabCreatedCallback) { - Tab tab = openNewTab(params, TabLaunchType.FROM_BROWSER_ACTIONS, null, false); - tabCreatedCallback.onResult(tab.getId()); + private void createNewTab(LoadUrlParams params) { + openNewTab(params, TabLaunchType.FROM_BROWSER_ACTIONS, null, false); } @Override @@ -245,12 +242,4 @@ public void addTabPersistentStoreObserver(TabPersistentStoreObserver observer) { mTabSaver.addObserver(observer); } - - /** - * Remove a {@link TabPersistentStoreObserver} from {@link TabPersistentStore}. - * @param observer The observer to remove. - */ - public void removeTabPersistentStoreObserver(TabPersistentStoreObserver observer) { - mTabSaver.removeObserver(observer); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java index 661b1c4..9efcf40 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -642,6 +642,8 @@ @Override public void swipeUpdated(float x, float y, float dx, float dy, float tx, float ty) { + if (getActiveLayout() == null) return; + // If scroll direction has been computed, send the event to super. if (mScrollDirection != ScrollDirection.UNKNOWN) { super.swipeUpdated(x, y, dx, dy, tx, ty); @@ -651,10 +653,11 @@ mScrollDirection = computeScrollDirection(dx, dy); if (mScrollDirection == ScrollDirection.UNKNOWN) return; - if (mScrollDirection == ScrollDirection.DOWN) { + if (mOverviewLayout != null && mScrollDirection == ScrollDirection.DOWN) { startShowing(mOverviewLayout, true); - } else if (mScrollDirection == ScrollDirection.LEFT - || mScrollDirection == ScrollDirection.RIGHT) { + } else if (mToolbarSwipeLayout != null + && (mScrollDirection == ScrollDirection.LEFT + || mScrollDirection == ScrollDirection.RIGHT)) { startShowing(mToolbarSwipeLayout, true); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBarDelegate.java index e84faf4e..a0a5f26f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBarDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBarDelegate.java
@@ -18,7 +18,7 @@ private InstantAppsBannerData mData; public static void launch(InstantAppsBannerData data) { - nativeLaunch(data.getWebContents(), data, data.getUrl()); + nativeLaunch(data.getWebContents(), data, data.getUrl(), data.isInstantAppDefault()); } @CalledByNative @@ -34,5 +34,5 @@ } private static native void nativeLaunch(WebContents webContents, InstantAppsBannerData data, - String url); + String url, boolean instantAppIsDefault); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java index 255a195..07d88bb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java
@@ -25,6 +25,7 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.util.IntentUtils; +import org.chromium.content_public.browser.WebContents; import java.util.concurrent.TimeUnit; @@ -282,19 +283,36 @@ * @return Whether an Instant App intent was started. */ public boolean handleNavigation(Context context, String url, Uri referrer, Tab tab) { - if (InstantAppsSettings.isInstantAppDefault(tab.getWebContents(), url)) { + boolean urlIsInstantAppDefault = + InstantAppsSettings.isInstantAppDefault(tab.getWebContents(), url); + if (shouldLaunchInstantApp(tab.getWebContents(), url, referrer, urlIsInstantAppDefault)) { return launchInstantAppForNavigation(context, url, referrer); } - maybeShowInstantAppBanner(context, url, referrer, tab); + maybeShowInstantAppBanner(context, url, referrer, tab, urlIsInstantAppDefault); return false; } /** - * Shows an Instant App banner if necessary for the page we're loading. + * Returns whether or not we should launch an instant app immediately for the given URL. + * + * @param webContents A {@link WebContents}. + * @param url The URL we might launch an instant app for. + * @param referrer The referring URL. + * @return Whether we should launch the instant app. */ - @Deprecated - protected void maybeShowInstantAppBanner(Context context, String url, Uri referrer, Tab tab) { - maybeShowInstantAppBanner(context, url, referrer, tab, false /* isInstantAppDefault */); + private boolean shouldLaunchInstantApp( + WebContents webContents, String url, Uri referrer, boolean urlIsInstantAppDefault) { + // Launch the instant app automatically on these conditions: + // a) The host of the current URL and referrer are different, and the user has chosen to + // launch this instant app in the past. + // b) The host of the current URL and referrer are the same, but the referrer URL isn't + // handled by an instant app and the current one is. + if (!urlIsInstantAppDefault) return false; + + String urlHost = Uri.parse(url).getHost(); + boolean sameHosts = + referrer != null && urlHost != null && urlHost.equals(referrer.getHost()); + return (sameHosts && getInstantAppIntentForUrl(referrer.toString()) == null) || !sameHosts; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java index d3c519f6..9f89445 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -94,7 +94,7 @@ /** * Default experiment parameter value for the logo height in dp in the condensed layout. */ - private static final int PARAM_DEFAULT_VALUE_CONDENSED_LAYOUT_LOGO_HEIGHT_DP = 50; + private static final int PARAM_DEFAULT_VALUE_CONDENSED_LAYOUT_LOGO_HEIGHT_DP = 100; private NewTabPageRecyclerView mRecyclerView;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksCache.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksCache.java deleted file mode 100644 index 7c8937b..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksCache.java +++ /dev/null
@@ -1,77 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.partnerbookmarks; - -import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; - -import org.chromium.base.VisibleForTesting; - -import java.util.Map; - -/** - * A cache for storing failed favicon loads along with a timestamp determining what point we can - * attempt retrieval again, as a way of throttling the number of requests made for previously failed - * favicon fetch attempts. - */ -public class PartnerBookmarksCache { - private static final String PREFERENCES_NAME = "partner_bookmarks_favicon_cache"; - - private final SharedPreferences mSharedPreferences; - - public PartnerBookmarksCache(Context context) { - this(context, PREFERENCES_NAME); - } - - @VisibleForTesting - PartnerBookmarksCache(Context context, String cacheName) { - mSharedPreferences = context.getSharedPreferences(cacheName, 0); - } - - /** - * Reads the favicon retrieval timestamp information from a cache-specific - * {@link SharedPreferences}. - * - * Suppressing "unchecked" because we're 100% sure we're storing only <String, Long> pairs in - * our cache. - * - * @return A map with the favicon URLs that failed retrieval and a timestamp after which we - * can retry again. - */ - @SuppressWarnings("unchecked") - public Map<String, Long> read() { - return (Map<String, Long>) mSharedPreferences.getAll(); - } - - /** - * Writes the provided map into the cache's {@link SharedPreferences}. - * This overwrites what was previously in the cache. - * - * @param inMap The favicon/timestamps to write to cache. - */ - public void write(Map<String, Long> inMap) { - if (inMap == null) { - throw new IllegalArgumentException("PartnerBookmarksCache: write() " - + "input cannot be null."); - } - - Editor editor = mSharedPreferences.edit(); - editor.clear(); - for (Map.Entry<String, Long> entry : inMap.entrySet()) { - editor.putLong(entry.getKey(), entry.getValue()); - } - editor.apply(); - } - - /** - * Called after tests so we don't leave behind test {@link SharedPreferences}, and have data - * from one test run into another. - */ - @VisibleForTesting - void clearCache() { - mSharedPreferences.edit().clear().apply(); - } -} \ No newline at end of file
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 new file mode 100644 index 0000000..1d972eaf --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java
@@ -0,0 +1,145 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.partnerbookmarks; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; + +import org.chromium.base.VisibleForTesting; +import org.chromium.base.metrics.RecordHistogram; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * Stores failed favicon loads along with a timestamp determining what point we can attempt + * retrieval again, as a way of throttling the number of requests made for previously failed favicon + * fetch attempts. + */ +public class PartnerBookmarksFaviconThrottle { + private static final String PREFERENCES_NAME = "partner_bookmarks_favicon_throttle"; + private static final long FAVICON_RETRIEVAL_TIMEOUT_MS = TimeUnit.DAYS.toMillis(30); + + private final SharedPreferences mSharedPreferences; + + private Map<String, Long> mCurrentEntries; + private Map<String, Long> mNewEntries; + + public PartnerBookmarksFaviconThrottle(Context context) { + this(context, PREFERENCES_NAME); + } + + @VisibleForTesting + PartnerBookmarksFaviconThrottle(Context context, String name) { + mSharedPreferences = context.getSharedPreferences(name, 0); + init(); + } + + /** + * Reads the favicon retrieval timestamp information from our own {@link SharedPreferences}. + * + * Suppressing "unchecked" because we're 100% sure we're storing only <String, Long> pairs. + */ + @SuppressWarnings("unchecked") + @VisibleForTesting + void init() { + mCurrentEntries = (Map<String, Long>) mSharedPreferences.getAll(); + RecordHistogram.recordCount100Histogram( + "PartnerBookmarksFaviconThrottle.NumEntries", mCurrentEntries.size()); + mNewEntries = new HashMap<String, Long>(); + } + + /** + * Writes the new map that was built as a result of the calls to {@link #onFaviconFetched} to + * disk in our {@link SharedPreferences}. This overwrites previously stored entries. + */ + public void commit() { + assert mNewEntries != null; + + // Save ourselves a write to disk if the current entries and new entries are identical. + if (mCurrentEntries.equals(mNewEntries)) { + return; + } + + Editor editor = mSharedPreferences.edit(); + editor.clear(); + for (Map.Entry<String, Long> entry : mNewEntries.entrySet()) { + editor.putLong(entry.getKey(), entry.getValue()); + } + editor.apply(); + } + + /** + * Calling this with each favicon fetch URL and result builds the new output entries to be + * written to disk when {@link #commit} is called. + * + * @param url The page URL we attempted to fetch a favicon for. + * @param result The {@link FaviconFetchResult} response we got for this URL. + */ + public void onFaviconFetched(String url, @FaviconFetchResult int result) { + assert mCurrentEntries != null; + assert mNewEntries != null; + + if (result == FaviconFetchResult.FAILURE_SERVER_ERROR) { + mNewEntries.put(url, System.currentTimeMillis() + FAVICON_RETRIEVAL_TIMEOUT_MS); + } else if (result != FaviconFetchResult.SUCCESS && !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. + mNewEntries.put(url, mCurrentEntries.get(url)); + } + } + + /** + * 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. + * + * @param url The page URL we need a favicon for. + * @return Whether or not we should fetch the favicon from server if necessary. + */ + public boolean shouldFetchFromServerIfNecessary(String url) { + Long expiryTimeMs = getExpiryOf(url); + return expiryTimeMs == null || System.currentTimeMillis() >= expiryTimeMs; + } + + /** + * Gets the expiry time in ms of a particular URL for which we're fetching a favicon. URLs that + * have previously failed to retrieve a favicon from a server will have a value at which point + * we should attempt a retrieval again, otherwise we return null for entries not in our set of + * entries. + * + * @param url The page URL we're trying to fetch a favicon for. + * @return The expiry time of the favicon fetching restriction in milliseconds, if we have a + * corresponding entry for this URL. + */ + private Long getExpiryOf(String url) { + assert mCurrentEntries != null; + + if (mCurrentEntries.containsKey(url)) { + return mCurrentEntries.get(url); + } + return null; + } + + /** + * Called after tests so we don't leave behind test {@link SharedPreferences}, and have data + * from one test run into another. + */ + @VisibleForTesting + void clearEntries() { + mSharedPreferences.edit().clear().apply(); + } + + /** + * @return Number of stored entries. + */ + @VisibleForTesting + int numEntries() { + assert mCurrentEntries != null; + return mCurrentEntries.size(); + } +}
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 73f589f..8a9b291 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
@@ -13,8 +13,6 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.AppHooks; -import org.chromium.chrome.browser.ChromeVersionInfo; -import org.chromium.chrome.browser.ntp.snippets.FaviconFetchResult; import java.util.HashSet; import java.util.LinkedHashMap; @@ -38,6 +36,9 @@ /** ID used to indicate an invalid bookmark node. */ static final long INVALID_BOOKMARK_ID = -1; + /** Storage for failed favicon retrieval attempts to throttle future requests. **/ + private PartnerBookmarksFaviconThrottle mFaviconThrottle; + // JNI c++ pointer private long mNativePartnerBookmarksReader; @@ -102,7 +103,11 @@ FetchFaviconCallback callback = new FetchFaviconCallback() { @Override public void onFaviconFetched(@FaviconFetchResult int result) { + RecordHistogram.recordEnumeratedHistogram( + "PartnerBookmark.FaviconThrottleFetchResult", result, + FaviconFetchResult.UMA_BOUNDARY); synchronized (mProgressLock) { + mFaviconThrottle.onFaviconFetched(url, result); --mNumFaviconsInProgress; if (mNumFaviconsInProgress == 0 && mFinishedReading) { shutDown(); @@ -117,11 +122,9 @@ } } }; - // TODO(thildebr): Enable fetching from server once we have a cache to store failed attempts - // to retrieve favicons so we don't retry too often. return nativeAddPartnerBookmark(mNativePartnerBookmarksReader, url, title, isFolder, parentId, favicon, touchicon, - ChromeVersionInfo.isCanaryBuild() /* fetchUncachedFaviconsFromServer */, callback); + mFaviconThrottle.shouldFetchFromServerIfNecessary(url), callback); } /** @@ -145,6 +148,9 @@ nativePartnerBookmarksCreationComplete(mNativePartnerBookmarksReader); nativeDestroy(mNativePartnerBookmarksReader); mNativePartnerBookmarksReader = 0; + if (mFaviconThrottle != null) { + mFaviconThrottle.commit(); + } mShutDown = true; } } @@ -165,6 +171,11 @@ @Override protected Void doInBackground(Void... params) { + if (mFaviconThrottle == null) { + // Initialize the throttle here since we need to load shared preferences on the + // background thread as well. + mFaviconThrottle = new PartnerBookmarksFaviconThrottle(mContext); + } PartnerBookmark.BookmarkIterator bookmarkIterator = AppHooks.get().getPartnerBookmarkIterator(); RecordHistogram.recordBooleanHistogram(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java index ef9d878..40363fe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
@@ -424,12 +424,4 @@ public void addTabPersistentStoreObserver(TabPersistentStoreObserver observer) { mTabSaver.addObserver(observer); } - - /** - * Remove a {@link TabPersistentStoreObserver} from {@link TabPersistentStore}. - * @param observer The observer to remove. - */ - public void removeTabPersistentStoreObserver(TabPersistentStoreObserver observer) { - mTabSaver.removeObserver(observer); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java index fc2ef7f..4069b1f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -29,6 +29,7 @@ import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.firstrun.FirstRunUtils; +import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.metrics.UmaSessionStats; import org.chromium.chrome.browser.omnibox.OmniboxPlaceholderFieldTrial; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; @@ -279,10 +280,7 @@ manager.setChromeHomeEnabled(isChromeHomeEnabled); PrefServiceBridge.getInstance().setChromeHomePersonalizedOmniboxSuggestionsEnabled( - !isChromeHomeEnabled() - ? false - : ChromeFeatureList.isEnabled( - ChromeFeatureList.CHROME_HOME_PERSONALIZED_OMNIBOX_SUGGESTIONS)); + areChromeHomePersonalizedOmniboxSuggestionsEnabled()); if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME_PROMO) && manager.isChromeHomeUserPreferenceSet()) { @@ -298,6 +296,14 @@ isChromeHomeEnabled() ? ENABLED_EXPERIMENT_GROUP : DISABLED_EXPERIMENT_GROUP); } + private static boolean areChromeHomePersonalizedOmniboxSuggestionsEnabled() { + LocaleManager localeManager = LocaleManager.getInstance(); + return isChromeHomeEnabled() && !localeManager.hasCompletedSearchEnginePromo() + && !localeManager.hasShownSearchEnginePromoThisSession() + && ChromeFeatureList.isEnabled( + ChromeFeatureList.CHROME_HOME_PERSONALIZED_OMNIBOX_SUGGESTIONS); + } + /** * Update the user's setting for Chrome Home. This is a user-facing setting different from the * one in chrome://flags. This setting will take prescience over the one in flags.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java index cfc6a29..a424229a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -1155,6 +1155,11 @@ mPaused = false; + // We call resume here to be symmetric with onPause in case we get paused/resumed without + // being hidden/shown. However, we still don't want to resume if we're not visible to avoid + // doing VR rendering that won't be seen. + if (mInVr && mVisible) mVrShell.resume(); + maybeUpdateVrSupportLevel(); StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); @@ -1221,13 +1226,13 @@ // Only resume VrShell once we're visible so that we don't start rendering before being // visible and delaying startup. - if (mInVr) mVrShell.resume(); + if (mInVr && !mPaused) mVrShell.resume(); } private void onActivityHidden() { mVisible = false; - // We defer pausing of VrShell until the app is no longer visible to keep head tracking - // working for as long as possible while going to daydream home. + // In case we're hidden before onPause is called, we pause here. Duplicate calls to pause + // are safe. if (mInVr) mVrShell.pause(); if (mShowingDaydreamDoff || mProbablyInDon) return; @@ -1257,6 +1262,7 @@ // vrdisplayactivate event should be dispatched in enterVRFromIntent. mListeningForWebVrActivateBeforePause = mListeningForWebVrActivate; + if (mInVr) mVrShell.pause(); if (mNativeVrShellDelegate != 0) nativeOnPause(mNativeVrShellDelegate); mIsDaydreamCurrentViewer = null; @@ -1391,6 +1397,10 @@ promptForFeedbackIfNeeded(stayingInChrome); + // Listener may not have been handled yet at this point due to other reasons (e.g back/close + // button was pressed while at exit prompt UI in VR), failure should be reported despite + // that we are exiting VR. + callOnExitVrRequestListener(false); assert mOnExitVrRequestListener == null; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java index dc40f23..5c0b8488 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -540,7 +540,7 @@ * @param microsPerDp The microseconds per dp being recorded. */ private void recordSwipeVelocity(String name, int microsPerDp) { - RecordHistogram.recordCustomCountHistogram(name, microsPerDp, 0, 20000, 50); + RecordHistogram.recordCustomCountHistogram(name, microsPerDp, 1, 20000, 50); } /**
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 3205c09..12e0090c 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2187,6 +2187,9 @@ </message> <!-- First Run strings --> + <message name="IDS_FRE_ACTIVITY_LABEL" desc="Label for first run dialog in Android Recents."> + Chrome First Run Experience + </message> <message name="IDS_FRE_SKIP_TEXT" desc="Text for second page skip button"> No thanks </message>
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index bb96d92..7fde439 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -796,7 +796,7 @@ "java/src/org/chromium/chrome/browser/page_info/ConnectionInfoPopup.java", "java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java", "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmark.java", - "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksCache.java", + "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java", "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java", "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java", "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java", @@ -1935,8 +1935,8 @@ "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java", "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java", "junit/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java", - "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksCacheTest.java", "junit/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizationsUnitTest.java", + "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java", "junit/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderUnitTest.java", "junit/src/org/chromium/chrome/browser/payments/AutofillContactTest.java", "junit/src/org/chromium/chrome/browser/payments/AutofillContactUnitTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java index e2f1d9a..1d63ce5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
@@ -247,7 +247,7 @@ @Override protected void maybeShowInstantAppBanner( - Context context, String url, Uri referrer, Tab tab) { + Context context, String url, Uri referrer, Tab tab, boolean instantAppIsDefault) { mStartedAsyncCall = true; } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java index 54707b8..6bce3a3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java
@@ -32,6 +32,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.R; @@ -58,6 +59,7 @@ @SmallTest @Feature({"Browser", "Notifications"}) @SuppressLint("NewApi") + @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228") public void testSetAll() { Context context = InstrumentationRegistry.getTargetContext(); @@ -144,6 +146,7 @@ @Test @SmallTest @Feature({"Browser", "Notifications"}) + @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228") public void testZeroActionButtons() { Context context = InstrumentationRegistry.getTargetContext(); Notification notification = @@ -161,6 +164,7 @@ @Test @SmallTest @Feature({"Browser", "Notifications"}) + @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228") public void testMaxActionButtons() { Context context = InstrumentationRegistry.getTargetContext(); NotificationBuilderBase builder = @@ -188,6 +192,7 @@ @Test @SmallTest @Feature({"Browser", "Notifications"}) + @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228") public void testPaintIcons() { Context context = InstrumentationRegistry.getTargetContext(); @@ -230,6 +235,7 @@ @Test @SmallTest @Feature({"Browser", "Notifications"}) + @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228") public void testCharSequenceLimits() { Context context = InstrumentationRegistry.getTargetContext(); int maxLength = CustomNotificationBuilder.MAX_CHARSEQUENCE_LENGTH; @@ -260,6 +266,7 @@ @Test @SmallTest @Feature({"Browser", "Notifications"}) + @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228") public void testCalculateMaxBodyLines() { Assert.assertEquals(7, CustomNotificationBuilder.calculateMaxBodyLines(-1000.0f)); Assert.assertEquals(7, CustomNotificationBuilder.calculateMaxBodyLines(0.5f)); @@ -271,6 +278,7 @@ @Test @SmallTest @Feature({"Browser", "Notifications"}) + @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228") public void testCalculateScaledPadding() { DisplayMetrics metrics = new DisplayMetrics(); metrics.density = 10.0f; @@ -287,6 +295,7 @@ @Test @SmallTest @Feature({"Browser", "Notifications"}) + @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228") public void testGeneratesLargeIconFromOriginWhenNoLargeIconProvided() { Context context = InstrumentationRegistry.getTargetContext(); NotificationBuilderBase notificationBuilder = @@ -304,6 +313,7 @@ @Test @SmallTest @Feature({"Browser", "Notifications"}) + @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228") public void testGeneratesLargeIconFromOriginWhenLargeIconProvidedIsNull() { Context context = InstrumentationRegistry.getTargetContext(); NotificationBuilderBase notificationBuilder = @@ -330,6 +340,7 @@ @TargetApi(Build.VERSION_CODES.KITKAT_WATCH) // RemoteInputs were only added in KITKAT_WATCH. @SmallTest @Feature({"Browser", "Notifications"}) + @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228") public void testAddTextActionSetsRemoteInput() { Context context = InstrumentationRegistry.getTargetContext(); NotificationBuilderBase notificationBuilder =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java new file mode 100644 index 0000000..99a54e9 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java
@@ -0,0 +1,45 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.profiling_host; + +import android.support.test.filters.MediumTest; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.test.ChromeActivityTestRule; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; + +/** + * Test suite for out of process heap profiling. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, + ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG}) +public class ProfilingProcessHostAndroidTest { + private static final String TAG = "ProfilingProcessHostAndroidTest"; + @Rule + public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = + new ChromeActivityTestRule<>(ChromeActivity.class); + + @Before + public void setUp() throws InterruptedException { + mActivityTestRule.startMainActivityOnBlankPage(); + } + + @Test + @MediumTest + @CommandLineFlags.Add({"memlog=browser"}) + public void testModeBrowser() throws Exception { + TestAndroidShim profilingProcessHost = new TestAndroidShim(); + Assert.assertTrue(profilingProcessHost.runTestForMode("browser")); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/TestAndroidShim.java b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/TestAndroidShim.java new file mode 100644 index 0000000..8679d6f --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/TestAndroidShim.java
@@ -0,0 +1,38 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.profiling_host; + +import org.chromium.base.annotations.MainDex; + +/** + * Provides direct access to test_android_shim, which in turn forwards to + * ProfilingTestDriver. Only used for testing. + */ +@MainDex +public class TestAndroidShim { + public TestAndroidShim() { + mNativeTestAndroidShim = nativeInit(); + } + + public boolean runTestForMode(String mode) { + return nativeRunTestForMode(mNativeTestAndroidShim, mode); + } + + /** + * Clean up the C++ side of this class. + * After the call, this class instance shouldn't be used. + */ + public void destroy() { + if (mNativeTestAndroidShim != 0) { + nativeDestroy(mNativeTestAndroidShim); + mNativeTestAndroidShim = 0; + } + } + + private long mNativeTestAndroidShim; + private native long nativeInit(); + private native void nativeDestroy(long nativeTestAndroidShim); + private native boolean nativeRunTestForMode(long nativeTestAndroidShim, String mode); +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java index b95d7c90..0eb8295 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java
@@ -323,19 +323,27 @@ Assert.assertFalse("Back button isn't disabled.", VrTransitionUtils.isBackButtonEnabled()); Assert.assertFalse( "Forward button isn't disabled.", VrTransitionUtils.isForwardButtonEnabled()); + // Opening a new tab shouldn't enable the back button mVrTestRule.loadUrlInNewTab(getUrl(Page.PAGE_2D), false, TabLaunchType.FROM_CHROME_UI); Assert.assertFalse("Back button isn't disabled.", VrTransitionUtils.isBackButtonEnabled()); Assert.assertFalse( "Forward button isn't disabled.", VrTransitionUtils.isForwardButtonEnabled()); + // Navigating to a new page should enable the back button mVrTestRule.loadUrl(getUrl(Page.PAGE_WEBVR)); Assert.assertTrue("Back button isn't enabled.", VrTransitionUtils.isBackButtonEnabled()); Assert.assertFalse( "Forward button isn't disabled.", VrTransitionUtils.isForwardButtonEnabled()); + // Navigating back should disable the back button and enable the forward button VrTransitionUtils.navigateBack(); + ChromeTabUtils.waitForTabPageLoaded( + mVrTestRule.getActivity().getActivityTab(), getUrl(Page.PAGE_2D)); Assert.assertFalse("Back button isn't disabled.", VrTransitionUtils.isBackButtonEnabled()); Assert.assertTrue( "Forward button isn't enabled.", VrTransitionUtils.isForwardButtonEnabled()); + // Navigating forward should disable the forward button and enable the back button VrTransitionUtils.navigateForward(); + ChromeTabUtils.waitForTabPageLoaded( + mVrTestRule.getActivity().getActivityTab(), getUrl(Page.PAGE_WEBVR)); Assert.assertTrue("Back button isn't enabled.", VrTransitionUtils.isBackButtonEnabled()); Assert.assertFalse( "Forward button isn't disabled.", VrTransitionUtils.isForwardButtonEnabled());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java index bdb1198..9dab16c9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
@@ -35,6 +35,7 @@ import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.OverrideUrlLoadingResult; import org.chromium.chrome.browser.firstrun.FirstRunStatus; import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl; +import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.MenuUtils; @@ -66,43 +67,79 @@ @Rule public final NativeLibraryTestRule mNativeLibraryTestRule = new NativeLibraryTestRule(); + /** + * Test that navigating a webapp whose launch intent does not specify a theme colour outside of + * the webapp scope by tapping a regular link: + * - Shows a CCT-like webapp toolbar. + * - Uses the default theme colour as the toolbar colour. + */ @Test @SmallTest @Feature({"Webapps"}) @RetryOnFailure - public void testRegularLinkOffOriginInCctNoWebappThemeColor() throws Exception { + public void testRegularLinkOffOriginNoWebappThemeColor() throws Exception { WebappActivity activity = runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent()); + assertToolbarShowState(activity, false); + + addAnchorAndClick(offOriginUrl(), "_self"); + + ChromeTabUtils.waitForTabPageLoaded(activity.getActivityTab(), offOriginUrl()); + assertToolbarShowState(activity, true); Assert.assertEquals( - "Toolbar should use default primary color if theme color is not specified", - ApiCompatibilityUtils.getColor( - activity.getResources(), R.color.default_primary_color), - activity.getToolbarManager().getPrimaryColor()); - - addAnchor("testId", offOriginUrl(), "_self"); - DOMUtils.clickNode(activity.getActivityTab().getContentViewCore(), "testId"); - mActivityTestRule.waitUntilIdle(); - - assertOffOrigin(activity); + getDefaultPrimaryColor(), activity.getToolbarManager().getPrimaryColor()); } + /** + * Test that navigating a webapp whose launch intent specifies a theme colour outside of the + * webapp scope by tapping a regular link: + * - Shows a CCT-like webapp toolbar. + * - Uses the webapp theme colour as the toolbar colour. + */ @Test @SmallTest @Feature({"Webapps"}) @RetryOnFailure - public void testWindowTopLocationOffOriginInCctAndWebappThemeColor() throws Exception { + public void testRegularLinkOffOriginThemeColor() throws Exception { WebappActivity activity = runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent().putExtra( ShortcutHelper.EXTRA_THEME_COLOR, (long) Color.CYAN)); - Assert.assertEquals("Toolbar should use the theme color of a webapp", Color.CYAN, - activity.getToolbarManager().getPrimaryColor()); + assertToolbarShowState(activity, false); + + addAnchorAndClick(offOriginUrl(), "_self"); + + ChromeTabUtils.waitForTabPageLoaded(activity.getActivityTab(), offOriginUrl()); + assertToolbarShowState(activity, true); + Assert.assertEquals(Color.CYAN, activity.getToolbarManager().getPrimaryColor()); + } + + /** + * Test that navigating outside of the webapp scope by changing the top location via JavaScript: + * - Shows a CCT-like webapp toolbar. + * - Preserves the theme color specified in the launch intent. + */ + @Test + @SmallTest + @Feature({"Webapps"}) + @RetryOnFailure + public void testWindowTopLocationOffOrigin() throws Exception { + WebappActivity activity = + runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent().putExtra( + ShortcutHelper.EXTRA_THEME_COLOR, (long) Color.CYAN)); + assertToolbarShowState(activity, false); mActivityTestRule.runJavaScriptCodeInCurrentTab( String.format("window.top.location = '%s'", offOriginUrl())); - mActivityTestRule.waitUntilIdle(); - assertOffOrigin(activity); + ChromeTabUtils.waitForTabPageLoaded(activity.getActivityTab(), offOriginUrl()); + assertToolbarShowState(activity, true); + Assert.assertEquals(Color.CYAN, activity.getToolbarManager().getPrimaryColor()); } + /** + * Test that navigating outside of the webapp scope by tapping a link with target="_blank": + * - Launches a CCT. + * - The CCT toolbar does not use the webapp theme colour. + */ @Test @SmallTest @Feature({"Webapps"}) @@ -110,40 +147,46 @@ public void testOffScopeNewTabLinkOpensInCct() throws Exception { runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent().putExtra( ShortcutHelper.EXTRA_THEME_COLOR, (long) Color.CYAN)); - addAnchor("testId", offOriginUrl(), "_blank"); - DOMUtils.clickNode( - mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), "testId"); - CustomTabActivity customTab = assertCustomTabActivityLaunchedForOffOriginUrl(); + addAnchorAndClick(offOriginUrl(), "_blank"); + CustomTabActivity customTab = waitFor(CustomTabActivity.class); + ChromeTabUtils.waitForTabPageLoaded(customTab.getActivityTab(), offOriginUrl()); + Assert.assertEquals( - "CCT Toolbar should use default primary color even if webapp has theme color", - ApiCompatibilityUtils.getColor( - customTab.getResources(), R.color.default_primary_color), - customTab.getToolbarManager().getPrimaryColor()); + getDefaultPrimaryColor(), customTab.getToolbarManager().getPrimaryColor()); } + /** + * Test that navigating within the webapp scope by tapping a link with target="_blank" launches + * a CCT. + */ @Test @SmallTest @Feature({"Webapps"}) @RetryOnFailure public void testInScopeNewTabLinkOpensInCct() throws Exception { + String inScopeUrl = mActivityTestRule.getTestServer().getURL(IN_SCOPE_PAGE_PATH); runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent().putExtra( ShortcutHelper.EXTRA_THEME_COLOR, (long) Color.CYAN)); - addAnchor("testId", mActivityTestRule.getTestServer().getURL(IN_SCOPE_PAGE_PATH), "_blank"); - DOMUtils.clickNode( - mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), "testId"); + addAnchorAndClick(inScopeUrl, "_blank"); CustomTabActivity customTab = waitFor(CustomTabActivity.class); - mActivityTestRule.waitUntilIdle(customTab); + ChromeTabUtils.waitForTabPageLoaded(customTab.getActivityTab(), inScopeUrl); Assert.assertTrue( mActivityTestRule.runJavaScriptCodeInCurrentTab("document.body.textContent") .contains("Do-nothing page with a service worker")); } + /** + * Test that navigating outside of the webapp via window.open(): + * - Launches a CCT. + * - The CCT toolbar does not use the webapp theme colour. + */ @Test @SmallTest @Feature({"Webapps"}) @RetryOnFailure public void testWindowOpenInCct() throws Exception { - runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent()); + runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent().putExtra( + ShortcutHelper.EXTRA_THEME_COLOR, (long) Color.CYAN)); // Executing window.open() through a click on a link, // as it needs user gesture to avoid Chrome blocking it as a popup. mActivityTestRule.runJavaScriptCodeInCurrentTab( @@ -159,30 +202,28 @@ DOMUtils.clickNode( mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), "testId"); - CustomTabActivity customTab = assertCustomTabActivityLaunchedForOffOriginUrl(); - Assert.assertEquals("CCT Toolbar should use default primary color", - ApiCompatibilityUtils.getColor( - customTab.getResources(), R.color.default_primary_color), - customTab.getToolbarManager().getPrimaryColor()); + CustomTabActivity customTab = waitFor(CustomTabActivity.class); + ChromeTabUtils.waitForTabPageLoaded(customTab.getActivityTab(), offOriginUrl()); + Assert.assertEquals( + getDefaultPrimaryColor(), customTab.getToolbarManager().getPrimaryColor()); } + /** + * Test that navigating a webapp within the webapp scope by tapping a regular link: + * - Does not show a CCT-like webapp toolbar. + * - Does not launch a CCT. + */ @Test @SmallTest @Feature({"Webapps"}) @RetryOnFailure public void testInScopeNavigationStaysInWebapp() throws Exception { - runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent()); - + WebappActivity activity = runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent()); String otherPageUrl = mActivityTestRule.getTestServer().getURL(IN_SCOPE_PAGE_PATH); - mActivityTestRule.loadUrlInTab(otherPageUrl, PageTransition.LINK, - mActivityTestRule.getActivity().getActivityTab()); + addAnchorAndClick(otherPageUrl, "_self"); + ChromeTabUtils.waitForTabPageLoaded(activity.getActivityTab(), otherPageUrl); - mActivityTestRule.waitUntilIdle(); - Assert.assertEquals( - otherPageUrl, mActivityTestRule.getActivity().getActivityTab().getUrl()); - - Assert.assertSame( - mActivityTestRule.getActivity(), ApplicationStatus.getLastTrackedFocusedActivity()); + assertToolbarShowState(activity, false); } @Test @@ -202,9 +243,7 @@ R.id.contextmenu_open_in_chrome); ChromeTabbedActivity tabbedChrome = waitFor(ChromeTabbedActivity.class); - - mActivityTestRule.waitUntilIdle(tabbedChrome); - assertOffOrigin(tabbedChrome); + ChromeTabUtils.waitForTabPageLoaded(tabbedChrome.getActivityTab(), offOriginUrl()); } @Test @@ -220,11 +259,8 @@ InstrumentationRegistry.getInstrumentation(), activity, R.id.open_in_browser_id); ChromeTabbedActivity tabbedChrome = waitFor(ChromeTabbedActivity.class); - mActivityTestRule.waitUntilIdle(tabbedChrome); - - Assert.assertEquals("Tab in tabbed activity should show the Web App page", - mActivityTestRule.getTestServer().getURL(WEB_APP_PATH), - tabbedChrome.getActivityTab().getUrl()); + ChromeTabUtils.waitForTabPageLoaded(tabbedChrome.getActivityTab(), + mActivityTestRule.getTestServer().getURL(WEB_APP_PATH)); } @Test @@ -237,9 +273,7 @@ InterceptNavigationDelegateImpl navigationDelegate = mActivityTestRule.getActivity().getActivityTab().getInterceptNavigationDelegate(); - addAnchor("testLink", YOUTUBE_URL, "_self"); - DOMUtils.clickNode( - mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), "testLink"); + addAnchorAndClick(YOUTUBE_URL, "_self"); waitForExternalAppOrIntentPicker(); Assert.assertEquals(OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, @@ -253,9 +287,7 @@ public void testNewTabLinkToExternalApp() throws Exception { runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent()); - addAnchor("testLink", YOUTUBE_URL, "_blank"); - DOMUtils.clickNode( - mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), "testLink"); + addAnchorAndClick(YOUTUBE_URL, "_blank"); waitForExternalAppOrIntentPicker(); } @@ -275,13 +307,9 @@ mActivityTestRule.getActivity(), R.id.open_in_browser_id); ChromeTabbedActivity tabbedChrome = waitFor(ChromeTabbedActivity.class); - mActivityTestRule.waitUntilIdle(tabbedChrome); - ThreadUtils.runOnUiThreadBlocking( () -> tabbedChrome.getActivityTab().loadUrl(new LoadUrlParams(offOriginUrl()))); - - mActivityTestRule.waitUntilIdle(tabbedChrome); - assertOffOrigin(tabbedChrome); + ChromeTabUtils.waitForTabPageLoaded(tabbedChrome.getActivityTab(), offOriginUrl()); } @Test @@ -290,30 +318,27 @@ @RetryOnFailure public void testCloseButtonReturnsToMostRecentInScopeUrl() throws Exception { WebappActivity activity = runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent()); + Tab tab = activity.getActivityTab(); String otherInScopeUrl = mActivityTestRule.getTestServer().getURL(IN_SCOPE_PAGE_PATH); mActivityTestRule.loadUrlInTab( otherInScopeUrl, PageTransition.LINK, activity.getActivityTab()); - Assert.assertEquals(otherInScopeUrl, activity.getActivityTab().getUrl()); + Assert.assertEquals(otherInScopeUrl, tab.getUrl()); - ThreadUtils.runOnUiThreadBlocking(() -> activity.getActivityTab().loadUrl( - new LoadUrlParams(offOriginUrl(), PageTransition.LINK))); - assertOffOrigin(activity); - ThreadUtils.runOnUiThreadBlocking(() -> activity.getActivityTab().loadUrl( - new LoadUrlParams("https://www.mozilla.org/", PageTransition.LINK))); - mActivityTestRule.waitUntilIdle(); + mActivityTestRule.loadUrlInTab(offOriginUrl(), PageTransition.LINK, tab); + String mozillaUrl = mActivityTestRule.getTestServer().getURLWithHostName( + "mozilla.org", "/defaultresponse"); + mActivityTestRule.loadUrlInTab(mozillaUrl, PageTransition.LINK, tab); + + // Toolbar with the close button should be visible. + assertToolbarShowState(activity, true); // Navigate back to in-scope through a close button. ThreadUtils.runOnUiThreadBlocking(() -> activity.getToolbarManager() .getToolbarLayout().findViewById(R.id.close_button).callOnClick()); // We should end up on most recent in-scope URL. - CriteriaHelper.pollUiThread(new Criteria() { - @Override - public boolean isSatisfied() { - return otherInScopeUrl.equals(activity.getActivityTab().getUrl()); - } - }); + ChromeTabUtils.waitForTabPageLoaded(tab, otherInScopeUrl); } @Test @@ -353,24 +378,24 @@ return mActivityTestRule.getActivity(); } - private CustomTabActivity assertCustomTabActivityLaunchedForOffOriginUrl() - throws InterruptedException { - CustomTabActivity customTab = waitFor(CustomTabActivity.class); + private void assertToolbarShowState(final ChromeActivity activity, final boolean showState) { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + Assert.assertEquals(showState, activity.getActivityTab().canShowBrowserControls()); + } + }); + } - mActivityTestRule.waitUntilIdle(customTab); - assertOffOrigin(customTab); - - return customTab; + private long getDefaultPrimaryColor() { + return ApiCompatibilityUtils.getColor( + mActivityTestRule.getActivity().getResources(), R.color.default_primary_color); } private String offOriginUrl() { return mActivityTestRule.getTestServer().getURLWithHostName("foo.com", "/defaultresponse"); } - private void assertOffOrigin(ChromeActivity activity) throws InterruptedException { - ChromeTabUtils.waitForTabPageLoaded(activity.getActivityTab(), offOriginUrl()); - } - private void addAnchor(String id, String url, String target) throws Exception { mActivityTestRule.runJavaScriptCodeInCurrentTab( String.format("var aTag = document.createElement('a');" @@ -382,14 +407,21 @@ id, url, target)); } + private void addAnchorAndClick(String url, String target) throws Exception { + addAnchor("testId", url, target); + DOMUtils.clickNode( + mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), "testId"); + } + @SuppressWarnings("unchecked") - private <T extends Activity> T waitFor(final Class<T> expectedClass) { + private <T extends ChromeActivity> T waitFor(final Class<T> expectedClass) { final Activity[] holder = new Activity[1]; CriteriaHelper.pollUiThread(new Criteria() { @Override public boolean isSatisfied() { holder[0] = ApplicationStatus.getLastTrackedFocusedActivity(); - return holder[0] != null && expectedClass.isAssignableFrom(holder[0].getClass()); + return holder[0] != null && expectedClass.isAssignableFrom(holder[0].getClass()) + && ((ChromeActivity) holder[0]).getActivityTab() != null; } }); return (T) holder[0];
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksCacheTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksCacheTest.java deleted file mode 100644 index 72fefae..0000000 --- a/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksCacheTest.java +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.partnerbookmarks; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -import org.chromium.testing.local.LocalRobolectricTestRunner; - -import java.util.HashMap; -import java.util.Map; - -/** - * Unit tests for {@link PartnerBookmarksCache}. - */ -@RunWith(LocalRobolectricTestRunner.class) -@Config(manifest = Config.NONE) -public class PartnerBookmarksCacheTest { - private static final String TEST_PREFERENCES_NAME = "partner_bookmarks_favicon_cache_test"; - - private PartnerBookmarksCache mCache; - - @Before - public void setUp() throws Exception { - mCache = new PartnerBookmarksCache(RuntimeEnvironment.application, TEST_PREFERENCES_NAME); - } - - @After - public void tearDown() throws Exception { - mCache.clearCache(); - } - - @Test - public void testReadEmptyCache() { - Assert.assertTrue(mCache.read().isEmpty()); - } - - @Test - public void testReadWrite() { - Map<String, Long> inMap = new HashMap<String, Long>(); - inMap.put("url1", 1L); - inMap.put("url2", 2L); - mCache.write(inMap); - - Map<String, Long> readMap = mCache.read(); - Assert.assertEquals(readMap.keySet().size(), 2); - Assert.assertTrue(readMap.keySet().containsAll(inMap.keySet())); - } - - @Test(expected = IllegalArgumentException.class) - public void testWriteNull() { - mCache.write(null); - } - - @Test - public void testWriteEmptyMap() { - Map<String, Long> inMap = new HashMap<String, Long>(); - inMap.put("url1", 1L); - inMap.put("url2", 2L); - mCache.write(inMap); - - mCache.write(new HashMap<String, Long>()); - Map<String, Long> readMap = mCache.read(); - Assert.assertEquals(readMap.keySet().size(), 0); - } -} \ No newline at end of file
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 new file mode 100644 index 0000000..50128436 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java
@@ -0,0 +1,123 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.partnerbookmarks; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import org.chromium.chrome.browser.DisableHistogramsRule; +import org.chromium.testing.local.LocalRobolectricTestRunner; + +/** + * Unit tests for {@link PartnerBookmarksFaviconThrottle}. + */ +@RunWith(LocalRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class PartnerBookmarksFaviconThrottleTest { + private static final String TEST_PREFERENCES_NAME = "partner_bookmarks_favicon_throttle_test"; + + private PartnerBookmarksFaviconThrottle mFaviconThrottle; + + @Rule + public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule(); + + @Before + public void setUp() throws Exception { + mFaviconThrottle = new PartnerBookmarksFaviconThrottle( + RuntimeEnvironment.application, TEST_PREFERENCES_NAME); + } + + @After + public void tearDown() throws Exception { + mFaviconThrottle.clearEntries(); + } + + @Test + public void testInitEmpty() { + Assert.assertEquals(mFaviconThrottle.numEntries(), 0); + } + + @Test + public void testCacheServerErrorFailures() { + mFaviconThrottle.onFaviconFetched("url1", FaviconFetchResult.FAILURE_SERVER_ERROR); + mFaviconThrottle.onFaviconFetched("url2", FaviconFetchResult.FAILURE_SERVER_ERROR); + mFaviconThrottle.onFaviconFetched("url3", FaviconFetchResult.FAILURE_CONNECTION_ERROR); + mFaviconThrottle.commit(); + + mFaviconThrottle.init(); + Assert.assertFalse(mFaviconThrottle.shouldFetchFromServerIfNecessary("url1")); + Assert.assertFalse(mFaviconThrottle.shouldFetchFromServerIfNecessary("url2")); + Assert.assertTrue(mFaviconThrottle.shouldFetchFromServerIfNecessary("url3")); + } + + @Test + public void testOnlySuccessRemovesEntry() { + mFaviconThrottle.onFaviconFetched("url1", FaviconFetchResult.FAILURE_SERVER_ERROR); + mFaviconThrottle.commit(); + + mFaviconThrottle.init(); + Assert.assertFalse(mFaviconThrottle.shouldFetchFromServerIfNecessary("url1")); + mFaviconThrottle.onFaviconFetched( + "url1", FaviconFetchResult.FAILURE_ICON_SERVICE_UNAVAILABLE); + mFaviconThrottle.commit(); + + mFaviconThrottle.init(); + Assert.assertFalse(mFaviconThrottle.shouldFetchFromServerIfNecessary("url1")); + mFaviconThrottle.onFaviconFetched("url1", FaviconFetchResult.FAILURE_NOT_IN_CACHE); + mFaviconThrottle.commit(); + + mFaviconThrottle.init(); + Assert.assertFalse(mFaviconThrottle.shouldFetchFromServerIfNecessary("url1")); + mFaviconThrottle.onFaviconFetched("url1", FaviconFetchResult.FAILURE_CONNECTION_ERROR); + mFaviconThrottle.commit(); + + mFaviconThrottle.init(); + Assert.assertFalse(mFaviconThrottle.shouldFetchFromServerIfNecessary("url1")); + mFaviconThrottle.onFaviconFetched("url1", FaviconFetchResult.SUCCESS); + mFaviconThrottle.commit(); + + mFaviconThrottle.init(); + Assert.assertTrue(mFaviconThrottle.shouldFetchFromServerIfNecessary("url1")); + } + + @Test + public void testNewPartnerBookmarksRemovesOldEntries() { + mFaviconThrottle.onFaviconFetched("url1", FaviconFetchResult.FAILURE_SERVER_ERROR); + mFaviconThrottle.commit(); + + mFaviconThrottle.init(); + Assert.assertEquals(mFaviconThrottle.numEntries(), 1); + mFaviconThrottle.onFaviconFetched("url2", FaviconFetchResult.FAILURE_SERVER_ERROR); + mFaviconThrottle.commit(); + + mFaviconThrottle.init(); + Assert.assertEquals(mFaviconThrottle.numEntries(), 1); + Assert.assertTrue(mFaviconThrottle.shouldFetchFromServerIfNecessary("url1")); + Assert.assertFalse(mFaviconThrottle.shouldFetchFromServerIfNecessary("url2")); + } + + @Test + public void testShouldFetchFromServerIfNecessaryTrueIfNoPreviousEntry() { + Assert.assertTrue(mFaviconThrottle.shouldFetchFromServerIfNecessary("unused_url")); + } + + // TODO(thildebr): Test the code path for #shouldFetchFromServerIfNecessary where the timeout + // has expired. This requires mocking out System.currentTimeMillis() somehow. + + @Test + public void testShouldFetchFromServerIfNecessaryFalseIfNotExpired() { + mFaviconThrottle.onFaviconFetched("url1", FaviconFetchResult.FAILURE_SERVER_ERROR); + mFaviconThrottle.commit(); + + mFaviconThrottle.init(); + Assert.assertFalse(mFaviconThrottle.shouldFetchFromServerIfNecessary("url1")); + } +}
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index cfc9654..5bfc0f2 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -41,7 +41,6 @@ #include "chrome/common/profiling.h" #include "chrome/common/profiling/memlog_allocator_shim.h" #include "chrome/common/profiling/memlog_stream.h" -#include "chrome/common/switch_utils.h" #include "chrome/common/trace_event_args_whitelist.h" #include "chrome/common/url_constants.h" #include "chrome/gpu/chrome_content_gpu_client.h" @@ -50,6 +49,7 @@ #include "components/component_updater/component_updater_paths.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/crash/content/app/crash_reporter_client.h" +#include "components/crash/core/common/crash_key.h" #include "components/nacl/common/features.h" #include "components/version_info/version_info.h" #include "content/public/common/content_client.h" @@ -770,6 +770,8 @@ std::string process_type = command_line.GetSwitchValueASCII(switches::kProcessType); + crash_reporter::InitializeCrashKeys(); + #if defined(OS_POSIX) crash_reporter::SetCrashReporterClient(g_chrome_crash_client.Pointer()); #endif
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 3db044cc..b1c3a21c 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -2087,6 +2087,9 @@ <message name="IDS_WEBSHARE_TARGET_PICKER_COMMIT" desc="Title of the button to share content to the chosen application."> Share </message> + <message name="IDS_WEBSHARE_TARGET_DIALOG_ITEM_TEXT" desc="Text for a Web Share Target item in the Web Share Target dialog."> + <ph name="APP_NAME">$1<ex>Google Maps</ex></ph> (<ph name="APP_URL">$2<ex>https://google.com/maps</ex></ph>) + </message> <!-- Content blocking strings --> <message name="IDS_MANAGE" desc="Text for a button on permission bubbles, which opens a more detailed content settings page where users can manage that particular setting."> @@ -10873,12 +10876,6 @@ <message name="IDS_IME_API_NEVER_SHOW" desc="Checkbox that controls whether this bubble will be shown every time."> Never show this again. </message> - <if expr="is_macosx"> - <message name="IDS_ANNOUNCEMENT_COMPLETION_AVAILABLE_MAC" desc="Text to be -read aloud to screenreader users to announce that a completion is available."> - Completion available: <ph name="COMPLETION_TEXT">$1</ph> - </message> - </if> <!-- Ad Blocking UI strings. --> <message name="IDS_ALWAYS_ALLOW_ADS" desc="Explanation associated with a toggle to allow ads after ads have been blocked on the page. To be used on pages where the ad blocking UI is governed by a persistent permissions-based whitelist.">
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 7622e11d..cc0c4c3f 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -2185,6 +2185,19 @@ Reset all settings </message> + <!-- Reset card title and Chrome Cleanup item on Windows --> + <if expr="is_win and _google_chrome"> + <message name="IDS_SETTINGS_RESET_AND_CLEANUP" desc="Title of a section in Chrome Settings. Imperative. 'Reset' refers to resetting settings to defaults. 'Clean up' refers to cleaning up harmful software on the user's computer."> + Reset and clean up + </message> + <message name="IDS_SETTINGS_RESET_CLEAN_UP_COMPUTER_TRIGGER" desc="Title for an item in the 'Reset and clean up' section of Chrome Settings. 'Clean up' refers to cleaning up harmful software on the user's computer. Imperative."> + Clean up computer + </message> + <message name="IDS_SETTINGS_RESET_CLEAN_UP_COMPUTER_TRIGGER_DESCRIPTION" desc="Description of an item in Chrome Settings. Imperative."> + Find and remove harmful software + </message> + </if> + <!-- Factory Reset / Powerwash --> <if expr="chromeos"> <message name="IDS_SETTINGS_FACTORY_RESET" desc="Name of the factory reset option on the Chrome settings page"> @@ -3682,14 +3695,54 @@ Change Password </message> - <!-- Reset Page --> + <!-- Chrome Cleanup Page --> <if expr="is_win and _google_chrome"> + <message name="IDS_SETTINGS_RESET_CLEAN_UP_COMPUTER_PAGE_TITLE" desc="Title for an item in the 'Reset and clean up' section of Chrome Settings. 'Clean up' refers to cleaning up harmful software on the user's computer. Imperative."> + Clean up computer + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_DETAILS_EXPLANATION" desc="Text that appears below the list of files, programs, and registry entries to be removed by Chrome as part of a cleanup process. 'privacy white paper' is a guide to Chrome's privacy policy and practices. In 'unwanted software protection,' the word 'unwanted' modifies 'software,' i.e. 'protection from unwanted software'."> + Items not listed here may also be removed, if needed. Learn more about <a href="<ph name="URL">$1<ex>https://www.google.com/chrome/browser/privacy/whitepaper.html#unwantedsoftware</ex></ph>">unwanted software protection</a> in the Chrome privacy white paper. + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_DETAILS_FILES_AND_PROGRAMS" desc="Introduces a bullet list containing the names of files and programs to be removed by Chrome."> + Files and programs: + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_DETAILS_ITEMS_TO_BE_REMOVED" desc="Label for an expansion arrow. On expansion, the screen displays a list of files and programs that Chrome will remove. Placeholder can be 2 or more items."> + {NUM_ITEMS, plural, + =1 {1 item to be removed} + other {# items to be removed}} + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_DETAILS_REGISTRY_ENTRIES" desc="Introduces a bullet list containing the names of registry entries to be removed/changed by Chrome."> + Registry entries: + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_DETAILS_MORE" desc="Link; on click, the screen shows items to be removed by Chrome. Items could include files, programs, or registry entries. This link is for advanced users. Placeholder can be 2 or more items."> + {NUM_DOWNLOAD, plural, + =1 {1 more} + other {# more}} + </message> <message name="IDS_SETTINGS_RESET_CLEANUP_DONE_BUTTON_LABEL" desc="A button on the web page for Chrome Cleanup. Clicking this button causes the card on the settings page to be dismissed."> Done </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_CLEANUP_ERROR" desc="Body of a generic error message that could appear during the cleanup of harmful software. Multiple causes for the error are possible."> + An error occurred while Chrome was removing harmful software. + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_FIND_AND_REMOVE" desc="Subtitle of the 'Find an remove harmful software' item. Imperative."> + Chrome can find harmful software on your computer and remove it. + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_NO_INTERNET_CONNECTION" desc="Body of error message that could appear during the cleanup of harmful software. Imperative instruction to user. This message will only appear on Windows desktop/laptop computers. Imperative."> + Connect to a network and try again + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_PERMISSIONS_NEEDED" desc="Body of error message that could appear during the cleanup of harmful software. Imperative. "> + Click Try Again, and accept the prompt on your computer + </message> <message name="IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_REMOVE" desc="Description in the Chrome Cleanup web page that Chrome browser shows when unwanted software, like ad injectors or software that changes the user's settings without their knowledge, is found on the user's computer. Appears under the title asking 'Remove harmful software.' Actor is Chrome; we are asking, Do you want Chrome to remove harmful software? 'it' is harmful software. The user can click 'Remove' to proceed with a cleanup. Preferrably, the translation for this string should match IDS_CHROME_CLEANUP_PROMPT_EXPLANATION."> Chrome found harmful software on your computer. Chrome can remove it and restore your settings to make your browser work normally again. </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_SCAN_ERROR" desc="Body of error message that could appear during the cleanup of harmful software."> + An error occurred while Chrome was searching for harmful software. + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_FIND_BUTTON_LABEL" desc="Button for the 'Find and remove harmful software' item in Chrome Settings. Imperative. On click, Chrome looks for harmful software on the user's computer. Imperative."> + Find + </message> <message name="IDS_SETTINGS_RESET_CLEANUP_FOOTER_POWERED_BY" desc="Branding footer on the web page for Chrome Cleanup. COMPANY_NAME is the name of a technology service that Chrome uses to remove harmful software from the user's computer. It is not necessary to translate 'powered by' literally; use an appropriate word for your language to convey the meaning of 'uses'. A similar use in other Google products is 'Powered by Google Translate.'"> Powered by <ph name="COMPANY_NAME">$1<ex>Google</ex></ph> </message> @@ -3702,9 +3755,24 @@ <message name="IDS_SETTINGS_RESET_CLEANUP_RESTART_BUTTON_LABEL" desc="Button on the web page for Chrome Cleanup. Clicking this button causes the user's computer to turn off (shut down) and turn back on again. Imperative. "> Restart computer </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_DONE" desc="Message confirming that Chrome has removed harmful software. Exclamation point is nice in EN-US but is optional in your language; please use or omit as appropriate. The UI will also display a checkmark icon to indicate the operation is done. "> + Done! + </message> <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_ERROR_CANT_REMOVE" desc="An error message, appearing on the Chrome Cleanup web page, that Chrome tried to clean up unwanted software, as requested by the user, but was unsuccessful. Omits subject, i.e. Chrome can't remove harmful software."> Can't remove harmful software </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_ERROR_PERMISSIONS_NEEDED" desc="Title of error message that could appear during the cleanup of harmful software. 'permission' refers to the user granting permission, e.g. from an operating system prompt, before the cleanup operation can continue."> + Chrome needs permission to continue + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_FIND_AND_REMOVE" desc="Title of an item in Chrome Settings. Imperative."> + Find and remove harmful software + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_NO_INTERNET_CONNECTION" desc="Title of error message that could appear during the cleanup of harmful software."> + No internet connection + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_NOTHING_FOUND" desc="Message displayed after Chrome looks for harmful software but doesn't find any. "> + No harmful software found + </message> <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_REMOVE" desc="Title of the Chrome Cleanup web page. Chrome browser shows the webpage when unwanted software, like ad injectors or software that changes the user's settings without their knowledge, is found on the user's computer. Appears above a description of what the cleanup does. 'Remove' is imperative."> Remove harmful software </message> @@ -3717,5 +3785,17 @@ <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_RESTART" desc="A status message, appearing on the Chrome Cleanup web page, that the cleanup of unwanted software initiated by the user was performed but isn't finished. User must take additional action to finish the cleanup. 'Restart' is imperative. Short for 'To finish removing harmful software...'"> To finish removing harmful software, restart your computer </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_SCANNING" desc="Message displayed after the user clicks the 'Find' button to find harmful software. Ellipses indicate that the operation is in process."> + Checking for harmful software... + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_ERROR_SCANNING_FAILED" desc="Title of error message that could appear during the cleanup of harmful software."> + Scanning failed + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_TRY_AGAIN_BUTTON_LABEL" desc="Generic button that appears next to a message indicating that an operation failed during the cleanup of harmful software."> + Try again + </message> + <message name="IDS_SETTINGS_RESET_CLEANUP_LOGS_PERMISSION_EXPLANATION" desc="Description for the 'Report details to Google' option. Subject, 'Details', is omitted. Although the plural subject would indicate usage of the plural verb, here, we use the plural form of the verb, 'includes', to avoid the impression that 'include' is an infinitive verb. 'Includes' is a present tense main verb. "> + Includes information about harmful software, system settings, and processes on your computer. + </message> </if> </grit-part>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 02fcb0b..07755a07 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3005,6 +3005,8 @@ if (!is_android && !is_chromeos) { sources += [ + "lifetime/switch_utils.cc", + "lifetime/switch_utils.h", "metrics/desktop_session_duration/audible_contents_tracker.cc", "metrics/desktop_session_duration/audible_contents_tracker.h", "metrics/desktop_session_duration/chrome_visibility_observer.cc", @@ -4071,7 +4073,7 @@ ] } if (is_chromeos) { - deps += [ "//ash/public/cpp:ash_public_cpp" ] + deps += [ "//ash/public/cpp" ] } } }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 0628342..5e3d1fe5 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -161,12 +161,12 @@ #endif using flags_ui::FeatureEntry; +using flags_ui::kOsAndroid; +using flags_ui::kOsCrOS; +using flags_ui::kOsCrOSOwnerOnly; +using flags_ui::kOsLinux; using flags_ui::kOsMac; using flags_ui::kOsWin; -using flags_ui::kOsLinux; -using flags_ui::kOsCrOS; -using flags_ui::kOsAndroid; -using flags_ui::kOsCrOSOwnerOnly; namespace about_flags { @@ -273,9 +273,36 @@ const FeatureEntry::Choice kDataReductionProxyServerExperiment[] = { {flags_ui::kGenericExperimentChoiceDefault, "", ""}, - {flag_descriptions::kDataReductionProxyServerAlternative, + {flag_descriptions::kDataReductionProxyServerAlternative1, data_reduction_proxy::switches::kDataReductionProxyExperiment, - data_reduction_proxy::switches::kDataReductionProxyServerAlternative}}; + data_reduction_proxy::switches::kDataReductionProxyServerAlternative1}, + {flag_descriptions::kDataReductionProxyServerAlternative2, + data_reduction_proxy::switches::kDataReductionProxyExperiment, + data_reduction_proxy::switches::kDataReductionProxyServerAlternative2}, + {flag_descriptions::kDataReductionProxyServerAlternative3, + data_reduction_proxy::switches::kDataReductionProxyExperiment, + data_reduction_proxy::switches::kDataReductionProxyServerAlternative3}, + {flag_descriptions::kDataReductionProxyServerAlternative4, + data_reduction_proxy::switches::kDataReductionProxyExperiment, + data_reduction_proxy::switches::kDataReductionProxyServerAlternative4}, + {flag_descriptions::kDataReductionProxyServerAlternative5, + data_reduction_proxy::switches::kDataReductionProxyExperiment, + data_reduction_proxy::switches::kDataReductionProxyServerAlternative5}, + {flag_descriptions::kDataReductionProxyServerAlternative6, + data_reduction_proxy::switches::kDataReductionProxyExperiment, + data_reduction_proxy::switches::kDataReductionProxyServerAlternative6}, + {flag_descriptions::kDataReductionProxyServerAlternative7, + data_reduction_proxy::switches::kDataReductionProxyExperiment, + data_reduction_proxy::switches::kDataReductionProxyServerAlternative7}, + {flag_descriptions::kDataReductionProxyServerAlternative8, + data_reduction_proxy::switches::kDataReductionProxyExperiment, + data_reduction_proxy::switches::kDataReductionProxyServerAlternative8}, + {flag_descriptions::kDataReductionProxyServerAlternative9, + data_reduction_proxy::switches::kDataReductionProxyExperiment, + data_reduction_proxy::switches::kDataReductionProxyServerAlternative9}, + {flag_descriptions::kDataReductionProxyServerAlternative10, + data_reduction_proxy::switches::kDataReductionProxyExperiment, + data_reduction_proxy::switches::kDataReductionProxyServerAlternative10}}; const FeatureEntry::Choice kShowSavedCopyChoices[] = { {flags_ui::kGenericExperimentChoiceDefault, "", ""}, @@ -1120,6 +1147,12 @@ "https://www.gstatic.com/chrome/ntp/doodle_test/ddljson_desktop0.json"}, {"(force test doodle 1)", search_provider_logos::switches::kGoogleDoodleUrl, "https://www.gstatic.com/chrome/ntp/doodle_test/ddljson_desktop1.json"}, + {"(force test doodle 2)", search_provider_logos::switches::kGoogleDoodleUrl, + "https://www.gstatic.com/chrome/ntp/doodle_test/ddljson_desktop2.json"}, + {"(force test doodle 3)", search_provider_logos::switches::kGoogleDoodleUrl, + "https://www.gstatic.com/chrome/ntp/doodle_test/ddljson_desktop3.json"}, + {"(force test doodle 4)", search_provider_logos::switches::kGoogleDoodleUrl, + "https://www.gstatic.com/chrome/ntp/doodle_test/ddljson_desktop4.json"}, #endif // defined(OS_ANDROID) };
diff --git a/chrome/browser/android/bookmarks/partner_bookmarks_reader.h b/chrome/browser/android/bookmarks/partner_bookmarks_reader.h index d6d6344..3f940dfa1 100644 --- a/chrome/browser/android/bookmarks/partner_bookmarks_reader.h +++ b/chrome/browser/android/bookmarks/partner_bookmarks_reader.h
@@ -48,6 +48,8 @@ const base::android::JavaParamRef<jobject>& obj); private: + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.partnerbookmarks enum class FaviconFetchResult { // Successfully fetched a favicon from cache or server. @@ -62,6 +64,8 @@ // Request sent out and a connection error occurred (no valid HTTP response // received). FAILURE_CONNECTION_ERROR = 4, + // Boundary value for UMA. + UMA_BOUNDARY, }; using FaviconFetchedCallback = base::OnceCallback<void(FaviconFetchResult)>;
diff --git a/chrome/browser/android/chrome_entry_point_for_test.cc b/chrome/browser/android/chrome_entry_point_for_test.cc new file mode 100644 index 0000000..1eb8e02 --- /dev/null +++ b/chrome/browser/android/chrome_entry_point_for_test.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 "base/android/jni_android.h" +#include "base/android/jni_utils.h" +#include "base/android/library_loader/library_loader_hooks.h" +#include "base/bind.h" +#include "base/test/test_support_android.h" +#include "chrome/app/android/chrome_jni_onload.h" +#include "chrome/browser/android/chrome_jni_for_test_registration.h" + +namespace { + +bool NativeInit() { + return android::OnJNIOnLoadInit(); +} + +} // namespace + +// This is called by the VM when the shared library is first loaded. +JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { + // By default, all JNI methods are registered. However, since render processes + // don't need very much Java code, we enable selective JNI registration on the + // Java side and only register a subset of JNI methods. + base::android::InitVM(vm); + JNIEnv* env = base::android::AttachCurrentThread(); + + if (!base::android::IsSelectiveJniRegistrationEnabled(env) && + !RegisterNonMainDexNatives(env)) { + return -1; + } + + if (!RegisterMainDexNatives(env)) { + return -1; + } + + if (!android::OnJNIOnLoadRegisterJNI(env)) { + return -1; + } + base::android::SetNativeInitializationHook(NativeInit); + return JNI_VERSION_1_4; +}
diff --git a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc index 3903f82..5cd85cd3 100644 --- a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc +++ b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc
@@ -21,21 +21,25 @@ // static void InstantAppsInfoBarDelegate::Create(content::WebContents* web_contents, const jobject jdata, - const std::string& url) { + const std::string& url, + bool instant_app_is_default) { InfoBarService* infobar_service = InfoBarService::FromWebContents(web_contents); infobar_service->AddInfoBar(base::MakeUnique<InstantAppsInfoBar>( std::unique_ptr<InstantAppsInfoBarDelegate>( - new InstantAppsInfoBarDelegate(web_contents, jdata, url)))); + new InstantAppsInfoBarDelegate(web_contents, jdata, url, + instant_app_is_default)))); } InstantAppsInfoBarDelegate::InstantAppsInfoBarDelegate( content::WebContents* web_contents, const jobject jdata, - const std::string& url) + const std::string& url, + bool instant_app_is_default) : content::WebContentsObserver(web_contents), url_(url), - has_navigated_away_from_launch_url_(false) { + has_navigated_away_from_launch_url_(false), + instant_app_is_default_(instant_app_is_default) { JNIEnv* env = base::android::AttachCurrentThread(); java_delegate_.Reset(Java_InstantAppsInfoBarDelegate_create(env)); data_.Reset(env, jdata); @@ -53,8 +57,13 @@ bool InstantAppsInfoBarDelegate::Accept() { JNIEnv* env = base::android::AttachCurrentThread(); - base::RecordAction(base::UserMetricsAction( - "Android.InstantApps.BannerOpen")); + if (instant_app_is_default_) { + base::RecordAction( + base::UserMetricsAction("Android.InstantApps.BannerOpenAppIsDefault")); + } else { + base::RecordAction( + base::UserMetricsAction("Android.InstantApps.BannerOpen")); + } Java_InstantAppsInfoBarDelegate_openInstantApp(env, java_delegate_, data_); return true; } @@ -69,8 +78,13 @@ content::WebContents* web_contents = InfoBarService::WebContentsFromInfoBar(infobar()); InstantAppsSettings::RecordInfoBarDismissEvent(web_contents, url_); - base::RecordAction(base::UserMetricsAction( - "Android.InstantApps.BannerDismissed")); + if (instant_app_is_default_) { + base::RecordAction(base::UserMetricsAction( + "Android.InstantApps.BannerDismissedAppIsDefault")); + } else { + base::RecordAction( + base::UserMetricsAction("Android.InstantApps.BannerDismissed")); + } } void InstantAppsInfoBarDelegate::DidStartNavigation( @@ -98,12 +112,20 @@ const base::android::JavaParamRef<jclass>& clazz, const base::android::JavaParamRef<jobject>& jweb_contents, const base::android::JavaParamRef<jobject>& jdata, - const base::android::JavaParamRef<jstring>& jurl) { + const base::android::JavaParamRef<jstring>& jurl, + const jboolean instant_app_is_default) { auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents); std::string url(base::android::ConvertJavaStringToUTF8(env, jurl)); - InstantAppsInfoBarDelegate::Create(web_contents, jdata, url); + InstantAppsInfoBarDelegate::Create(web_contents, jdata, url, + instant_app_is_default); InstantAppsSettings::RecordInfoBarShowEvent(web_contents, url); - base::RecordAction(base::UserMetricsAction( - "Android.InstantApps.BannerShown")); + + if (instant_app_is_default) { + base::RecordAction( + base::UserMetricsAction("Android.InstantApps.BannerShownAppIsDefault")); + } else { + base::RecordAction( + base::UserMetricsAction("Android.InstantApps.BannerShown")); + } }
diff --git a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h index 335f2d4..19e129d 100644 --- a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h +++ b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h
@@ -20,7 +20,8 @@ static void Create(content::WebContents* web_contents, const jobject jdata, - const std::string& url); + const std::string& url, + const bool instant_app_is_default); base::android::ScopedJavaGlobalRef<jobject> data() { return data_; } @@ -36,7 +37,8 @@ private: explicit InstantAppsInfoBarDelegate(content::WebContents* web_contents, const jobject jdata, - const std::string& url); + const std::string& url, + const bool instant_app_is_default); // ConfirmInfoBarDelegate: infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override; @@ -49,6 +51,7 @@ base::android::ScopedJavaGlobalRef<jobject> data_; std::string url_; bool has_navigated_away_from_launch_url_; + bool instant_app_is_default_; DISALLOW_COPY_AND_ASSIGN(InstantAppsInfoBarDelegate); };
diff --git a/chrome/browser/android/preferences/pref_service_bridge.cc b/chrome/browser/android/preferences/pref_service_bridge.cc index 99b77ed7..1c7cc44 100644 --- a/chrome/browser/android/preferences/pref_service_bridge.cc +++ b/chrome/browser/android/preferences/pref_service_bridge.cc
@@ -319,12 +319,12 @@ static jboolean GetTranslateEnabled(JNIEnv* env, const JavaParamRef<jobject>& obj) { - return GetPrefService()->GetBoolean(prefs::kEnableTranslate); + return GetPrefService()->GetBoolean(prefs::kOfferTranslateEnabled); } static jboolean GetTranslateManaged(JNIEnv* env, const JavaParamRef<jobject>& obj) { - return GetPrefService()->IsManagedPreference(prefs::kEnableTranslate); + return GetPrefService()->IsManagedPreference(prefs::kOfferTranslateEnabled); } static jboolean GetSearchSuggestEnabled(JNIEnv* env, @@ -752,7 +752,7 @@ static void SetTranslateEnabled(JNIEnv* env, const JavaParamRef<jobject>& obj, jboolean enabled) { - GetPrefService()->SetBoolean(prefs::kEnableTranslate, enabled); + GetPrefService()->SetBoolean(prefs::kOfferTranslateEnabled, enabled); } static void ResetTranslateDefaults(JNIEnv* env,
diff --git a/chrome/browser/android/vr_shell/vr_compositor.cc b/chrome/browser/android/vr_shell/vr_compositor.cc index 673efc0..517d76f2 100644 --- a/chrome/browser/android/vr_shell/vr_compositor.cc +++ b/chrome/browser/android/vr_shell/vr_compositor.cc
@@ -56,6 +56,10 @@ compositor_->SetWindowBounds(size); } +void VrCompositor::SetDeferCommits(bool defer_commits) { + compositor_->SetDeferCommits(defer_commits); +} + void VrCompositor::SurfaceChanged(jobject surface) { compositor_->SetSurface(surface); }
diff --git a/chrome/browser/android/vr_shell/vr_compositor.h b/chrome/browser/android/vr_shell/vr_compositor.h index 1f7f8a3..eb4baf66 100644 --- a/chrome/browser/android/vr_shell/vr_compositor.h +++ b/chrome/browser/android/vr_shell/vr_compositor.h
@@ -36,6 +36,7 @@ void SurfaceDestroyed(); void SetWindowBounds(gfx::Size size); + void SetDeferCommits(bool defer_commits); void SurfaceChanged(jobject surface); void SetLayer(content::WebContents* web_contents);
diff --git a/chrome/browser/android/vr_shell/vr_gl_thread.cc b/chrome/browser/android/vr_shell/vr_gl_thread.cc index 319a328..eff5f1b 100644 --- a/chrome/browser/android/vr_shell/vr_gl_thread.cc +++ b/chrome/browser/android/vr_shell/vr_gl_thread.cc
@@ -224,41 +224,39 @@ enabled, show_toast)); } -void VrGLThread::SetAudioCapturingIndicator(bool enabled) { +void VrGLThread::SetAudioCaptureEnabled(bool enabled) { DCHECK(OnMainThread()); task_runner()->PostTask( - FROM_HERE, base::Bind(&vr::BrowserUiInterface::SetAudioCapturingIndicator, + FROM_HERE, base::Bind(&vr::BrowserUiInterface::SetAudioCaptureEnabled, browser_ui_, enabled)); } -void VrGLThread::SetLocationAccessIndicator(bool enabled) { +void VrGLThread::SetLocationAccess(bool enabled) { + DCHECK(OnMainThread()); + task_runner()->PostTask(FROM_HERE, + base::Bind(&vr::BrowserUiInterface::SetLocationAccess, + browser_ui_, enabled)); +} + +void VrGLThread::SetVideoCaptureEnabled(bool enabled) { DCHECK(OnMainThread()); task_runner()->PostTask( - FROM_HERE, base::Bind(&vr::BrowserUiInterface::SetLocationAccessIndicator, + FROM_HERE, base::Bind(&vr::BrowserUiInterface::SetVideoCaptureEnabled, browser_ui_, enabled)); } -void VrGLThread::SetVideoCapturingIndicator(bool enabled) { +void VrGLThread::SetScreenCaptureEnabled(bool enabled) { DCHECK(OnMainThread()); task_runner()->PostTask( - FROM_HERE, base::Bind(&vr::BrowserUiInterface::SetVideoCapturingIndicator, + FROM_HERE, base::Bind(&vr::BrowserUiInterface::SetScreenCaptureEnabled, browser_ui_, enabled)); } -void VrGLThread::SetScreenCapturingIndicator(bool enabled) { +void VrGLThread::SetBluetoothConnected(bool enabled) { DCHECK(OnMainThread()); task_runner()->PostTask( - FROM_HERE, - base::Bind(&vr::BrowserUiInterface::SetScreenCapturingIndicator, - browser_ui_, enabled)); -} - -void VrGLThread::SetBluetoothConnectedIndicator(bool enabled) { - DCHECK(OnMainThread()); - task_runner()->PostTask( - FROM_HERE, - base::Bind(&vr::BrowserUiInterface::SetBluetoothConnectedIndicator, - browser_ui_, enabled)); + FROM_HERE, base::Bind(&vr::BrowserUiInterface::SetBluetoothConnected, + browser_ui_, enabled)); } void VrGLThread::SetIsExiting() {
diff --git a/chrome/browser/android/vr_shell/vr_gl_thread.h b/chrome/browser/android/vr_shell/vr_gl_thread.h index 8571376..a377bc3 100644 --- a/chrome/browser/android/vr_shell/vr_gl_thread.h +++ b/chrome/browser/android/vr_shell/vr_gl_thread.h
@@ -76,11 +76,11 @@ void SetLoadProgress(float progress) override; void SetIsExiting() override; void SetHistoryButtonsEnabled(bool can_go_back, bool can_go_forward) override; - void SetVideoCapturingIndicator(bool enabled) override; - void SetScreenCapturingIndicator(bool enabled) override; - void SetAudioCapturingIndicator(bool enabled) override; - void SetBluetoothConnectedIndicator(bool enabled) override; - void SetLocationAccessIndicator(bool enabled) override; + void SetVideoCaptureEnabled(bool enabled) override; + void SetScreenCaptureEnabled(bool enabled) override; + void SetAudioCaptureEnabled(bool enabled) override; + void SetBluetoothConnected(bool enabled) override; + void SetLocationAccess(bool enabled) override; void SetExitVrPromptEnabled(bool enabled, vr::UiUnsupportedMode reason) override; void SetSpeechRecognitionEnabled(bool enabled) override;
diff --git a/chrome/browser/android/vr_shell/vr_shell.cc b/chrome/browser/android/vr_shell/vr_shell.cc index 3bcb02f..ca834faa 100644 --- a/chrome/browser/android/vr_shell/vr_shell.cc +++ b/chrome/browser/android/vr_shell/vr_shell.cc
@@ -147,6 +147,10 @@ g_instance = this; j_vr_shell_.Reset(env, obj); + // Defer applying commits to the renderer until we know the desired + // content resolution and DPR. + compositor_->SetDeferCommits(true); + gl_thread_ = base::MakeUnique<VrGLThread>( weak_ptr_factory_.GetWeakPtr(), main_thread_task_runner_, gvr_api, ui_initial_state, reprojected_rendering_, HasDaydreamSupport(env)); @@ -731,6 +735,7 @@ JNIEnv* env = base::android::AttachCurrentThread(); Java_VrShellImpl_setContentCssSize(env, j_vr_shell_, window_size.width(), window_size.height(), dpr); + compositor_->SetDeferCommits(false); } void VrShell::SetVoiceSearchActive(bool active) { @@ -820,19 +825,19 @@ bool is_capturing_screen = num_tabs_capturing_screen > 0; bool is_bluetooth_connected = num_tabs_bluetooth_connected > 0; if (is_capturing_audio != is_capturing_audio_) { - ui_->SetAudioCapturingIndicator(is_capturing_audio); + ui_->SetAudioCaptureEnabled(is_capturing_audio); is_capturing_audio_ = is_capturing_audio; } if (is_capturing_video != is_capturing_video_) { - ui_->SetVideoCapturingIndicator(is_capturing_video); + ui_->SetVideoCaptureEnabled(is_capturing_video); is_capturing_video_ = is_capturing_video; } if (is_capturing_screen != is_capturing_screen_) { - ui_->SetScreenCapturingIndicator(is_capturing_screen); + ui_->SetScreenCaptureEnabled(is_capturing_screen); is_capturing_screen_ = is_capturing_screen; } if (is_bluetooth_connected != is_bluetooth_connected_) { - ui_->SetBluetoothConnectedIndicator(is_bluetooth_connected); + ui_->SetBluetoothConnected(is_bluetooth_connected); is_bluetooth_connected_ = is_bluetooth_connected; } } @@ -840,7 +845,7 @@ void VrShell::SetHighAccuracyLocation(bool high_accuracy_location) { if (high_accuracy_location == high_accuracy_location_) return; - ui_->SetLocationAccessIndicator(high_accuracy_location); + ui_->SetLocationAccess(high_accuracy_location); high_accuracy_location_ = high_accuracy_location; }
diff --git a/chrome/browser/autofill/autofill_metrics_browsertest.cc b/chrome/browser/autofill/autofill_metrics_browsertest.cc new file mode 100644 index 0000000..294daaa4 --- /dev/null +++ b/chrome/browser/autofill/autofill_metrics_browsertest.cc
@@ -0,0 +1,190 @@ +// 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 <memory> +#include <utility> + +#include "base/command_line.h" +#include "base/macros.h" +#include "base/path_service.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_navigator_params.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/network_session_configurator/common/network_switches.h" +#include "components/ukm/test_ukm_recorder.h" +#include "components/ukm/ukm_source.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/content_switches.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_utils.h" +#include "net/dns/mock_host_resolver.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "services/metrics/public/cpp/ukm_builders.h" +#include "url/gurl.h" + +class AutofillMetricsMetricsBrowserTest : public InProcessBrowserTest { + public: + AutofillMetricsMetricsBrowserTest() {} + + ~AutofillMetricsMetricsBrowserTest() override {} + + protected: + void SetUpCommandLine(base::CommandLine* command_line) override { + // HTTPS server only serves a valid cert for localhost, so this is needed + // to load pages from other hosts without an error. + command_line->AppendSwitch(switches::kIgnoreCertificateErrors); + } + + void PreRunTestOnMainThread() override { + InProcessBrowserTest::PreRunTestOnMainThread(); + + test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>(); + } + + void SetUpOnMainThread() override { + https_server_.reset( + new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); + host_resolver()->AddRule("*", "127.0.0.1"); + ASSERT_TRUE(https_server_->InitializeAndListen()); + content::SetupCrossSiteRedirector(https_server_.get()); + https_server_->ServeFilesFromSourceDirectory( + "components/test/data/autofill"); + https_server_->StartAcceptingConnections(); + } + + std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_; + std::unique_ptr<net::EmbeddedTestServer> https_server_; + + private: + DISALLOW_COPY_AND_ASSIGN(AutofillMetricsMetricsBrowserTest); +}; + +IN_PROC_BROWSER_TEST_F(AutofillMetricsMetricsBrowserTest, + CorrectSourceForCrossSiteEmbeddedAddressForm) { + GURL main_frame_url = + https_server_->GetURL("a.com", "/autofill_iframe_embedder.html"); + ui_test_utils::NavigateToURL(browser(), main_frame_url); + + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + GURL iframe_url = + https_server_->GetURL("b.com", "/autofill_address_form.html"); + EXPECT_TRUE(content::NavigateIframeToURL(tab, "test", iframe_url)); + + EXPECT_TRUE(tab->GetRenderWidgetHostView()->IsShowing()); + content::RenderFrameHost* frame = ChildFrameAt(tab->GetMainFrame(), 0); + EXPECT_TRUE(frame); + + // Make sure the UKM were logged for the main frame url and none for the + // iframe url. + std::vector<const ukm::UkmSource*> sources = + test_ukm_recorder_->GetSourcesForUrl(iframe_url.spec().c_str()); + EXPECT_TRUE(sources.empty()); + sources = test_ukm_recorder_->GetSourcesForUrl(main_frame_url.spec().c_str()); + EXPECT_FALSE(sources.empty()); +} + +IN_PROC_BROWSER_TEST_F(AutofillMetricsMetricsBrowserTest, + CorrectSourceForCrossSiteEmbeddedCreditCardForm) { + GURL main_frame_url = + https_server_->GetURL("a.com", "/autofill_iframe_embedder.html"); + ui_test_utils::NavigateToURL(browser(), main_frame_url); + + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + GURL iframe_url = + https_server_->GetURL("b.com", "/autofill_credit_card_form.html"); + EXPECT_TRUE(content::NavigateIframeToURL(tab, "test", iframe_url)); + + EXPECT_TRUE(tab->GetRenderWidgetHostView()->IsShowing()); + content::RenderFrameHost* frame = ChildFrameAt(tab->GetMainFrame(), 0); + EXPECT_TRUE(frame); + + // Make sure the UKM were logged for the main frame url and none for the + // iframe url. + std::vector<const ukm::UkmSource*> sources = + test_ukm_recorder_->GetSourcesForUrl(iframe_url.spec().c_str()); + EXPECT_TRUE(sources.empty()); + sources = test_ukm_recorder_->GetSourcesForUrl(main_frame_url.spec().c_str()); + EXPECT_FALSE(sources.empty()); +} + +class SitePerProcessAutofillMetricsMetricsBrowserTest + : public AutofillMetricsMetricsBrowserTest { + public: + SitePerProcessAutofillMetricsMetricsBrowserTest() {} + + ~SitePerProcessAutofillMetricsMetricsBrowserTest() override {} + + protected: + void SetUpCommandLine(base::CommandLine* command_line) override { + AutofillMetricsMetricsBrowserTest::SetUpCommandLine(command_line); + + // Append --site-per-process flag. + content::IsolateAllSitesForTesting(command_line); + } + + private: + DISALLOW_COPY_AND_ASSIGN(SitePerProcessAutofillMetricsMetricsBrowserTest); +}; + +IN_PROC_BROWSER_TEST_F(SitePerProcessAutofillMetricsMetricsBrowserTest, + CorrectSourceForCrossSiteEmbeddedAddressForm) { + GURL main_frame_url = + https_server_->GetURL("a.com", "/autofill_iframe_embedder.html"); + ui_test_utils::NavigateToURL(browser(), main_frame_url); + + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + GURL iframe_url = + https_server_->GetURL("b.com", "/autofill_address_form.html"); + EXPECT_TRUE(content::NavigateIframeToURL(tab, "test", iframe_url)); + + EXPECT_TRUE(tab->GetRenderWidgetHostView()->IsShowing()); + content::RenderFrameHost* frame = ChildFrameAt(tab->GetMainFrame(), 0); + EXPECT_TRUE(frame); + EXPECT_NE(frame->GetSiteInstance(), tab->GetMainFrame()->GetSiteInstance()); + + // Make sure the UKM were logged for the main frame url and none for the + // iframe url. + std::vector<const ukm::UkmSource*> sources = + test_ukm_recorder_->GetSourcesForUrl(iframe_url.spec().c_str()); + EXPECT_TRUE(sources.empty()); + sources = test_ukm_recorder_->GetSourcesForUrl(main_frame_url.spec().c_str()); + EXPECT_FALSE(sources.empty()); +} + +IN_PROC_BROWSER_TEST_F(SitePerProcessAutofillMetricsMetricsBrowserTest, + CorrectSourceForCrossSiteEmbeddedCreditCardForm) { + GURL main_frame_url = + https_server_->GetURL("a.com", "/autofill_iframe_embedder.html"); + ui_test_utils::NavigateToURL(browser(), main_frame_url); + + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + GURL iframe_url = + https_server_->GetURL("b.com", "/autofill_credit_card_form.html"); + EXPECT_TRUE(content::NavigateIframeToURL(tab, "test", iframe_url)); + + EXPECT_TRUE(tab->GetRenderWidgetHostView()->IsShowing()); + content::RenderFrameHost* frame = ChildFrameAt(tab->GetMainFrame(), 0); + EXPECT_TRUE(frame); + EXPECT_NE(frame->GetSiteInstance(), tab->GetMainFrame()->GetSiteInstance()); + + // Make sure the UKM were logged for the main frame url and none for the + // iframe url. + std::vector<const ukm::UkmSource*> sources = + test_ukm_recorder_->GetSourcesForUrl(iframe_url.spec().c_str()); + EXPECT_TRUE(sources.empty()); + sources = test_ukm_recorder_->GetSourcesForUrl(main_frame_url.spec().c_str()); + EXPECT_FALSE(sources.empty()); +}
diff --git a/chrome/browser/autofill/risk_util.cc b/chrome/browser/autofill/risk_util.cc index 1b775261..71dd999 100644 --- a/chrome/browser/autofill/risk_util.cc +++ b/chrome/browser/autofill/risk_util.cc
@@ -21,7 +21,10 @@ #include "components/metrics/metrics_service.h" #include "components/prefs/pref_service.h" #include "components/version_info/version_info.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/service_manager_connection.h" +#include "services/service_manager/public/cpp/connector.h" #if !defined(OS_ANDROID) #include "chrome/browser/ui/browser_finder.h" @@ -83,11 +86,16 @@ base::Time install_time = base::Time::FromTimeT( g_browser_process->metrics_service()->GetInstallDate()); - risk::GetFingerprint(obfuscated_gaia_id, window_bounds, web_contents, - version_info::GetVersionNumber(), charset, - accept_languages, install_time, - g_browser_process->GetApplicationLocale(), - GetUserAgent(), base::Bind(PassRiskData, callback)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(content::ServiceManagerConnection::GetForProcess()); + service_manager::Connector* connector = + content::ServiceManagerConnection::GetForProcess()->GetConnector(); + + risk::GetFingerprint( + obfuscated_gaia_id, window_bounds, web_contents, + version_info::GetVersionNumber(), charset, accept_languages, install_time, + g_browser_process->GetApplicationLocale(), GetUserAgent(), + base::Bind(PassRiskData, callback), connector); } } // namespace autofill
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index d308af0..6b6ce769 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -54,6 +54,7 @@ #include "chrome/browser/intranet_redirect_detector.h" #include "chrome/browser/io_thread.h" #include "chrome/browser/lifetime/application_lifetime.h" +#include "chrome/browser/lifetime/switch_utils.h" #include "chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/metrics/chrome_metrics_services_manager_client.h" @@ -86,7 +87,6 @@ #include "chrome/common/extensions/extension_process_policy.h" #include "chrome/common/features.h" #include "chrome/common/pref_names.h" -#include "chrome/common/switch_utils.h" #include "chrome/common/url_constants.h" #include "chrome/installer/util/google_update_settings.h" #include "components/component_updater/component_updater_service.h"
diff --git a/chrome/browser/browser_shutdown.cc b/chrome/browser/browser_shutdown.cc index eb3272f2..5c4fbb96 100644 --- a/chrome/browser/browser_shutdown.cc +++ b/chrome/browser/browser_shutdown.cc
@@ -25,13 +25,13 @@ #include "chrome/browser/about_flags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/lifetime/application_lifetime.h" +#include "chrome/browser/lifetime/switch_utils.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_metrics.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/crash_keys.h" #include "chrome/common/pref_names.h" -#include "chrome/common/switch_utils.h" #include "components/metrics/metrics_service.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index bc9a0fd4..b65b9ea 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -43,11 +43,12 @@ # TODO(tbarzic): Cleanup this list. ":attestation_proto", ":device_policy_remover_generated", + ":user_activity_event_proto", "//apps", "//ash", "//ash:ash_with_content", "//ash/autoclick/mus/public/interfaces", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//cc/paint", "//chrome/app:command_ids", "//chrome/app/vector_icons", @@ -2044,6 +2045,12 @@ ] } +proto_library("user_activity_event_proto") { + sources = [ + "power/ml/user_activity_event.proto", + ] +} + service_manifest("ash_pref_connector_manifest") { name = "ash_pref_connector" source = "prefs/ash_pref_connector_manifest.json"
diff --git a/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc b/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc index 0163beda..8bd9af9 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc
@@ -255,7 +255,7 @@ const base::DictionaryValue* extension = nullptr; if (!it.value().GetAsDictionary(&extension)) { - LOG(ERROR) << "Found bad entry in manifest type " << it.value().GetType(); + LOG(ERROR) << "Found bad entry in manifest type " << it.value().type(); continue; }
diff --git a/chrome/browser/chromeos/arc/arc_auth_notification.cc b/chrome/browser/chromeos/arc/arc_auth_notification.cc index 59378d5..5f7a94e 100644 --- a/chrome/browser/chromeos/arc/arc_auth_notification.cc +++ b/chrome/browser/chromeos/arc/arc_auth_notification.cc
@@ -14,6 +14,7 @@ #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/chromeos/arc/arc_optin_uma.h" #include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "chrome/grit/generated_resources.h" @@ -23,8 +24,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/chromeos/devicetype_utils.h" -#include "ui/message_center/message_center.h" -#include "ui/message_center/message_center_observer.h" #include "ui/message_center/notification.h" #include "ui/message_center/notification_delegate.h" #include "ui/message_center/public/cpp/message_center_switches.h" @@ -39,74 +38,45 @@ const char kFirstRunNotificationId[] = "arc_auth/first_run"; class ArcAuthNotificationDelegate - : public message_center::NotificationDelegate, - public message_center::MessageCenterObserver { + : public message_center::NotificationDelegate { public: explicit ArcAuthNotificationDelegate(Profile* profile) : profile_(profile) {} - // message_center::MessageCenterObserver - void OnNotificationUpdated(const std::string& notification_id) override { - if (notification_id != kFirstRunNotificationId) - return; - - StopObserving(); - message_center::Notification* notification = - message_center::MessageCenter::Get()->FindVisibleNotificationById( - notification_id); - if (!notification) { - NOTREACHED(); - return; - } - - if (!notification->IsRead()) - UpdateOptInActionUMA(arc::OptInActionType::NOTIFICATION_TIMED_OUT); - } - // message_center::NotificationDelegate - void Display() override { StartObserving(); } - // TODO(tetsui): Remove this method when IsNewStyleNotificationEnabled() flag // is removed. void ButtonClick(int button_index) override { - StopObserving(); if (button_index == 0) { - UpdateOptInActionUMA(arc::OptInActionType::NOTIFICATION_ACCEPTED); + LogUma(arc::OptInActionType::NOTIFICATION_ACCEPTED); arc::SetArcPlayStoreEnabledForProfile(profile_, true); } else { - UpdateOptInActionUMA(arc::OptInActionType::NOTIFICATION_DECLINED); + LogUma(arc::OptInActionType::NOTIFICATION_DECLINED); arc::SetArcPlayStoreEnabledForProfile(profile_, false); } } void Click() override { - StopObserving(); - UpdateOptInActionUMA(arc::OptInActionType::NOTIFICATION_ACCEPTED); + LogUma(arc::OptInActionType::NOTIFICATION_ACCEPTED); arc::SetArcPlayStoreEnabledForProfile(profile_, true); } - void Close(bool by_user) override { StopObserving(); } + void Close(bool by_user) override { + LogUma(arc::OptInActionType::NOTIFICATION_TIMED_OUT); + } private: - ~ArcAuthNotificationDelegate() override { StopObserving(); } + ~ArcAuthNotificationDelegate() override {} - void StartObserving() { - if (observing_message_center_) - return; - message_center::MessageCenter::Get()->AddObserver(this); - observing_message_center_ = true; + void LogUma(arc::OptInActionType action) { + if (!uma_logged_) + UpdateOptInActionUMA(action); + uma_logged_ = true; } - void StopObserving() { - if (!observing_message_center_) - return; - message_center::MessageCenter::Get()->RemoveObserver(this); - observing_message_center_ = false; - } - - // Unowned pointer. Profile* const profile_; - // To prevent double observing. - bool observing_message_center_ = false; + + // Whether a UMA action has been logged. + bool uma_logged_ = false; DISALLOW_COPY_AND_ASSIGN(ArcAuthNotificationDelegate); }; @@ -181,15 +151,13 @@ l10n_util::GetStringUTF16(IDS_ARC_NOTIFICATION_DISPLAY_SOURCE), GURL(), notifier_id, data, new ArcAuthNotificationDelegate(profile_)); } - message_center::MessageCenter::Get()->AddNotification( - std::move(notification)); + NotificationDisplayService::GetForProfile(profile_)->Display( + NotificationCommon::TRANSIENT, *notification); } void ArcAuthNotification::Hide() { - message_center::MessageCenter* message_center = - message_center::MessageCenter::Get(); - if (message_center) - message_center->RemoveNotification(kFirstRunNotificationId, false); + NotificationDisplayService::GetForProfile(profile_)->Close( + NotificationCommon::TRANSIENT, kFirstRunNotificationId); session_manager::SessionManager* session_manager = session_manager::SessionManager::Get();
diff --git a/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc b/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc index 8746ac4..83e783a9 100644 --- a/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc +++ b/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/chromeos/arc/arc_migration_constants.h" #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/lifetime/application_lifetime.h" +#include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "chrome/grit/generated_resources.h" @@ -25,7 +26,6 @@ #include "ui/chromeos/devicetype_utils.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/paint_vector_icon.h" -#include "ui/message_center/message_center.h" #include "ui/message_center/notification.h" #include "ui/message_center/notification_delegate.h" #include "ui/message_center/public/cpp/message_center_switches.h" @@ -54,33 +54,35 @@ DISALLOW_COPY_AND_ASSIGN(ArcMigrationGuideNotificationDelegate); }; -void DoShowArcMigrationSuccessNotification( - const message_center::NotifierId& notifier_id) { +void DoShowArcMigrationSuccessNotification(Profile* profile) { + message_center::NotifierId notifier_id( + message_center::NotifierId::SYSTEM_COMPONENT, kNotifierId); + notifier_id.profile_id = + multi_user_util::GetAccountIdFromProfile(profile).GetUserEmail(); + + std::unique_ptr<message_center::Notification> notification; if (message_center::IsNewStyleNotificationEnabled()) { - message_center::MessageCenter::Get()->AddNotification( - message_center::Notification::CreateSystemNotification( - message_center::NOTIFICATION_TYPE_SIMPLE, kSuccessNotificationId, - l10n_util::GetStringUTF16(IDS_ARC_MIGRATE_ENCRYPTION_SUCCESS_TITLE), - l10n_util::GetStringUTF16( - IDS_ARC_MIGRATE_ENCRYPTION_SUCCESS_MESSAGE), - gfx::Image(), base::string16(), GURL(), notifier_id, - message_center::RichNotificationData(), - new message_center::NotificationDelegate(), - ash::kNotificationSettingsIcon, - message_center::SystemNotificationWarningLevel::NORMAL)); + notification = message_center::Notification::CreateSystemNotification( + message_center::NOTIFICATION_TYPE_SIMPLE, kSuccessNotificationId, + l10n_util::GetStringUTF16(IDS_ARC_MIGRATE_ENCRYPTION_SUCCESS_TITLE), + l10n_util::GetStringUTF16(IDS_ARC_MIGRATE_ENCRYPTION_SUCCESS_MESSAGE), + gfx::Image(), base::string16(), GURL(), notifier_id, + message_center::RichNotificationData(), nullptr, + ash::kNotificationSettingsIcon, + message_center::SystemNotificationWarningLevel::NORMAL); } else { - message_center::MessageCenter::Get()->AddNotification( - std::make_unique<message_center::Notification>( - message_center::NOTIFICATION_TYPE_SIMPLE, kSuccessNotificationId, - l10n_util::GetStringUTF16(IDS_ARC_MIGRATE_ENCRYPTION_SUCCESS_TITLE), - l10n_util::GetStringUTF16( - IDS_ARC_MIGRATE_ENCRYPTION_SUCCESS_MESSAGE), - gfx::Image(gfx::CreateVectorIcon( - kArcMigrateEncryptionNotificationIcon, gfx::kPlaceholderColor)), - base::string16(), GURL(), notifier_id, - message_center::RichNotificationData(), - new message_center::NotificationDelegate())); + notification = std::make_unique<message_center::Notification>( + message_center::NOTIFICATION_TYPE_SIMPLE, kSuccessNotificationId, + l10n_util::GetStringUTF16(IDS_ARC_MIGRATE_ENCRYPTION_SUCCESS_TITLE), + l10n_util::GetStringUTF16(IDS_ARC_MIGRATE_ENCRYPTION_SUCCESS_MESSAGE), + gfx::Image(gfx::CreateVectorIcon(kArcMigrateEncryptionNotificationIcon, + gfx::kPlaceholderColor)), + base::string16(), GURL(), notifier_id, + message_center::RichNotificationData(), nullptr); } + + NotificationDisplayService::GetForProfile(profile)->Display( + NotificationCommon::TRANSIENT, *notification); } } // namespace @@ -89,8 +91,8 @@ void ShowArcMigrationGuideNotification(Profile* profile) { // Always remove the notification to make sure the notification appears // as a popup in any situation. - message_center::MessageCenter::Get()->RemoveNotification( - kSuggestNotificationId, false /* by_user */); + NotificationDisplayService::GetForProfile(profile)->Close( + NotificationCommon::TRANSIENT, kSuggestNotificationId); message_center::NotifierId notifier_id( message_center::NotifierId::SYSTEM_COMPONENT, kNotifierId); @@ -109,32 +111,34 @@ : l10n_util::GetStringUTF16( IDS_ARC_MIGRATE_ENCRYPTION_NOTIFICATION_MESSAGE); + std::unique_ptr<message_center::Notification> notification; if (message_center::IsNewStyleNotificationEnabled()) { - message_center::MessageCenter::Get()->AddNotification( - message_center::Notification::CreateSystemNotification( - message_center::NOTIFICATION_TYPE_SIMPLE, kSuggestNotificationId, - l10n_util::GetStringUTF16( - IDS_ARC_MIGRATE_ENCRYPTION_NOTIFICATION_TITLE), - message, gfx::Image(), base::string16(), GURL(), notifier_id, - message_center::RichNotificationData(), - new ArcMigrationGuideNotificationDelegate(), - ash::kNotificationSettingsIcon, - message_center::SystemNotificationWarningLevel::NORMAL)); + notification = message_center::Notification::CreateSystemNotification( + message_center::NOTIFICATION_TYPE_SIMPLE, kSuggestNotificationId, + l10n_util::GetStringUTF16( + IDS_ARC_MIGRATE_ENCRYPTION_NOTIFICATION_TITLE), + message, gfx::Image(), base::string16(), GURL(), notifier_id, + message_center::RichNotificationData(), + new ArcMigrationGuideNotificationDelegate(), + ash::kNotificationSettingsIcon, + message_center::SystemNotificationWarningLevel::NORMAL); } else { message_center::RichNotificationData data; data.buttons.push_back(message_center::ButtonInfo(l10n_util::GetStringUTF16( IDS_ARC_MIGRATE_ENCRYPTION_NOTIFICATION_RESTART_BUTTON))); - message_center::MessageCenter::Get()->AddNotification( - std::make_unique<message_center::Notification>( - message_center::NOTIFICATION_TYPE_SIMPLE, kSuggestNotificationId, - l10n_util::GetStringUTF16( - IDS_ARC_MIGRATE_ENCRYPTION_NOTIFICATION_TITLE), - message, - gfx::Image(gfx::CreateVectorIcon( - kArcMigrateEncryptionNotificationIcon, gfx::kPlaceholderColor)), - base::string16(), GURL(), notifier_id, data, - new ArcMigrationGuideNotificationDelegate())); + notification = std::make_unique<message_center::Notification>( + message_center::NOTIFICATION_TYPE_SIMPLE, kSuggestNotificationId, + l10n_util::GetStringUTF16( + IDS_ARC_MIGRATE_ENCRYPTION_NOTIFICATION_TITLE), + message, + gfx::Image(gfx::CreateVectorIcon(kArcMigrateEncryptionNotificationIcon, + gfx::kPlaceholderColor)), + base::string16(), GURL(), notifier_id, data, + new ArcMigrationGuideNotificationDelegate()); } + + NotificationDisplayService::GetForProfile(profile)->Display( + NotificationCommon::TRANSIENT, *notification); } void ShowArcMigrationSuccessNotificationIfNeeded(Profile* profile) { @@ -161,15 +165,11 @@ // except for some exceptional situation or due to some bug. LOG(WARNING) << "Migration has happened for an ARC-disallowed user."; } else { - message_center::NotifierId notifier_id( - message_center::NotifierId::SYSTEM_COMPONENT, kNotifierId); - notifier_id.profile_id = account_id.GetUserEmail(); - // Delay the notification to make sure that it is not hidden behind windows // which are shown at the beginning of user session (e.g. Chrome). base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, - base::BindOnce(&DoShowArcMigrationSuccessNotification, notifier_id), + base::BindOnce(&DoShowArcMigrationSuccessNotification, profile), kSuccessNotificationDelay); }
diff --git a/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc b/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc index afc0758..0370556c 100644 --- a/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc +++ b/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc
@@ -13,6 +13,7 @@ #include "base/memory/singleton.h" #include "base/message_loop/message_loop.h" #include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/chromeos/ash_config.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_browser_context_keyed_service_factory_base.h" #include "components/arc/common/video_decode_accelerator.mojom.h" @@ -23,21 +24,13 @@ #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/service_manager/public/cpp/interface_provider.h" +#include "services/ui/public/cpp/gpu/gpu.h" +#include "ui/aura/env.h" namespace arc { namespace { -void ConnectToVideoDecodeAcceleratorOnIOThread( - mojom::VideoDecodeAcceleratorRequest request) { - content::BindInterfaceInGpuProcess(std::move(request)); -} - -void ConnectToVideoEncodeAcceleratorOnIOThread( - mojom::VideoEncodeAcceleratorRequest request) { - content::BindInterfaceInGpuProcess(std::move(request)); -} - // Singleton factory for GpuArcVideoServiceHost. class GpuArcVideoServiceHostFactory : public internal::ArcBrowserContextKeyedServiceFactoryBase< @@ -65,18 +58,32 @@ void CreateDecodeAccelerator( mojom::VideoDecodeAcceleratorRequest request) override { - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::BindOnce(&ConnectToVideoDecodeAcceleratorOnIOThread, - base::Passed(&request))); + if (chromeos::GetAshConfig() != ash::Config::CLASSIC) { + aura::Env::GetInstance() + ->GetGpuConnection() + ->CreateArcVideoDecodeAccelerator(std::move(request)); + } else { + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&content::BindInterfaceInGpuProcess< + mojom::VideoDecodeAccelerator>, + base::Passed(&request))); + } } void CreateEncodeAccelerator( mojom::VideoEncodeAcceleratorRequest request) override { - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::BindOnce(&ConnectToVideoEncodeAcceleratorOnIOThread, - base::Passed(&request))); + if (chromeos::GetAshConfig() != ash::Config::CLASSIC) { + aura::Env::GetInstance() + ->GetGpuConnection() + ->CreateArcVideoEncodeAccelerator(std::move(request)); + } else { + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&content::BindInterfaceInGpuProcess< + mojom::VideoEncodeAccelerator>, + base::Passed(&request))); + } } private:
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 18f468b..898a9fd 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
@@ -351,18 +351,6 @@ voice_interaction_controller_client_->NotifyStatusChanged(state); } -void ArcVoiceInteractionFrameworkService::OnMetalayerClosed() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - LOG(ERROR) << "Deprecated method called: " - "VoiceInteractionFrameworkHost.OnInstanceClosed"; -} - -void ArcVoiceInteractionFrameworkService::SetMetalayerEnabled(bool enabled) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - LOG(ERROR) << "Deprecated method called: " - "VoiceInteractionFrameworkHost.SetMetalayerEnabled"; -} - void ArcVoiceInteractionFrameworkService::ShowMetalayer() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); NotifyMetalayerStatusChanged(true);
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 ccea2ba..f8fe2f2d 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
@@ -65,9 +65,6 @@ // mojom::VoiceInteractionFrameworkHost overrides. void CaptureFullscreen(CaptureFullscreenCallback callback) override; - // TODO(kaznacheev) remove usages of this obsolete method from the container. - void OnMetalayerClosed() override; - void SetMetalayerEnabled(bool enabled) override; void SetVoiceInteractionState( arc::mojom::VoiceInteractionState state) override;
diff --git a/chrome/browser/chromeos/extensions/echo_private_apitest.cc b/chrome/browser/chromeos/extensions/echo_private_apitest.cc index c701b26..7c676080 100644 --- a/chrome/browser/chromeos/extensions/echo_private_apitest.cc +++ b/chrome/browser/chromeos/extensions/echo_private_apitest.cc
@@ -55,7 +55,7 @@ browser())); ASSERT_TRUE(result.get()); - ASSERT_EQ(base::Value::Type::BOOLEAN, result->GetType()); + ASSERT_EQ(base::Value::Type::BOOLEAN, result->type()); bool result_as_boolean = false; ASSERT_TRUE(result->GetAsBoolean(&result_as_boolean));
diff --git a/chrome/browser/chromeos/extensions/external_cache.cc b/chrome/browser/chromeos/extensions/external_cache.cc index 9736948..40a2a5904 100644 --- a/chrome/browser/chromeos/extensions/external_cache.cc +++ b/chrome/browser/chromeos/extensions/external_cache.cc
@@ -97,7 +97,7 @@ const base::DictionaryValue* entry = NULL; if (!it.value().GetAsDictionary(&entry)) { NOTREACHED() << "ExternalCache found bad entry with type " - << it.value().GetType(); + << it.value().type(); continue; } @@ -240,7 +240,7 @@ const base::DictionaryValue* entry = NULL; if (!it.value().GetAsDictionary(&entry)) { LOG(ERROR) << "ExternalCache found bad entry with type " - << it.value().GetType(); + << it.value().type(); continue; }
diff --git a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc index f642ccf7..1fd028f59 100644 --- a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc +++ b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
@@ -222,11 +222,11 @@ std::set<std::string> languages; const base::Value* language_value = NULL; if (dict.Get(extensions::manifest_keys::kLanguage, &language_value)) { - if (language_value->GetType() == base::Value::Type::STRING) { + if (language_value->is_string()) { std::string language_str; language_value->GetAsString(&language_str); languages.insert(language_str); - } else if (language_value->GetType() == base::Value::Type::LIST) { + } else if (language_value->is_list()) { const base::ListValue* language_list = NULL; language_value->GetAsList(&language_list); for (size_t j = 0; j < language_list->GetSize(); ++j) {
diff --git a/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.cc b/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.cc index 53bc65ff..cb3ffdc 100644 --- a/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.cc +++ b/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.cc
@@ -8,6 +8,8 @@ #include <utility> +#include "ash/app_list/model/search/tokenized_string.h" +#include "ash/app_list/model/search/tokenized_string_match.h" #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service_factory.h" @@ -16,8 +18,6 @@ #include "extensions/browser/extension_registry.h" #include "extensions/common/extension_set.h" #include "extensions/common/permissions/permissions_data.h" -#include "ui/app_list/search/tokenized_string.h" -#include "ui/app_list/search/tokenized_string_match.h" namespace api_launcher_search_provider = extensions::api::launcher_search_provider;
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.cc index c77ec62e..d94cad4 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.cc
@@ -46,13 +46,17 @@ } void EasyUnlockRemoveKeysOperation::RemoveKey() { - cryptohome::Identification id(user_context_.GetAccountId()); const Key* const auth_key = user_context_.GetKey(); - cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel()); - - // TODO(xiyuan): Use ListKeyEx and delete by label instead of by index. + cryptohome::RemoveKeyRequest request; + request.mutable_key()->mutable_data()->set_label( + EasyUnlockKeyManager::GetKeyLabel(key_index_)); + // TODO(crbug.com/558497): Use ListKeyEx and delete by label instead of by + // index. cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx( - id, auth, EasyUnlockKeyManager::GetKeyLabel(key_index_), + cryptohome::Identification((user_context_.GetAccountId())), + cryptohome::CreateAuthorizationRequest(auth_key->GetLabel(), + auth_key->GetSecret()), + request, base::Bind(&EasyUnlockRemoveKeysOperation::OnKeyRemoved, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_password_browsertest.cc b/chrome/browser/chromeos/login/supervised/supervised_user_password_browsertest.cc index 2b7bf74c..680845b 100644 --- a/chrome/browser/chromeos/login/supervised/supervised_user_password_browsertest.cc +++ b/chrome/browser/chromeos/login/supervised/supervised_user_password_browsertest.cc
@@ -107,7 +107,7 @@ // place. IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest, PasswordChangeFromUserTest) { EXPECT_CALL(*mock_homedir_methods_, MountEx(_, _, _, _)).Times(1); - EXPECT_CALL(*mock_homedir_methods_, UpdateKeyEx(_, _, _, _, _)).Times(1); + EXPECT_CALL(*mock_homedir_methods_, UpdateKeyEx(_, _, _, _)).Times(1); SigninAsSupervisedUser(false, 0, kTestSupervisedUserDisplayName); testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_); } @@ -171,7 +171,7 @@ IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest, PasswordChangeFromManagerTest) { EXPECT_CALL(*mock_homedir_methods_, MountEx(_, _, _, _)).Times(1); - EXPECT_CALL(*mock_homedir_methods_, UpdateKeyEx(_, _, _, _, _)).Times(0); + EXPECT_CALL(*mock_homedir_methods_, UpdateKeyEx(_, _, _, _)).Times(0); SigninAsSupervisedUser(false, 1, kTestSupervisedUserDisplayName); testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_); } @@ -261,7 +261,7 @@ IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest, PasswordChangeUserAndManagerTest) { EXPECT_CALL(*mock_homedir_methods_, MountEx(_, _, _, _)).Times(1); - EXPECT_CALL(*mock_homedir_methods_, UpdateKeyEx(_, _, _, _, _)).Times(0); + EXPECT_CALL(*mock_homedir_methods_, UpdateKeyEx(_, _, _, _)).Times(0); SigninAsSupervisedUser(false, 1, kTestSupervisedUserDisplayName); testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_); }
diff --git a/chrome/browser/chromeos/mobile/mobile_activator.cc b/chrome/browser/chromeos/mobile/mobile_activator.cc index 8399421..547a657e 100644 --- a/chrome/browser/chromeos/mobile/mobile_activator.cc +++ b/chrome/browser/chromeos/mobile/mobile_activator.cc
@@ -134,7 +134,7 @@ std::unique_ptr<base::Value> root = base::JSONReader::Read(config, base::JSON_ALLOW_TRAILING_COMMAS); DCHECK(root.get() != NULL); - if (!root.get() || root->GetType() != base::Value::Type::DICTIONARY) { + if (!root.get() || !root->is_dict()) { LOG(WARNING) << "Bad cellular config file"; return false; }
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc index 0a122a38..6f44860 100644 --- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc +++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
@@ -68,9 +68,9 @@ return false; } const base::Value* value = CrosSettings::Get()->GetPref(kDeviceOwner); - if (!value || value->GetType() != base::Value::Type::STRING) + if (!value || !value->is_string()) return false; - return static_cast<const base::Value*>(value)->GetString() == user_id; + return value->GetString() == user_id; } void LoadPrivateKeyByPublicKeyOnWorkerThread(
diff --git a/chrome/browser/chromeos/platform_keys/key_permissions.cc b/chrome/browser/chromeos/platform_keys/key_permissions.cc index ac8a3ab..816143ac9 100644 --- a/chrome/browser/chromeos/platform_keys/key_permissions.cc +++ b/chrome/browser/chromeos/platform_keys/key_permissions.cc
@@ -319,7 +319,7 @@ &new_entry.sign_unlimited); state_store_entries_.push_back(new_entry); } else { - LOG(ERROR) << "Found invalid entry of type " << entry.GetType() + LOG(ERROR) << "Found invalid entry of type " << entry.type() << " in PlatformKeys state store."; continue; }
diff --git a/chrome/browser/chromeos/power/ml/user_activity_event.proto b/chrome/browser/chromeos/power/ml/user_activity_event.proto new file mode 100644 index 0000000..4f23d07 --- /dev/null +++ b/chrome/browser/chromeos/power/ml/user_activity_event.proto
@@ -0,0 +1,131 @@ +// 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. + +syntax = "proto2"; + +package chromeos.power.ml; + +option optimize_for = LITE_RUNTIME; + +// This proto will represent one logged event to be used as a training example. +// It contains both features and labels. +message UserActivityEvent { + message ModelParams { + // Event logging will be triggered after inactivity of start_delay_sec. + // Value will be in the range of 10sec - 20sec, which may be tuned following + // experiments. + optional int32 start_delay_sec = 1; + // timeout_delay_sec defines extended idle period following screen-off, at + // which point we will log event type to be TIMEOUT. Value will be ~10sec or + // shorter, which may be tuned following experiments. + optional int32 timeout_delay_sec = 2; + } + + // Event describes what happens after user is inactive for start_delay_sec. It + // will be used as training labels. + message Event { + // Event type describes whether user reactivates or turns off the system or + // remains idle until model times out. This will be used as labels. + enum Type { + REACTIVATE = 1; + OFF = 2; + TIMEOUT = 3; + } + optional Type type = 1; + + // Trigger of the event. They won't be used as labels and will be used for + // analysis only. + enum Reason { + USER_ACTIVITY = 1; + VIDEO_ACTIVITY = 2; + POWER_CHANGED = 3; + LID_CLOSED = 4; + SHUTDOWN = 5; + SESSION_STOPPED = 6; + SCREEN_OFF = 7; + SCREEN_LOCK = 8; + IDLE_SLEEP = 9; + } + optional Reason reason = 2; + } + + message Features { + // Time taken to transition between states. + optional int32 on_to_dim_sec = 1; + optional int32 dim_to_screen_off_sec = 2; + + // Last activity and last user activity as seconds since midnight in the + // local time zone. Last activity may not be user-related, e.g. it may be a + // video-playing activity. Below we record both general activity time and + // user activity time. + optional int32 last_activity_time_sec = 3; + optional int32 last_user_activity_time_sec = 4; + + enum DayOfWeek { + MON = 1; + TUE = 2; + WED = 3; + THU = 4; + FRI = 5; + SAT = 6; + SUN = 7; + } + optional DayOfWeek last_activity_day = 5; + + // Time from last mouse/key event to when the logging starts (for training + // data generation). This may not be the same as start_delay_sec, depending + // on what the last activity is. + optional int32 time_since_last_mouse_sec = 6; + optional int32 time_since_last_key_sec = 7; + + // Duration of activity (user or video) up to last_activity_time_sec. If + // activity starts at time t1, then recent_time_active_sec = + // |last_activity_time_sec - t1|. We ignore short periods of idle time (i.e. + // user is considered active in this idle period), but the short periods + // must be shorter than start_delay_sec. + // TODO(jiameng): we may consider a different way of measuring continued + // activity following experiments. + optional int32 recent_time_active_sec = 8; + + // At the moment, we only log events when device is Chromebook, hence we + // ignore types such as Chromebase, Chromebit and Chromebox. + enum DeviceType { + UNKNOWN_DEVICE = 0; + CHROMEBOOK = 1; + } + + optional DeviceType device_type = 9; + + // Device mode. + enum DeviceMode { + UNKNOWN_MODE = 0; + // Lid is closed. + CLOSED_LID = 1; + // Lid is open, tablet mode is off or unsupported. + CLAMSHELL = 2; + // Lid is open, tablet mode is on or no lid at all. + TABLET = 3; + } + optional DeviceMode device_mode = 10; + + optional float battery_percent = 11; + optional bool on_battery = 12; + + // Whether user/device is managed. + enum ManagementType { + UNKNOWN_MANAGEMENT = 0; + MANAGED = 1; + UNMANAGED = 2; + } + optional ManagementType user_management = 13; + optional ManagementType device_management = 14; + + // Whether network is connected. + optional bool is_online = 15; + } + + optional ModelParams params = 1; + optional Event event = 2; + optional Features features = 3; +}
diff --git a/chrome/browser/chromeos/proxy_cros_settings_parser.cc b/chrome/browser/chromeos/proxy_cros_settings_parser.cc index baee7de..a552923 100644 --- a/chrome/browser/chromeos/proxy_cros_settings_parser.cc +++ b/chrome/browser/chromeos/proxy_cros_settings_parser.cc
@@ -264,7 +264,7 @@ } } else if (path == kProxyIgnoreList) { net::ProxyBypassRules bypass_rules; - if (in_value->GetType() == base::Value::Type::LIST) { + if (in_value->is_list()) { const base::ListValue* list_value = static_cast<const base::ListValue*>(in_value); for (size_t x = 0; x < list_value->GetSize(); x++) {
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc index 4ffc5b6..f2b4891 100644 --- a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc +++ b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
@@ -39,7 +39,6 @@ void AssertInterceptedIO( const GURL& url, net::URLRequestJobFactory* interceptor) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); net::URLRequestContext context; std::unique_ptr<net::URLRequest> request(context.CreateRequest( url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS)); @@ -52,7 +51,6 @@ void AssertIntercepted( const GURL& url, net::URLRequestJobFactory* interceptor) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::BindOnce(AssertInterceptedIO, url, base::Unretained(interceptor))); @@ -98,7 +96,6 @@ const std::string& scheme, bool expected, ProtocolHandlerRegistry::JobInterceptorFactory* interceptor) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); interceptor->Chain(std::unique_ptr<net::URLRequestJobFactory>( new FakeURLRequestJobFactory())); ASSERT_EQ(expected, interceptor->IsHandledProtocol(scheme)); @@ -109,7 +106,6 @@ const std::string& scheme, bool expected, ProtocolHandlerRegistry::JobInterceptorFactory* interceptor) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::BindOnce(AssertWillHandleIO, scheme, expected, base::Unretained(interceptor)));
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc index 4c970bf..aab5b56 100644 --- a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc +++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
@@ -34,14 +34,15 @@ using content::DevToolsAgentHost; -char ChromeDevToolsManagerDelegate::kTypeApp[] = "app"; -char ChromeDevToolsManagerDelegate::kTypeBackgroundPage[] = "background_page"; +const char ChromeDevToolsManagerDelegate::kTypeApp[] = "app"; +const char ChromeDevToolsManagerDelegate::kTypeBackgroundPage[] = + "background_page"; namespace { -char kLocationsParam[] = "locations"; -char kHostParam[] = "host"; -char kPortParam[] = "port"; +const char kLocationsParam[] = "locations"; +const char kHostParam[] = "host"; +const char kPortParam[] = "port"; bool GetExtensionInfo(content::WebContents* wc, std::string* name, @@ -60,9 +61,9 @@ *name = extension->name(); *type = ChromeDevToolsManagerDelegate::kTypeBackgroundPage; return true; - } else if (extension->is_hosted_app() || - extension->is_legacy_packaged_app() || - extension->is_platform_app()) { + } + if (extension->is_hosted_app() || extension->is_legacy_packaged_app() || + extension->is_platform_app()) { *name = extension->name(); *type = ChromeDevToolsManagerDelegate::kTypeApp; return true;
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.h b/chrome/browser/devtools/chrome_devtools_manager_delegate.h index f426f7b0..645e0d0 100644 --- a/chrome/browser/devtools/chrome_devtools_manager_delegate.h +++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.h
@@ -25,8 +25,8 @@ public content::DevToolsManagerDelegate, public content::DevToolsAgentHostObserver { public: - static char kTypeApp[]; - static char kTypeBackgroundPage[]; + static const char kTypeApp[]; + static const char kTypeBackgroundPage[]; ChromeDevToolsManagerDelegate(); ~ChromeDevToolsManagerDelegate() override;
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc index 4a099b2..e447142 100644 --- a/chrome/browser/devtools/devtools_sanity_browsertest.cc +++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -67,8 +67,6 @@ #include "content/public/browser/url_data_source.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui_controller.h" -#include "content/public/browser/worker_service.h" -#include "content/public/browser/worker_service_observer.h" #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "content/public/test/browser_test_utils.h" @@ -96,12 +94,11 @@ using app_modal::NativeAppModalDialog; using content::BrowserThread; using content::DevToolsAgentHost; +using content::DevToolsAgentHostObserver; using content::NavigationController; using content::RenderFrameHost; using content::RenderViewHost; using content::WebContents; -using content::WorkerService; -using content::WorkerServiceObserver; using extensions::Extension; namespace { @@ -659,116 +656,53 @@ WorkerDevToolsSanityTest() : window_(NULL) {} protected: - class WorkerData : public base::RefCountedThreadSafe<WorkerData> { + class WorkerCreationObserver : public DevToolsAgentHostObserver { public: - WorkerData() : worker_process_id(0), worker_route_id(0) {} - int worker_process_id; - int worker_route_id; - - private: - friend class base::RefCountedThreadSafe<WorkerData>; - ~WorkerData() {} - }; - - class WorkerCreationObserver : public WorkerServiceObserver { - public: - explicit WorkerCreationObserver(const std::string& path, - WorkerData* worker_data) - : path_(path), worker_data_(worker_data) {} - - private: - ~WorkerCreationObserver() override {} - - void WorkerCreated(const GURL& url, - const std::string& name, - int process_id, - int route_id) override { - if (url.path().rfind(path_) == std::string::npos) - return; - worker_data_->worker_process_id = process_id; - worker_data_->worker_route_id = route_id; - WorkerService::GetInstance()->RemoveObserver(this); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::MessageLoop::QuitWhenIdleClosure()); - delete this; + WorkerCreationObserver(const std::string& path, + scoped_refptr<DevToolsAgentHost>* out_host, + base::Closure quit) + : path_(path), out_host_(out_host), quit_(quit) { + DevToolsAgentHost::AddObserver(this); } + + private: + ~WorkerCreationObserver() override { + DevToolsAgentHost::RemoveObserver(this); + } + + void DevToolsAgentHostCreated(DevToolsAgentHost* host) override { + if (host->GetType() == DevToolsAgentHost::kTypeSharedWorker && + host->GetURL().path().rfind(path_) != std::string::npos) { + *out_host_ = host; + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_); + delete this; + } + } + std::string path_; - scoped_refptr<WorkerData> worker_data_; + scoped_refptr<DevToolsAgentHost>* out_host_; + base::Closure quit_; }; - class WorkerTerminationObserver : public WorkerServiceObserver { - public: - explicit WorkerTerminationObserver(WorkerData* worker_data) - : worker_data_(worker_data) { + static scoped_refptr<DevToolsAgentHost> WaitForFirstSharedWorker( + const char* path) { + for (auto& host : DevToolsAgentHost::GetOrCreateAll()) { + if (host->GetType() == DevToolsAgentHost::kTypeSharedWorker && + host->GetURL().path().rfind(path) != std::string::npos) { + return host; + } } - - private: - ~WorkerTerminationObserver() override {} - - void WorkerDestroyed(int process_id, int route_id) override { - ASSERT_EQ(worker_data_->worker_process_id, process_id); - ASSERT_EQ(worker_data_->worker_route_id, route_id); - WorkerService::GetInstance()->RemoveObserver(this); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::MessageLoop::QuitWhenIdleClosure()); - delete this; - } - scoped_refptr<WorkerData> worker_data_; - }; - - void RunTest(const char* test_name, - const char* test_page, - const char* worker_path) { - ASSERT_TRUE(spawned_test_server()->Start()); - GURL url = spawned_test_server()->GetURL(test_page); - ui_test_utils::NavigateToURL(browser(), url); - - scoped_refptr<WorkerData> worker_data = - WaitForFirstSharedWorker(worker_path); - OpenDevToolsWindowForSharedWorker(worker_data.get()); - RunTestFunction(window_, test_name); - CloseDevToolsWindow(); + scoped_refptr<DevToolsAgentHost> host; + base::RunLoop run_loop; + new WorkerCreationObserver(path, &host, run_loop.QuitWhenIdleClosure()); + content::RunThisRunLoop(&run_loop); + return host; } - static void TerminateWorker(scoped_refptr<WorkerData> worker_data) { - if (!WorkerService::GetInstance()->TerminateWorker( - worker_data->worker_process_id, worker_data->worker_route_id)) - FAIL() << "Failed to terminate worker.\n"; - - WorkerService::GetInstance()->AddObserver( - new WorkerTerminationObserver(worker_data.get())); - - content::RunMessageLoop(); - } - - static scoped_refptr<WorkerData> WaitForFirstSharedWorker(const char* path) { - scoped_refptr<WorkerData> worker_data(new WorkerData()); - - std::vector<WorkerService::WorkerInfo> worker_info = - WorkerService::GetInstance()->GetWorkers(); - for (size_t i = 0; i < worker_info.size(); i++) { - if (worker_info[i].url.path().rfind(path) == std::string::npos) - continue; - worker_data->worker_process_id = worker_info[0].process_id; - worker_data->worker_route_id = worker_info[0].route_id; - return worker_data; - } - - WorkerService::GetInstance()->AddObserver( - new WorkerCreationObserver(path, worker_data.get())); - - content::RunMessageLoop(); - return worker_data; - } - - void OpenDevToolsWindowForSharedWorker(WorkerData* worker_data) { + void OpenDevToolsWindow(scoped_refptr<DevToolsAgentHost> agent_host) { Profile* profile = browser()->profile(); - scoped_refptr<DevToolsAgentHost> agent_host( - DevToolsAgentHost::GetForWorker( - worker_data->worker_process_id, - worker_data->worker_route_id)); - window_ = DevToolsWindowTesting::OpenDevToolsWindowForWorkerSync( - profile, agent_host.get()); + window_ = + DevToolsWindowTesting::OpenDevToolsWindowSync(profile, agent_host); } void CloseDevToolsWindow() { @@ -1893,7 +1827,15 @@ } IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest, InspectSharedWorker) { - RunTest("testSharedWorker", kSharedWorkerTestPage, kSharedWorkerTestWorker); + ASSERT_TRUE(spawned_test_server()->Start()); + GURL url = spawned_test_server()->GetURL(kSharedWorkerTestPage); + ui_test_utils::NavigateToURL(browser(), url); + + scoped_refptr<DevToolsAgentHost> host = + WaitForFirstSharedWorker(kSharedWorkerTestWorker); + OpenDevToolsWindow(host); + RunTestFunction(window_, "testSharedWorker"); + CloseDevToolsWindow(); } // Flaky on multiple platforms. See http://crbug.com/432444 @@ -1903,15 +1845,15 @@ GURL url = spawned_test_server()->GetURL(kReloadSharedWorkerTestPage); ui_test_utils::NavigateToURL(browser(), url); - scoped_refptr<WorkerData> worker_data = + scoped_refptr<DevToolsAgentHost> host = WaitForFirstSharedWorker(kReloadSharedWorkerTestWorker); - OpenDevToolsWindowForSharedWorker(worker_data.get()); + OpenDevToolsWindow(host); // We should make sure that the worker inspector has loaded before // terminating worker. RunTestFunction(window_, "testPauseInSharedWorkerInitialization1"); - TerminateWorker(worker_data); + host->Close(); // Reload page to restart the worker. ui_test_utils::NavigateToURL(browser(), url);
diff --git a/chrome/browser/devtools/devtools_targets_ui.cc b/chrome/browser/devtools/devtools_targets_ui.cc index 08168e3..1776c366 100644 --- a/chrome/browser/devtools/devtools_targets_ui.cc +++ b/chrome/browser/devtools/devtools_targets_ui.cc
@@ -19,19 +19,9 @@ #include "base/version.h" #include "chrome/browser/devtools/device/devtools_android_bridge.h" #include "chrome/browser/devtools/serialize_host_descriptions.h" -#include "content/public/browser/browser_child_process_observer.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/child_process_data.h" #include "content/public/browser/devtools_agent_host.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/notification_types.h" -#include "content/public/browser/worker_service.h" -#include "content/public/browser/worker_service_observer.h" -#include "content/public/common/process_type.h" -#include "net/base/escape.h" +#include "content/public/browser/devtools_agent_host_observer.h" using content::BrowserThread; using content::DevToolsAgentHost; @@ -90,56 +80,10 @@ base::WeakPtrFactory<CancelableTimer> weak_factory_; }; -// WorkerObserver ------------------------------------------------------------- - -class WorkerObserver - : public content::WorkerServiceObserver, - public base::RefCountedThreadSafe<WorkerObserver> { - public: - WorkerObserver() {} - - void Start(base::Closure callback) { - DCHECK(callback_.is_null()); - DCHECK(!callback.is_null()); - callback_ = callback; - content::WorkerService::GetInstance()->AddObserver(this); - } - - void Stop() { - DCHECK(!callback_.is_null()); - callback_ = base::Closure(); - content::WorkerService::GetInstance()->RemoveObserver(this); - } - - private: - friend class base::RefCountedThreadSafe<WorkerObserver>; - ~WorkerObserver() override {} - - // content::WorkerServiceObserver overrides: - void WorkerCreated(const GURL& url, - const std::string& name, - int process_id, - int route_id) override { - Notify(); - } - - void WorkerDestroyed(int process_id, int route_id) override { Notify(); } - - void Notify() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (callback_.is_null()) - return; - callback_.Run(); - } - - base::Closure callback_; -}; - // LocalTargetsUIHandler --------------------------------------------- -class LocalTargetsUIHandler - : public DevToolsTargetsUIHandler, - public content::NotificationObserver { +class LocalTargetsUIHandler : public DevToolsTargetsUIHandler, + public content::DevToolsAgentHostObserver { public: explicit LocalTargetsUIHandler(const Callback& callback); ~LocalTargetsUIHandler() override; @@ -148,49 +92,40 @@ void ForceUpdate() override; private: - // content::NotificationObserver overrides. - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + // content::DevToolsAgentHostObserver overrides. + bool ShouldForceDevToolsAgentHostCreation() override; + void DevToolsAgentHostCreated(DevToolsAgentHost* agent_host) override; + void DevToolsAgentHostDestroyed(DevToolsAgentHost* agent_host) override; - void ScheduleUpdate(); - void UpdateTargets(); - void SendTargets(const DevToolsAgentHost::List& targets); + void ScheduleUpdate(); + void UpdateTargets(); + void SendTargets(const DevToolsAgentHost::List& targets); - content::NotificationRegistrar notification_registrar_; - std::unique_ptr<CancelableTimer> timer_; - scoped_refptr<WorkerObserver> observer_; - base::WeakPtrFactory<LocalTargetsUIHandler> weak_factory_; + std::unique_ptr<CancelableTimer> timer_; + base::WeakPtrFactory<LocalTargetsUIHandler> weak_factory_; }; LocalTargetsUIHandler::LocalTargetsUIHandler( const Callback& callback) : DevToolsTargetsUIHandler(kTargetSourceLocal, callback), - observer_(new WorkerObserver()), weak_factory_(this) { - notification_registrar_.Add(this, - content::NOTIFICATION_WEB_CONTENTS_CONNECTED, - content::NotificationService::AllSources()); - notification_registrar_.Add(this, - content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, - content::NotificationService::AllSources()); - notification_registrar_.Add(this, - content::NOTIFICATION_WEB_CONTENTS_DESTROYED, - content::NotificationService::AllSources()); - observer_->Start(base::Bind(&LocalTargetsUIHandler::ScheduleUpdate, - base::Unretained(this))); + DevToolsAgentHost::AddObserver(this); UpdateTargets(); } LocalTargetsUIHandler::~LocalTargetsUIHandler() { - notification_registrar_.RemoveAll(); - observer_->Stop(); + DevToolsAgentHost::RemoveObserver(this); } -void LocalTargetsUIHandler::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { +bool LocalTargetsUIHandler::ShouldForceDevToolsAgentHostCreation() { + return true; +} + +void LocalTargetsUIHandler::DevToolsAgentHostCreated(DevToolsAgentHost*) { + ScheduleUpdate(); +} + +void LocalTargetsUIHandler::DevToolsAgentHostDestroyed(DevToolsAgentHost*) { ScheduleUpdate(); }
diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h index 8ee560a0..a12f2d54 100644 --- a/chrome/browser/devtools/devtools_window.h +++ b/chrome/browser/devtools/devtools_window.h
@@ -102,11 +102,6 @@ // Node frontend is always undocked. static void OpenNodeFrontendWindow(Profile* profile); - // Worker frontend is always undocked. - static void OpenDevToolsWindowForWorker( - Profile* profile, - const scoped_refptr<content::DevToolsAgentHost>& worker_agent); - static void InspectElement(content::RenderFrameHost* inspected_frame_host, int x, int y); @@ -214,6 +209,9 @@ static void OpenDevToolsWindowForFrame( Profile* profile, const scoped_refptr<content::DevToolsAgentHost>& agent_host); + static void OpenDevToolsWindowForWorker( + Profile* profile, + const scoped_refptr<content::DevToolsAgentHost>& worker_agent); // DevTools lifecycle typically follows this way: // - Toggle/Open: client call;
diff --git a/chrome/browser/devtools/devtools_window_testing.cc b/chrome/browser/devtools/devtools_window_testing.cc index e46c36a0..19ee642f 100644 --- a/chrome/browser/devtools/devtools_window_testing.cc +++ b/chrome/browser/devtools/devtools_window_testing.cc
@@ -132,11 +132,11 @@ } // static -DevToolsWindow* DevToolsWindowTesting::OpenDevToolsWindowForWorkerSync( - Profile* profile, content::DevToolsAgentHost* worker_agent) { - DevToolsWindow::OpenDevToolsWindowForWorker( - profile, worker_agent); - DevToolsWindow* window = DevToolsWindow::FindDevToolsWindow(worker_agent); +DevToolsWindow* DevToolsWindowTesting::OpenDevToolsWindowSync( + Profile* profile, + scoped_refptr<content::DevToolsAgentHost> agent_host) { + DevToolsWindow::OpenDevToolsWindow(agent_host, profile); + DevToolsWindow* window = DevToolsWindow::FindDevToolsWindow(agent_host.get()); WaitForDevToolsWindowLoad(window); return window; }
diff --git a/chrome/browser/devtools/devtools_window_testing.h b/chrome/browser/devtools/devtools_window_testing.h index 19fd9ee55..bb10fc09 100644 --- a/chrome/browser/devtools/devtools_window_testing.h +++ b/chrome/browser/devtools/devtools_window_testing.h
@@ -29,8 +29,9 @@ bool is_docked); static DevToolsWindow* OpenDevToolsWindowSync( Browser* browser, bool is_docked); - static DevToolsWindow* OpenDevToolsWindowForWorkerSync( - Profile* profile, content::DevToolsAgentHost* worker_agent); + static DevToolsWindow* OpenDevToolsWindowSync( + Profile* profile, + scoped_refptr<content::DevToolsAgentHost> agent_host); // Closes the window like it was user-initiated. static void CloseDevToolsWindow(DevToolsWindow* window);
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 332cba78..66b71f7 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -976,7 +976,7 @@ } deps += [ "//ash", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//components/arc", "//components/chrome_apps", "//components/constrained_window",
diff --git a/chrome/browser/extensions/DEPS b/chrome/browser/extensions/DEPS index 175ae864..c668eb2 100644 --- a/chrome/browser/extensions/DEPS +++ b/chrome/browser/extensions/DEPS
@@ -12,6 +12,9 @@ # For access to testing command line switches. "+ppapi/shared_impl", + + # TODO(hejq): Remove this once app_list is migrated. http://crbug.com/733662 + "+ash/app_list/model", ] specific_include_rules = { "bookmark_app_helper\.cc": [
diff --git a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc index bf473d6..897c7ef 100644 --- a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc +++ b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc
@@ -10,14 +10,17 @@ #include "extensions/common/error_utils.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" -namespace extensions { -namespace api { +namespace { const char kGoogleDotCom[] = "google.com"; -const char* kGoogleGstaticAppIds[] = { - "https://www.gstatic.com/securitykey/origins.json", - "https://www.gstatic.com/securitykey/a/google.com/origins.json" -}; +constexpr const char* kGoogleGstaticAppIds[] = { + "https://www.gstatic.com/securitykey/origins.json", + "https://www.gstatic.com/securitykey/a/google.com/origins.json"}; + +} // namespace + +namespace extensions { +namespace api { CryptotokenPrivateCanOriginAssertAppIdFunction:: CryptotokenPrivateCanOriginAssertAppIdFunction() @@ -69,12 +72,9 @@ // gstatic.com appIds. // TODO(juanlang): remove when legacy constraints are removed. if (origin_etldp1 == kGoogleDotCom) { - for (size_t i = 0; - i < sizeof(kGoogleGstaticAppIds) / sizeof(kGoogleGstaticAppIds[0]); - i++) { - if (params->app_id_url == kGoogleGstaticAppIds[i]) { + for (const char* id : kGoogleGstaticAppIds) { + if (params->app_id_url == id) return RespondNow(OneArgument(base::MakeUnique<base::Value>(true))); - } } } return RespondNow(OneArgument(base::MakeUnique<base::Value>(false)));
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc index 6f20452..1c1aa455 100644 --- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc
@@ -529,7 +529,7 @@ extensions::api_test_utils::RunFunctionAndReturnSingleResult( function.get(), "[]", profile())); ASSERT_TRUE(value.get()); - ASSERT_EQ(base::Value::Type::LIST, value->GetType()); + ASSERT_EQ(base::Value::Type::LIST, value->type()); base::ListValue* list_value = static_cast<base::ListValue*>(value.get()); EXPECT_EQ(0u, list_value->GetSize());
diff --git a/chrome/browser/extensions/api/launcher_page/launcher_page_api.cc b/chrome/browser/extensions/api/launcher_page/launcher_page_api.cc index 3817c0f..06c44235 100644 --- a/chrome/browser/extensions/api/launcher_page/launcher_page_api.cc +++ b/chrome/browser/extensions/api/launcher_page/launcher_page_api.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/extensions/api/launcher_page/launcher_page_api.h" +#include "ash/app_list/model/app_list_model.h" #include "base/lazy_instance.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_service.h" @@ -11,7 +12,6 @@ #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" #include "chrome/common/extensions/api/launcher_page.h" #include "content/public/browser/web_contents.h" -#include "ui/app_list/app_list_model.h" namespace extensions {
diff --git a/chrome/browser/extensions/api/preference/preference_api.cc b/chrome/browser/extensions/api/preference/preference_api.cc index a3f92263..b388308 100644 --- a/chrome/browser/extensions/api/preference/preference_api.cc +++ b/chrome/browser/extensions/api/preference/preference_api.cc
@@ -126,7 +126,7 @@ APIPermission::kPrivacy, APIPermission::kPrivacy}, {"thirdPartyCookiesAllowed", prefs::kBlockThirdPartyCookies, APIPermission::kPrivacy, APIPermission::kPrivacy}, - {"translationServiceEnabled", prefs::kEnableTranslate, + {"translationServiceEnabled", prefs::kOfferTranslateEnabled, APIPermission::kPrivacy, APIPermission::kPrivacy}, #if BUILDFLAG(ENABLE_WEBRTC) // webRTCMultipleRoutesEnabled and webRTCNonProxiedUdpEnabled have been @@ -467,7 +467,7 @@ extension_prefs()->pref_service()->FindPreference(pref_key); DCHECK(pref) << "Extension controlled preference key " << pref_key << " not registered."; - DCHECK_EQ(pref->GetType(), value->GetType()) + DCHECK_EQ(pref->GetType(), value->type()) << "Extension controlled preference " << pref_key << " has wrong type."; #endif
diff --git a/chrome/browser/extensions/api/preference/preference_apitest.cc b/chrome/browser/extensions/api/preference/preference_apitest.cc index 631a0bb..96ea4385 100644 --- a/chrome/browser/extensions/api/preference/preference_apitest.cc +++ b/chrome/browser/extensions/api/preference/preference_apitest.cc
@@ -50,7 +50,7 @@ EXPECT_FALSE(prefs->GetBoolean(prefs::kBlockThirdPartyCookies)); EXPECT_TRUE(prefs->GetBoolean(prefs::kEnableHyperlinkAuditing)); EXPECT_TRUE(prefs->GetBoolean(prefs::kEnableReferrers)); - EXPECT_TRUE(prefs->GetBoolean(prefs::kEnableTranslate)); + EXPECT_TRUE(prefs->GetBoolean(prefs::kOfferTranslateEnabled)); EXPECT_EQ(chrome_browser_net::NETWORK_PREDICTION_DEFAULT, prefs->GetInteger(prefs::kNetworkPredictionOptions)); EXPECT_TRUE( @@ -70,7 +70,7 @@ EXPECT_TRUE(prefs->GetBoolean(prefs::kBlockThirdPartyCookies)); EXPECT_FALSE(prefs->GetBoolean(prefs::kEnableHyperlinkAuditing)); EXPECT_FALSE(prefs->GetBoolean(prefs::kEnableReferrers)); - EXPECT_FALSE(prefs->GetBoolean(prefs::kEnableTranslate)); + EXPECT_FALSE(prefs->GetBoolean(prefs::kOfferTranslateEnabled)); EXPECT_EQ(chrome_browser_net::NETWORK_PREDICTION_NEVER, prefs->GetInteger(prefs::kNetworkPredictionOptions)); EXPECT_FALSE( @@ -121,7 +121,7 @@ prefs->SetBoolean(prefs::kBlockThirdPartyCookies, true); prefs->SetBoolean(prefs::kEnableHyperlinkAuditing, false); prefs->SetBoolean(prefs::kEnableReferrers, false); - prefs->SetBoolean(prefs::kEnableTranslate, false); + prefs->SetBoolean(prefs::kOfferTranslateEnabled, false); prefs->SetInteger(prefs::kNetworkPredictionOptions, chrome_browser_net::NETWORK_PREDICTION_NEVER); prefs->SetBoolean(password_manager::prefs::kCredentialsEnableService, false);
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index ea1bdfce..b614c53 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -181,7 +181,7 @@ settings_private::PrefType::PREF_TYPE_LIST; (*s_whitelist)[spellcheck::prefs::kSpellCheckUseSpellingService] = settings_private::PrefType::PREF_TYPE_BOOLEAN; - (*s_whitelist)[::prefs::kEnableTranslate] = + (*s_whitelist)[::prefs::kOfferTranslateEnabled] = settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[translate::TranslatePrefs::kPrefTranslateBlockedLanguages] = settings_private::PrefType::PREF_TYPE_LIST; @@ -484,7 +484,7 @@ return nullptr; } pref_object->key = name; - pref_object->type = GetType(name, value->GetType()); + pref_object->type = GetType(name, value->type()); pref_object->value.reset(value->DeepCopy()); #endif
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc index daf800a..6d01025 100644 --- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc +++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
@@ -62,15 +62,55 @@ // http://crbug.com/710371 content::RenderProcessHost* WebrtcLoggingPrivateFunction::RphFromRequest( const RequestInfo& request, const std::string& security_origin) { + // There are 2 ways these API functions can get called. + // + // 1. From a whitelisted component extension on behalf of a page with the + // appropriate origin via a message from that page. In this case, either the + // guest process id or the tab id is on the message received by the component + // extension, and the extension can pass that along in RequestInfo as + // |guest_process_id| or |tab_id|. + // + // 2. From a whitelisted app that hosts a page in a webview. In this case, + // the app should call these API functions with the |target_webview| flag + // set, from a web contents that has exactly 1 webview . + + // If |target_webview| is set, lookup the guest content's render process in + // the sender's web contents. There should be exactly 1 guest. + if (request.target_webview.get()) { + content::RenderProcessHost* target_host = nullptr; + int guests_found = 0; + auto get_guest = [](int* guests_found, + content::RenderProcessHost** target_host, + content::WebContents* guest_contents) { + *guests_found = *guests_found + 1; + *target_host = guest_contents->GetMainFrame()->GetProcess(); + // Don't short-circuit, so we can count how many other guest contents + // there are. + return false; + }; + guest_view::GuestViewManager::FromBrowserContext(browser_context()) + ->ForEachGuest(GetSenderWebContents(), + base::Bind(get_guest, &guests_found, &target_host)); + if (!target_host) { + error_ = "No webview render process found"; + return nullptr; + } + if (guests_found > 1) { + error_ = "Multiple webviews found"; + return nullptr; + } + return target_host; + } + // If |guest_process_id| is defined, directly use this id to find the // corresponding RenderProcessHost. if (request.guest_process_id.get()) return content::RenderProcessHost::FromID(*request.guest_process_id); - // Otherwise, use the |tab_id|. If there's no |tab_id| and no - // |guest_process_id|, we can't look up the RenderProcessHost. + // Otherwise, use the |tab_id|. If there's no |target_viewview|, no |tab_id|, + // and no |guest_process_id|, we can't look up the RenderProcessHost. if (!request.tab_id.get()) { - error_ = "No tab ID or guest process ID specified."; + error_ = "No webview, tab ID, or guest process ID specified."; return nullptr; }
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc index ca4f2481..fd6654f 100644 --- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc +++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc
@@ -7,6 +7,7 @@ #include "base/threading/thread_restrictions.h" #include "chrome/browser/apps/app_browsertest_util.h" #include "chrome/browser/media/webrtc/webrtc_log_list.h" +#include "chrome/common/chrome_switches.h" class WebrtcLoggingPrivateApiBrowserTest : public extensions::PlatformAppBrowserTest { @@ -54,3 +55,13 @@ "api_test/webrtc_logging_private/no_get_logs_directory_permissions")) << message_; } + +IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiBrowserTest, + TestStartAudioDebugRecordingsForWebviewFromApp) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableAudioDebugRecordingsFromExtension); + ASSERT_TRUE( + RunPlatformAppTest("api_test/webrtc_logging_private/audio_debug/" + "start_audio_debug_recordings_for_webview_from_app")) + << message_; +}
diff --git a/chrome/browser/extensions/chrome_app_icon_unittest.cc b/chrome/browser/extensions/chrome_app_icon_unittest.cc index dbbcca9..3641e3f 100644 --- a/chrome/browser/extensions/chrome_app_icon_unittest.cc +++ b/chrome/browser/extensions/chrome_app_icon_unittest.cc
@@ -4,6 +4,7 @@ #include <memory> +#include "ash/app_list/model/app_list_item.h" #include "base/macros.h" #include "base/run_loop.h" #include "chrome/browser/extensions/chrome_app_icon.h" @@ -17,7 +18,6 @@ #include "chrome/common/chrome_constants.h" #include "chrome/test/base/testing_profile.h" #include "extensions/common/constants.h" -#include "ui/app_list/app_list_item.h" #include "ui/gfx/image/image_unittest_util.h" #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc index 020925b..378f8a66 100644 --- a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc +++ b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc
@@ -333,6 +333,7 @@ } void Init() { + ExtensionErrorReporter::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/external_pref_loader.cc b/chrome/browser/extensions/external_pref_loader.cc index 814386ce..3304559 100644 --- a/chrome/browser/extensions/external_pref_loader.cc +++ b/chrome/browser/extensions/external_pref_loader.cc
@@ -37,7 +37,7 @@ namespace { -base::FilePath::CharType kExternalExtensionJson[] = +constexpr base::FilePath::CharType kExternalExtensionJson[] = FILE_PATH_LITERAL("external_extensions.json"); std::set<base::FilePath> GetPrefsCandidateFilesFromFolder(
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc index 21cbe22..72e3b0a 100644 --- a/chrome/browser/extensions/tab_helper.cc +++ b/chrome/browser/extensions/tab_helper.cc
@@ -299,27 +299,6 @@ }); content::BrowserContext* context = web_contents()->GetBrowserContext(); - ExtensionRegistry* registry = ExtensionRegistry::Get(context); - const ExtensionSet& enabled_extensions = registry->enabled_extensions(); - - if (util::IsNewBookmarkAppsEnabled()) { - Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); - if (browser && browser->is_app()) { - const Extension* extension = registry->GetExtensionById( - web_app::GetExtensionIdFromApplicationName(browser->app_name()), - ExtensionRegistry::EVERYTHING); - if (extension && AppLaunchInfo::GetFullLaunchURL(extension).is_valid()) - SetExtensionApp(extension); - } else { - UpdateExtensionAppIcon( - enabled_extensions.GetExtensionOrAppByURL( - navigation_handle->GetURL())); - } - } else { - UpdateExtensionAppIcon( - enabled_extensions.GetExtensionOrAppByURL(navigation_handle->GetURL())); - } - if (!navigation_handle->IsSameDocument()) ExtensionActionAPI::Get(context)->ClearAllValuesForTab(web_contents()); }
diff --git a/chrome/browser/feature_engagement/bookmark/bookmark_tracker_unittest.cc b/chrome/browser/feature_engagement/bookmark/bookmark_tracker_unittest.cc index 6be37f6..7f6b727 100644 --- a/chrome/browser/feature_engagement/bookmark/bookmark_tracker_unittest.cc +++ b/chrome/browser/feature_engagement/bookmark/bookmark_tracker_unittest.cc
@@ -149,7 +149,7 @@ "name:bookmark_clicked;comparator:any;window:3650;storage:3650"; bookmark_params["session_rate"] = "<=3"; bookmark_params["availability"] = "any"; - bookmark_params["x_date_released_in_seconds"] = base::DoubleToString( + bookmark_params["x_date_released_in_seconds"] = base::Int64ToString( first_run::GetFirstRunSentinelCreationTime().ToDoubleT()); SetFeatureParams(kIPHBookmarkFeature, bookmark_params);
diff --git a/chrome/browser/feature_engagement/feature_tracker.h b/chrome/browser/feature_engagement/feature_tracker.h index 7cbddc7c..236688c 100644 --- a/chrome/browser/feature_engagement/feature_tracker.h +++ b/chrome/browser/feature_engagement/feature_tracker.h
@@ -57,7 +57,7 @@ // Returns if a user is new, whether or not the promo should be displayed. bool ShouldShowPromo(); - void UseDefaultForChromeVariationConfirgurationReleaseTimeForTesting() { + void UseDefaultForChromeVariationConfigurationReleaseTimeForTesting() { use_default_for_chrome_variation_configuration_release_time_for_testing_ = true; }
diff --git a/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_browsertest.cc b/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_browsertest.cc index d5d6511..907df6c 100644 --- a/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_browsertest.cc +++ b/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_browsertest.cc
@@ -87,7 +87,7 @@ incognito_window_tracker->OnSessionTimeMet(); incognito_window_tracker - ->UseDefaultForChromeVariationConfirgurationReleaseTimeForTesting(); + ->UseDefaultForChromeVariationConfigurationReleaseTimeForTesting(); // Set up feature engagement ShouldTriggerHelpUI mock. EXPECT_CALL(*feature_engagement_tracker_,
diff --git a/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_unittest.cc b/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_unittest.cc index 42e1041..5f6e18fd 100644 --- a/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_unittest.cc +++ b/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_unittest.cc
@@ -152,9 +152,8 @@ "name:incognito_window_clicked;comparator:any;window:3650;storage:3650"; incognito_window_params["session_rate"] = "<=3"; incognito_window_params["availability"] = "any"; - incognito_window_params["x_date_released_in_seconds"] = - base::DoubleToString( - first_run::GetFirstRunSentinelCreationTime().ToDoubleT()); + incognito_window_params["x_date_released_in_seconds"] = base::Int64ToString( + first_run::GetFirstRunSentinelCreationTime().ToDoubleT()); SetFeatureParams(kIPHIncognitoWindowFeature, incognito_window_params); // Start the DesktopSessionDurationTracker to track active session time.
diff --git a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc index 2acd2c3..d2f6b88 100644 --- a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc +++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc
@@ -93,7 +93,7 @@ NewTabTrackerFactory::GetInstance()->GetForProfile(browser()->profile()); new_tab_tracker->OnSessionTimeMet(); new_tab_tracker - ->UseDefaultForChromeVariationConfirgurationReleaseTimeForTesting(); + ->UseDefaultForChromeVariationConfigurationReleaseTimeForTesting(); // Navigate in the omnibox. EXPECT_CALL(*feature_engagement_tracker_,
diff --git a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc index 150aa362..7babfd5 100644 --- a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc +++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc
@@ -159,7 +159,7 @@ "name:new_tab_clicked;comparator:any;window:3650;storage:3650"; new_tab_params["session_rate"] = "<=3"; new_tab_params["availability"] = "any"; - new_tab_params["x_date_released_in_seconds"] = base::DoubleToString( + new_tab_params["x_date_released_in_seconds"] = base::Int64ToString( first_run::GetFirstRunSentinelCreationTime().ToDoubleT()); SetFeatureParams(kIPHNewTabFeature, new_tab_params);
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc index 56d0798..62c0d96 100644 --- a/chrome/browser/first_run/first_run.cc +++ b/chrome/browser/first_run/first_run.cc
@@ -423,6 +423,19 @@ } } +// Reads the creation time of the first run sentinel file. If the first run +// sentinel file does not exist, it will return base::Time(). +base::Time ReadFirstRunSentinelCreationTime() { + base::Time first_run_sentinel_creation_time = base::Time(); + base::FilePath first_run_sentinel; + if (first_run::internal::GetFirstRunSentinelFilePath(&first_run_sentinel)) { + base::File::Info info; + if (base::GetFileInfo(first_run_sentinel, &info)) + first_run_sentinel_creation_time = info.creation_time; + } + return first_run_sentinel_creation_time; +} + } // namespace namespace first_run { @@ -555,17 +568,15 @@ void CreateSentinelIfNeeded() { if (IsChromeFirstRun()) internal::CreateSentinel(); + + // Causes the first run sentinel creation time to be read and cached, while + // I/O is still allowed. + ignore_result(GetFirstRunSentinelCreationTime()); } base::Time GetFirstRunSentinelCreationTime() { - base::FilePath first_run_sentinel; - base::Time first_run_sentinel_creation_time = base::Time(); - if (first_run::internal::GetFirstRunSentinelFilePath(&first_run_sentinel)) { - base::File::Info info; - if (base::GetFileInfo(first_run_sentinel, &info)) - first_run_sentinel_creation_time = info.creation_time; - } - return first_run_sentinel_creation_time; + static const base::Time cached_time = ReadFirstRunSentinelCreationTime(); + return cached_time; } bool SetShowFirstRunBubblePref(FirstRunBubbleOptions show_bubble_option) {
diff --git a/chrome/browser/first_run/first_run.h b/chrome/browser/first_run/first_run.h index 5cca60f..6e903ec 100644 --- a/chrome/browser/first_run/first_run.h +++ b/chrome/browser/first_run/first_run.h
@@ -115,8 +115,8 @@ // (http://crbug.com/264694). void CreateSentinelIfNeeded(); -// Returns the creation time of the first run sentinel file. If the first run -// sentinel file does not exist, it will return base::Time(). +// Returns the first run sentinel creation time. This only requires I/O +// permission on the sequence it is first called on. base::Time GetFirstRunSentinelCreationTime(); // Sets the kShowFirstRunBubbleOption local state pref so that the browser
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index bbe3e91..b579eb5 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -343,8 +343,17 @@ "shown instead of image placeholders when Lo-Fi is on. Data Saver and " "Lo-Fi must be enabled for lite pages to be shown."; -const char kDataReductionProxyServerAlternative[] = - "Use alternative server configuration"; +const char kDataReductionProxyServerAlternative1[] = "Use alt. server config 1"; +const char kDataReductionProxyServerAlternative2[] = "Use alt. server config 2"; +const char kDataReductionProxyServerAlternative3[] = "Use alt. server config 3"; +const char kDataReductionProxyServerAlternative4[] = "Use alt. server config 4"; +const char kDataReductionProxyServerAlternative5[] = "Use alt. server config 5"; +const char kDataReductionProxyServerAlternative6[] = "Use alt. server config 6"; +const char kDataReductionProxyServerAlternative7[] = "Use alt. server config 7"; +const char kDataReductionProxyServerAlternative8[] = "Use alt. server config 8"; +const char kDataReductionProxyServerAlternative9[] = "Use alt. server config 9"; +const char kDataReductionProxyServerAlternative10[] = + "Use alt. server config 10"; const char kEnableDataReductionProxyServerExperimentName[] = "Use an alternative Data Saver back end configuration."; const char kEnableDataReductionProxyServerExperimentDescription[] = @@ -1029,8 +1038,7 @@ const char kParallelDownloadingName[] = "Parallel downloading"; const char kParallelDownloadingDescription[] = - "Enable parallel downloading to" - "accelerate download speed."; + "Enable parallel downloading to accelerate download speed."; const char kPassiveEventListenerDefaultName[] = "Passive Event Listener Override";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 078876b..8e04d72 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -231,7 +231,16 @@ extern const char kEnableDataReductionProxyLitePageName[]; extern const char kEnableDataReductionProxyLitePageDescription[]; -extern const char kDataReductionProxyServerAlternative[]; +extern const char kDataReductionProxyServerAlternative1[]; +extern const char kDataReductionProxyServerAlternative2[]; +extern const char kDataReductionProxyServerAlternative3[]; +extern const char kDataReductionProxyServerAlternative4[]; +extern const char kDataReductionProxyServerAlternative5[]; +extern const char kDataReductionProxyServerAlternative6[]; +extern const char kDataReductionProxyServerAlternative7[]; +extern const char kDataReductionProxyServerAlternative8[]; +extern const char kDataReductionProxyServerAlternative9[]; +extern const char kDataReductionProxyServerAlternative10[]; extern const char kEnableDataReductionProxyServerExperimentName[]; extern const char kEnableDataReductionProxyServerExperimentDescription[];
diff --git a/chrome/browser/generic_sensor/sensor_permission_context.cc b/chrome/browser/generic_sensor/sensor_permission_context.cc index 5fc323ce..4e219e7 100644 --- a/chrome/browser/generic_sensor/sensor_permission_context.cc +++ b/chrome/browser/generic_sensor/sensor_permission_context.cc
@@ -20,15 +20,24 @@ content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, const GURL& embedding_origin) const { - if (requesting_origin != embedding_origin) - return CONTENT_SETTING_BLOCK; + // TODO(juncai): We may need to add cross-origin iframes check here when we + // can grant permission for certain sensor types. Currently this function + // doesn't have any information of which sensor type requests permission. + // The Generic Sensor API is not allowed in cross-origin iframes and + // this is enforced by the renderer. + // https://crbug.com/787019 + // This is to allow DeviceMotion and DeviceOrientation Event to be + // able to access sensors (which are provided by generic sensor) in + // cross-origin iframes. The Generic Sensor API is not allowed in + // cross-origin iframes and this is enforced by the renderer. return CONTENT_SETTING_ALLOW; } bool SensorPermissionContext::IsRestrictedToSecureOrigins() const { // This is to allow non-secure origins that use DeviceMotion and // DeviceOrientation Event to be able to access sensors that are provided - // by generic_sensor. + // by generic_sensor. The Generic Sensor API is not allowed in non-secure + // origins and this is enforced by the renderer. return false; }
diff --git a/chrome/browser/importer/firefox_profile_lock.cc b/chrome/browser/importer/firefox_profile_lock.cc index a5afafc..d0ca9735 100644 --- a/chrome/browser/importer/firefox_profile_lock.cc +++ b/chrome/browser/importer/firefox_profile_lock.cc
@@ -55,18 +55,18 @@ // static #if defined(OS_MACOSX) -const base::FilePath::CharType* FirefoxProfileLock::kLockFileName = +const base::FilePath::CharType FirefoxProfileLock::kLockFileName[] = FILE_PATH_LITERAL(".parentlock"); -const base::FilePath::CharType* FirefoxProfileLock::kOldLockFileName = +const base::FilePath::CharType FirefoxProfileLock::kOldLockFileName[] = FILE_PATH_LITERAL("parent.lock"); #elif defined(OS_POSIX) // http://www.google.com/codesearch/p?hl=en#e_ObwTAVPyo/profile/dirserviceprovider/src/nsProfileLock.cpp&l=433 -const base::FilePath::CharType* FirefoxProfileLock::kLockFileName = +const base::FilePath::CharType FirefoxProfileLock::kLockFileName[] = FILE_PATH_LITERAL(".parentlock"); -const base::FilePath::CharType* FirefoxProfileLock::kOldLockFileName = +const base::FilePath::CharType FirefoxProfileLock::kOldLockFileName[] = FILE_PATH_LITERAL("lock"); #else -const base::FilePath::CharType* FirefoxProfileLock::kLockFileName = +const base::FilePath::CharType FirefoxProfileLock::kLockFileName[] = FILE_PATH_LITERAL("parent.lock"); #endif
diff --git a/chrome/browser/importer/firefox_profile_lock.h b/chrome/browser/importer/firefox_profile_lock.h index b35d86d..0068200 100644 --- a/chrome/browser/importer/firefox_profile_lock.h +++ b/chrome/browser/importer/firefox_profile_lock.h
@@ -81,8 +81,8 @@ FRIEND_TEST_ALL_PREFIXES(FirefoxProfileLockTest, ProfileLock); FRIEND_TEST_ALL_PREFIXES(FirefoxProfileLockTest, ProfileLockOrphaned); - static const base::FilePath::CharType* kLockFileName; - static const base::FilePath::CharType* kOldLockFileName; + static const base::FilePath::CharType kLockFileName[]; + static const base::FilePath::CharType kOldLockFileName[]; void Init();
diff --git a/chrome/common/switch_utils.cc b/chrome/browser/lifetime/switch_utils.cc similarity index 96% rename from chrome/common/switch_utils.cc rename to chrome/browser/lifetime/switch_utils.cc index 9d850e2d..47f6406 100644 --- a/chrome/common/switch_utils.cc +++ b/chrome/browser/lifetime/switch_utils.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/common/switch_utils.h" +#include "chrome/browser/lifetime/switch_utils.h" #include <stddef.h>
diff --git a/chrome/common/switch_utils.h b/chrome/browser/lifetime/switch_utils.h similarity index 72% rename from chrome/common/switch_utils.h rename to chrome/browser/lifetime/switch_utils.h index 6a06567..646c24b 100644 --- a/chrome/common/switch_utils.h +++ b/chrome/browser/lifetime/switch_utils.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_COMMON_SWITCH_UTILS_H_ -#define CHROME_COMMON_SWITCH_UTILS_H_ +#ifndef CHROME_BROWSER_LIFETIME_SWITCH_UTILS_H_ +#define CHROME_BROWSER_LIFETIME_SWITCH_UTILS_H_ #include "base/command_line.h" @@ -14,4 +14,4 @@ } // namespace switches -#endif // CHROME_COMMON_SWITCH_UTILS_H_ +#endif // CHROME_BROWSER_LIFETIME_SWITCH_UTILS_H_
diff --git a/chrome/common/switch_utils_unittest.cc b/chrome/browser/lifetime/switch_utils_unittest.cc similarity index 98% rename from chrome/common/switch_utils_unittest.cc rename to chrome/browser/lifetime/switch_utils_unittest.cc index 3ce5aa54..fb63af41 100644 --- a/chrome/common/switch_utils_unittest.cc +++ b/chrome/browser/lifetime/switch_utils_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/common/switch_utils.h" +#include "chrome/browser/lifetime/switch_utils.h" #include "base/command_line.h" #include "base/files/file_path.h"
diff --git a/chrome/browser/media/router/issue_manager_unittest.cc b/chrome/browser/media/router/issue_manager_unittest.cc index f886e80b..9f12f49 100644 --- a/chrome/browser/media/router/issue_manager_unittest.cc +++ b/chrome/browser/media/router/issue_manager_unittest.cc
@@ -31,7 +31,7 @@ class IssueManagerTest : public ::testing::Test { protected: IssueManagerTest() - : task_runner_(new base::TestMockTimeTaskRunner()), + : task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>()), runner_handler_(task_runner_) { manager_.set_task_runner_for_test(task_runner_); }
diff --git a/chrome/browser/metrics/chrome_stability_metrics_provider.cc b/chrome/browser/metrics/chrome_stability_metrics_provider.cc index 8ea898e..7b10ba52 100644 --- a/chrome/browser/metrics/chrome_stability_metrics_provider.cc +++ b/chrome/browser/metrics/chrome_stability_metrics_provider.cc
@@ -143,7 +143,9 @@ const breakpad::CrashDumpManager::CrashDumpDetails& details) { // There is a delay for OOM flag to be removed when app goes to background, so // we can't just check for OOM_PROTECTED flag. - if (details.process_type == content::PROCESS_TYPE_RENDERER && + if (details.status == + breakpad::CrashDumpManager::CrashDumpStatus::kValidDump && + details.process_type == content::PROCESS_TYPE_RENDERER && details.termination_status == base::TERMINATION_STATUS_OOM_PROTECTED && (details.app_state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES ||
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc index a1ecdf07..b806d9dd 100644 --- a/chrome/browser/net/chrome_network_delegate.cc +++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -462,21 +462,12 @@ } bool ChromeNetworkDelegate::OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) { // nullptr during tests, or when we're running in the system context. if (!cookie_settings_.get()) return true; - // TODO: Push CanonicalCookie further up the network stack. - net::CookieOptions cookie_options; - cookie_options.set_include_httponly(); - std::unique_ptr<net::CanonicalCookie> canonical_cookie = - net::CanonicalCookie::Create(request.url(), cookie_line, - base::Time::Now(), cookie_options); - if (!canonical_cookie) - return false; - bool allow = cookie_settings_->IsCookieAccessAllowed( request.url(), request.site_for_cookies()); @@ -486,8 +477,7 @@ BrowserThread::UI, FROM_HERE, base::BindOnce(&TabSpecificContentSettings::CookieChanged, info->GetWebContentsGetterForRequest(), request.url(), - request.site_for_cookies(), *canonical_cookie, *options, - !allow)); + request.site_for_cookies(), cookie, *options, !allow)); } return allow;
diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h index 446c7df2..ae49e8a 100644 --- a/chrome/browser/net/chrome_network_delegate.h +++ b/chrome/browser/net/chrome_network_delegate.h
@@ -185,7 +185,7 @@ bool OnCanGetCookies(const net::URLRequest& request, const net::CookieList& cookie_list) override; bool OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) override; bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& original_path,
diff --git a/chrome/browser/notifications/message_center_display_service.cc b/chrome/browser/notifications/message_center_display_service.cc index a3325700..d94ff20 100644 --- a/chrome/browser/notifications/message_center_display_service.cc +++ b/chrome/browser/notifications/message_center_display_service.cc
@@ -32,7 +32,9 @@ NotificationCommon::Type notification_type) : profile_(profile), notification_(notification), - notification_type_(notification_type) {} + notification_type_(notification_type) { + DCHECK_NE(notification_type, NotificationCommon::TRANSIENT); + } void Close(bool by_user) override { NotificationDisplayServiceFactory::GetForProfile(profile_) @@ -80,10 +82,6 @@ NotificationCommon::Type notification_type, const message_center::Notification& notification, std::unique_ptr<NotificationCommon::Metadata> metadata) { - // TODO(miguelg): MCDS should stop relying on the |notification|'s delegate - // for Close/Click operations once the Notification object becomes a mojom - // type. - // This can be called when the browser is shutting down and the // NotificationUiManager has already destructed. NotificationUIManager* ui_manager = @@ -95,7 +93,8 @@ if (handler) handler->OnShow(profile_, notification.id()); - if (notification.delegate()) { + if (notification.delegate() || + notification_type == NotificationCommon::TRANSIENT) { ui_manager->Add(notification, profile_); return; }
diff --git a/chrome/browser/notifications/native_notification_display_service.cc b/chrome/browser/notifications/native_notification_display_service.cc index 5aac1564..185ff5c 100644 --- a/chrome/browser/notifications/native_notification_display_service.cc +++ b/chrome/browser/notifications/native_notification_display_service.cc
@@ -81,7 +81,8 @@ profile_->IsOffTheRecord(), notification, std::move(metadata)); NotificationHandler* handler = GetNotificationHandler(notification_type); - handler->OnShow(profile_, notification.id()); + if (handler) + handler->OnShow(profile_, notification.id()); } else if (message_center_display_service_) { message_center_display_service_->Display(notification_type, notification, std::move(metadata));
diff --git a/chrome/browser/notifications/notification_channels_provider_android.cc b/chrome/browser/notifications/notification_channels_provider_android.cc index 2435da2..337b7a6b 100644 --- a/chrome/browser/notifications/notification_channels_provider_android.cc +++ b/chrome/browser/notifications/notification_channels_provider_android.cc
@@ -388,8 +388,6 @@ } else { auto old_channel_status = bridge_->GetChannelStatus(channel_entry->second.id); - // TODO(awdf): Maybe remove this DCHECK - channel status could change any - // time so this may be vulnerable to a race condition. DCHECK_EQ(old_channel_status, new_channel_status); } }
diff --git a/chrome/browser/notifications/notification_template_builder.cc b/chrome/browser/notifications/notification_template_builder.cc index 3486cc6c..2222e8a4 100644 --- a/chrome/browser/notifications/notification_template_builder.cc +++ b/chrome/browser/notifications/notification_template_builder.cc
@@ -44,10 +44,12 @@ const char kInputElement[] = "input"; const char kInputId[] = "id"; const char kInputType[] = "type"; +const char kStatus[] = "status"; const char kNotificationSettings[] = "notificationSettings"; const char kPlaceholderContent[] = "placeHolderContent"; const char kPlacement[] = "placement"; const char kPlacementAppLogoOverride[] = "appLogoOverride"; +const char kProgress[] = "progress"; const char kReminder[] = "reminder"; const char kScenario[] = "scenario"; const char kSilent[] = "silent"; @@ -59,6 +61,7 @@ const char kToastElementLaunchAttribute[] = "launch"; const char kTrue[] = "true"; const char kUserResponse[] = "userResponse"; +const char kValue[] = "value"; const char kVisualElement[] = "visual"; // Name of the template used for default Chrome notifications. @@ -99,6 +102,9 @@ if (!notification.image().IsEmpty()) builder->WriteLargeImageElement(notification); + if (notification.type() == message_center::NOTIFICATION_TYPE_PROGRESS) + builder->WriteProgressElement(notification); + builder->EndBindingElement(); builder->EndVisualElement(); @@ -230,6 +236,19 @@ } } +void NotificationTemplateBuilder::WriteProgressElement( + const message_center::Notification& notification) { + // Two other attributes are supported by Microsoft: + // title: A string shown on the left side of the toast, just above the bar. + // valueStringOverride: A string that replaces the percentage on the right. + xml_writer_->StartElement(kProgress); + // Status is mandatory, without it the progress bar is not shown. + xml_writer_->AddAttribute(kStatus, std::string()); + xml_writer_->AddAttribute( + kValue, base::StringPrintf("%3.2f", 1.0 * notification.progress() / 100)); + xml_writer_->EndElement(); +} + void NotificationTemplateBuilder::AddActions( const message_center::Notification& notification) { const std::vector<message_center::ButtonInfo>& buttons =
diff --git a/chrome/browser/notifications/notification_template_builder.h b/chrome/browser/notifications/notification_template_builder.h index ff9ab8a..c2050afd 100644 --- a/chrome/browser/notifications/notification_template_builder.h +++ b/chrome/browser/notifications/notification_template_builder.h
@@ -91,6 +91,9 @@ const std::string& placement, const std::string& hint_crop); + // Adds a progress bar to the notification XML. + void WriteProgressElement(const message_center::Notification& notification); + // Writes the <actions> element. void StartActionsElement(); void EndActionsElement();
diff --git a/chrome/browser/notifications/notification_template_builder_unittest.cc b/chrome/browser/notifications/notification_template_builder_unittest.cc index 237fd507..17c83ada 100644 --- a/chrome/browser/notifications/notification_template_builder_unittest.cc +++ b/chrome/browser/notifications/notification_template_builder_unittest.cc
@@ -395,3 +395,29 @@ ASSERT_NO_FATAL_FAILURE(VerifyXml(*notification, kExpectedXml)); } + +TEST_F(NotificationTemplateBuilderTest, ProgressBar) { + std::unique_ptr<message_center::Notification> notification = + InitializeBasicNotification(); + + notification->set_type(message_center::NOTIFICATION_TYPE_PROGRESS); + notification->set_progress(30); + + const wchar_t kExpectedXml[] = + LR"(<toast launch="notification_id" displayTimestamp="1998-09-04T01:02:03Z"> + <visual> + <binding template="ToastGeneric"> + <text>My Title</text> + <text>My Message</text> + <text placement="attribution">example.com</text> + <progress status="" value="0.30"/> + </binding> + </visual> + <actions> + <action content="settings" placement="contextMenu" activationType="foreground" arguments="notificationSettings"/> + </actions> +</toast> +)"; + + ASSERT_NO_FATAL_FAILURE(VerifyXml(*notification, kExpectedXml)); +}
diff --git a/chrome/browser/permissions/permission_manager.cc b/chrome/browser/permissions/permission_manager.cc index f609fed..4ac3f55 100644 --- a/chrome/browser/permissions/permission_manager.cc +++ b/chrome/browser/permissions/permission_manager.cc
@@ -210,20 +210,20 @@ // be run when a permission prompt has been ignored, but it's important that we // know when a prompt is ignored to clean up |pending_requests_| correctly. // If the callback is destroyed without being run, the destructor here will -// cancel the request to clean up. +// cancel the request to clean up. |permission_manager| must outlive this +// object. class PermissionManager::PermissionResponseCallback { public: - PermissionResponseCallback( - const base::WeakPtr<PermissionManager>& permission_manager, - int request_id, - int permission_id) + PermissionResponseCallback(PermissionManager* permission_manager, + int request_id, + int permission_id) : permission_manager_(permission_manager), request_id_(request_id), permission_id_(permission_id), request_answered_(false) {} ~PermissionResponseCallback() { - if (!request_answered_ && permission_manager_.get() && + if (!request_answered_ && permission_manager_->pending_requests_.Lookup(request_id_)) { permission_manager_->pending_requests_.Remove(request_id_); } @@ -231,17 +231,14 @@ void OnPermissionsRequestResponseStatus(ContentSetting content_setting) { request_answered_ = true; - if (permission_manager_.get()) { - permission_manager_->OnPermissionsRequestResponseStatus( - request_id_, permission_id_, content_setting); - } + permission_manager_->OnPermissionsRequestResponseStatus( + request_id_, permission_id_, content_setting); } private: - base::WeakPtr<PermissionManager> permission_manager_; + PermissionManager* permission_manager_; int request_id_; int permission_id_; - bool request_answered_; DISALLOW_COPY_AND_ASSIGN(PermissionResponseCallback); @@ -260,9 +257,7 @@ return PermissionManagerFactory::GetForProfile(profile); } -PermissionManager::PermissionManager(Profile* profile) - : profile_(profile), - weak_ptr_factory_(this) { +PermissionManager::PermissionManager(Profile* profile) : profile_(profile) { permission_contexts_[CONTENT_SETTINGS_TYPE_MIDI_SYSEX] = base::MakeUnique<MidiSysexPermissionContext>(profile); permission_contexts_[CONTENT_SETTINGS_TYPE_MIDI] = @@ -371,8 +366,8 @@ PermissionContextBase* context = GetPermissionContext(permission); DCHECK(context); - auto callback = base::MakeUnique<PermissionResponseCallback>( - weak_ptr_factory_.GetWeakPtr(), request_id, i); + auto callback = + base::MakeUnique<PermissionResponseCallback>(this, request_id, i); context->RequestPermission( web_contents, request, canonical_requesting_origin, user_gesture, base::Bind(
diff --git a/chrome/browser/permissions/permission_manager.h b/chrome/browser/permissions/permission_manager.h index f747a35..ec5c9a0 100644 --- a/chrome/browser/permissions/permission_manager.h +++ b/chrome/browser/permissions/permission_manager.h
@@ -10,7 +10,6 @@ #include "base/callback_forward.h" #include "base/containers/id_map.h" #include "base/macros.h" -#include "base/memory/weak_ptr.h" #include "chrome/browser/permissions/permission_util.h" #include "components/content_settings/core/browser/content_settings_observer.h" #include "components/content_settings/core/common/content_settings.h" @@ -160,8 +159,6 @@ ContentSettingsTypeHash> permission_contexts_; - base::WeakPtrFactory<PermissionManager> weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(PermissionManager); };
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index b56b96c..ab4a819 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -313,7 +313,7 @@ prefs::kCloudPrintSubmitEnabled, base::Value::Type::BOOLEAN }, { key::kTranslateEnabled, - prefs::kEnableTranslate, + prefs::kOfferTranslateEnabled, base::Value::Type::BOOLEAN }, { key::kAllowOutdatedPlugins, prefs::kPluginsAllowOutdated,
diff --git a/chrome/browser/policy/policy_path_parser_linux.cc b/chrome/browser/policy/policy_path_parser_linux.cc index a36417d..669a85b 100644 --- a/chrome/browser/policy/policy_path_parser_linux.cc +++ b/chrome/browser/policy/policy_path_parser_linux.cc
@@ -15,8 +15,8 @@ namespace path_parser { -const char* kMachineNamePolicyVarName = "${machine_name}"; -const char* kUserNamePolicyVarName = "${user_name}"; +const char kMachineNamePolicyVarName[] = "${machine_name}"; +const char kUserNamePolicyVarName[] = "${user_name}"; // Replaces all variable occurrences in the policy string with the respective // system settings values.
diff --git a/chrome/browser/policy/policy_path_parser_mac.mm b/chrome/browser/policy/policy_path_parser_mac.mm index 53826fa8..92e32e4 100644 --- a/chrome/browser/policy/policy_path_parser_mac.mm +++ b/chrome/browser/policy/policy_path_parser_mac.mm
@@ -23,10 +23,10 @@ namespace path_parser { -const char* kUserNamePolicyVarName = "${user_name}"; -const char* kMachineNamePolicyVarName = "${machine_name}"; -const char* kMacUsersDirectory = "${users}"; -const char* kMacDocumentsFolderVarName = "${documents}"; +const char kUserNamePolicyVarName[] = "${user_name}"; +const char kMachineNamePolicyVarName[] = "${machine_name}"; +const char kMacUsersDirectory[] = "${users}"; +const char kMacDocumentsFolderVarName[] = "${documents}"; struct MacFolderNamesToSPDMaping { const char* name;
diff --git a/chrome/browser/printing/cloud_print/privet_notifications.cc b/chrome/browser/printing/cloud_print/privet_notifications.cc index d3ebe2b..1b7a0b7 100644 --- a/chrome/browser/printing/cloud_print/privet_notifications.cc +++ b/chrome/browser/printing/cloud_print/privet_notifications.cc
@@ -13,12 +13,11 @@ #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "base/single_thread_task_runner.h" -#include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/local_discovery/service_discovery_shared_client.h" -#include "chrome/browser/notifications/notification_common.h" -#include "chrome/browser/notifications/notification_display_service.h" +#include "chrome/browser/notifications/notification_ui_manager.h" #include "chrome/browser/printing/cloud_print/privet_device_lister_impl.h" #include "chrome/browser/printing/cloud_print/privet_http_asynchronous_factory.h" #include "chrome/browser/profiles/profile.h" @@ -242,27 +241,6 @@ bool added) { DCHECK_GT(devices_active, 0); - NotificationDisplayService::GetForProfile( - Profile::FromBrowserContext(profile_)) - ->GetDisplayed(base::Bind(&PrivetNotificationService::AddNotification, - AsWeakPtr(), devices_active, added)); -} - -void PrivetNotificationService::AddNotification( - int devices_active, - bool device_added, - std::unique_ptr<std::set<std::string>> displayed_notifications, - bool supports_synchronization) { - // If the UI is already open or a device was removed, we'll update the - // existing notification but not add a new one. - const bool notification_exists = - base::ContainsKey(*displayed_notifications, kPrivetNotificationID); - const bool add_new_notification = - device_added && - !local_discovery::LocalDiscoveryUIHandler::GetHasVisible(); - if (!notification_exists && !add_new_notification) - return; - message_center::RichNotificationData rich_notification_data; rich_notification_data.buttons.push_back( message_center::ButtonInfo(l10n_util::GetStringUTF16( @@ -289,19 +267,21 @@ kPrivetNotificationID), rich_notification_data, CreateNotificationDelegate(profile)); - if (add_new_notification) + auto* notification_ui_manager = g_browser_process->notification_ui_manager(); + bool updated = notification_ui_manager->Update(notification, profile); + if (!updated && added && + !local_discovery::LocalDiscoveryUIHandler::GetHasVisible()) { ReportPrivetUmaEvent(PRIVET_NOTIFICATION_SHOWN); - - NotificationDisplayService::GetForProfile( - Profile::FromBrowserContext(profile_)) - ->Display(NotificationCommon::TRANSIENT, notification); + notification_ui_manager->Add(notification, profile); + } } void PrivetNotificationService::PrivetRemoveNotification() { ReportPrivetUmaEvent(PRIVET_NOTIFICATION_CANCELED); - NotificationDisplayService::GetForProfile( - Profile::FromBrowserContext(profile_)) - ->Close(NotificationCommon::TRANSIENT, kPrivetNotificationID); + Profile* profile_object = Profile::FromBrowserContext(profile_); + g_browser_process->notification_ui_manager()->CancelById( + kPrivetNotificationID, + NotificationUIManager::GetProfileID(profile_object)); } void PrivetNotificationService::Start() { @@ -407,8 +387,8 @@ } void PrivetNotificationDelegate::CloseNotification() { - NotificationDisplayService::GetForProfile(profile_)->Close( - NotificationCommon::TRANSIENT, kPrivetNotificationID); + g_browser_process->notification_ui_manager()->CancelById( + kPrivetNotificationID, NotificationUIManager::GetProfileID(profile_)); } } // namespace cloud_print
diff --git a/chrome/browser/printing/cloud_print/privet_notifications.h b/chrome/browser/printing/cloud_print/privet_notifications.h index c322f0ee..9fb698b 100644 --- a/chrome/browser/printing/cloud_print/privet_notifications.h +++ b/chrome/browser/printing/cloud_print/privet_notifications.h
@@ -121,12 +121,6 @@ void OnNotificationsEnabledChanged(); void StartLister(); - void AddNotification( - int devices_active, - bool device_added, - std::unique_ptr<std::set<std::string>> displayed_notifications, - bool supports_synchronization); - // Virtual for testing. The returned delegate is refcounted. virtual PrivetNotificationDelegate* CreateNotificationDelegate( Profile* profile);
diff --git a/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc b/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc index dad0f0a..666056e 100644 --- a/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc +++ b/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc
@@ -290,8 +290,6 @@ TEST_F(PrivetNotificationsNotificationTest, AddToCloudPrint) { TestPrivetNotificationService service(profile()); service.PrivetNotify(1 /* devices_active */, true /* added */); - // The notification is added asynchronously. - base::RunLoop().RunUntilIdle(); ASSERT_EQ(1U, ui_manager()->GetNotificationCount()); const auto& notification = ui_manager()->GetNotificationAt(0); @@ -306,8 +304,6 @@ TEST_F(PrivetNotificationsNotificationTest, DontShowAgain) { TestPrivetNotificationService service(profile()); service.PrivetNotify(1 /* devices_active */, true /* added */); - // The notification is added asynchronously. - base::RunLoop().RunUntilIdle(); ASSERT_EQ(1U, ui_manager()->GetNotificationCount()); const auto& notification = ui_manager()->GetNotificationAt(0);
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc index 4a4ccd2..e2e5b01 100644 --- a/chrome/browser/printing/print_view_manager_base.cc +++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -80,9 +80,7 @@ printing_rfh_(nullptr), printing_succeeded_(false), inside_inner_message_loop_(false), -#if !defined(OS_MACOSX) expecting_first_page_(true), -#endif queue_(g_browser_process->print_job_manager()->queue()), weak_ptr_factory_(this) { DCHECK(queue_.get()); @@ -161,12 +159,8 @@ return; } -#if defined(OS_MACOSX) - const bool metafile_must_be_valid = true; -#else const bool metafile_must_be_valid = expecting_first_page_; expecting_first_page_ = false; -#endif // Only used when |metafile_must_be_valid| is true. std::unique_ptr<base::SharedMemory> shared_buf; @@ -488,9 +482,7 @@ // DO NOT wait for the job to finish. ReleasePrintJob(); } -#if !defined(OS_MACOSX) expecting_first_page_ = true; -#endif } void PrintViewManagerBase::TerminatePrintJob(bool cancel) {
diff --git a/chrome/browser/printing/print_view_manager_base.h b/chrome/browser/printing/print_view_manager_base.h index e9706e3..3860074 100644 --- a/chrome/browser/printing/print_view_manager_base.h +++ b/chrome/browser/printing/print_view_manager_base.h
@@ -170,10 +170,8 @@ // print settings are being loaded. bool inside_inner_message_loop_; -#if !defined(OS_MACOSX) // Set to true when OnDidPrintPage() should be expecting the first page. bool expecting_first_page_; -#endif // Whether printing is enabled. BooleanPrefMember printing_enabled_;
diff --git a/chrome/browser/profiling_host/BUILD.gn b/chrome/browser/profiling_host/BUILD.gn index 2061c10..9d7dbf3 100644 --- a/chrome/browser/profiling_host/BUILD.gn +++ b/chrome/browser/profiling_host/BUILD.gn
@@ -8,6 +8,8 @@ sources = [ "memlog_browsertest.cc", + "profiling_test_driver.cc", + "profiling_test_driver.h", ] defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] @@ -21,7 +23,46 @@ ] } } else { + import("//build/config/android/rules.gni") + # In-process browser tests aren't supported on Android. group("profiling_browsertests") { } + + generate_jni("jni_headers") { + sources = [ + "../../android/javatests/src/org/chromium/chrome/browser/profiling_host/TestAndroidShim.java", + ] + jni_package = "chrome_profiling_host" + } + + # This library must be included by the apk_under_test in order for the JNI + # shim to function correctly. + android_library("profiling_host_java_test_support") { + testonly = true + java_files = [ "../../android/javatests/src/org/chromium/chrome/browser/profiling_host/TestAndroidShim.java" ] + deps = [ + "//base:base_java", + ] + } + + # This library must be included by the instrumentation_test. It must not be + # included by the apk_under_test, since in debug builds, java classes that + # appear in the apk_under_test are stripped from the instrumentation_test. + # This library contains dependencies that must not be stripped from the + # instrumentation_test. + android_library("profiling_host_javatests") { + testonly = true + java_files = [ "../../android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java" ] + deps = [ + ":profiling_host_java_test_support", + "//base:base_java", + "//base:base_java_test_support", + "//chrome/android:chrome_java", + "//chrome/test/android:chrome_java_test_support", + "//third_party/android_support_test_runner:rules_java", + "//third_party/android_support_test_runner:runner_java", + "//third_party/junit", + ] + } }
diff --git a/chrome/browser/profiling_host/memlog_browsertest.cc b/chrome/browser/profiling_host/memlog_browsertest.cc index 9abf95a8..3fd6138 100644 --- a/chrome/browser/profiling_host/memlog_browsertest.cc +++ b/chrome/browser/profiling_host/memlog_browsertest.cc
@@ -3,17 +3,13 @@ // found in the LICENSE file. #include "base/allocator/features.h" -#include "base/allocator/partition_allocator/partition_alloc.h" #include "base/json/json_reader.h" -#include "base/memory/ref_counted_memory.h" -#include "base/run_loop.h" -#include "base/task_scheduler/post_task.h" #include "base/threading/thread_restrictions.h" #include "base/trace_event/trace_buffer.h" -#include "base/trace_event/trace_config_memory_test_util.h" #include "base/trace_event/trace_log.h" #include "build/build_config.h" #include "chrome/browser/profiling_host/profiling_process_host.h" +#include "chrome/browser/profiling_host/profiling_test_driver.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" @@ -21,7 +17,6 @@ #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" -#include "content/public/browser/tracing_controller.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -408,60 +403,15 @@ // Ensure invocations via TracingController can generate a valid JSON file with // expected data. IN_PROC_BROWSER_TEST_P(MemlogBrowserTest, TracingControllerEndToEnd) { - if (!GetParam()) { - // Test that nothing has been started if the flag is not passed. Then early - // exit. - ASSERT_FALSE(profiling::ProfilingProcessHost::has_started()); - return; - } else { - ASSERT_TRUE(profiling::ProfilingProcessHost::has_started()); - } + profiling::ProfilingTestDriver driver; + profiling::ProfilingTestDriver::Options options; + options.mode = + GetParam() + ? profiling::ProfilingProcessHost::ConvertStringToMode(GetParam()) + : profiling::ProfilingProcessHost::Mode::kNone; + options.profiling_already_started = true; - MakeTestAllocations(); - - base::RunLoop run_loop; - scoped_refptr<base::RefCountedString> result; - - // Once the ProfilingProcessHost has dumped to the trace, stop the trace and - // collate the results into |result|, then quit the nested run loop. - auto finish_sink_callback = base::Bind( - [](scoped_refptr<base::RefCountedString>* result, base::Closure finished, - std::unique_ptr<const base::DictionaryValue> metadata, - base::RefCountedString* in) { - *result = in; - std::move(finished).Run(); - }, - &result, run_loop.QuitClosure()); - scoped_refptr<content::TracingController::TraceDataEndpoint> sink = - content::TracingController::CreateStringEndpoint( - std::move(finish_sink_callback)); - base::OnceClosure stop_tracing_closure = base::BindOnce( - base::IgnoreResult<bool (content::TracingController::*)( // NOLINT - const scoped_refptr<content::TracingController::TraceDataEndpoint>&)>( - &content::TracingController::StopTracing), - base::Unretained(content::TracingController::GetInstance()), sink); - base::OnceClosure stop_tracing_ui_thread_closure = - base::BindOnce(base::IgnoreResult(&base::TaskRunner::PostTask), - base::ThreadTaskRunnerHandle::Get(), FROM_HERE, - std::move(stop_tracing_closure)); - profiling::ProfilingProcessHost::GetInstance() - ->SetDumpProcessForTracingCallback( - std::move(stop_tracing_ui_thread_closure)); - - // Spin a nested RunLoop until the heap dump has been added to the trace. - content::TracingController::GetInstance()->StartTracing( - base::trace_event::TraceConfig( - base::trace_event::TraceConfigMemoryTestUtil:: - GetTraceConfig_PeriodicTriggers(100000, 100000)), - base::Closure()); - run_loop.Run(); - - std::unique_ptr<base::Value> dump_json = - base::JSONReader::Read(result->data()); - ASSERT_TRUE(dump_json); - ValidateBrowserAllocations(dump_json.get()); - ValidateRendererAllocations(dump_json.get()); - // TODO(ajwong): Test GPU dumps http://crbug.com/780955 + EXPECT_TRUE(driver.RunTest(options)); } // TODO(ajwong): Test what happens if profiling process crashes.
diff --git a/chrome/browser/profiling_host/profiling_process_host.cc b/chrome/browser/profiling_host/profiling_process_host.cc index 9f74d08..bfda42d0 100644 --- a/chrome/browser/profiling_host/profiling_process_host.cc +++ b/chrome/browser/profiling_host/profiling_process_host.cc
@@ -371,19 +371,7 @@ kOOPHeapProfilingFeature, kOOPHeapProfilingFeatureMode); } - if (mode == switches::kMemlogModeAll) - return Mode::kAll; - if (mode == switches::kMemlogModeMinimal) - return Mode::kMinimal; - if (mode == switches::kMemlogModeBrowser) - return Mode::kBrowser; - if (mode == switches::kMemlogModeGpu) - return Mode::kGpu; - if (mode == switches::kMemlogModeRendererSampling) - return Mode::kRendererSampling; - - DLOG(ERROR) << "Unsupported value: \"" << mode << "\" passed to --" - << switches::kMemlog; + return ConvertStringToMode(mode); } return Mode::kNone; #else @@ -396,6 +384,24 @@ } // static +ProfilingProcessHost::Mode ProfilingProcessHost::ConvertStringToMode( + const std::string& mode) { + if (mode == switches::kMemlogModeAll) + return Mode::kAll; + if (mode == switches::kMemlogModeMinimal) + return Mode::kMinimal; + if (mode == switches::kMemlogModeBrowser) + return Mode::kBrowser; + if (mode == switches::kMemlogModeGpu) + return Mode::kGpu; + if (mode == switches::kMemlogModeRendererSampling) + return Mode::kRendererSampling; + DLOG(ERROR) << "Unsupported value: \"" << mode << "\" passed to --" + << switches::kMemlog; + return Mode::kNone; +} + +// static ProfilingProcessHost* ProfilingProcessHost::Start( content::ServiceManagerConnection* connection, Mode mode) {
diff --git a/chrome/browser/profiling_host/profiling_process_host.h b/chrome/browser/profiling_host/profiling_process_host.h index 8df0e71b..94cc7a9 100644 --- a/chrome/browser/profiling_host/profiling_process_host.h +++ b/chrome/browser/profiling_host/profiling_process_host.h
@@ -89,6 +89,7 @@ // Returns the mode set on the current process' command line. static Mode GetCurrentMode(); + static Mode ConvertStringToMode(const std::string& input); bool ShouldProfileProcessType(int process_type); // Launches the profiling process and returns a pointer to it. @@ -123,6 +124,7 @@ friend struct base::DefaultSingletonTraits<ProfilingProcessHost>; friend class BackgroundProfilingTriggersTest; friend class MemlogBrowserTest; + friend class ProfilingTestDriver; FRIEND_TEST_ALL_PREFIXES(ProfilingProcessHost, ShouldProfileNewRenderer); ProfilingProcessHost();
diff --git a/chrome/browser/profiling_host/profiling_test_driver.cc b/chrome/browser/profiling_host/profiling_test_driver.cc new file mode 100644 index 0000000..6539461 --- /dev/null +++ b/chrome/browser/profiling_host/profiling_test_driver.cc
@@ -0,0 +1,502 @@ +// 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/profiling_host/profiling_test_driver.h" + +#include <string> + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/json/json_reader.h" +#include "base/process/process_handle.h" +#include "base/run_loop.h" +#include "base/task_scheduler/post_task.h" +#include "base/trace_event/trace_config_memory_test_util.h" +#include "base/values.h" +#include "build/build_config.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/tracing_controller.h" +#include "content/public/common/service_manager_connection.h" + +namespace profiling { + +namespace { + +// Make some specific allocations in Browser to do a deeper test of the +// allocation tracking. +constexpr int kMallocAllocSize = 7907; +constexpr int kMallocAllocCount = 157; + +constexpr int kVariadicAllocCount = 157; + +// Test fixed-size partition alloc. The size must be aligned to system pointer +// size. +constexpr int kPartitionAllocSize = 8 * 23; +constexpr int kPartitionAllocCount = 107; +static const char* kPartitionAllocTypeName = "kPartitionAllocTypeName"; + +// On success, populates |pid|. +int NumProcessesWithName(base::Value* dump_json, std::string name, int* pid) { + int num_processes = 0; + base::Value* events = dump_json->FindKey("traceEvents"); + for (base::Value& event : events->GetList()) { + const base::Value* found_name = + event.FindKeyOfType("name", base::Value::Type::STRING); + if (!found_name) + continue; + if (found_name->GetString() != "process_name") + continue; + const base::Value* found_args = + event.FindKeyOfType("args", base::Value::Type::DICTIONARY); + if (!found_args) + continue; + const base::Value* found_process_name = + found_args->FindKeyOfType("name", base::Value::Type::STRING); + if (!found_process_name) + continue; + if (found_process_name->GetString() != name) + continue; + + if (pid) { + const base::Value* found_pid = + event.FindKeyOfType("pid", base::Value::Type::INTEGER); + if (!found_pid) { + LOG(ERROR) << "Process missing pid."; + return 0; + } + *pid = found_pid->GetInt(); + } + + ++num_processes; + } + return num_processes; +} + +base::Value* FindHeapsV2(base::ProcessId pid, base::Value* dump_json) { + base::Value* events = dump_json->FindKey("traceEvents"); + base::Value* dumps = nullptr; + base::Value* heaps_v2 = nullptr; + for (base::Value& event : events->GetList()) { + const base::Value* found_name = + event.FindKeyOfType("name", base::Value::Type::STRING); + if (!found_name) + continue; + if (found_name->GetString() != "periodic_interval") + continue; + const base::Value* found_pid = + event.FindKeyOfType("pid", base::Value::Type::INTEGER); + if (!found_pid) + continue; + if (static_cast<base::ProcessId>(found_pid->GetInt()) != pid) + continue; + dumps = &event; + heaps_v2 = dumps->FindPath({"args", "dumps", "heaps_v2"}); + if (heaps_v2) + return heaps_v2; + } + return nullptr; +} + +// Verify expectations are present in heap dump. +bool ValidateDump(base::Value* heaps_v2, + int expected_alloc_size, + int expected_alloc_count, + const char* allocator_name, + const char* type_name) { + base::Value* sizes = + heaps_v2->FindPath({"allocators", allocator_name, "sizes"}); + if (!sizes) { + LOG(ERROR) << "Failed to find path: 'allocators." << allocator_name + << ".sizes' in heaps v2"; + return false; + } + + const base::Value::ListStorage& sizes_list = sizes->GetList(); + if (sizes_list.empty()) { + LOG(ERROR) << "'allocators." << allocator_name + << ".sizes' is an empty list"; + return false; + } + + base::Value* counts = + heaps_v2->FindPath({"allocators", allocator_name, "counts"}); + if (!counts) { + LOG(ERROR) << "Failed to find path: 'allocators." << allocator_name + << ".counts' in heaps v2"; + return false; + } + + const base::Value::ListStorage& counts_list = counts->GetList(); + if (sizes_list.size() != counts_list.size()) { + LOG(ERROR) + << "'allocators." << allocator_name + << ".sizes' does not have the same number of elements as *.counts"; + return false; + } + + base::Value* types = + heaps_v2->FindPath({"allocators", allocator_name, "types"}); + if (!types) { + LOG(ERROR) << "Failed to find path: 'allocators." << allocator_name + << ".types' in heaps v2"; + return false; + } + + const base::Value::ListStorage& types_list = types->GetList(); + if (types_list.empty()) { + LOG(ERROR) << "'allocators." << allocator_name + << ".types' is an empty list"; + return false; + } + + if (sizes_list.size() != types_list.size()) { + LOG(ERROR) + << "'allocators." << allocator_name + << ".types' does not have the same number of elements as *.sizes"; + return false; + } + + bool found_browser_alloc = false; + size_t browser_alloc_index = 0; + for (size_t i = 0; i < sizes_list.size(); i++) { + if (counts_list[i].GetInt() == expected_alloc_count && + sizes_list[i].GetInt() != expected_alloc_size) { + LOG(WARNING) << "Allocation candidate (size:" << sizes_list[i].GetInt() + << " count:" << counts_list[i].GetInt() << ")"; + } + if (sizes_list[i].GetInt() == expected_alloc_size && + counts_list[i].GetInt() == expected_alloc_count) { + browser_alloc_index = i; + found_browser_alloc = true; + break; + } + } + + if (!found_browser_alloc) { + LOG(ERROR) << "Failed to find an allocation of the " + "appropriate size. Did the send buffer " + "not flush? (size: " + << expected_alloc_size << " count:" << expected_alloc_count + << ")"; + return false; + } + + // Find the type, if an expectation was passed in. + if (type_name) { + bool found = false; + int type = types_list[browser_alloc_index].GetInt(); + base::Value* strings = heaps_v2->FindPath({"maps", "strings"}); + for (base::Value& dict : strings->GetList()) { + // Each dict has the format {"id":1,"string":"kPartitionAllocTypeName"} + int id = dict.FindKey("id")->GetInt(); + if (id == type) { + found = true; + std::string name = dict.FindKey("string")->GetString(); + if (name != type_name) { + LOG(ERROR) << "actual name: " << name + << " expected name: " << type_name; + return false; + } + break; + } + } + if (!found) { + LOG(ERROR) << "Failed to find type name string: " << type_name; + return false; + } + } + return true; +} + +} // namespace + +ProfilingTestDriver::ProfilingTestDriver() + : wait_for_ui_thread_(base::WaitableEvent::ResetPolicy::AUTOMATIC, + base::WaitableEvent::InitialState::NOT_SIGNALED) { + partition_allocator_.init(); +} +ProfilingTestDriver::~ProfilingTestDriver() {} + +bool ProfilingTestDriver::RunTest(const Options& options) { + options_ = options; + + running_on_ui_thread_ = + content::BrowserThread::CurrentlyOn(content::BrowserThread::UI); + + // The only thing to test for Mode::kNone is that profiling hasn't started. + if (options_.mode == ProfilingProcessHost::Mode::kNone) { + if (ProfilingProcessHost::has_started()) { + LOG(ERROR) << "Profiling should not have started"; + return false; + } + return true; + } + + if (running_on_ui_thread_) { + if (!RunInitializationOnUIThread()) + return false; + CollectResults(true); + } else { + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&ProfilingTestDriver::RunInitializationOnUIThreadAndSignal, + base::Unretained(this))); + wait_for_ui_thread_.Wait(); + if (!initialization_success_) + return false; + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&ProfilingTestDriver::CollectResults, base::Unretained(this), + false)); + wait_for_ui_thread_.Wait(); + } + + std::unique_ptr<base::Value> dump_json = + base::JSONReader::Read(serialized_trace_->data()); + if (!dump_json) { + LOG(ERROR) << "Failed to deserialize trace."; + return false; + } + + if (!ValidateBrowserAllocations(dump_json.get())) { + LOG(ERROR) << "Failed to validate browser allocations"; + return false; + } + + if (!ValidateRendererAllocations(dump_json.get())) { + LOG(ERROR) << "Failed to validate renderer allocations"; + return false; + } + + return true; +} + +void ProfilingTestDriver::RunInitializationOnUIThreadAndSignal() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + initialization_success_ = RunInitializationOnUIThread(); + wait_for_ui_thread_.Signal(); +} + +bool ProfilingTestDriver::RunInitializationOnUIThread() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + + if (options_.mode == ProfilingProcessHost::Mode::kRendererSampling) { + profiling::ProfilingProcessHost::GetInstance() + ->SetRendererSamplingAlwaysProfileForTest(); + } + + LOG(ERROR) << "RunInitializationOnUIThread: " + << base::CommandLine::ForCurrentProcess()->GetCommandLineString(); + if (!CheckOrStartProfiling()) + return false; + + MakeTestAllocations(); + return true; +} + +bool ProfilingTestDriver::CheckOrStartProfiling() { + if (options_.profiling_already_started) { + if (ProfilingProcessHost::has_started()) + return true; + LOG(ERROR) << "Profiling should have been started, but wasn't"; + return false; + } + + content::ServiceManagerConnection* connection = + content::ServiceManagerConnection::GetForProcess(); + if (!connection) { + LOG(ERROR) << "A ServiceManagerConnection was not available for the " + "current process."; + return false; + } + + ProfilingProcessHost::Start(connection, options_.mode); + return true; +} + +void ProfilingTestDriver::MakeTestAllocations() { + leaks_.reserve(2 * kMallocAllocCount + kPartitionAllocSize); + for (int i = 0; i < kMallocAllocCount; ++i) { + leaks_.push_back(new char[kMallocAllocSize]); + } + + for (int i = 0; i < kPartitionAllocCount; ++i) { + leaks_.push_back(static_cast<char*>( + PartitionAllocGeneric(partition_allocator_.root(), kPartitionAllocSize, + kPartitionAllocTypeName))); + } + + for (int i = 0; i < kVariadicAllocCount; ++i) { + leaks_.push_back(new char[i + 8000]); // Variadic allocation. + total_variadic_allocations_ += i + 8000; + } + + // // Navigate around to force allocations in the renderer. + // ASSERT_TRUE(embedded_test_server()->Start()); + // ui_test_utils::NavigateToURL( + // browser(), embedded_test_server()->GetURL("/english_page.html")); + // // Vive la France! + // ui_test_utils::NavigateToURL( + // browser(), embedded_test_server()->GetURL("/french_page.html")); +} + +void ProfilingTestDriver::CollectResults(bool synchronous) { + base::Closure finish_tracing_closure; + std::unique_ptr<base::RunLoop> run_loop; + + if (synchronous) { + run_loop.reset(new base::RunLoop); + finish_tracing_closure = run_loop->QuitClosure(); + } else { + finish_tracing_closure = base::Bind(&base::WaitableEvent::Signal, + base::Unretained(&wait_for_ui_thread_)); + } + + // Once the ProfilingProcessHost has dumped to the trace, stop the trace and + // collate the results into |result|, then quit the nested run loop. + auto finish_sink_callback = base::Bind( + [](scoped_refptr<base::RefCountedString>* result, base::Closure finished, + std::unique_ptr<const base::DictionaryValue> metadata, + base::RefCountedString* in) { + *result = in; + std::move(finished).Run(); + }, + &serialized_trace_, std::move(finish_tracing_closure)); + + scoped_refptr<content::TracingController::TraceDataEndpoint> sink = + content::TracingController::CreateStringEndpoint( + std::move(finish_sink_callback)); + base::OnceClosure stop_tracing_closure = base::BindOnce( + base::IgnoreResult<bool (content::TracingController::*)( // NOLINT + const scoped_refptr<content::TracingController::TraceDataEndpoint>&)>( + &content::TracingController::StopTracing), + base::Unretained(content::TracingController::GetInstance()), sink); + base::OnceClosure stop_tracing_ui_thread_closure = + base::BindOnce(base::IgnoreResult(&base::TaskRunner::PostTask), + base::ThreadTaskRunnerHandle::Get(), FROM_HERE, + std::move(stop_tracing_closure)); + profiling::ProfilingProcessHost::GetInstance() + ->SetDumpProcessForTracingCallback( + std::move(stop_tracing_ui_thread_closure)); + + // Spin a nested RunLoop until the heap dump has been added to the trace. + content::TracingController::GetInstance()->StartTracing( + base::trace_event::TraceConfig( + base::trace_event::TraceConfigMemoryTestUtil:: + GetTraceConfig_PeriodicTriggers(100000, 100000)), + base::Closure()); + + if (synchronous) + run_loop->Run(); +} + +bool ProfilingTestDriver::ValidateBrowserAllocations(base::Value* dump_json) { + base::Value* heaps_v2 = + FindHeapsV2(base::Process::Current().Pid(), dump_json); + + if (options_.mode != ProfilingProcessHost::Mode::kAll && + options_.mode != ProfilingProcessHost::Mode::kBrowser && + options_.mode != ProfilingProcessHost::Mode::kMinimal) { + if (heaps_v2) { + LOG(ERROR) << "There should be no heap dump for the browser."; + return false; + } + return true; + } + + bool result = false; + +// TODO(ajwong): This step fails on Nexus 5X devices running kit-kat. It works +// on Nexus 5X devices running oreo. The problem is that all allocations have +// the same [an effectively empty] backtrace and get glommed together. More +// investigation is necessary. For now, I'm turning this off for Android. +// https://crbug.com/786450. +#if !defined(OS_ANDROID) + result = ValidateDump(heaps_v2, kMallocAllocSize * kMallocAllocCount, + kMallocAllocCount, "malloc", nullptr); + if (!result) { + LOG(ERROR) << "Failed to validate malloc fixed allocations"; + return false; + } + + result = ValidateDump(heaps_v2, total_variadic_allocations_, + kVariadicAllocCount, "malloc", nullptr); + if (!result) { + LOG(ERROR) << "Failed to validate malloc variadic allocations"; + return false; + } +#endif + + // TODO(ajwong): Like malloc, all Partition-Alloc allocations get glommed + // together for some Android device/OS configurations. However, since there is + // only one place that uses partition alloc in the browser process [this + // test], the count is still valid. This should still be made more robust by + // fixing backtrace. https://crbug.com/786450. + result = ValidateDump(heaps_v2, kPartitionAllocSize * kPartitionAllocCount, + kPartitionAllocCount, "partition_alloc", + kPartitionAllocTypeName); + if (!result) { + LOG(ERROR) << "Failed to validate PA allocations"; + return false; + } + + int process_count = NumProcessesWithName(dump_json, "Browser", nullptr); + if (process_count != 1) { + LOG(ERROR) << "Found " << process_count + << " processes with name: Browser. Expected 1."; + return false; + } + + return true; +} + +bool ProfilingTestDriver::ValidateRendererAllocations(base::Value* dump_json) { + int pid; + bool result = NumProcessesWithName(dump_json, "Renderer", &pid) == 1; + if (!result) { + LOG(ERROR) << "Failed to find process with name Renderer"; + return false; + } + + base::ProcessId renderer_pid = static_cast<base::ProcessId>(pid); + base::Value* heaps_v2 = FindHeapsV2(renderer_pid, dump_json); + if (options_.mode == ProfilingProcessHost::Mode::kAll || + options_.mode == ProfilingProcessHost::Mode::kRendererSampling) { + if (!heaps_v2) { + LOG(ERROR) << "Failed to find heaps v2 for renderer"; + return false; + } + + // ValidateDump doesn't always succeed for the renderer, since we don't do + // anything to flush allocations, there are very few allocations recorded + // by the heap profiler. When we do a heap dump, we prune small + // allocations...and this can cause all allocations to be pruned. + // ASSERT_NO_FATAL_FAILURE(ValidateDump(dump_json.get(), 0, 0)); + } else { + if (heaps_v2) { + LOG(ERROR) << "There should be no heap dump for the renderer."; + return false; + } + } + + // RendererSampling guarantees only 1 renderer is ever sampled at a time. + if (options_.mode == ProfilingProcessHost::Mode::kRendererSampling) { + if (NumProcessesWithName(dump_json, "Renderer", nullptr) != 1) { + LOG(ERROR) << "There should be exactly 1 renderer dump"; + return false; + } + } else { + if (NumProcessesWithName(dump_json, "Renderer", nullptr) == 0) { + LOG(ERROR) << "There should be more than 1 renderer dump"; + return false; + } + } + + return true; +} + +// Attempt to dump a gpu process. +// TODO(ajwong): Implement this. http://crbug.com/780955 + +} // namespace profiling
diff --git a/chrome/browser/profiling_host/profiling_test_driver.h b/chrome/browser/profiling_host/profiling_test_driver.h new file mode 100644 index 0000000..3820e2a --- /dev/null +++ b/chrome/browser/profiling_host/profiling_test_driver.h
@@ -0,0 +1,118 @@ +// 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_PROFILING_HOST_PROFILING_TEST_DRIVER_H_ +#define CHROME_BROWSER_PROFILING_HOST_PROFILING_TEST_DRIVER_H_ + +#include <vector> + +#include "base/allocator/partition_allocator/partition_alloc.h" +#include "base/macros.h" +#include "base/memory/ref_counted_memory.h" +#include "base/synchronization/waitable_event.h" +#include "chrome/browser/profiling_host/profiling_process_host.h" + +namespace base { +class Value; +} // namespace base + +namespace profiling { + +// This class runs tests for the profiling service, a cross-platform, +// multi-process component. Chrome on Android does not support browser_tests. It +// does support content_browsertests, but those are not multi-process tests. On +// Android, processes have to be started via the Activity mechanism, and the +// test infrastructure does not support this. +// +// To avoid test-code duplication, all tests are pulled into this class. +// browser_tests will directly call this class. The android +// chrome_public_test_apk will invoke this class via a JNI shim. Since the +// latter is not running within the gtest framework, this class cannot use +// EXPECT* and ASSERT* macros. Instead, this class will return a bool indicating +// success of the entire test. On failure, errors will be output via LOG(ERROR). +// These will show up in the browser_tests output stream, and will be captured +// by logcat [the Android logging facility]. The latter is already the canonical +// mechanism for investigating test failures. +// +// Note: Outputting to stderr will not have the desired effect, since that is +// not captured by logcat. +class ProfilingTestDriver { + public: + struct Options { + // The profiling mode to test. + ProfilingProcessHost::Mode mode; + + // Whether the caller has already started profiling with the given mode. + // TODO(erikchen): Implement and test the case where this member is false. + // Starting profiling is an asynchronous operation, so this requires adding + // some more plumbing. https://crbug.com/753218. + bool profiling_already_started; + }; + + ProfilingTestDriver(); + ~ProfilingTestDriver(); + + // If this is called on the content::BrowserThread::UI thread, then the + // platform must support nested message loops. [This is currently not + // supported on Android]. + // + // Returns whether the test run was successful. Expectation/Assertion failures + // will be printed via LOG(ERROR). + bool RunTest(const Options& options); + + private: + // Populates |initialization_success_| with the result of + // |RunInitializationOnUIThread|, and then signals |wait_for_ui_thread_|. + void RunInitializationOnUIThreadAndSignal(); + + // Starts profiling. Makes allocations. + bool RunInitializationOnUIThread(); + + // If profiling is expected to already be started, confirm it. + // Otherwise, start profiling with the given mode. + bool CheckOrStartProfiling(); + + // Performs allocations. These are expected to be profiled. + void MakeTestAllocations(); + + // Collects a trace that contains a heap dump. The result is stored in + // |serialized_trace_|. + // + // When |synchronous| is true, this method spins a nested message loop. When + // |synchronous| is false, this method posts some tasks that will eventually + // signal |wait_for_ui_thread_|. + void CollectResults(bool synchronous); + + bool ValidateBrowserAllocations(base::Value* dump_json); + bool ValidateRendererAllocations(base::Value* dump_json); + + Options options_; + + // Allocations made by this class. Intentionally leaked, since deallocating + // them would trigger a large number of IPCs, which is slow. + std::vector<char*> leaks_; + + // Sum of size of all variadic allocations. + size_t total_variadic_allocations_ = 0; + + // Use to make PA allocations, which should also be shimmed. + base::PartitionAllocatorGeneric partition_allocator_; + + // Contains nothing until |CollectResults| has been called. + scoped_refptr<base::RefCountedString> serialized_trace_; + + // Whether the test was invoked on the ui thread. + bool running_on_ui_thread_ = true; + + // Whether an error has occurred. + bool initialization_success_ = false; + + base::WaitableEvent wait_for_ui_thread_; + + DISALLOW_COPY_AND_ASSIGN(ProfilingTestDriver); +}; + +} // namespace profiling + +#endif // CHROME_BROWSER_PROFILING_HOST_PROFILING_TEST_DRIVER_H_
diff --git a/chrome/browser/profiling_host/test_android_shim.cc b/chrome/browser/profiling_host/test_android_shim.cc new file mode 100644 index 0000000..1d0bcaa --- /dev/null +++ b/chrome/browser/profiling_host/test_android_shim.cc
@@ -0,0 +1,38 @@ +// 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/profiling_host/test_android_shim.h" + +#include "base/android/jni_string.h" +#include "chrome/browser/profiling_host/profiling_process_host.h" +#include "chrome/browser/profiling_host/profiling_test_driver.h" +#include "jni/TestAndroidShim_jni.h" + +using base::android::JavaParamRef; +using base::android::ScopedJavaLocalRef; + +static jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj) { + TestAndroidShim* profiler = new TestAndroidShim(env, obj); + return reinterpret_cast<intptr_t>(profiler); +} + +TestAndroidShim::TestAndroidShim(JNIEnv* env, jobject obj) {} + +TestAndroidShim::~TestAndroidShim() {} + +void TestAndroidShim::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) { + delete this; +} + +jboolean TestAndroidShim::RunTestForMode( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jstring>& mode) { + profiling::ProfilingTestDriver driver; + profiling::ProfilingTestDriver::Options options; + options.mode = profiling::ProfilingProcessHost::ConvertStringToMode( + base::android::ConvertJavaStringToUTF8(mode)); + options.profiling_already_started = true; + return driver.RunTest(options); +}
diff --git a/chrome/browser/profiling_host/test_android_shim.h b/chrome/browser/profiling_host/test_android_shim.h new file mode 100644 index 0000000..de6dd73 --- /dev/null +++ b/chrome/browser/profiling_host/test_android_shim.h
@@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PROFILING_HOST_TEST_ANDROID_SHIM_H_ +#define CHROME_BROWSER_PROFILING_HOST_TEST_ANDROID_SHIM_H_ + +#include "base/android/jni_android.h" +#include "base/android/scoped_java_ref.h" +#include "base/macros.h" + +// This class implements the native methods of TestAndroidShim.java, +// and acts as a bridge to ProfilingProcessHost. Note that this class is only +// used for testing. +class TestAndroidShim { + public: + TestAndroidShim(JNIEnv* env, jobject obj); + void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); + + jboolean RunTestForMode(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jstring>&); + + private: + ~TestAndroidShim(); + + DISALLOW_COPY_AND_ASSIGN(TestAndroidShim); +}; + +#endif // CHROME_BROWSER_PROFILING_HOST_TEST_ANDROID_SHIM_H_
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 2820362..37347c5 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1285,15 +1285,21 @@ AppendMediaRouterItem(); if (TranslateService::IsTranslatableURL(params_.page_url)) { - // TODO(crbug.com/711217): We should not allow to use the translate when the - // feature is disabled by the PolicyList. - std::string locale = GetTargetLanguage(); - base::string16 language = - l10n_util::GetDisplayNameForLocale(locale, locale, true); - menu_model_.AddItem( - IDC_CONTENT_CONTEXT_TRANSLATE, - l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_TRANSLATE, language)); - AddGoogleIconToLastMenuItem(&menu_model_); + std::unique_ptr<translate::TranslatePrefs> prefs( + ChromeTranslateClient::CreateTranslatePrefs( + GetPrefs(browser_context_))); + if (prefs->IsTranslateAllowedByPolicy()) { + language::LanguageModel* language_model = + LanguageModelFactory::GetForBrowserContext(browser_context_); + std::string locale = translate::TranslateManager::GetTargetLanguage( + prefs.get(), language_model); + base::string16 language = + l10n_util::GetDisplayNameForLocale(locale, locale, true); + menu_model_.AddItem( + IDC_CONTENT_CONTEXT_TRANSLATE, + l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_TRANSLATE, language)); + AddGoogleIconToLastMenuItem(&menu_model_); + } } }
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 58db0a4e..a4cda8703 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
@@ -302,8 +302,6 @@ if (node.role == RoleType.EMBEDDED_OBJECT || node.role == RoleType.WEB_VIEW) return; - this.createTextEditHandlerIfNeeded_(evt.target); - // Category flush speech triggered by events with no source. This includes // views. if (evt.eventFrom == '') @@ -329,6 +327,9 @@ } var event = new CustomAutomationEvent(EventType.FOCUS, node, evt.eventFrom); this.onEventDefault(event); + + // Refresh the handler, if needed, now that ChromeVox focus is up to date. + this.createTextEditHandlerIfNeeded_(node); }, /**
diff --git a/chrome/browser/resources/interventions_internals/index.css b/chrome/browser/resources/interventions_internals/index.css index ada814d1..bb04a5b0 100644 --- a/chrome/browser/resources/interventions_internals/index.css +++ b/chrome/browser/resources/interventions_internals/index.css
@@ -10,6 +10,25 @@ user-select: none; } +.section-header { + color: rgb(43, 96, 222); + font-size: 120%; + font-weight: bold; + margin-top: 20px; +} + +.previews-status-value { + margin-top: 5px; +} + +.previews-flag-container { + margin-top: 5px; +} + +.previews-flag-value { + margin-left: 10px; +} + button { background: rgb(53, 106, 222); border-radius: 5px; @@ -194,6 +213,10 @@ width: 60%; } + #previews-flags-table { + width: 30%; + } + .log-time { width: 15%; } @@ -229,7 +252,7 @@ width: 30%; } - #blacklisted-hosts-table { + #previews-flags-table { width: 30%; }
diff --git a/chrome/browser/resources/interventions_internals/index.html b/chrome/browser/resources/interventions_internals/index.html index b5d35f94..da429f2 100644 --- a/chrome/browser/resources/interventions_internals/index.html +++ b/chrome/browser/resources/interventions_internals/index.html
@@ -17,8 +17,8 @@ <nav class="tab-select"> <label class="active-tab"> <input type="radio" id="statuses-tab" name="tabs" - value="previews-statuses" checked="checked"> - <span>Previews Modes</span> + value="previews-status" checked="checked"> + <span>Interventions</span> </label> <label class="inactive-tab"> <input type="radio" id="logs-tab" name="tabs" value="message-logs"> @@ -35,7 +35,23 @@ </label> </nav> - <div class="tab-content" id="previews-statuses"> + <div class="tab-content" id="previews-status"> + <div id="previews-enabled-status"> + <div class="section-header"> + Intervention Status + </div> + </div> + <div id="previews-flags-status"> + <div class="section-header"> + Intervention Flags + </div> + <table id="previews-flags-table"> + <tr> + <th class="flag-name" id="flag-name-header">Flag</th> + <th class="flag-value" id="flag-value-header">Value</th> + </tr> + </table> + </div> </div> <div class="tab-content" id="message-logs">
diff --git a/chrome/browser/resources/interventions_internals/index.js b/chrome/browser/resources/interventions_internals/index.js index b8fbc48..3a76696 100644 --- a/chrome/browser/resources/interventions_internals/index.js +++ b/chrome/browser/resources/interventions_internals/index.js
@@ -322,6 +322,7 @@ function init(handler) { pageHandler = handler; getPreviewsEnabled(); + getPreviewsFlagsDetails(); let ignoreButton = $('ignore-blacklist-button'); ignoreButton.addEventListener('click', () => { @@ -333,29 +334,38 @@ } /** + * Sort keys by the value of each value by its description attribute of a + * |mapObject|. + * + * @param mapObject {!Map<string, Object} A map where all values have a + * description attribute. + * @return A list of keys sorted by their descriptions. + */ + function getSortedKeysByDescription(mapObject) { + let sortedKeys = Array.from(mapObject.keys()); + sortedKeys.sort((a, b) => { + return mapObject.get(a).description > mapObject.get(b).description; + }); + return sortedKeys; + } + + /** * Retrieves the statuses of previews (i.e. Offline, LoFi, AMP Redirection), * and posts them on chrome://intervention-internals. */ function getPreviewsEnabled() { pageHandler.getPreviewsEnabled() .then((response) => { - let statuses = $('previews-statuses'); + let statuses = $('previews-enabled-status'); - // Sorting the keys by the status's description. - let sortedKeys = Array.from(response.statuses.keys()); - sortedKeys.sort((a, b) => { - return response.statuses.get(a).description > - response.statuses.get(b).description; - }); - - sortedKeys.forEach((key) => { + getSortedKeysByDescription(response.statuses).forEach((key) => { let value = response.statuses.get(key); let message = value.description + ': '; message += value.enabled ? 'Enabled' : 'Disabled'; assert(!$(key), 'Component ' + key + ' already existed!'); - let node = document.createElement('p'); + let node = document.createElement('div'); node.setAttribute('class', 'previews-status-value'); node.setAttribute('id', key); node.textContent = message; @@ -367,6 +377,41 @@ }); } + function getPreviewsFlagsDetails() { + pageHandler.getPreviewsFlagsDetails() + .then((response) => { + let flags = $('previews-flags-table'); + + getSortedKeysByDescription(response.flags).forEach((key) => { + let value = response.flags.get(key); + assert(!$(key), 'Component ' + key + ' already existed!'); + + let flagDescription = document.createElement('a'); + flagDescription.setAttribute('class', 'previews-flag-description'); + flagDescription.setAttribute('id', key + 'Description'); + flagDescription.setAttribute('href', value.link); + flagDescription.textContent = value.description; + + let flagNameTd = document.createElement('td'); + flagNameTd.appendChild(flagDescription); + + let flagValueTd = document.createElement('td'); + flagValueTd.setAttribute('class', 'previews-flag-value'); + flagValueTd.setAttribute('id', key + 'Value'); + flagValueTd.textContent = value.value; + + let node = document.createElement('tr'); + node.setAttribute('class', 'previews-flag-container'); + node.appendChild(flagNameTd); + node.appendChild(flagValueTd); + flags.appendChild(node); + }); + }) + .catch((error) => { + console.error(error.message); + }); + } + return { init: init, };
diff --git a/chrome/browser/resources/md_extensions/item_list.html b/chrome/browser/resources/md_extensions/item_list.html index 3c817e05..8e74342 100644 --- a/chrome/browser/resources/md_extensions/item_list.html +++ b/chrome/browser/resources/md_extensions/item_list.html
@@ -73,8 +73,8 @@ filter="[[computeFilter_(filter)]]" rendered-item-count="{{shownExtensionsCount_::dom-change}}" notify-dom-change> - <extensions-item data="[[item]]" delegate="[[delegate]]" - in-dev-mode="[[inDevMode]]"> + <extensions-item id="[[item.id]]" data="[[item]]" + delegate="[[delegate]]" in-dev-mode="[[inDevMode]]"> </extensions-item> </template> </div> @@ -87,8 +87,8 @@ filter="[[computeFilter_(filter)]]" rendered-item-count="{{shownAppsCount_::dom-change}}" notify-dom-change> - <extensions-item data="[[item]]" delegate="[[delegate]]" - in-dev-mode="[[inDevMode]]"> + <extensions-item id="[[item.id]]" data="[[item]]" + delegate="[[delegate]]" in-dev-mode="[[inDevMode]]"> </extensions-item> </template> </div>
diff --git a/chrome/browser/resources/md_extensions/item_list.js b/chrome/browser/resources/md_extensions/item_list.js index a7c9531..d749f229 100644 --- a/chrome/browser/resources/md_extensions/item_list.js +++ b/chrome/browser/resources/md_extensions/item_list.js
@@ -41,6 +41,22 @@ }, /** + * @param {string} id + * @return {?Element} + */ + getDetailsButton: function(id) { + return this.$$(`#${id} /deep/ #details-button`); + }, + + /** + * @param {string} id + * @return {?Element} + */ + getErrorsButton: function(id) { + return this.$$(`#${id} /deep/ #errors-button`); + }, + + /** * Computes the filter function to be used for determining which items * should be shown. A |null| value indicates that everything should be * shown.
diff --git a/chrome/browser/resources/md_extensions/manager.js b/chrome/browser/resources/md_extensions/manager.js index 4c61157..fe561e7 100644 --- a/chrome/browser/resources/md_extensions/manager.js +++ b/chrome/browser/resources/md_extensions/manager.js
@@ -118,6 +118,10 @@ // </if> }, + listeners: { + 'view-exit-finish': 'onViewExitFinish_', + }, + /** * The current page being shown. Default to null, and initPage_ will figure * out the initial page based on url. @@ -476,6 +480,26 @@ this.showPackDialog_ = false; }, + /** @private */ + onViewExitFinish_: function(e) { + const viewType = e.path[0].tagName; + if (viewType == 'EXTENSIONS-ITEM-LIST' || + viewType == 'EXTENSIONS-KEYBOARD-SHORTCUT') { + return; + } + + const extensionId = e.path[0].data.id; + const list = this.$$('extensions-item-list'); + const button = viewType == 'EXTENSIONS-DETAIL-VIEW' ? + list.getDetailsButton(extensionId) : + list.getErrorsButton(extensionId); + + // The button will not exist, when returning from a details page + // because the corresponding extension/app was deleted. + if (button) + button.focus(); + }, + // <if expr="chromeos"> /** @private */ onKioskTap_: function() {
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html index d2c2fc0..955204a 100644 --- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html +++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
@@ -98,11 +98,12 @@ <span>[[title_]]</span> <template is="dom-if" if="[[showDetails_]]"> <!-- Force line break to display learn-more inlined with - chromeCleanupExplanation or with the title_ (if showDetails_ is - false) despite these two elements being on different lines. --> + chromeCleanupExplanationRemove or with the title_ (if + showDetails_ is false) despite these two elements being on + different lines. --> <div></div> <span class="secondary"> - $i18n{chromeCleanupExplanation} + $i18n{chromeCleanupExplanationRemove} </span> </template> <a id="learn-more" href="$i18n{chromeCleanupLearnMoreUrl}"
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_page.html b/chrome/browser/resources/settings/date_time_page/date_time_page.html index 2a869b67..d946c09c 100644 --- a/chrome/browser/resources/settings/date_time_page/date_time_page.html +++ b/chrome/browser/resources/settings/date_time_page/date_time_page.html
@@ -1,11 +1,11 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="../controls/settings_toggle_button.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="../prefs/prefs_behavior.html"> @@ -31,7 +31,7 @@ width: 100%; } - paper-toggle-button { + cr-toggle { -webkit-margin-start: var(--settings-control-label-spacing); } @@ -55,13 +55,13 @@ icon-aria-label="$i18n{timeZoneGeolocation}"> </cr-policy-indicator> </template> - <paper-toggle-button + <cr-toggle id="timeZoneAutoDetect" aria-label="$i18n{timeZoneGeolocation}" checked="[[timeZoneAutoDetect_]]" disabled="[[hasTimeZoneAutoDetectPolicyRestriction_]]" on-change="onTimeZoneAutoDetectChange_"> - </paper-toggle-button> + </cr-toggle> </div> </template> <template is="dom-if"
diff --git a/chrome/browser/resources/settings/device_page/display.html b/chrome/browser/resources/settings/device_page/display.html index 5c47d12..46cb7649 100644 --- a/chrome/browser/resources/settings/device_page/display.html +++ b/chrome/browser/resources/settings/device_page/display.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> @@ -9,7 +10,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.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-tabs/paper-tabs.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="display_layout.html"> <link rel="import" href="display_overscan_dialog.html"> <link rel="import" href="night_light_slider.html"> @@ -114,10 +114,10 @@ [[getUnifiedDesktopText_(unifiedDesktopMode_)]] </div> </div> - <paper-toggle-button checked="[[unifiedDesktopMode_]]" + <cr-toggle checked="[[unifiedDesktopMode_]]" on-tap="onUnifiedDesktopTap_" aria-labelledby="displayUnifiedDesktopCheckboxLabel"> - </paper-toggle-button> + </cr-toggle> </div> </template>
diff --git a/chrome/browser/resources/settings/device_page/stylus.html b/chrome/browser/resources/settings/device_page/stylus.html index ac5e133..6a0dad0 100644 --- a/chrome/browser/resources/settings/device_page/stylus.html +++ b/chrome/browser/resources/settings/device_page/stylus.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/html/action_link.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="../controls/settings_toggle_button.html"> @@ -105,12 +106,12 @@ indicator-type="[[userPolicyIndicator_]]"> </cr-policy-indicator> </template> - <paper-toggle-button id="enable-app-on-lock-screen-toggle" + <cr-toggle id="enable-app-on-lock-screen-toggle" aria-labelledby="lock-screen-toggle-label" disabled="[[disallowedOnLockScreenByPolicy_(selectedApp_)]]" checked="[[lockScreenSupportEnabled_(selectedApp_)]]" on-change="toggleLockScreenSupport_"> - </paper-toggle-button> + </cr-toggle> </div> <template is="dom-if" if="[[lockScreenSupportEnabled_(selectedApp_)]]">
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html index cfa11d4a..76bec8e9 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.html +++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -9,10 +9,10 @@ <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.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-toggle-button/paper-toggle-button.html"> <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> <link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html"> <link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="add_languages_dialog.html"> <link rel="import" href="languages.html"> @@ -222,11 +222,11 @@ actionable$="[[item.language.supportsSpellcheck]]"> [[item.language.displayName]] </div> - <paper-toggle-button on-change="onSpellCheckChange_" + <cr-toggle on-change="onSpellCheckChange_" disabled="[[!item.language.supportsSpellcheck]]" checked="[[item.spellCheckEnabled]]" aria-label$="[[item.language.displayName]]"> - </paper-toggle-button> + </cr-toggle> </div> </template> <div class="list-item" on-tap="onEditDictionaryTap_" actionable>
diff --git a/chrome/browser/resources/settings/people_page/manage_profile.html b/chrome/browser/resources/settings/people_page/manage_profile.html index 656400b..fbc49f4 100644 --- a/chrome/browser/resources/settings/people_page/manage_profile.html +++ b/chrome/browser/resources/settings/people_page/manage_profile.html
@@ -1,10 +1,10 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="manage_profile_browser_proxy.html"> <link rel="import" href="../route.html"> @@ -27,11 +27,11 @@ <template is="dom-if" if="[[isProfileShortcutSettingVisible_]]"> <div class="settings-box first"> <div id="showShortcutLabel" class="start">$i18n{showShortcutLabel}</div> - <paper-toggle-button id="hasShortcutToggle" + <cr-toggle id="hasShortcutToggle" checked="{{hasProfileShortcut_}}" on-change="onHasProfileShortcutChange_" aria-labelledby="showShortcutLabel"> - </paper-toggle-button> + </cr-toggle> </div> </template> <cr-profile-avatar-selector id="selector" avatars="[[availableIcons]]"
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html index 9d6fba8..07ae46a 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.html +++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -3,9 +3,9 @@ <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html"> @@ -103,23 +103,23 @@ <div id="syncEverythingCheckboxLabel" class="start"> $i18n{syncEverythingCheckboxLabel} </div> - <paper-toggle-button id="syncAllDataTypesControl" + <cr-toggle id="syncAllDataTypesControl" checked="{{syncPrefs.syncAllDataTypes}}" on-change="onSyncAllDataTypesChanged_" aria-labelledby="syncEverythingCheckboxLabel"> - </paper-toggle-button> + </cr-toggle> </div> <div class="list-frame" id="sync-data-types"> <div class="layout horizontal list-item" hidden="[[!syncPrefs.appsRegistered]]"> <div id="appCheckboxLabel" class="flex">$i18n{appCheckboxLabel}</div> - <paper-toggle-button checked="{{syncPrefs.appsSynced}}" + <cr-toggle checked="{{syncPrefs.appsSynced}}" on-change="onSingleSyncDataTypeChanged_" disabled="[[shouldSyncCheckboxBeDisabled_( syncPrefs.syncAllDataTypes, syncPrefs.appsEnforced)]]" aria-labelledby="appCheckboxLabel"> - </paper-toggle-button> + </cr-toggle> </div> <div class="layout horizontal list-item" @@ -129,12 +129,12 @@ </div> <!-- Autofill has a special on-change handler to deal with Payments integriation. --> - <paper-toggle-button checked="{{syncPrefs.autofillSynced}}" + <cr-toggle checked="{{syncPrefs.autofillSynced}}" on-change="onAutofillDataTypeChanged_" disabled="[[shouldSyncCheckboxBeDisabled_( syncPrefs.syncAllDataTypes, syncPrefs.autofillEnforced)]]" aria-labelledby="autofillCheckboxLabel"> - </paper-toggle-button> + </cr-toggle> </div> <div class="layout horizontal list-item" @@ -142,12 +142,12 @@ <div id="bookmarksCheckboxLabel" class="flex"> $i18n{bookmarksCheckboxLabel} </div> - <paper-toggle-button checked="{{syncPrefs.bookmarksSynced}}" + <cr-toggle checked="{{syncPrefs.bookmarksSynced}}" on-change="onSingleSyncDataTypeChanged_" disabled="[[shouldSyncCheckboxBeDisabled_( syncPrefs.syncAllDataTypes, syncPrefs.bookmarksEnforced)]]" aria-labelledby="bookmarksCheckboxLabel"> - </paper-toggle-button> + </cr-toggle> </div> <div class="layout horizontal list-item" @@ -155,12 +155,12 @@ <div id="extensionsCheckboxLabel" class="flex"> $i18n{extensionsCheckboxLabel} </div> - <paper-toggle-button checked="{{syncPrefs.extensionsSynced}}" + <cr-toggle checked="{{syncPrefs.extensionsSynced}}" on-change="onSingleSyncDataTypeChanged_" disabled="[[shouldSyncCheckboxBeDisabled_( syncPrefs.syncAllDataTypes, syncPrefs.extensionsEnforced)]]" aria-labelledby="extensionsCheckboxLabel"> - </paper-toggle-button> + </cr-toggle> </div> <div class="layout horizontal list-item" @@ -168,12 +168,12 @@ <div id="historyCheckboxLabel" class="flex"> $i18n{historyCheckboxLabel} </div> - <paper-toggle-button checked="{{syncPrefs.typedUrlsSynced}}" + <cr-toggle checked="{{syncPrefs.typedUrlsSynced}}" on-change="onSingleSyncDataTypeChanged_" disabled="[[shouldSyncCheckboxBeDisabled_( syncPrefs.syncAllDataTypes, syncPrefs.typedUrlsEnforced)]]" aria-labelledby="historyCheckboxLabel"> - </paper-toggle-button> + </cr-toggle> </div> <div class="layout horizontal list-item" @@ -181,12 +181,12 @@ <div id="passwordsCheckboxLabel" class="flex"> $i18n{passwordsCheckboxLabel} </div> - <paper-toggle-button checked="{{syncPrefs.passwordsSynced}}" + <cr-toggle checked="{{syncPrefs.passwordsSynced}}" on-change="onSingleSyncDataTypeChanged_" disabled="[[shouldSyncCheckboxBeDisabled_( syncPrefs.syncAllDataTypes, syncPrefs.passwordsEnforced)]]" aria-labelledby="passwordsCheckboxLabel"> - </paper-toggle-button> + </cr-toggle> </div> <div class="layout horizontal list-item" @@ -194,12 +194,12 @@ <div id="settingsCheckboxLabel" class="flex"> $i18n{settingsCheckboxLabel} </div> - <paper-toggle-button checked="{{syncPrefs.preferencesSynced}}" + <cr-toggle checked="{{syncPrefs.preferencesSynced}}" on-change="onSingleSyncDataTypeChanged_" disabled="[[shouldSyncCheckboxBeDisabled_( syncPrefs.syncAllDataTypes, syncPrefs.preferencesEnforced)]]" aria-labelledby="settingsCheckboxLabel"> - </paper-toggle-button> + </cr-toggle> </div> <div class="layout horizontal list-item" @@ -207,12 +207,12 @@ <div id="themesAndWallpapersCheckboxLabel" class="flex"> $i18n{themesAndWallpapersCheckboxLabel} </div> - <paper-toggle-button checked="{{syncPrefs.themesSynced}}" + <cr-toggle checked="{{syncPrefs.themesSynced}}" on-change="onSingleSyncDataTypeChanged_" disabled="[[shouldSyncCheckboxBeDisabled_( syncPrefs.syncAllDataTypes, syncPrefs.themesEnforced)]]" aria-labelledby="themesAndWallpapersCheckboxLabel"> - </paper-toggle-button> + </cr-toggle> </div> <div class="layout horizontal list-item" @@ -220,12 +220,12 @@ <div id="openTabsCheckboxLabel" class="flex"> $i18n{openTabsCheckboxLabel} </div> - <paper-toggle-button checked="{{syncPrefs.tabsSynced}}" + <cr-toggle checked="{{syncPrefs.tabsSynced}}" on-change="onSingleSyncDataTypeChanged_" disabled="[[shouldSyncCheckboxBeDisabled_( syncPrefs.syncAllDataTypes, syncPrefs.tabsEnforced)]]" aria-labelledby="openTabsCheckboxLabel"> - </paper-toggle-button> + </cr-toggle> </div> <div class="layout horizontal list-item" @@ -239,13 +239,13 @@ $i18n{learnMore} </a> </div> - <paper-toggle-button + <cr-toggle checked="{{syncPrefs.paymentsIntegrationEnabled}}" on-change="onSingleSyncDataTypeChanged_" disabled="[[shouldPaymentsCheckboxBeDisabled_( syncPrefs.syncAllDataTypes, syncPrefs.autofillSynced)]]" aria-label="$i18n{enablePaymentsIntegrationCheckboxLabel}"> - </paper-toggle-button> + </cr-toggle> </div> </div>
diff --git a/chrome/browser/resources/settings/reset_page/reset_page.html b/chrome/browser/resources/settings/reset_page/reset_page.html index 754c477..44214d07 100644 --- a/chrome/browser/resources/settings/reset_page/reset_page.html +++ b/chrome/browser/resources/settings/reset_page/reset_page.html
@@ -66,14 +66,14 @@ <div class="settings-box two-line" id="chromeCleanupSubpageTrigger" on-tap="onChromeCleanupTap_" actionable> <div class="start"> - $i18n{chromeCleanupPageTitle} + $i18n{resetCleanupComputerTrigger} <div class="secondary" id="chromeCleanupSecondary"> - $i18n{chromeCleanupPageTriggerDescription} + $i18n{resetCleanupComputerTriggerDescription} </div> </div> <button id="chromeCleanupArrow" is="paper-icon-button-light" class="subpage-arrow" - aria-label="$i18n{chromeCleanupPageTitle}" + aria-label="$i18n{resetCleanupComputerTrigger}" aria-describedby="chromeCleanupSecondary"></button> </div> </template> @@ -84,7 +84,7 @@ <template is="dom-if" route-path="/cleanup"> <settings-subpage id="chromeCleanupSubpage" associated-control="[[$$('#chromeCleanupSubpageTrigger')]]" - page-title="$i18n{chromeCleanupPageTitle}" + page-title="$i18n{resetCleanupComputerTrigger}" learn-more-url="$i18n{chromeCleanupLearnMoreUrl}"> <settings-chrome-cleanup-page></settings-chrome-cleanup-page> </settings-subpage>
diff --git a/chrome/browser/resources/settings/site_settings/protocol_handlers.html b/chrome/browser/resources/settings/site_settings/protocol_handlers.html index 868c743..a37356e 100644 --- a/chrome/browser/resources/settings/site_settings/protocol_handlers.html +++ b/chrome/browser/resources/settings/site_settings/protocol_handlers.html
@@ -1,10 +1,10 @@ <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/cr_elements/icons.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> +<link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="site_settings_behavior.html"> @@ -27,9 +27,9 @@ <div id="categoryLabel" class="start"> [[computeHandlersDescription_(categoryEnabled)]] </div> - <paper-toggle-button id="toggle" checked="{{categoryEnabled}}" + <cr-toggle id="toggle" checked="{{categoryEnabled}}" on-change="onToggleChange_" aria-labelledby="categoryLabel"> - </paper-toggle-button> + </cr-toggle> </div> <template is="dom-repeat" items="[[protocols]]" as="protocol">
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.h b/chrome/browser/safe_browsing/client_side_detection_host.h index f1603081..645b4fd 100644 --- a/chrome/browser/safe_browsing/client_side_detection_host.h +++ b/chrome/browser/safe_browsing/client_side_detection_host.h
@@ -56,6 +56,8 @@ virtual scoped_refptr<SafeBrowsingDatabaseManager> database_manager(); + BrowseInfo* GetBrowseInfo() const { return browse_info_.get(); } + protected: explicit ClientSideDetectionHost(content::WebContents* tab); @@ -67,15 +69,18 @@ SafeBrowsingUIManager* ui_manager, SafeBrowsingDatabaseManager* database_manager); + // Called when pre-classification checks are done for the malware classifiers. + // Overridden in test. + virtual void OnMalwarePreClassificationDone(bool should_classify); + private: friend class ClientSideDetectionHostTest; class ShouldClassifyUrlRequest; friend class ShouldClassifyUrlRequest; - // These methods are called when pre-classification checks are done for - // the phishing and malware clasifiers. + // Called when pre-classification checks are done for the phishing + // classifiers. void OnPhishingPreClassificationDone(bool should_classify); - void OnMalwarePreClassificationDone(bool should_classify); // Verdict is an encoded ClientPhishingRequest protocol message. void OnPhishingDetectionDone(const std::string& verdict);
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_browsertest.cc b/chrome/browser/safe_browsing/client_side_detection_host_browsertest.cc new file mode 100644 index 0000000..2048913 --- /dev/null +++ b/chrome/browser/safe_browsing/client_side_detection_host_browsertest.cc
@@ -0,0 +1,79 @@ +// 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/safe_browsing/client_side_detection_host.h" + +#include "base/run_loop.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/prefs/pref_service.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +using content::WebContents; + +namespace safe_browsing { +namespace { + +class TestClientSideDetectionHost : public ClientSideDetectionHost { + public: + explicit TestClientSideDetectionHost(WebContents* tab) + : ClientSideDetectionHost(tab) {} + + private: + void OnMalwarePreClassificationDone(bool should_classify_not_used) override { + ClientSideDetectionHost::OnMalwarePreClassificationDone(true); + } + + void DidStopLoading() override {} +}; + +bool FindExpectedIPUrlInfo(const IPUrlInfo& expected_info, + const std::vector<IPUrlInfo>& ip_url_vector) { + auto result = std::find_if( + ip_url_vector.begin(), ip_url_vector.end(), + [expected_info](const IPUrlInfo& ip_url_info) { + return expected_info.url == ip_url_info.url && + expected_info.method == ip_url_info.method && + expected_info.referrer == ip_url_info.referrer && + expected_info.resource_type == ip_url_info.resource_type; + }); + return result != ip_url_vector.end(); +} + +} // namespace + +using ClientSideDetectionHostBrowserTest = InProcessBrowserTest; + +IN_PROC_BROWSER_TEST_F(ClientSideDetectionHostBrowserTest, + VerifyIPAddressCollection) { + browser()->profile()->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnabled, + false); + ASSERT_TRUE(embedded_test_server()->Start()); + std::unique_ptr<TestClientSideDetectionHost> csd_host = + base::MakeUnique<TestClientSideDetectionHost>( + browser()->tab_strip_model()->GetActiveWebContents()); + GURL page_url(embedded_test_server()->GetURL("/safe_browsing/malware.html")); + ui_test_utils::NavigateToURL(browser(), page_url); + + BrowseInfo* browse_info = csd_host->GetBrowseInfo(); + ASSERT_EQ(1u, browse_info->ips.size()); + const std::vector<IPUrlInfo>& ip_urls = + browse_info->ips[embedded_test_server()->base_url().host()]; + IPUrlInfo expected_result_1( + embedded_test_server()->GetURL("/safe_browsing/malware_image.png").spec(), + "GET", page_url.spec(), content::RESOURCE_TYPE_IMAGE); + IPUrlInfo expected_result_2(embedded_test_server() + ->GetURL("/safe_browsing/malware_iframe.html") + .spec(), + "GET", page_url.spec(), + content::RESOURCE_TYPE_SUB_FRAME); + ASSERT_TRUE(FindExpectedIPUrlInfo(expected_result_1, ip_urls)); + ASSERT_TRUE(FindExpectedIPUrlInfo(expected_result_2, ip_urls)); +} + +} // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/incident_reporting/platform_state_store.cc b/chrome/browser/safe_browsing/incident_reporting/platform_state_store.cc index 0f771880..49d0c919 100644 --- a/chrome/browser/safe_browsing/incident_reporting/platform_state_store.cc +++ b/chrome/browser/safe_browsing/incident_reporting/platform_state_store.cc
@@ -47,8 +47,7 @@ for (base::DictionaryValue::Iterator iter(keys_and_digests); !iter.IsAtEnd(); iter.Advance()) { uint32_t digest = 0; - if (iter.value().GetType() != base::Value::Type::STRING || - !iter.value().GetAsString(&digest_value) || + if (!iter.value().is_string() || !iter.value().GetAsString(&digest_value) || !base::StringToUint(digest_value, &digest)) { NOTREACHED(); continue;
diff --git a/chrome/browser/ssl/mitm_software_blocking_page.cc b/chrome/browser/ssl/mitm_software_blocking_page.cc index 8214301d..9200f12 100644 --- a/chrome/browser/ssl/mitm_software_blocking_page.cc +++ b/chrome/browser/ssl/mitm_software_blocking_page.cc
@@ -52,8 +52,9 @@ } // namespace // static -InterstitialPageDelegate::TypeID MITMSoftwareBlockingPage::kTypeForTesting = - &MITMSoftwareBlockingPage::kTypeForTesting; +const InterstitialPageDelegate::TypeID + MITMSoftwareBlockingPage::kTypeForTesting = + &MITMSoftwareBlockingPage::kTypeForTesting; // Note that we always create a navigation entry with SSL errors. // No error happening loading a sub-resource triggers an interstitial so far.
diff --git a/chrome/browser/ssl/mitm_software_blocking_page.h b/chrome/browser/ssl/mitm_software_blocking_page.h index a0a43f7..b9b39b74 100644 --- a/chrome/browser/ssl/mitm_software_blocking_page.h +++ b/chrome/browser/ssl/mitm_software_blocking_page.h
@@ -33,7 +33,7 @@ : public security_interstitials::SecurityInterstitialPage { public: // Interstitial type, used in tests. - static InterstitialPageDelegate::TypeID kTypeForTesting; + static const InterstitialPageDelegate::TypeID kTypeForTesting; // If the blocking page isn't shown, the caller is responsible for cleaning // up the blocking page. Otherwise, the interstitial takes ownership when
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index aa22998..b0b3234d 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -1665,6 +1665,7 @@ ui_test_utils::NavigateToURL(browser(), wss_server_expired_.GetURL("connect_check.html") .ReplaceComponents(replacements)); + WaitForInterstitialAttach(tab); CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
diff --git a/chrome/browser/sync/DEPS b/chrome/browser/sync/DEPS index 88800dc5..69bb425a 100644 --- a/chrome/browser/sync/DEPS +++ b/chrome/browser/sync/DEPS
@@ -4,4 +4,7 @@ "+components/sync_sessions", "+components/sync_wifi", "+google/cacheinvalidation", + + # TODO(hejq): Remove this once app_list is migrated. http://crbug.com/733662 + "+ash/app_list/model", ]
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc index 3f7d526..a820a37 100644 --- a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc +++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
@@ -533,9 +533,12 @@ } std::string ProfileSyncServiceHarness::GetServiceStatus() { + AccountInfo primary_account_info; + primary_account_info.email = username_; + primary_account_info.gaia = gaia_id_; std::unique_ptr<base::DictionaryValue> value( - syncer::sync_ui_util::ConstructAboutInformation_DEPRECATED( - service(), chrome::GetChannel())); + syncer::sync_ui_util::ConstructAboutInformation( + service(), primary_account_info, chrome::GetChannel())); std::string service_status; base::JSONWriter::WriteWithOptions( *value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &service_status);
diff --git a/chrome/browser/sync/test/integration/sync_app_list_helper.cc b/chrome/browser/sync/test/integration/sync_app_list_helper.cc index 40c47ef..72c552b 100644 --- a/chrome/browser/sync/test/integration/sync_app_list_helper.cc +++ b/chrome/browser/sync/test/integration/sync_app_list_helper.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/sync/test/integration/sync_app_list_helper.h" +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" #include "base/strings/stringprintf.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/test/integration/sync_datatype_helper.h" @@ -13,9 +16,6 @@ #include "chrome/common/extensions/sync_helper.h" #include "extensions/browser/app_sorting.h" #include "extensions/browser/extension_system.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" using app_list::AppListFolderItem; using app_list::AppListItem;
diff --git a/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc b/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc index 090f2ab0..3980c64 100644 --- a/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc
@@ -4,6 +4,8 @@ #include <stddef.h> +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" #include "base/command_line.h" #include "base/macros.h" #include "build/build_config.h" @@ -22,8 +24,6 @@ #include "content/public/test/test_utils.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_system.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_switches.h" using apps_helper::DisableApp;
diff --git a/chrome/browser/themes/theme_service_win.h b/chrome/browser/themes/theme_service_win.h index 6ea367f1..eba1cb2 100644 --- a/chrome/browser/themes/theme_service_win.h +++ b/chrome/browser/themes/theme_service_win.h
@@ -37,9 +37,9 @@ // The frame color when active. If empty the default colors should be used. base::Optional<SkColor> dwm_frame_color_; - // True if we took dwm_inactive_frame_color_ from the registry (vs calculating - // it ourselves) and thus Windows will use it too. - bool inactive_frame_color_from_registry_; + // True if we took |dwm_inactive_frame_color_| from the registry (vs + // calculating it ourselves) and thus Windows will use it too. + bool inactive_frame_color_from_registry_ = false; // The frame color when inactive. If empty the default colors should be used. base::Optional<SkColor> dwm_inactive_frame_color_;
diff --git a/chrome/browser/translate/translate_manager_render_view_host_unittest.cc b/chrome/browser/translate/translate_manager_render_view_host_unittest.cc index 5c2ce6f..1e74f9511 100644 --- a/chrome/browser/translate/translate_manager_render_view_host_unittest.cc +++ b/chrome/browser/translate/translate_manager_render_view_host_unittest.cc
@@ -1228,7 +1228,7 @@ Profile* profile = Profile::FromBrowserContext(web_contents()->GetBrowserContext()); PrefService* prefs = profile->GetPrefs(); - prefs->SetBoolean(prefs::kEnableTranslate, true); + prefs->SetBoolean(prefs::kOfferTranslateEnabled, true); SimulateNavigation(GURL("http://www.google.fr"), "fr", true); @@ -1237,7 +1237,7 @@ EXPECT_TRUE(infobar != NULL); // Disable translate. - prefs->SetBoolean(prefs::kEnableTranslate, false); + prefs->SetBoolean(prefs::kOfferTranslateEnabled, false); // Navigate to a new page, that should close the previous infobar. GURL url("http://www.youtube.fr");
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 862095eb..8fe0b858 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1501,7 +1501,7 @@ deps += [ "//ash", "//ash:ash_with_content", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//ash/resources/vector_icons", "//ash/strings", "//chrome/browser/chromeos", @@ -3734,7 +3734,7 @@ "ash/test_wallpaper_controller.cc", "ash/test_wallpaper_controller.h", ] - deps += [ "//ash/public/cpp:ash_public_cpp" ] + deps += [ "//ash/public/cpp" ] } if (enable_extensions) {
diff --git a/chrome/browser/ui/app_list/DEPS b/chrome/browser/ui/app_list/DEPS new file mode 100644 index 0000000..4eed37a5 --- /dev/null +++ b/chrome/browser/ui/app_list/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + # TODO(hejq): Remove this once app_list is migrated. http://crbug.com/733662 + "+ash/app_list/model", +]
diff --git a/chrome/browser/ui/app_list/app_list_controller_browsertest.cc b/chrome/browser/ui/app_list/app_list_controller_browsertest.cc index 8d9f864..03ee1f0 100644 --- a/chrome/browser/ui/app_list/app_list_controller_browsertest.cc +++ b/chrome/browser/ui/app_list/app_list_controller_browsertest.cc
@@ -4,6 +4,10 @@ #include <stddef.h> +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/search_box_model.h" +#include "ash/app_list/model/search_result.h" +#include "ash/app_list/model/search_result_observer.h" #include "base/command_line.h" #include "base/macros.h" #include "base/path_service.h" @@ -23,11 +27,7 @@ #include "chrome/test/base/testing_profile.h" #include "chromeos/chromeos_switches.h" #include "components/user_manager/user_names.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_switches.h" -#include "ui/app_list/search_box_model.h" -#include "ui/app_list/search_result.h" -#include "ui/app_list/search_result_observer.h" #include "ui/base/models/list_model_observer.h" // Browser Test for AppListController that runs on all platforms supporting
diff --git a/chrome/browser/ui/app_list/app_list_controller_delegate.cc b/chrome/browser/ui/app_list/app_list_controller_delegate.cc index 1a43777..d3bf0a9 100644 --- a/chrome/browser/ui/app_list/app_list_controller_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_controller_delegate.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" #include "base/metrics/histogram_macros.h" #include "build/build_config.h" #include "chrome/browser/extensions/extension_util.h" @@ -23,8 +25,6 @@ #include "extensions/common/manifest_url_handlers.h" #include "net/base/url_util.h" #include "rlz/features/features.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_switches.h" #include "ui/display/display.h" #include "ui/display/screen.h"
diff --git a/chrome/browser/ui/app_list/app_list_model_builder.cc b/chrome/browser/ui/app_list/app_list_model_builder.cc index eba94fe..174a3040 100644 --- a/chrome/browser/ui/app_list/app_list_model_builder.cc +++ b/chrome/browser/ui/app_list/app_list_model_builder.cc
@@ -6,9 +6,9 @@ #include <utility> +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" #include "chrome/browser/ui/app_list/app_list_syncable_service.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" AppListModelBuilder::AppListModelBuilder(AppListControllerDelegate* controller, const char* item_type)
diff --git a/chrome/browser/ui/app_list/app_list_model_builder.h b/chrome/browser/ui/app_list/app_list_model_builder.h index a2846f5f..513cf03 100644 --- a/chrome/browser/ui/app_list/app_list_model_builder.h +++ b/chrome/browser/ui/app_list/app_list_model_builder.h
@@ -7,10 +7,10 @@ #include <string> +#include "ash/app_list/model/app_list_item_list_observer.h" +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "chrome/browser/ui/app_list/app_list_syncable_service.h" -#include "ui/app_list/app_list_item_list_observer.h" -#include "ui/app_list/app_list_model.h" class AppListControllerDelegate; class Profile;
diff --git a/chrome/browser/ui/app_list/app_list_service_impl.cc b/chrome/browser/ui/app_list/app_list_service_impl.cc index fc4f094..b350a684 100644 --- a/chrome/browser/ui/app_list/app_list_service_impl.cc +++ b/chrome/browser/ui/app_list/app_list_service_impl.cc
@@ -9,6 +9,7 @@ #include <string> #include <utility> +#include "ash/app_list/model/app_list_model.h" #include "base/bind.h" #include "base/command_line.h" #include "base/location.h" @@ -27,7 +28,6 @@ #include "chrome/common/chrome_constants.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_switches.h" namespace {
diff --git a/chrome/browser/ui/app_list/app_list_service_impl_browsertest.cc b/chrome/browser/ui/app_list/app_list_service_impl_browsertest.cc index 16da1dd..10301e52 100644 --- a/chrome/browser/ui/app_list/app_list_service_impl_browsertest.cc +++ b/chrome/browser/ui/app_list/app_list_service_impl_browsertest.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/app_list/app_list_service_impl.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" @@ -16,8 +18,6 @@ #include "chrome/test/base/in_process_browser_test.h" #include "components/prefs/pref_service.h" #include "extensions/common/constants.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" #include "ui/base/models/menu_model.h" namespace test {
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.cc b/chrome/browser/ui/app_list/app_list_syncable_service.cc index 03ad643bb..fbfffc6 100644 --- a/chrome/browser/ui/app_list/app_list_syncable_service.cc +++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -7,6 +7,10 @@ #include <set> #include <utility> +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/app_list_model_observer.h" #include "base/command_line.h" #include "base/macros.h" #include "base/memory/ptr_util.h" @@ -41,10 +45,6 @@ #include "extensions/browser/uninstall_reason.h" #include "extensions/common/constants.h" #include "extensions/common/one_shot_event.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" -#include "ui/app_list/app_list_model_observer.h" #include "ui/app_list/app_list_switches.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc index 0c64aa3..61b85a1 100644 --- a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc +++ b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
@@ -3,6 +3,8 @@ // found in the LICENSE file. #include "chrome/browser/ui/app_list/app_list_syncable_service.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" #include "base/files/scoped_temp_dir.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile_manager.h" @@ -17,8 +19,6 @@ #include "components/sync/protocol/sync.pb.h" #include "extensions/browser/extension_system.h" #include "extensions/common/constants.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" using namespace crx_file::id_util;
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc index 2590802..ce844bd 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -8,6 +8,9 @@ #include <vector> +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/app_list_view_state.h" +#include "ash/app_list/model/search_box_model.h" #include "ash/public/interfaces/constants.mojom.h" #include "base/command_line.h" #include "base/metrics/histogram_macros.h" @@ -44,11 +47,8 @@ #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/launcher_page_info.h" #include "services/service_manager/public/cpp/connector.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/app_list_view_delegate_observer.h" -#include "ui/app_list/app_list_view_state.h" -#include "ui/app_list/search_box_model.h" #include "ui/app_list/search_controller.h" #include "ui/app_list/speech_ui_model.h" #include "ui/base/resource/resource_bundle.h"
diff --git a/chrome/browser/ui/app_list/arc/arc_app_item.h b/chrome/browser/ui/app_list/arc/arc_app_item.h index 94755694..a0dd7a4 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_item.h +++ b/chrome/browser/ui/app_list/arc/arc_app_item.h
@@ -7,11 +7,11 @@ #include <string> +#include "ash/app_list/model/app_list_item.h" #include "base/macros.h" #include "chrome/browser/ui/app_list/app_context_menu_delegate.h" #include "chrome/browser/ui/app_list/arc/arc_app_icon.h" #include "chrome/browser/ui/app_list/chrome_app_list_item.h" -#include "ui/app_list/app_list_item.h" class ArcAppContextMenu; class Profile;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc index 1ebe86d7..7848690 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "ash/app_list/model/app_list_model.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/macros.h" @@ -55,7 +56,6 @@ #include "extensions/common/manifest_constants.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/app_list/app_list_constants.h" -#include "ui/app_list/app_list_model.h" #include "ui/display/types/display_constants.h" #include "ui/events/event_constants.h" #include "ui/gfx/geometry/safe_integer_conversions.h"
diff --git a/chrome/browser/ui/app_list/chrome_app_list_item.h b/chrome/browser/ui/app_list/chrome_app_list_item.h index 14383d4..396eaca9 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_item.h +++ b/chrome/browser/ui/app_list/chrome_app_list_item.h
@@ -7,9 +7,9 @@ #include <string> +#include "ash/app_list/model/app_list_item.h" #include "base/macros.h" #include "chrome/browser/ui/app_list/app_list_syncable_service.h" -#include "ui/app_list/app_list_item.h" class AppListControllerDelegate; class Profile;
diff --git a/chrome/browser/ui/app_list/extension_app_model_builder_unittest.cc b/chrome/browser/ui/app_list/extension_app_model_builder_unittest.cc index 85c75aa..134212e2 100644 --- a/chrome/browser/ui/app_list/extension_app_model_builder_unittest.cc +++ b/chrome/browser/ui/app_list/extension_app_model_builder_unittest.cc
@@ -9,6 +9,7 @@ #include <memory> #include <string> +#include "ash/app_list/model/app_list_item.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/run_loop.h" @@ -33,7 +34,6 @@ #include "extensions/common/extension_set.h" #include "extensions/common/manifest.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/app_list/app_list_item.h" using extensions::AppSorting; using extensions::ExtensionSystem;
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_result.h b/chrome/browser/ui/app_list/search/answer_card/answer_card_result.h index 7b2803d..3ab8bcb 100644 --- a/chrome/browser/ui/app_list/search/answer_card/answer_card_result.h +++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_result.h
@@ -8,7 +8,7 @@ #include <memory> #include <string> -#include "ui/app_list/search_result.h" +#include "ash/app_list/model/search_result.h" class AppListControllerDelegate; class Profile;
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc index d5a222e9..ea58100 100644 --- a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc +++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "ash/app_list/model/app_list_model.h" #include "base/command_line.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" @@ -18,7 +19,6 @@ #include "components/omnibox/browser/autocomplete_match.h" #include "components/search_engines/template_url_service.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_model.h" namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc index 0b26014..e317807 100644 --- a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc
@@ -9,6 +9,8 @@ #include <string> #include <utility> +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_params.h" @@ -23,8 +25,6 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_model.h" -#include "ui/app_list/search_result.h" #include "ui/views/view.h" using ::testing::_;
diff --git a/chrome/browser/ui/app_list/search/app_result.h b/chrome/browser/ui/app_list/search/app_result.h index 98e1288..d69b630 100644 --- a/chrome/browser/ui/app_list/search/app_result.h +++ b/chrome/browser/ui/app_list/search/app_result.h
@@ -8,9 +8,9 @@ #include <memory> #include <string> +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "chrome/browser/ui/app_list/app_context_menu_delegate.h" -#include "ui/app_list/search_result.h" class AppListControllerDelegate; class Profile;
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.cc b/chrome/browser/ui/app_list/search/app_search_provider.cc index d246124..da2099f 100644 --- a/chrome/browser/ui/app_list/search/app_search_provider.cc +++ b/chrome/browser/ui/app_list/search/app_search_provider.cc
@@ -10,6 +10,10 @@ #include <string> #include <utility> +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/search/tokenized_string.h" +#include "ash/app_list/model/search/tokenized_string_match.h" #include "base/bind.h" #include "base/location.h" #include "base/macros.h" @@ -32,10 +36,6 @@ #include "extensions/browser/extension_system.h" #include "extensions/common/extension.h" #include "extensions/common/extension_set.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" -#include "ui/app_list/search/tokenized_string.h" -#include "ui/app_list/search/tokenized_string_match.h" using extensions::ExtensionRegistry;
diff --git a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc index deeb4683..8af9d8f 100644 --- a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
@@ -10,6 +10,10 @@ #include <string> #include <utility> +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" @@ -30,10 +34,6 @@ #include "extensions/common/extension_builder.h" #include "extensions/common/extension_set.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" -#include "ui/app_list/search_result.h" namespace app_list { namespace test {
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc index e2ec5a8..541d85b 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc
@@ -8,6 +8,7 @@ #include <string> #include <utility> +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/extensions/extension_service.h" @@ -18,7 +19,6 @@ #include "chrome/test/base/testing_profile.h" #include "extensions/common/extension_builder.h" #include "extensions/common/value_builder.h" -#include "ui/app_list/search_result.h" namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h index f3b5f4b9..1c1fe66 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h +++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h
@@ -9,10 +9,10 @@ #include <string> #include <vector> +#include "ash/app_list/model/search_result.h" #include "base/optional.h" #include "chrome/browser/ui/app_list/app_context_menu_delegate.h" #include "components/arc/common/app.mojom.h" -#include "ui/app_list/search_result.h" class AppListControllerDelegate; class ArcPlayStoreAppContextMenu;
diff --git a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.h b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.h index 96afc96..b68a6c50 100644 --- a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.h +++ b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.h
@@ -8,11 +8,11 @@ #include <memory> #include <string> +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader.h" #include "extensions/common/extension.h" -#include "ui/app_list/search_result.h" #include "url/gurl.h" namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/omnibox_provider.cc b/chrome/browser/ui/app_list/search/omnibox_provider.cc index cd789723..9dfb228e 100644 --- a/chrome/browser/ui/app_list/search/omnibox_provider.cc +++ b/chrome/browser/ui/app_list/search/omnibox_provider.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/app_list/search/omnibox_provider.h" +#include "ash/app_list/model/search_result.h" #include "base/memory/ptr_util.h" #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h" #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" @@ -15,7 +16,6 @@ #include "components/omnibox/browser/autocomplete_controller.h" #include "components/omnibox/browser/autocomplete_input.h" #include "third_party/metrics_proto/omnibox_event.pb.h" -#include "ui/app_list/search_result.h" #include "url/gurl.h" namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/omnibox_result.h b/chrome/browser/ui/app_list/search/omnibox_result.h index f55c8c9..75ab73f 100644 --- a/chrome/browser/ui/app_list/search/omnibox_result.h +++ b/chrome/browser/ui/app_list/search/omnibox_result.h
@@ -7,9 +7,9 @@ #include <memory> +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "components/omnibox/browser/autocomplete_match.h" -#include "ui/app_list/search_result.h" class AppListControllerDelegate; class AutocompleteController;
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc index 0b315b2..eb4814af 100644 --- a/chrome/browser/ui/app_list/search/search_controller_factory.cc +++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -6,6 +6,7 @@ #include <stddef.h> +#include "ash/app_list/model/app_list_model.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/metrics/field_trial.h" @@ -24,7 +25,6 @@ #include "chrome/common/chrome_switches.h" #include "components/arc/arc_util.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/search/mixer.h" #include "ui/app_list/search_controller.h"
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.h b/chrome/browser/ui/app_list/search/search_controller_factory.h index 5e103e90..56a2939d 100644 --- a/chrome/browser/ui/app_list/search/search_controller_factory.h +++ b/chrome/browser/ui/app_list/search/search_controller_factory.h
@@ -7,7 +7,7 @@ #include <memory> -#include "ui/app_list/app_list_model.h" +#include "ash/app_list/model/app_list_model.h" class AppListControllerDelegate; class Profile;
diff --git a/chrome/browser/ui/app_list/search/search_resource_manager.cc b/chrome/browser/ui/app_list/search/search_resource_manager.cc index 6b57a31..011b1708 100644 --- a/chrome/browser/ui/app_list/search/search_resource_manager.cc +++ b/chrome/browser/ui/app_list/search/search_resource_manager.cc
@@ -4,12 +4,12 @@ #include "chrome/browser/ui/app_list/search/search_resource_manager.h" +#include "ash/app_list/model/search_box_model.h" #include "base/memory/ptr_util.h" #include "chrome/browser/ui/app_list/start_page_service.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/search_box_model.h" #include "ui/app_list/speech_ui_model.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h"
diff --git a/chrome/browser/ui/app_list/search/search_webstore_result.h b/chrome/browser/ui/app_list/search/search_webstore_result.h index f382c1a..26c53c3 100644 --- a/chrome/browser/ui/app_list/search/search_webstore_result.h +++ b/chrome/browser/ui/app_list/search/search_webstore_result.h
@@ -7,8 +7,8 @@ #include <string> +#include "ash/app_list/model/search_result.h" #include "base/macros.h" -#include "ui/app_list/search_result.h" #include "url/gurl.h" class AppListControllerDelegate;
diff --git a/chrome/browser/ui/app_list/search/suggestions/suggestions_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/suggestions/suggestions_search_provider_unittest.cc index bea13e27b..094944a0 100644 --- a/chrome/browser/ui/app_list/search/suggestions/suggestions_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/suggestions/suggestions_search_provider_unittest.cc
@@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/sync/profile_sync_test_util.h" @@ -20,7 +21,6 @@ #include "components/suggestions/suggestions_store.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/app_list/search_result.h" using suggestions::ChromeSuggestion; using suggestions::SuggestionsProfile;
diff --git a/chrome/browser/ui/app_list/search/suggestions/url_suggestion_result.h b/chrome/browser/ui/app_list/search/suggestions/url_suggestion_result.h index d5854c79..8e8afdf 100644 --- a/chrome/browser/ui/app_list/search/suggestions/url_suggestion_result.h +++ b/chrome/browser/ui/app_list/search/suggestions/url_suggestion_result.h
@@ -7,10 +7,10 @@ #include <memory> +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "base/task/cancelable_task_tracker.h" #include "components/suggestions/proto/suggestions.pb.h" -#include "ui/app_list/search_result.h" class AppListControllerDelegate; class GURL;
diff --git a/chrome/browser/ui/app_list/search/webstore/webstore_provider.cc b/chrome/browser/ui/app_list/search/webstore/webstore_provider.cc index 060a64d..a25a23d1 100644 --- a/chrome/browser/ui/app_list/search/webstore/webstore_provider.cc +++ b/chrome/browser/ui/app_list/search/webstore/webstore_provider.cc
@@ -7,6 +7,8 @@ #include <string> #include <utility> +#include "ash/app_list/model/search/tokenized_string.h" +#include "ash/app_list/model/search/tokenized_string_match.h" #include "base/bind.h" #include "base/callback.h" #include "base/strings/string_util.h" @@ -20,8 +22,6 @@ #include "chrome/browser/ui/app_list/search/search_webstore_result.h" #include "chrome/browser/ui/app_list/search/webstore/webstore_result.h" #include "extensions/common/extension_urls.h" -#include "ui/app_list/search/tokenized_string.h" -#include "ui/app_list/search/tokenized_string_match.h" #include "url/gurl.h" namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/webstore/webstore_provider_browsertest.cc b/chrome/browser/ui/app_list/search/webstore/webstore_provider_browsertest.cc index 6a00d66..1ced97a54 100644 --- a/chrome/browser/ui/app_list/search/webstore/webstore_provider_browsertest.cc +++ b/chrome/browser/ui/app_list/search/webstore/webstore_provider_browsertest.cc
@@ -11,6 +11,7 @@ #include <string> #include <utility> +#include "ash/app_list/model/search_result.h" #include "base/bind.h" #include "base/command_line.h" #include "base/macros.h" @@ -28,7 +29,6 @@ #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" #include "ui/app_list/app_list_switches.h" -#include "ui/app_list/search_result.h" using content::BrowserThread; using extensions::Manifest;
diff --git a/chrome/browser/ui/app_list/search/webstore/webstore_result.h b/chrome/browser/ui/app_list/search/webstore/webstore_result.h index b7bd296e..12582ee 100644 --- a/chrome/browser/ui/app_list/search/webstore/webstore_result.h +++ b/chrome/browser/ui/app_list/search/webstore/webstore_result.h
@@ -7,13 +7,13 @@ #include <string> +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/extensions/install_observer.h" #include "chrome/common/extensions/webstore_install_result.h" #include "extensions/browser/extension_registry_observer.h" #include "extensions/common/manifest.h" -#include "ui/app_list/search_result.h" #include "url/gurl.h" class AppListControllerDelegate;
diff --git a/chrome/browser/ui/ash/app_list/app_list_service_ash.h b/chrome/browser/ui/ash/app_list/app_list_service_ash.h index e237ae24..8248c4de 100644 --- a/chrome/browser/ui/ash/app_list/app_list_service_ash.h +++ b/chrome/browser/ui/ash/app_list/app_list_service_ash.h
@@ -7,9 +7,9 @@ #include <memory> +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "chrome/browser/ui/app_list/app_list_service_impl.h" -#include "ui/app_list/app_list_model.h" class AppListPresenterService;
diff --git a/chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.cc b/chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.cc index 3b766a2..bdf16872 100644 --- a/chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.cc +++ b/chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.cc
@@ -4,8 +4,8 @@ #include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h" +#include "ash/app_list/model/app_list_model.h" #include "chrome/browser/ui/ash/app_sync_ui_state.h" -#include "ui/app_list/app_list_model.h" AppSyncUIStateWatcher::AppSyncUIStateWatcher(Profile* profile, app_list::AppListModel* model)
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc index 7be0099..9af1690c 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -1202,7 +1202,9 @@ EXPECT_EQ(0u, NumberOfDetectedLauncherBrowsers(false)); EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount()); - LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, + // Use a different app here because LoadAndLaunchExtension() will unload + // the previous extension and close all its windows. + LoadAndLaunchExtension("app2", extensions::LAUNCH_CONTAINER_TAB, WindowOpenDisposition::NEW_WINDOW); // A new browser should get detected and one more should be running.
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index a6b21d4..97cc1bb 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -1470,10 +1470,11 @@ WindowOpenDisposition::NEW_WINDOW, extensions::SOURCE_TEST)); ASSERT_TRUE(app_window); - // Apps launched in a window from the NTP have an extensions tab helper but - // do not have extension_app set in it. + // Apps launched in a window from the NTP have an extensions tab helper and + // an extension_app set in it. ASSERT_TRUE(extensions::TabHelper::FromWebContents(app_window)); - EXPECT_FALSE( + EXPECT_EQ( + extension_app, extensions::TabHelper::FromWebContents(app_window)->extension_app()); EXPECT_EQ(extensions::AppLaunchInfo::GetFullLaunchURL(extension_app), app_window->GetURL());
diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc index 90f4ea0c..7beb5f4 100644 --- a/chrome/browser/ui/browser_ui_prefs.cc +++ b/chrome/browser/ui/browser_ui_prefs.cc
@@ -61,8 +61,7 @@ registry->RegisterBooleanPref(prefs::kWebAppCreateInAppsMenu, true); registry->RegisterBooleanPref(prefs::kWebAppCreateInQuickLaunchBar, true); registry->RegisterBooleanPref( - prefs::kEnableTranslate, - true, + prefs::kOfferTranslateEnabled, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterStringPref(prefs::kCloudPrintEmail, std::string()); registry->RegisterBooleanPref(prefs::kCloudPrintProxyEnabled, true);
diff --git a/chrome/browser/ui/cocoa/applescript/apple_event_util.mm b/chrome/browser/ui/cocoa/applescript/apple_event_util.mm index a82a74b0..bce3d2d 100644 --- a/chrome/browser/ui/cocoa/applescript/apple_event_util.mm +++ b/chrome/browser/ui/cocoa/applescript/apple_event_util.mm
@@ -21,7 +21,7 @@ NSAppleEventDescriptor* ValueToAppleEventDescriptor(const base::Value* value) { NSAppleEventDescriptor* descriptor = nil; - switch (value->GetType()) { + switch (value->type()) { case base::Value::Type::NONE: descriptor = [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h index dab5832..79c4d50 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h
@@ -79,7 +79,7 @@ void SetFocus() override; void ApplyCaretVisibility() override; void OnTemporaryTextMaybeChanged(const base::string16& display_text, - AutocompleteMatch::Type match_type, + const AutocompleteMatch& match, bool save_original_selection, bool notify_text_changed) override; bool OnInlineAutocompleteTextMaybeChanged(const base::string16& display_text,
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm index 7866c20a..fab2ce1 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
@@ -598,7 +598,7 @@ void OmniboxViewMac::OnTemporaryTextMaybeChanged( const base::string16& display_text, - AutocompleteMatch::Type match_type, + const AutocompleteMatch& match, bool save_original_selection, bool notify_text_changed) { if (save_original_selection) @@ -610,7 +610,8 @@ [field_ clearUndoChain]; AnnounceAutocompleteForScreenReader( - AutocompleteMatchType::ToAccessibilityLabel(match_type, display_text)); + AutocompleteMatchType::ToAccessibilityLabel(match.type, display_text, + match.description)); } bool OmniboxViewMac::OnInlineAutocompleteTextMaybeChanged( @@ -1082,13 +1083,11 @@ void OmniboxViewMac::AnnounceAutocompleteForScreenReader( const base::string16& display_text) { - NSString* announcement = - l10n_util::GetNSStringF(IDS_ANNOUNCEMENT_COMPLETION_AVAILABLE_MAC, - display_text); NSDictionary* notification_info = @{ - NSAccessibilityAnnouncementKey : announcement, - NSAccessibilityPriorityKey : @(NSAccessibilityPriorityHigh) + NSAccessibilityAnnouncementKey : base::SysUTF16ToNSString(display_text), + NSAccessibilityPriorityKey : @(NSAccessibilityPriorityHigh) }; + // We direct the screen reader to announce the friendly text. NSAccessibilityPostNotificationWithUserInfo( [field_ window], NSAccessibilityAnnouncementRequestedNotification,
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_controller.mm index a5998f9..2c349344 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_controller.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
@@ -133,7 +133,23 @@ - (id)init { if ((self = [super init])) { - // Create the TabView. + BOOL isRTL = cocoa_l10n_util::ShouldDoExperimentalRTLLayout(); + + // Create the close button. + const CGFloat closeButtonXOrigin = + isRTL ? kTabTrailingPadding + : kInitialTabWidth - kCloseButtonSize - kTabTrailingPadding; + NSRect closeButtonFrame = NSMakeRect(closeButtonXOrigin, kTabElementYOrigin, + kCloseButtonSize, kCloseButtonSize); + closeButton_.reset( + [[HoverCloseButton alloc] initWithFrame:closeButtonFrame]); + [closeButton_ + setAutoresizingMask:isRTL ? NSViewMaxXMargin : NSViewMinXMargin]; + [closeButton_ setTarget:self]; + [closeButton_ setAction:@selector(closeTab:)]; + + // Create the TabView. The TabView works directly with the closeButton so + // here (the TabView handles adding it as a subview). base::scoped_nsobject<TabView> tabView([[TabView alloc] initWithFrame:NSMakeRect(0, 0, kInitialTabWidth, [TabController defaultTabHeight]) @@ -144,8 +160,6 @@ [tabView setPostsBoundsChangedNotifications:NO]; [super setView:tabView]; - BOOL isRTL = cocoa_l10n_util::ShouldDoExperimentalRTLLayout(); - // Add the favicon view. NSRect iconViewFrame = NSMakeRect(0, kTabElementYOrigin, gfx::kFaviconSize, gfx::kFaviconSize); @@ -154,6 +168,7 @@ : NSViewMaxXMargin | NSViewMinYMargin]; [self updateIconViewFrameWithAnimation:NO]; [tabView addSubview:iconView_]; + isIconShowing_ = YES; // Set up the title. const CGFloat titleXOrigin = @@ -164,22 +179,6 @@ kInitialTitleWidth, kTitleHeight); [tabView setTitleFrame:titleFrame]; - // Add the close button. - const CGFloat closeButtonXOrigin = - isRTL ? kTabTrailingPadding - : kInitialTabWidth - kCloseButtonSize - kTabTrailingPadding; - NSRect closeButtonFrame = NSMakeRect(closeButtonXOrigin, kTabElementYOrigin, - kCloseButtonSize, kCloseButtonSize); - closeButton_.reset([[HoverCloseButton alloc] initWithFrame: - closeButtonFrame]); - [closeButton_ - setAutoresizingMask:isRTL ? NSViewMaxXMargin : NSViewMinXMargin]; - [closeButton_ setTarget:self]; - [closeButton_ setAction:@selector(closeTab:)]; - - [tabView addSubview:closeButton_]; - - isIconShowing_ = YES; NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; [defaultCenter addObserver:self selector:@selector(themeChangedNotification:)
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view.mm b/chrome/browser/ui/cocoa/tabs/tab_view.mm index f801da8..929513a4 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_view.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_view.mm
@@ -88,11 +88,6 @@ + (void)setTabEdgeStrokeColor; @end -@interface TabController(Private) -// The TabView's close button. -- (HoverCloseButton*)closeButton; -@end - extern NSString* const _Nonnull NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification; namespace { @@ -223,6 +218,7 @@ if (self) { controller_ = controller; closeButton_ = closeButton; + [self addSubview:closeButton_]; // Make a text field for the title, but don't add it as a subview. // We will use the cell to draw the text directly into our layer, @@ -719,9 +715,9 @@ AlertIndicatorButton* const indicator = [controller_ alertIndicatorButton]; const int indicatorLeft = (!indicator || [indicator isHidden]) ? NSWidth([self frame]) : NSMinX([indicator frame]); - HoverCloseButton* const closeButton = [controller_ closeButton]; - const int closeButtonLeft = (!closeButton || [closeButton isHidden]) ? - NSWidth([self frame]) : NSMinX([closeButton frame]); + const int closeButtonLeft = (!closeButton_ || [closeButton_ isHidden]) + ? NSWidth([self frame]) + : NSMinX([closeButton_ frame]); return std::min(indicatorLeft, closeButtonLeft); }
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm index d7b4ea44..f20e38d 100644 --- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
@@ -112,6 +112,7 @@ extensions::ExtensionSystem::Get(profile()) ->extension_service() ->AddExtension(extension.get()); + ExtensionErrorReporter::Init(true); ToolbarActionsModel* model = extensions::extension_action_test_util::CreateToolbarModelForProfile( profile());
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc index b258492a..d768daef 100644 --- a/chrome/browser/ui/extensions/application_launch.cc +++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -224,8 +224,12 @@ (extension ? ui::PAGE_TRANSITION_AUTO_BOOKMARK : ui::PAGE_TRANSITION_AUTO_TOPLEVEL); - WebContents* web_contents = - chrome::AddSelectedTabWithURL(browser, url, transition); + chrome::NavigateParams nav_params(browser, url, transition); + nav_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; + nav_params.extension_app_id = params.extension_id; + chrome::Navigate(&nav_params); + + WebContents* web_contents = nav_params.target_contents; web_contents->GetMutableRendererPrefs()->can_accept_load_drops = false; web_contents->GetRenderViewHost()->SyncRendererPrefs();
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc b/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc index d69b19d..71bc4df 100644 --- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc +++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc
@@ -56,6 +56,7 @@ BROWSER_SWITCHED = 5, DIALOG_BUTTON_CLICKED = 6, TAB_NAVIGATED = 7, + TAB_SWITCHED_OUT = 8, MAX, }; @@ -283,6 +284,21 @@ HandleTabSwitchAway(DismissalCause::BROWSER_SWITCHED); } } + +void JavaScriptDialogTabHelper::TabReplacedAt( + TabStripModel* tab_strip_model, + content::WebContents* old_contents, + content::WebContents* new_contents, + int index) { + if (old_contents == WebContentsObserver::web_contents()) { + // At this point, this WebContents is no longer in the tabstrip. The usual + // teardown will not be able to turn off the attention indicator, so that + // must be done here. + SetTabNeedsAttentionImpl(false, tab_strip_model, index); + + CloseDialog(DismissalCause::TAB_SWITCHED_OUT, false, base::string16()); + } +} #endif void JavaScriptDialogTabHelper::LogDialogDismissalCause( @@ -347,8 +363,10 @@ std::move(dialog_callback_).Run(success, user_input); // If there's a pending dialog, then the tab is still in the "needs attention" - // state; clear it out. - if (pending_dialog_) + // state; clear it out. However, if the tab was switched out, the turning off + // of the "needs attention" state was done in TabReplacedAt() because + // SetTabNeedsAttention won't work, so don't call it. + if (pending_dialog_ && cause != DismissalCause::TAB_SWITCHED_OUT) SetTabNeedsAttention(false); dialog_.reset(); @@ -364,9 +382,23 @@ #if !defined(OS_ANDROID) content::WebContents* web_contents = WebContentsObserver::web_contents(); Browser* browser = chrome::FindBrowserWithWebContents(web_contents); - DCHECK(browser); - browser->tab_strip_model()->SetTabNeedsAttentionAt( - browser->tab_strip_model()->GetIndexOfWebContents(web_contents), - attention); + TabStripModel* tab_strip_model = browser->tab_strip_model(); + + SetTabNeedsAttentionImpl( + attention, tab_strip_model, + tab_strip_model->GetIndexOfWebContents(web_contents)); #endif } + +#if !defined(OS_ANDROID) +void JavaScriptDialogTabHelper::SetTabNeedsAttentionImpl( + bool attention, + TabStripModel* tab_strip_model, + int index) { + tab_strip_model->SetTabNeedsAttentionAt(index, attention); + if (attention) + tab_strip_model->AddObserver(this); + else + tab_strip_model->RemoveObserver(this); +} +#endif
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h b/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h index 933afa51..d0044e1 100644 --- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h +++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h
@@ -18,6 +18,7 @@ #if !defined(OS_ANDROID) #include "chrome/browser/ui/browser_list_observer.h" +#include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #endif // A class, attached to WebContentses in browser windows, that is the @@ -43,6 +44,7 @@ public content::WebContentsObserver, #if !defined(OS_ANDROID) public chrome::BrowserListObserver, + public TabStripModelObserver, #endif public content::WebContentsUserData<JavaScriptDialogTabHelper> { public: @@ -81,6 +83,12 @@ #if !defined(OS_ANDROID) // BrowserListObserver: void OnBrowserSetLastActive(Browser* browser) override; + + // TabStripModelObserver: + void TabReplacedAt(TabStripModel* tab_strip_model, + content::WebContents* old_contents, + content::WebContents* new_contents, + int index) override; #endif private: @@ -99,9 +107,17 @@ bool success, const base::string16& user_input); - // Marks the tab as needing attention. + // Marks the tab as needing attention. The WebContents must be in a browser + // window. void SetTabNeedsAttention(bool attention); +#if !defined(OS_ANDROID) + // Marks the tab as needing attention. + void SetTabNeedsAttentionImpl(bool attention, + TabStripModel* tab_strip_model, + int index); +#endif + // There can be at most one dialog (pending or not) being shown at any given // time on a tab. Depending on the type of the dialog, the variables // |dialog_|, |pending_dialog_|, and |dialog_callback_| can be present in
diff --git a/chrome/browser/ui/search/local_ntp_browsertest.cc b/chrome/browser/ui/search/local_ntp_browsertest.cc index 300cc94b..e99f5a5 100644 --- a/chrome/browser/ui/search/local_ntp_browsertest.cc +++ b/chrome/browser/ui/search/local_ntp_browsertest.cc
@@ -11,6 +11,7 @@ #include "base/i18n/base_i18n_switches.h" #include "base/json/string_escape.h" #include "base/memory/ptr_util.h" +#include "base/metrics/statistics_recorder.h" #include "base/optional.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -58,6 +59,7 @@ #include "media/base/media_switches.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gmock/include/gmock/gmock.h" +#include "third_party/WebKit/public/platform/web_feature.mojom.h" #include "ui/base/resource/resource_bundle.h" using search_provider_logos::EncodedLogo; @@ -427,6 +429,56 @@ EXPECT_TRUE(console_observer.message().empty()) << console_observer.message(); } +// Tests that blink::UseCounter do not track feature usage for NTP activities. +IN_PROC_BROWSER_TEST_F(LocalNTPTest, ShouldNotTrackBlinkUseCounterForNTP) { + base::HistogramTester histogram_tester; + const char kFeaturesHistogramName[] = "Blink.UseCounter.Features"; + + // Set up a test server, so we have some arbitrary non-NTP URL to navigate to. + net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); + test_server.ServeFilesFromSourceDirectory("chrome/test/data"); + ASSERT_TRUE(test_server.Start()); + const GURL other_url = test_server.GetURL("/simple.html"); + + // Open an NTP. + content::WebContents* active_tab = + OpenNewTab(browser(), GURL(chrome::kChromeUINewTabURL)); + ASSERT_TRUE(search::IsInstantNTP(active_tab)); + // Expect no PageVisits count. + EXPECT_EQ(nullptr, + base::StatisticsRecorder::FindHistogram(kFeaturesHistogramName)); + // Navigate somewhere else in the same tab. + ui_test_utils::NavigateToURLWithDisposition( + browser(), other_url, WindowOpenDisposition::CURRENT_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + ASSERT_FALSE(search::IsInstantNTP(active_tab)); + // Navigate back to NTP. + content::TestNavigationObserver back_observer(active_tab); + chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB); + back_observer.Wait(); + ASSERT_TRUE(search::IsInstantNTP(active_tab)); + // There should be exactly 1 count of PageVisits. + histogram_tester.ExpectBucketCount( + kFeaturesHistogramName, + static_cast<int32_t>(blink::mojom::WebFeature::kPageVisits), 1); + + // Navigate forward to the non-NTP page. + content::TestNavigationObserver fwd_observer(active_tab); + chrome::GoForward(browser(), WindowOpenDisposition::CURRENT_TAB); + fwd_observer.Wait(); + ASSERT_FALSE(search::IsInstantNTP(active_tab)); + // Navigate to a new NTP instance. + ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL(chrome::kChromeUINewTabURL), + WindowOpenDisposition::CURRENT_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + ASSERT_TRUE(search::IsInstantNTP(active_tab)); + // There should be 2 counts of PageVisits. + histogram_tester.ExpectBucketCount( + kFeaturesHistogramName, + static_cast<int32_t>(blink::mojom::WebFeature::kPageVisits), 2); +} + class LocalNTPRTLTest : public LocalNTPTest { public: LocalNTPRTLTest() {}
diff --git a/chrome/browser/ui/startup/bad_flags_prompt.cc b/chrome/browser/ui/startup/bad_flags_prompt.cc index 7c136847..44906af 100644 --- a/chrome/browser/ui/startup/bad_flags_prompt.cc +++ b/chrome/browser/ui/startup/bad_flags_prompt.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/switch_utils.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/autofill/core/common/autofill_switches.h"
diff --git a/chrome/browser/ui/tabs/tab_data_experimental.cc b/chrome/browser/ui/tabs/tab_data_experimental.cc index 09eb207..6c43d3ef 100644 --- a/chrome/browser/ui/tabs/tab_data_experimental.cc +++ b/chrome/browser/ui/tabs/tab_data_experimental.cc
@@ -58,10 +58,11 @@ TabDataExperimental& TabDataExperimental::operator=(TabDataExperimental&&) = default; -const base::string16& TabDataExperimental::GetTitle() const { - DCHECK(type() == Type::kSingle); +base::string16 TabDataExperimental::GetTitle() const { // TODO(brettw) this will need to use TabUIHelper. - return contents_->GetTitle(); + if (contents_) + return contents_->GetTitle(); + return base::string16(); } bool TabDataExperimental::CountsAsViewIndex() const {
diff --git a/chrome/browser/ui/tabs/tab_data_experimental.h b/chrome/browser/ui/tabs/tab_data_experimental.h index 5d1bc87..b270cd9d 100644 --- a/chrome/browser/ui/tabs/tab_data_experimental.h +++ b/chrome/browser/ui/tabs/tab_data_experimental.h
@@ -49,12 +49,13 @@ TabDataExperimental* parent() { return parent_; } Type type() const { return type_; } + void set_type(Type t) { type_ = t; } + bool expanded() const { return expanded_; } content::WebContents* contents() { return contents_; } - // Valid when type() == kSingle or kHubAndSpoke. - const base::string16& GetTitle() const; + base::string16 GetTitle() const; // Returns true if this tab data itself is counted as a enumerable item when // going through the view.
diff --git a/chrome/browser/ui/tabs/tab_strip_model_experimental.cc b/chrome/browser/ui/tabs/tab_strip_model_experimental.cc index fa4ba440..238ccc0 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_experimental.cc +++ b/chrome/browser/ui/tabs/tab_strip_model_experimental.cc
@@ -379,12 +379,30 @@ delegate_->WillAddWebContents(contents); bool active = (add_types & ADD_ACTIVE) != 0; + TabDataExperimental* data = nullptr; - // Always insert tabs at the end for now (so parent is always null). - TabDataExperimental* parent = nullptr; - tabs_.emplace_back(std::make_unique<TabDataExperimental>( - parent, TabDataExperimental::Type::kSingle, contents, this)); - const TabDataExperimental* data = tabs_.back().get(); + if ((add_types & ADD_INHERIT_GROUP) && active_index() >= 0 && + active_index() < count()) { + // Add as a child following opener. + TabDataExperimental* parent = GetDataForViewIndex(active_index()); + if (parent->type() == TabDataExperimental::Type::kSingle) { + // Promote parent to hub-and-spoke. + parent->set_type(TabDataExperimental::Type::kHubAndSpoke); + for (auto& observer : exp_observers_) + observer.TabChanged(parent); + } + + parent->children_.push_back(std::make_unique<TabDataExperimental>( + parent, TabDataExperimental::Type::kSingle, contents, this)); + data = parent->children_.back().get(); + + } else { + // Add at toplevel. + tabs_.push_back(std::make_unique<TabDataExperimental>( + nullptr, TabDataExperimental::Type::kSingle, contents, this)); + data = tabs_.back().get(); + } + UpdateViewCount(); index = tab_view_count_ - 1; @@ -407,7 +425,6 @@ uint32_t close_types) { ViewIterator found = FindViewIndex(view_index); DCHECK(found != end()); - DCHECK(found->type() == TabDataExperimental::Type::kSingle); content::WebContents* closing = found->contents_; if (closing) InternalCloseTabs(base::span<content::WebContents*>(&closing, 1)); @@ -527,8 +544,21 @@ return &*found; } +int TabStripModelExperimental::GetViewIndexForData( + const TabDataExperimental* data) const { + int view_index = 0; + for (const auto& cur : *this) { + if (&cur == data) + return view_index; + ++view_index; + } + return kNoTab; +} + void TabStripModelExperimental::ActivateTabAt(int index, bool user_gesture) { - DCHECK(ContainsIndex(index)); + if (!ContainsIndex(index)) + return; + ui::ListSelectionModel new_model = selection_model_; new_model.SetSelectedIndex(index); SetSelection(std::move(new_model), @@ -649,7 +679,6 @@ } bool TabStripModelExperimental::IsTabBlocked(int index) const { - NOTIMPLEMENTED(); return false; } @@ -689,6 +718,10 @@ int index, ui::PageTransition transition, int add_types) { + // Force group inheritance for link click transitions. + if (ui::PageTransitionTypeIncludingQualifiersIs(transition, + ui::PAGE_TRANSITION_LINK)) + add_types |= ADD_INHERIT_GROUP; InsertWebContentsAt(index, contents, add_types); } @@ -769,6 +802,7 @@ NOTREACHED(); // WebContents not found in this model. return; } + TabDataExperimental* data = &*found; bool was_selected; if (view_index == kNoTab) @@ -777,12 +811,31 @@ was_selected = IsTabSelected(view_index); int next_selected_index = view_index; - if (found->parent_) { - // Erase in parent. - found->parent_->children_.erase(found->parent_->children_.begin() + - found.inner_index_); + if (data->parent_) { + TabDataExperimental* parent = data->parent_; + // Erase out of the parent. + parent->children_.erase(parent->children_.begin() + found.inner_index_); - // TODO(brettw) remove the parent if it's empty! + if (parent->children_.empty()) { + if (parent->type() == TabDataExperimental::Type::kHubAndSpoke) { + // Erasing the last child of a hub and spoke one converts it back to + // a single. + parent->set_type(TabDataExperimental::Type::kSingle); + for (auto& observer : exp_observers_) + observer.TabChanged(parent); + } else { + DCHECK(parent->type() == TabDataExperimental::Type::kGroup); + // TODO(brettw) remove group. Notifications might be tricky. + } + } + } else if (data->type() == TabDataExperimental::Type::kHubAndSpoke) { + // Removing the "hub" from a hub and spoke converts to a group. + + data->set_type(TabDataExperimental::Type::kGroup); + data->contents_ = + nullptr; // TODO(brettw) does this delete things properly? + for (auto& observer : exp_observers_) + observer.TabChanged(data); } else { // Just remove from tabs. tabs_.erase(tabs_.begin() + found.toplevel_index_);
diff --git a/chrome/browser/ui/tabs/tab_strip_model_experimental.h b/chrome/browser/ui/tabs/tab_strip_model_experimental.h index 4c50358..d931cf8 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_experimental.h +++ b/chrome/browser/ui/tabs/tab_strip_model_experimental.h
@@ -196,6 +196,9 @@ const TabDataExperimental* GetDataForViewIndex(int view_index) const; TabDataExperimental* GetDataForViewIndex(int view_index); + // Returns kNoTab if there isn't a view index for this data. + int GetViewIndexForData(const TabDataExperimental* data) const; + void AddExperimentalObserver(TabStripModelExperimentalObserver* observer); void RemoveExperimentalObserver(TabStripModelExperimentalObserver* observer);
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 3dde11b..e9eeb46 100644 --- a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc +++ b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
@@ -38,6 +38,7 @@ void SetUp() override { BrowserWithTestWindowTest::SetUp(); + ExtensionErrorReporter::Init(true); toolbar_actions_model_ = extensions::extension_action_test_util::CreateToolbarModelForProfile(
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc index 2b6b47a..cd18f168 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
@@ -613,6 +613,17 @@ ResizeDelegate(gfx::Tween::LINEAR); } +void ToolbarActionsBar::OnToolbarActionLoadFailed() { + // When an extension is re-uploaded, it is first unloaded from Chrome. At this + // point, the extension's icon is initially removed from the toolbar, leaving + // an empty slot in the toolbar. Then the (newer version of the) extension is + // loaded, and its icon populates the empty slot. + // + // If the extension failed to load, then the empty slot should be removed and + // hence we resize the toolbar. + ResizeDelegate(gfx::Tween::EASE_OUT); +} + void ToolbarActionsBar::OnToolbarActionRemoved(const std::string& action_id) { ToolbarActions::iterator iter = toolbar_actions_.begin(); while (iter != toolbar_actions_.end() && (*iter)->GetId() != action_id)
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.h b/chrome/browser/ui/toolbar/toolbar_actions_bar.h index 6a7f37f..d6f581e 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar.h +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.h
@@ -259,6 +259,7 @@ int index) override; void OnToolbarActionRemoved(const std::string& action_id) override; void OnToolbarActionMoved(const std::string& action_id, int index) override; + void OnToolbarActionLoadFailed() override; void OnToolbarActionUpdated(const std::string& action_id) override; void OnToolbarVisibleCountChanged() override; void OnToolbarHighlightModeChanged(bool is_highlighting) override;
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc index 17948a3..ce3e9fc 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc
@@ -5,15 +5,18 @@ #include "chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.h" #include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/extensions/api/extension_action/extension_action_api.h" #include "chrome/browser/extensions/extension_action.h" #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/test_extension_dir.h" #include "chrome/browser/extensions/test_extension_system.h" +#include "chrome/browser/extensions/unpacked_installer.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -23,8 +26,11 @@ #include "chrome/common/pref_names.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" +#include "content/public/test/test_utils.h" #include "extensions/browser/extension_prefs.h" +#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" +#include "extensions/browser/test_extension_registry_observer.h" #include "extensions/common/extension.h" #include "ui/base/test/material_design_controller_test_api.h" @@ -32,6 +38,21 @@ using ActionType = extensions::ExtensionBuilder::ActionType; +const extensions::Extension* GetExtensionByPath( + const extensions::ExtensionSet& extensions, + const base::FilePath& path) { + base::ScopedAllowBlockingForTesting allow_blocking; + base::FilePath extension_path = base::MakeAbsoluteFilePath(path); + EXPECT_TRUE(!extension_path.empty()); + for (const scoped_refptr<const extensions::Extension>& extension : + extensions) { + if (extension->path() == extension_path) { + return extension.get(); + } + } + return nullptr; +} + // Verifies that the toolbar order matches for the given |actions_bar|. If the // order matches, the return value is empty; otherwise, it contains the error. std::string VerifyToolbarOrderForBar( @@ -87,6 +108,35 @@ return error; } +// The ToolbarActionErrorTestObserver is used to notify when an extension +// failed to load. +class ToolbarActionErrorTestObserver : public ExtensionErrorReporter::Observer { + public: + ToolbarActionErrorTestObserver() : extension_error_reporter_observer_(this) { + extension_error_reporter_observer_.Add( + ExtensionErrorReporter::GetInstance()); + } + + ~ToolbarActionErrorTestObserver() override {} + + void WaitForOnLoadFailure() { run_loop_.Run(); } + + private: + // ExtensionErrorReporter::Observer: + void OnLoadFailure(content::BrowserContext* browser_context, + const base::FilePath& extension_path, + const std::string& error) override { + run_loop_.Quit(); + } + + base::RunLoop run_loop_; + + ScopedObserver<ExtensionErrorReporter, ExtensionErrorReporter::Observer> + extension_error_reporter_observer_; + + DISALLOW_COPY_AND_ASSIGN(ToolbarActionErrorTestObserver); +}; + } // namespace ToolbarActionsBarUnitTest::ToolbarActionsBarUnitTest() @@ -96,6 +146,7 @@ void ToolbarActionsBarUnitTest::SetUp() { BrowserWithTestWindowTest::SetUp(); + ExtensionErrorReporter::Init(true); // The toolbar typically displays extension icons, so create some extension // test infrastructure. @@ -564,3 +615,75 @@ EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount()); EXPECT_TRUE(toolbar_actions_bar()->NeedsOverflow()); } + +// Tests that both the extension icon and its allocated slot in the toolbar are +// removed when an extension is reloaded with manifest errors and therefore +// fails to be loaded into Chrome, +// +// TODO(catmullings): Convert this from TEST_P to TEST_F since there is no test +// parameter dependence. +TEST_P(ToolbarActionsBarUnitTest, ReuploadExtensionFailed) { + ExtensionService* service = + extensions::ExtensionSystem::Get(profile())->extension_service(); + extensions::ExtensionRegistry* registry = + extensions::ExtensionRegistry::Get(profile()); + + extensions::TestExtensionDir ext_dir; + const char kManifest[] = + "{" + " 'name': 'Test'," + " 'version': '1'," + " 'manifest_version': 2" + "}"; + ext_dir.WriteManifestWithSingleQuotes(kManifest); + + scoped_refptr<extensions::UnpackedInstaller> installer = + extensions::UnpackedInstaller::Create(service); + installer->Load(ext_dir.UnpackedPath()); + content::RunAllTasksUntilIdle(); + + EXPECT_EQ(1u, registry->enabled_extensions().size()); + EXPECT_EQ(0u, registry->disabled_extensions().size()); + + const extensions::Extension* extension = GetExtensionByPath( + registry->enabled_extensions(), ext_dir.UnpackedPath()); + ASSERT_TRUE(extension); + + // Ensure that the toolbar has the 1 icon for the extension loaded. + int width = toolbar_actions_bar()->GetFullSize().width(); + EXPECT_EQ(width, toolbar_actions_bar()->GetFullSize().width()); + EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount()); + + // Reload the extension again. + extensions::TestExtensionRegistryObserver registry_observer(registry); + service->ReloadExtension(extension->id()); + ASSERT_TRUE(registry_observer.WaitForExtensionLoaded()); + + // Ensure that after reload, the toolbar still contains the 1 icon for the + // extension. + EXPECT_EQ(width, toolbar_actions_bar()->GetFullSize().width()); + EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount()); + + // Replace the extension's valid manifest with one containing errors. In this + // case, the error is that both the 'browser_action' and 'page_action' keys + // are specified instead of only one. + const char kManifestWithErrors[] = + "{" + " 'name': 'Test'," + " 'version': '1'," + " 'manifest_version': 2," + " 'page_action' : {}," + " 'browser_action' : {}" + "}"; + ext_dir.WriteManifestWithSingleQuotes(kManifestWithErrors); + + // Reload the extension again. Check that the updated extension cannot be + // loaded due to the manifest errors. + service->ReloadExtensionWithQuietFailure(extension->id()); + base::RunLoop().RunUntilIdle(); + + // Since the extension is removed, its icon should no longer be in the + // toolbar. + EXPECT_EQ(0, toolbar_actions_bar()->GetFullSize().width()); + EXPECT_EQ(0u, toolbar_actions_bar()->GetIconCount()); +}
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.cc b/chrome/browser/ui/toolbar/toolbar_actions_model.cc index c453da4..a29ce30 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
@@ -56,6 +56,7 @@ has_active_bubble_(false), extension_action_observer_(this), extension_registry_observer_(this), + extension_error_reporter_observer_(this), weak_ptr_factory_(this) { extensions::ExtensionSystem::Get(profile_)->ready().Post( FROM_HERE, base::Bind(&ToolbarActionsModel::OnReady, @@ -233,6 +234,15 @@ RemovePref(ToolbarItem(extension->id(), EXTENSION_ACTION)); } +void ToolbarActionsModel::OnLoadFailure( + content::BrowserContext* browser_context, + const base::FilePath& extension_path, + const std::string& error) { + for (ToolbarActionsModel::Observer& observer : observers_) { + observer.OnToolbarActionLoadFailed(); + } +} + void ToolbarActionsModel::RemovePref(const ToolbarItem& item) { std::vector<std::string>::iterator pos = std::find( last_known_positions_.begin(), last_known_positions_.end(), item.id); @@ -245,6 +255,9 @@ void ToolbarActionsModel::OnReady() { InitializeActionList(); + + extension_error_reporter_observer_.Add(ExtensionErrorReporter::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 // taken from prefs.
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.h b/chrome/browser/ui/toolbar/toolbar_actions_model.h index 662844d..4eb179b 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model.h +++ b/chrome/browser/ui/toolbar/toolbar_actions_model.h
@@ -13,6 +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/ui/toolbar/component_action_delegate.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" @@ -41,6 +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::ExtensionRegistryObserver, public KeyedService, public ComponentActionDelegate { @@ -93,6 +95,10 @@ // adjusted order, action should be at |index|). virtual void OnToolbarActionMoved(const std::string& id, int index) = 0; + // Signals that the extension, corresponding to the toolbar action, has + // failed to load. + virtual void OnToolbarActionLoadFailed() = 0; + // Signals that the browser action with |id| has been updated. virtual void OnToolbarActionUpdated(const std::string& id) = 0; @@ -226,6 +232,11 @@ content::WebContents* web_contents, content::BrowserContext* browser_context) override; + // ExtensionErrorReporter::Observer: + void OnLoadFailure(content::BrowserContext* browser_context, + const base::FilePath& extension_path, + const std::string& error) override; + // To be called after the extension service is ready; gets loaded extensions // from the ExtensionRegistry, their saved order from the pref service, and // the initial set of component actions from the @@ -335,6 +346,9 @@ PrefChangeRegistrar pref_change_registrar_; base::Closure pref_change_callback_; + ScopedObserver<ExtensionErrorReporter, ExtensionErrorReporter::Observer> + extension_error_reporter_observer_; + base::WeakPtrFactory<ToolbarActionsModel> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ToolbarActionsModel);
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc index 0b6dd7d8..f4951c0b 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc
@@ -74,6 +74,8 @@ ++removed_count_; } + void OnToolbarActionLoadFailed() override {} + void OnToolbarActionMoved(const std::string& id, int index) override { ++moved_count_; }
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 4765700..5643324 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -693,7 +693,7 @@ : GetSecureTextColor(security_level); location_icon_view_->SetImage(gfx::CreateVectorIcon( omnibox_view_->GetVectorIcon(), kIconWidth, icon_color)); - location_icon_view_->UpdateInkDropMode(); + location_icon_view_->Update(); } bool LocationBarView::RefreshContentSettingViews() {
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.cc b/chrome/browser/ui/views/location_bar/location_icon_view.cc index 5241c32..fb2fa9e 100644 --- a/chrome/browser/ui/views/location_bar/location_icon_view.cc +++ b/chrome/browser/ui/views/location_bar/location_icon_view.cc
@@ -24,13 +24,7 @@ animation_(this) { label()->SetElideBehavior(gfx::ELIDE_MIDDLE); set_id(VIEW_ID_LOCATION_ICON); - SetInkDropMode(InkDropMode::ON); - -#if defined(OS_MACOSX) - SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); -#else - SetFocusBehavior(FocusBehavior::ALWAYS); -#endif + Update(); animation_.SetSlideDuration(kOpenTimeMS); } @@ -113,13 +107,25 @@ OnNativeThemeChanged(GetNativeTheme()); } -void LocationIconView::UpdateInkDropMode() { - // If the omnibox is empty or editing, the ink drop mode should be off - // since the icon isn't clickable in this state. - InkDropMode mode = location_bar_->GetOmniboxView()->IsEditingOrEmpty() - ? InkDropMode::OFF - : InkDropMode::ON; - SetInkDropMode(mode); +void LocationIconView::Update() { + // If the omnibox is empty or editing, the user should not be able to left + // click on the icon. As such, the icon should not show a highlight or be + // focusable. Note: using the middle mouse to copy-and-paste should still + // work on the icon. + if (location_bar_->GetOmniboxView() && + location_bar_->GetOmniboxView()->IsEditingOrEmpty()) { + SetInkDropMode(InkDropMode::OFF); + SetFocusBehavior(FocusBehavior::NEVER); + return; + } + + SetInkDropMode(InkDropMode::ON); + +#if defined(OS_MACOSX) + SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); +#else + SetFocusBehavior(FocusBehavior::ALWAYS); +#endif } bool LocationIconView::IsTriggerableEvent(const ui::Event& event) {
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.h b/chrome/browser/ui/views/location_bar/location_icon_view.h index fdb8878..04a0a65 100644 --- a/chrome/browser/ui/views/location_bar/location_icon_view.h +++ b/chrome/browser/ui/views/location_bar/location_icon_view.h
@@ -45,8 +45,8 @@ // any necessary transition to this state should be animated. void SetTextVisibility(bool should_show, bool should_animate); - // Updates the ink drop mode. - void UpdateInkDropMode(); + // Updates the icon's ink drop mode and focusable behavior. + void Update(); protected: // IconLabelBubbleView:
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view_browsertest.cc b/chrome/browser/ui/views/location_bar/location_icon_view_browsertest.cc index 81aa929d..47e5db45 100644 --- a/chrome/browser/ui/views/location_bar/location_icon_view_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/location_icon_view_browsertest.cc
@@ -42,13 +42,13 @@ IN_PROC_BROWSER_TEST_F(LocationIconViewBrowserTest, InkDropMode) { OmniboxEditModel* model = location_bar()->GetOmniboxView()->model(); model->SetInputInProgress(true); - icon_view()->UpdateInkDropMode(); + icon_view()->Update(); EXPECT_EQ(IconLabelBubbleView::InkDropMode::OFF, views::test::InkDropHostViewTestApi(icon_view()).ink_drop_mode()); model->SetInputInProgress(false); - icon_view()->UpdateInkDropMode(); + icon_view()->Update(); EXPECT_EQ(IconLabelBubbleView::InkDropMode::ON, views::test::InkDropHostViewTestApi(icon_view()).ink_drop_mode());
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index e384f5e1..c977109 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -471,7 +471,7 @@ void OmniboxViewViews::OnTemporaryTextMaybeChanged( const base::string16& display_text, - AutocompleteMatch::Type match_type, + const AutocompleteMatch& match, bool save_original_selection, bool notify_text_changed) { if (save_original_selection)
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h index d7978ae..0d3ec4a4 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -146,7 +146,7 @@ void UpdatePopup() override; void ApplyCaretVisibility() override; void OnTemporaryTextMaybeChanged(const base::string16& display_text, - AutocompleteMatch::Type match_type, + const AutocompleteMatch& match, bool save_original_selection, bool notify_text_changed) override; bool OnInlineAutocompleteTextMaybeChanged(const base::string16& display_text,
diff --git a/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc index 22d245c..a623d8b 100644 --- a/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc
@@ -2,17 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> + #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "base/test/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/views/payments/payment_request_browsertest_base.h" +#include "chrome/test/base/ui_test_utils.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/credit_card.h" #include "components/payments/core/journey_logger.h" +#include "components/ukm/test_ukm_recorder.h" #include "content/public/common/content_features.h" #include "content/public/test/browser_test_utils.h" +#include "services/metrics/public/cpp/ukm_builders.h" namespace payments { @@ -1014,10 +1020,74 @@ protected: PaymentRequestIframeTest() {} + void PreRunTestOnMainThread() override { + InProcessBrowserTest::PreRunTestOnMainThread(); + + test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>(); + } + + std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_; + private: DISALLOW_COPY_AND_ASSIGN(PaymentRequestIframeTest); }; +IN_PROC_BROWSER_TEST_F(PaymentRequestIframeTest, CrossOriginIframe) { + base::HistogramTester histogram_tester; + + GURL main_frame_url = + https_server()->GetURL("a.com", "/payment_request_main.html"); + ui_test_utils::NavigateToURL(browser(), main_frame_url); + + // The iframe calls show() immediately. + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + GURL iframe_url = + https_server()->GetURL("b.com", "/payment_request_iframe.html"); + ResetEventObserver(DialogEvent::DIALOG_OPENED); + EXPECT_TRUE(content::NavigateIframeToURL(tab, "test", iframe_url)); + WaitForObservedEvent(); + + // Simulate that the user cancels the PR. + ClickOnCancel(); + + int64_t expected_step_metric = + JourneyLogger::EVENT_SHOWN | + JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD | + JourneyLogger::EVENT_USER_ABORTED; + + // Make sure the correct UMA events were logged. + std::vector<base::Bucket> buckets = + histogram_tester.GetAllSamples("PaymentRequest.Events"); + ASSERT_EQ(1U, buckets.size()); + EXPECT_EQ(expected_step_metric, buckets[0].min); + + // Important: Even though the Payment Request is in the iframe, no UKM was + // logged for the iframe URL, only for the main frame. + std::vector<const ukm::UkmSource*> sources = + test_ukm_recorder_->GetSourcesForUrl(iframe_url.spec().c_str()); + EXPECT_TRUE(sources.empty()); + + sources = test_ukm_recorder_->GetSourcesForUrl(main_frame_url.spec().c_str()); + EXPECT_FALSE(sources.empty()); + + // Make sure the UKM was logged correctly. + auto entries = test_ukm_recorder_->GetEntriesByName( + ukm::builders::PaymentRequest_CheckoutEvents::kEntryName); + EXPECT_EQ(1u, entries.size()); + for (const auto* const entry : entries) { + test_ukm_recorder_->ExpectEntrySourceHasUrl(entry, main_frame_url); + EXPECT_EQ(2U, entry->metrics.size()); + test_ukm_recorder_->ExpectEntryMetric( + entry, + ukm::builders::PaymentRequest_CheckoutEvents::kCompletionStatusName, + JourneyLogger::COMPLETION_STATUS_USER_ABORTED); + test_ukm_recorder_->ExpectEntryMetric( + entry, ukm::builders::PaymentRequest_CheckoutEvents::kEventsName, + expected_step_metric); + } +} + IN_PROC_BROWSER_TEST_F(PaymentRequestIframeTest, IframeNavigation_UserAborted) { NavigateTo("/payment_request_free_shipping_with_iframe_test.html"); base::HistogramTester histogram_tester;
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index cc532d2..1c0aaab 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -264,8 +264,7 @@ explicit TabCloseButton(Tab* tab) : views::ImageButton(tab), tab_(tab) { - SetEventTargeter( - std::unique_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); + SetEventTargeter(std::make_unique<views::ViewTargeter>(this)); } ~TabCloseButton() override {} @@ -461,8 +460,7 @@ title_->SetText(CoreTabHelper::GetDefaultTitle()); AddChildView(title_); - SetEventTargeter( - std::unique_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); + SetEventTargeter(std::make_unique<views::ViewTargeter>(this)); throbber_ = new ThrobberView(this); throbber_->SetVisible(false);
diff --git a/chrome/browser/ui/views/tabs/tab_experimental.cc b/chrome/browser/ui/views/tabs/tab_experimental.cc index 535aa92..2662b9515 100644 --- a/chrome/browser/ui/views/tabs/tab_experimental.cc +++ b/chrome/browser/ui/views/tabs/tab_experimental.cc
@@ -6,11 +6,13 @@ #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/tab_contents/core_tab_helper.h" -#include "chrome/browser/ui/tabs/tab_data_experimental.h" +#include "chrome/browser/ui/tabs/tab_strip_model_experimental.h" #include "chrome/browser/ui/view_ids.h" #include "components/grit/components_scaled_resources.h" #include "ui/views/border.h" #include "ui/views/controls/label.h" +#include "ui/views/masked_targeter_delegate.h" +#include "ui/views/widget/widget.h" namespace { @@ -27,9 +29,12 @@ } // namespace -TabExperimental::TabExperimental(const TabDataExperimental* data) +TabExperimental::TabExperimental(TabStripModelExperimental* model, + const TabDataExperimental* data) : views::View(), + model_(model), data_(data), + type_(data->type()), title_(new views::Label), hover_controller_(this), paint_(this) { @@ -40,6 +45,8 @@ title_->SetText(CoreTabHelper::GetDefaultTitle()); AddChildView(title_); + SetEventTargeter(std::make_unique<views::ViewTargeter>(this)); + // So we get don't get enter/exit on children and don't prematurely stop the // hover. set_notify_enter_exit_on_child(true); @@ -73,23 +80,84 @@ } void TabExperimental::DataUpdated() { + type_ = data_->type(); title_->SetText(data_->GetTitle()); } +void TabExperimental::SetGroupLayoutParams(int first_child_begin_x) { + first_child_begin_x_ = first_child_begin_x; +} + int TabExperimental::GetOverlap() { // We want to overlap the endcap portions entirely. return gfx::ToCeiledInt(GetTabEndcapWidth()); } +bool TabExperimental::GetHitTestMask(gfx::Path* mask) const { + // When the window is maximized we don't want to shave off the edges or top + // shadow of the tab, such that the user can click anywhere along the top + // edge of the screen to select a tab. Ditto for immersive fullscreen. + const views::Widget* widget = GetWidget(); + *mask = paint_.GetBorderPath( + GetWidget()->GetCompositor()->device_scale_factor(), true, + widget && (widget->IsMaximized() || widget->IsFullscreen()), + GetTabEndcapWidth(), size()); + return true; +} + void TabExperimental::OnPaint(gfx::Canvas* canvas) { - paint_.PaintTabBackground(canvas, active_, 0, 0, nullptr); + if (type_ == TabDataExperimental::Type::kSingle) + paint_.PaintTabBackground(canvas, active_, 0, 0, nullptr); + else + paint_.PaintGroupBackground(canvas, active_); } void TabExperimental::Layout() { + // Space between the favicon and title. constexpr int kTitleSpacing = 6; const gfx::Rect bounds = GetContentsBounds(); - title_->SetBoundsRect(gfx::Rect(bounds.x() + kTitleSpacing, bounds.y(), - bounds.width() - (kTitleSpacing * 2), - bounds.height())); + int title_left = bounds.x() + kTitleSpacing; + int title_right; + if (first_child_begin_x_ >= 0) + title_right = first_child_begin_x_; + else + title_right = bounds.width() - kTitleSpacing; + + title_->SetBoundsRect(gfx::Rect(title_left, bounds.y(), + title_right - title_left, bounds.height())); +} + +bool TabExperimental::OnMousePressed(const ui::MouseEvent& event) { + // TODO(brettw) the non-experimental one has some stuff about touch and + // multi-selection here. + if (event.IsOnlyLeftMouseButton()) + model_->ActivateTabAt(model_->GetViewIndexForData(data_), true); + return true; +} + +void TabExperimental::OnMouseReleased(const ui::MouseEvent& event) { + // Close tab on middle click, but only if the button is released over the tab + // (normal windows behavior is to discard presses of a UI element where the + // releases happen off the element). + if (event.IsMiddleMouseButton()) { + if (HitTestPoint(event.location())) { + // TODO(brettw) old one did PrepareForCloseAt which does some animation + // stuff. + model_->CloseWebContentsAt( + model_->GetViewIndexForData(data_), + TabStripModel::CLOSE_USER_GESTURE | + TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); + } else if (closing_) { + // We're animating closed and a middle mouse button was pushed on us but + // we don't contain the mouse anymore. We assume the user is clicking + // quicker than the animation and we should close the tab that falls under + // the mouse. + /* TODO(brettw) fast closing. + Tab* closest_tab = controller_->GetTabAt(this, event.location()); + if (closest_tab) + controller_->CloseTab(closest_tab, CLOSE_TAB_FROM_MOUSE); + */ + } + } }
diff --git a/chrome/browser/ui/views/tabs/tab_experimental.h b/chrome/browser/ui/views/tabs/tab_experimental.h index 5c8ae5b..850f9cc 100644 --- a/chrome/browser/ui/views/tabs/tab_experimental.h +++ b/chrome/browser/ui/views/tabs/tab_experimental.h
@@ -6,24 +6,33 @@ #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_EXPERIMENTAL_H_ #include "base/macros.h" +#include "chrome/browser/ui/tabs/tab_data_experimental.h" #include "chrome/browser/ui/views/tabs/tab_experimental_paint.h" #include "ui/views/controls/glow_hover_controller.h" +#include "ui/views/masked_targeter_delegate.h" #include "ui/views/view.h" class TabDataExperimental; +class TabStripModelExperimental; namespace views { class Label; } -class TabExperimental : public views::View { +class TabExperimental : public views::MaskedTargeterDelegate, + public views::View { public: - explicit TabExperimental(const TabDataExperimental* data); + explicit TabExperimental(TabStripModelExperimental* model, + const TabDataExperimental* data); ~TabExperimental() override; // Will be null when closing. const TabDataExperimental* data() const { return data_; } + // Cached stuff from data_ that can be used regardless of whether the data + // pointer is null or not. + TabDataExperimental::Type type() const { return type_; } + // The view order is stored on a tab for the use of TabStrip layout and // computatations. It is not used directly by this class. It represents this // tab's position in the current layout. @@ -52,17 +61,30 @@ // to redraw everything. void DataUpdated(); + // Called for group types when layout is done to set the bounds of the + // first tab. This is used to determine some painting parameters. + void SetGroupLayoutParams(int first_child_begin_x); + // Returns the overlap between adjacent tabs. static int GetOverlap(); private: + // views::MaskedTargeterDelegate: + bool GetHitTestMask(gfx::Path* mask) const override; + // views::View: void OnPaint(gfx::Canvas* canvas) override; void Layout() override; + bool OnMousePressed(const ui::MouseEvent& event) override; + void OnMouseReleased(const ui::MouseEvent& event) override; + + TabStripModelExperimental* model_; // Will be null when closing. const TabDataExperimental* data_; + TabDataExperimental::Type type_; + size_t view_order_ = static_cast<size_t>(-1); gfx::Rect ideal_bounds_; @@ -72,6 +94,9 @@ views::Label* title_; // Non-owning (owned by View hierarchy). + // Location of the first child tab. Negative indicates unused. + int first_child_begin_x_ = -1; + views::GlowHoverController hover_controller_; TabExperimentalPaint paint_;
diff --git a/chrome/browser/ui/views/tabs/tab_experimental_paint.cc b/chrome/browser/ui/views/tabs/tab_experimental_paint.cc index 9d972d1..e3527d6 100644 --- a/chrome/browser/ui/views/tabs/tab_experimental_paint.cc +++ b/chrome/browser/ui/views/tabs/tab_experimental_paint.cc
@@ -7,6 +7,7 @@ #include "cc/paint/paint_recorder.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/layout_constants.h" +#include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" #include "third_party/skia/include/pathops/SkPathOps.h" @@ -52,7 +53,9 @@ // Returns a path corresponding to the tab's content region inside the outer // stroke. -gfx::Path GetFillPath(float scale, const gfx::Size& size, float endcap_width) { +gfx::Path GetTabFillPath(float scale, + const gfx::Size& size, + float endcap_width) { const float right = size.width() * scale; // The bottom of the tab needs to be pixel-aligned or else when we call // ClipPath with anti-aliasing enabled it can cause artifacts. @@ -90,11 +93,11 @@ // |extend_to_top| is true, the path is extended vertically to the top of the // tab bounds. The caller uses this for Fitts' Law purposes in // maximized/fullscreen mode. -gfx::Path GetBorderPath(float scale, - bool unscale_at_end, - bool extend_to_top, - float endcap_width, - const gfx::Size& size) { +gfx::Path GetTabBorderPath(float scale, + bool unscale_at_end, + bool extend_to_top, + float endcap_width, + const gfx::Size& size) { const float top = scale - 1; const float right = size.width() * scale; const float bottom = size.height() * scale; @@ -132,6 +135,62 @@ return path; } +// Returns a path corresponding to the tab's content region inside the outer +// stroke. +gfx::Path GetHubAndSpokeFillPath(float scale, + const gfx::Size& size, + float endcap_width) { + const float right = size.width() * scale; + // The bottom of the tab needs to be pixel-aligned or else when we call + // ClipPath with anti-aliasing enabled it can cause artifacts. + const float bottom = std::ceil(size.height() * scale); + + gfx::Path fill; + fill.moveTo(right - 1, bottom); + fill.rCubicTo(-0.75 * scale, 0, -1.625 * scale, -0.5 * scale, -2 * scale, + -1.5 * scale); + fill.lineTo(right - 1 - (endcap_width - 2) * scale, 2.5 * scale); + // Prevent overdraw in the center near minimum width (only happens if + // scale < 2). We could instead avoid this by increasing the tab inset + // values, but that would shift all the content inward as well, unless we + // then overlapped the content on the endcaps, by which point we'd have a + // huge mess. + const float scaled_endcap_width = 1 + endcap_width * scale; + const float overlap = scaled_endcap_width * 2 - right; + const float offset = (overlap > 0) ? (overlap / 2) : 0; + fill.rCubicTo(-0.375 * scale, -1 * scale, -1.25 * scale + offset, + -1.5 * scale, -2 * scale + offset, -1.5 * scale); + if (overlap < 0) + fill.lineTo(scaled_endcap_width, scale); + fill.rCubicTo(-0.75 * scale, 0, -1.625 * scale - offset, 0.5 * scale, + -2 * scale - offset, 1.5 * scale); + fill.lineTo(1 + 2 * scale, bottom - 1.5 * scale); + fill.rCubicTo(-0.375 * scale, scale, -1.25 * scale, 1.5 * scale, -2 * scale, + 1.5 * scale); + fill.close(); + return fill; +} + +gfx::Path GetHubAndSpokeBorderPath(float scale, + float endcap_width, + const gfx::Size& size) { + const float top = scale - 1; + const float right = size.width() * scale; + const float bottom = size.height() * scale; + + gfx::Path path; + path.moveTo(0, bottom); + path.rLineTo(0, -1); + path.rCubicTo(0.75 * scale, 0, 1.625 * scale, -0.5 * scale, 2 * scale, + -1.5 * scale); + path.lineTo((endcap_width - 2) * scale, top + 1.5 * scale); + path.rCubicTo(0.375 * scale, -scale, 1.25 * scale, -1.5 * scale, 2 * scale, + -1.5 * scale); + path.lineTo(right, top); + + return path; +} + } // namespace // TabExperimentalPaint::BackgroundCache --------------------------------------- @@ -166,6 +225,48 @@ TabExperimentalPaint::TabExperimentalPaint(views::View* view) : view_(view) {} TabExperimentalPaint::~TabExperimentalPaint() {} +gfx::Path TabExperimentalPaint::GetBorderPath(float scale, + bool unscale_at_end, + bool extend_to_top, + float endcap_width, + const gfx::Size& size) const { + const float top = scale - 1; + const float right = size.width() * scale; + const float bottom = size.height() * scale; + + gfx::Path path; + path.moveTo(0, bottom); + path.rLineTo(0, -1); + path.rCubicTo(0.75 * scale, 0, 1.625 * scale, -0.5 * scale, 2 * scale, + -1.5 * scale); + path.lineTo((endcap_width - 2) * scale, top + 1.5 * scale); + if (extend_to_top) { + // Create the vertical extension by extending the side diagonals until + // they reach the top of the bounds. + const float dy = 2.5 * scale - 1; + const float dx = Tab::GetInverseDiagonalSlope() * dy; + path.rLineTo(dx, -dy); + path.lineTo(right - (endcap_width - 2) * scale - dx, 0); + path.rLineTo(dx, dy); + } else { + path.rCubicTo(0.375 * scale, -scale, 1.25 * scale, -1.5 * scale, 2 * scale, + -1.5 * scale); + path.lineTo(right - endcap_width * scale, top); + path.rCubicTo(0.75 * scale, 0, 1.625 * scale, 0.5 * scale, 2 * scale, + 1.5 * scale); + } + path.lineTo(right - 2 * scale, bottom - 1 - 1.5 * scale); + path.rCubicTo(0.375 * scale, scale, 1.25 * scale, 1.5 * scale, 2 * scale, + 1.5 * scale); + path.rLineTo(0, 1); + path.close(); + + if (unscale_at_end && (scale != 1)) + path.transform(SkMatrix::MakeScale(1.f / scale)); + + return path; +} + void TabExperimentalPaint::PaintTabBackground(gfx::Canvas* canvas, bool active, int fill_id, @@ -179,8 +280,12 @@ const SkColor active_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR); const SkColor inactive_color = tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB); - const SkColor stroke_color = - 0xFFFF; // controller_->GetToolbarTopSeparatorColor(); + + // TODO(brettw) in the old code this was stroke_color = + // controller_->GetToolbarTopSeparatorColor() which handles theming, + // activation, and incognito. + const SkColor stroke_color = ThemeProperties::GetDefaultColor( + ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR, false); const bool paint_hover_effect = false; //! active && hover_controller_.ShouldDraw(); @@ -193,9 +298,9 @@ // cache based on the hover states. if (fill_id || paint_hover_effect) { gfx::Path fill_path = - GetFillPath(canvas->image_scale(), view_->size(), endcap_width); - gfx::Path stroke_path = GetBorderPath(canvas->image_scale(), false, false, - endcap_width, view_->size()); + GetTabFillPath(canvas->image_scale(), view_->size(), endcap_width); + gfx::Path stroke_path = GetTabBorderPath( + canvas->image_scale(), false, false, endcap_width, view_->size()); PaintTabBackgroundFill(canvas, fill_path, active, paint_hover_effect, active_color, inactive_color, fill_id, y_offset); gfx::ScopedCanvas scoped_canvas(clip ? canvas : nullptr); @@ -211,9 +316,9 @@ if (!cache.CacheKeyMatches(canvas->image_scale(), view_->size(), active_color, inactive_color, stroke_color)) { gfx::Path fill_path = - GetFillPath(canvas->image_scale(), view_->size(), endcap_width); - gfx::Path stroke_path = GetBorderPath(canvas->image_scale(), false, false, - endcap_width, view_->size()); + GetTabFillPath(canvas->image_scale(), view_->size(), endcap_width); + gfx::Path stroke_path = GetTabBorderPath( + canvas->image_scale(), false, false, endcap_width, view_->size()); cc::PaintRecorder recorder; { @@ -243,6 +348,64 @@ if (clip) canvas->sk_canvas()->clipPath(*clip, SkClipOp::kDifference, true); canvas->sk_canvas()->drawPicture(cache.stroke_record); + + // Bottom border. + if (!active) { + BrowserView::Paint1pxHorizontalLine( + canvas, + ThemeProperties::GetDefaultColor( + ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR, false), + view_->GetLocalBounds(), true); + } +} + +void TabExperimentalPaint::PaintGroupBackground(gfx::Canvas* canvas, + bool active) { + // const ui::ThemeProvider* tp = view_->GetThemeProvider(); + // const SkColor active_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR); + // const SkColor inactive_color = + // tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB); + + // TODO(brettw) in the old code this was stroke_color = + // controller_->GetToolbarTopSeparatorColor() which handles theming, + // activation, and incognito. + SkColor stroke_color = ThemeProperties::GetDefaultColor( + ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR, false); + + const ui::ThemeProvider* tp = view_->GetThemeProvider(); + const SkColor active_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR); + const SkColor inactive_color = + tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB); + float endcap_width = GetTabEndcapWidth(); + const bool paint_hover_effect = + false; //! active && hover_controller_.ShouldDraw(); + + gfx::Path fill_path = GetHubAndSpokeFillPath(canvas->image_scale(), + view_->size(), endcap_width); + PaintTabBackgroundFill(canvas, fill_path, active, paint_hover_effect, + active_color, inactive_color, 0, 0); + + { + gfx::ScopedCanvas scoped_canvas(canvas); + float scale = canvas->UndoDeviceScaleFactor(); + gfx::Path path = + GetHubAndSpokeBorderPath(scale, endcap_width, view_->size()); + cc::PaintFlags flags; + flags.setAntiAlias(true); + flags.setColor(stroke_color); + flags.setStyle(cc::PaintFlags::kStroke_Style); + + canvas->DrawPath(path, flags); + } + + // Bottom border. + if (!active) { + BrowserView::Paint1pxHorizontalLine( + canvas, + ThemeProperties::GetDefaultColor( + ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR, false), + view_->GetLocalBounds(), true); + } } void TabExperimentalPaint::PaintTabBackgroundFill(gfx::Canvas* canvas, @@ -254,7 +417,7 @@ int fill_id, int y_offset) { gfx::ScopedCanvas scoped_canvas(canvas); - const float scale = canvas->UndoDeviceScaleFactor(); + float scale = canvas->UndoDeviceScaleFactor(); canvas->ClipPath(fill_path, true); if (fill_id) {
diff --git a/chrome/browser/ui/views/tabs/tab_experimental_paint.h b/chrome/browser/ui/views/tabs/tab_experimental_paint.h index 106d975..2521fbc 100644 --- a/chrome/browser/ui/views/tabs/tab_experimental_paint.h +++ b/chrome/browser/ui/views/tabs/tab_experimental_paint.h
@@ -26,12 +26,26 @@ explicit TabExperimentalPaint(views::View* view); ~TabExperimentalPaint(); + // Returns a path corresponding to the tab's outer border for a given tab + // |size|, |scale|, and |endcap_width|. If |unscale_at_end| is true, this + // path will be normalized to a 1x scale by scaling by 1/scale before + // returning. If |extend_to_top| is true, the path is extended vertically to + // the top of the tab bounds. The caller uses this for Fitts' Law purposes + // in maximized/fullscreen mode. + gfx::Path GetBorderPath(float scale, + bool unscale_at_end, + bool extend_to_top, + float endcap_width, + const gfx::Size& size) const; + void PaintTabBackground(gfx::Canvas* canvas, bool active, int fill_id, int y_offset, gfx::Path* clip); + void PaintGroupBackground(gfx::Canvas* canvas, bool active); + private: class BackgroundCache { public:
diff --git a/chrome/browser/ui/views/tabs/tab_strip_experimental.cc b/chrome/browser/ui/views/tabs/tab_strip_experimental.cc index b86b441a..f7ff533d 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_experimental.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_experimental.cc
@@ -97,6 +97,9 @@ const int kPinnedToNonPinnedOffset = 3; #endif +// Additional size above the tabs used for group bounds. +const int kTopPaddingForGroups = 2; + // Returns the width needed for the new tab button (and padding). int GetNewTabButtonWidth() { return GetLayoutSize(NEW_TAB_BUTTON).width() - @@ -168,6 +171,23 @@ AnimationEnded(animation); } +// Returns how much spacing should go after the tab with the given index. The +// return value will be negative for overlapped tabs. +int TabSpacingAfter( + const std::vector<std::unique_ptr<TabDataExperimental>>& tabs, + size_t index) { + if (index == tabs.size() - 1) + return 0; // No space after the last tab. + + // All non-single-tabs have no overlap. + if (tabs[index]->type() != TabDataExperimental::Type::kSingle || + tabs[index + 1]->type() != TabDataExperimental::Type::kSingle) + return 0; + + // Everything else gets the standard overlap. + return -TabExperimental::GetOverlap(); +} + } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -502,7 +522,7 @@ bool is_active) { InvalidateViewOrder(); - TabExperimental* tab = new TabExperimental(data); + TabExperimental* tab = new TabExperimental(model_, data); AddChildView(tab); tab->SetVisible(true); tabs_.emplace(data, tab); @@ -546,6 +566,9 @@ if (!tab) return; + // TODO(brettw) this uses view order to tell if it's the last tab, but this + // is not correct. It should look only at the tabs structure and we should + // be able to delte view_order() on the TabExperimental. if (in_tab_close_ && tab->view_order() != view_order_.size() - 1) StartMouseInitiatedRemoveTabAnimation(tab); else @@ -583,6 +606,8 @@ void TabStripExperimental::TabSelectionChanged( const TabDataExperimental* old_data, const TabDataExperimental* new_data) { + InvalidateViewOrder(); + TabExperimental* old_tab = TabForData(old_data); if (old_tab) { old_tab->SetActive(false); @@ -623,8 +648,26 @@ void TabStripExperimental::PaintChildren(const views::PaintInfo& paint_info) { EnsureViewOrderUpToDate(); - // The order stored by the view itself doesn't match the paint order. The - // paint order is the reverse of the view_order_ vector (to paint + // TODO(brettw) The color should be + // controller_->GetToolbarTopSeparatorColor() which handles theming, + // activation, and incognito. + // TODO(brettw) only paint this where there are no tabs, as the tabs also + // paint their own bottom border and this will be overpainting. + { + ui::PaintRecorder recorder(paint_info.context(), + paint_info.paint_recording_size(), + paint_info.paint_recording_scale_x(), + paint_info.paint_recording_scale_y(), nullptr); + gfx::Canvas* canvas = recorder.canvas(); + BrowserView::Paint1pxHorizontalLine( + canvas, + ThemeProperties::GetDefaultColor( + ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR, false), + GetLocalBounds(), true); + } + + // The order stored by the view::View itself doesn't match the paint order. + // The paint order is the reverse of the view_order_ vector (to paint // back-to-front). for (TabExperimental* tab : base::Reversed(view_order_)) tab->Paint(paint_info); @@ -645,10 +688,6 @@ SkClipOp::kDifference); } */ - /* TODO(brettw) top of toolbar. - BrowserView::Paint1pxHorizontalLine(canvas, GetToolbarTopSeparatorColor(), - GetLocalBounds(), true); - */ } const char* TabStripExperimental::GetClassName() const { @@ -684,8 +723,9 @@ needed_tab_width = std::min(std::max(needed_tab_width, min_selected_width), largest_min_tab_width); - return gfx::Size(needed_tab_width + GetNewTabButtonWidth(), - Tab::GetMinimumInactiveSize().height()); + return gfx::Size( + needed_tab_width + GetNewTabButtonWidth(), + Tab::GetMinimumInactiveSize().height() + kTopPaddingForGroups); } void TabStripExperimental::OnDragEntered(const DropTargetEvent& event) { @@ -824,14 +864,8 @@ GenerateIdealBounds(); // Set the current bounds to be the correct place but 0 width. - DCHECK(view_order_[tab->view_order()] == tab); - if (tab->view_order() == 0) { - tab->SetBounds(0, tab->ideal_bounds().y(), 0, tab->ideal_bounds().height()); - } else { - TabExperimental* prev_tab = view_order_[tab->view_order() - 1]; - tab->SetBounds(prev_tab->bounds().right() - TabExperimental::GetOverlap(), - tab->ideal_bounds().y(), 0, tab->ideal_bounds().height()); - } + tab->SetBounds(tab->ideal_bounds().x(), tab->ideal_bounds().y(), 0, + tab->ideal_bounds().height()); // Animate in to the full width. AnimateToIdealBounds(); @@ -845,10 +879,10 @@ void TabStripExperimental::StartRemoveTabAnimation(TabExperimental* tab) { PrepareForAnimation(); - tab->SetClosing(); - RemoveTabFromViewModel(tab); ScheduleRemoveTabAnimation(tab); + + tab->SetClosing(); } void TabStripExperimental::ScheduleRemoveTabAnimation(TabExperimental* tab) { @@ -876,7 +910,11 @@ void TabStripExperimental::AnimateToIdealBounds() { EnsureViewOrderUpToDate(); - for (TabExperimental* tab : view_order_) { + // Don't iterate over view_order since that will contain tabs that are + // in the process of being deleted. Asking them to animate again will + // cancel the previous animation which will cause them to be deleted. + for (const auto& pair : tabs_) { + TabExperimental* tab = pair.second; bounds_animator_.AnimateViewTo(tab, tab->ideal_bounds()); bounds_animator_.SetAnimationDelegate( tab, std::make_unique<TabAnimationDelegate>(this, tab)); @@ -1107,10 +1145,10 @@ void TabStripExperimental::AddMessageLoopObserver() { if (!mouse_watcher_.get()) { - mouse_watcher_.reset(new views::MouseWatcher( + mouse_watcher_ = std::make_unique<views::MouseWatcher>( new views::MouseWatcherViewHost( this, gfx::Insets(0, 0, kTabStripAnimationVSlop, 0)), - this)); + this); } mouse_watcher_->Start(); } @@ -1286,16 +1324,70 @@ ? GetTabAreaWidth() : available_width_for_tabs_; + auto& tabs = model_->top_level_tabs(); + int overlap = TabExperimental::GetOverlap(); + + // Precompute the spacing to know how much space can be distributed to + // the tabs. Thia is usually negative since the tabs overlap slightly. + int spacing_accumulator = 0; + for (size_t i = 0; i < tabs.size() - 1; i++) { + switch (tabs[i]->type()) { + case TabDataExperimental::Type::kSingle: + spacing_accumulator += TabSpacingAfter(tabs, i); + break; + case TabDataExperimental::Type::kHubAndSpoke: + // Hub and spoke gets overlap between the hub and first child. + spacing_accumulator -= overlap; + // Fall through to group for counting the children. + case TabDataExperimental::Type::kGroup: + for (size_t inner_i = 0; inner_i < tabs[i]->children().size(); + inner_i++) + spacing_accumulator += TabSpacingAfter(tabs[i]->children(), inner_i); + break; + } + } + gfx::Size standard_size = Tab::GetStandardSize(); - int tab_width = available_width / view_order_.size(); + int tab_width = (available_width - spacing_accumulator) / view_order_.size(); if (tab_width > standard_size.width()) tab_width = standard_size.width(); int x = 0; - for (size_t i = 0; i < view_order_.size(); i++) { - view_order_[i]->set_ideal_bounds( - gfx::Rect(x, 0, tab_width, standard_size.height())); - x += tab_width; + for (size_t i = 0; i < tabs.size(); i++) { + const TabDataExperimental* top_data = tabs[i].get(); + const auto top_found = tabs_.find(top_data); + if (top_found == tabs_.end()) + continue; // Can happen during tab close. + + if (top_data->type() == TabDataExperimental::Type::kSingle) { + top_found->second->set_ideal_bounds(gfx::Rect( + x, kTopPaddingForGroups, tab_width, standard_size.height())); + x += tab_width + TabSpacingAfter(tabs, i); + } else { + int top_x = x; + x += tab_width - overlap; // Will increment for each child. + + top_found->second->SetGroupLayoutParams(x - top_x); + + // Layout children inside. + for (size_t inner_i = 0; inner_i < top_data->children().size(); + inner_i++) { + const TabDataExperimental* inner_data = + top_data->children()[inner_i].get(); + const auto inner_found = tabs_.find(inner_data); + if (inner_found == tabs_.end()) { + NOTREACHED(); + } else { + inner_found->second->set_ideal_bounds(gfx::Rect( + x, kTopPaddingForGroups, tab_width, standard_size.height())); + } + x += tab_width + TabSpacingAfter(top_data->children(), inner_i); + } + + // Layout group. + top_found->second->set_ideal_bounds(gfx::Rect( + top_x, 0, x - top_x, standard_size.height() + kTopPaddingForGroups)); + } } /* TODO(brettw) need to notify of max X. @@ -1418,30 +1510,12 @@ TabExperimental* TabStripExperimental::FindTabHitByPoint( const gfx::Point& point) { - /* TODO(brettw) hit testing. // The display order doesn't necessarily match the child order, so we iterate // in display order. - for (int i = 0; i < tab_count(); ++i) { - // If we don't first exclude points outside the current tab, the code below - // will return the wrong tab if the next tab is selected, the following tab - // is active, and |point| is in the overlap region between the two. - TabExperimental* tab = tab_at(i); - if (!IsPointInTab(tab, point)) - continue; - - // Selected tabs render atop unselected ones, and active tabs render atop - // everything. Check whether the next tab renders atop this one and |point| - // is in the overlap region. - TabExperimental* next_tab = i < (tab_count() - 1) ? tab_at(i + 1) : nullptr; - if (next_tab && - (next_tab->active() || (next_tab->selected() && !tab->selected())) && - IsPointInTab(next_tab, point)) - return next_tab; - - // This is the topmost tab for this point. - return tab; + for (TabExperimental* tab : view_order_) { + if (IsPointInTab(tab, point)) + return tab; } - */ return nullptr; } @@ -1632,29 +1706,9 @@ return; view_order_.reserve(tabs_.size()); - - for (const auto& top_data : model_->top_level_tabs()) { - // Add children. This assumes a two-level hierarchy. If more nesting is - // required, this will need to be recursive. - for (const auto& inner_data : top_data->children()) { - const auto inner_found = tabs_.find(inner_data.get()); - if (inner_found == tabs_.end()) { - NOTREACHED(); - } else { - inner_found->second->set_view_order(view_order_.size()); - view_order_.push_back(inner_found->second); - } - } - - // The group itself goes below the child tabs. - const auto top_found = tabs_.find(top_data.get()); - if (top_found == tabs_.end()) { - NOTREACHED(); - } else { - top_found->second->set_view_order(view_order_.size()); - view_order_.push_back(top_found->second); - } - } + const TabDataExperimental* selected_data = + model_->GetDataForViewIndex(model_->active_index()); + ComputeViewOrder(model_->top_level_tabs(), selected_data, &view_order_); // Put the closing tabs at the back. // TODO(brettw) this isn't right, they should go in the order they were @@ -1665,3 +1719,43 @@ view_order_.push_back(tab); } } + +void TabStripExperimental::ComputeViewOrder( + base::span<const std::unique_ptr<TabDataExperimental>> tabs, + const TabDataExperimental* selected, + std::vector<TabExperimental*>* output) const { + // Stores the selected one if we encounter it. + const std::unique_ptr<TabDataExperimental>* top = nullptr; + + size_t begin_index = output->size(); + + for (const auto& data : tabs) { + const auto found_tab = tabs_.find(data.get()); + if (found_tab == tabs_.end()) + continue; // Can happen during tab close. + if (data.get() == selected) { + // Save the selected one for last. + top = &data; + continue; + } + + // Recursively order children. + if (!data->children().empty()) + ComputeViewOrder(data->children(), selected, output); + + found_tab->second->set_view_order(output->size()); + output->push_back(found_tab->second); + } + + // Add the selected one (and any children) to the front. + if (top) { + // Recursively call ComputeViewOrder since the selected tab may be a group + // that needs its children laid out. + std::vector<TabExperimental*> temp_output; + ComputeViewOrder( + base::span<const std::unique_ptr<TabDataExperimental>>(top, 1), nullptr, + &temp_output); + output->insert(output->begin() + begin_index, temp_output.begin(), + temp_output.end()); + } +}
diff --git a/chrome/browser/ui/views/tabs/tab_strip_experimental.h b/chrome/browser/ui/views/tabs/tab_strip_experimental.h index 22faa102..c1793d3 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_experimental.h +++ b/chrome/browser/ui/views/tabs/tab_strip_experimental.h
@@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" +#include "base/containers/span.h" #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -423,6 +424,12 @@ // Ensures that view_order_ corresponds to the latest tabs_ structure. void EnsureViewOrderUpToDate() const; + // Recursive backend for EnsureViewOrderUpToDate. + void ComputeViewOrder( + base::span<const std::unique_ptr<TabDataExperimental>> tabs, + const TabDataExperimental* selected, + std::vector<TabExperimental*>* output) const; + // -- Member Variables ------------------------------------------------------ TabStripModelExperimental* model_; @@ -437,8 +444,9 @@ // this will cause them to be painted in order of their memory address! base::flat_set<TabExperimental*> closing_tabs_; - // Cached ordered vector for painting the tabs. This will include everything - // in the tabs_ map and also the items in closing_tabs_. + // Cached ordered vector for painting the tabs. The topmost view is at the + // front(). This will include everything in the tabs_ map and also the items + // in closing_tabs_. // // This is computed by EnsureViewOrderUpToDate(). mutable std::vector<TabExperimental*> view_order_;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_impl.cc b/chrome/browser/ui/views/tabs/tab_strip_impl.cc index c490ecf..969171e 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_impl.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_impl.cc
@@ -1934,10 +1934,10 @@ void TabStripImpl::AddMessageLoopObserver() { if (!mouse_watcher_.get()) { - mouse_watcher_.reset(new views::MouseWatcher( + mouse_watcher_ = std::make_unique<views::MouseWatcher>( new views::MouseWatcherViewHost( this, gfx::Insets(0, 0, kTabStripAnimationVSlop, 0)), - this)); + this); } mouse_watcher_->Start(); }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h index 1361d0d..638c8da 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -27,7 +27,7 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h" #include "chrome/browser/ui/views/intent_picker_bubble_view.h" -#include "components/arc/common/intent_helper.mojom.h" +#include "components/arc/common/intent_helper.mojom.h" // nogncheck https://crbug.com/784179 #include "components/arc/intent_helper/arc_intent_helper_bridge.h" #endif // defined(OS_CHROMEOS)
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 83e845d..6b485956 100644 --- a/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc +++ b/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc
@@ -55,9 +55,10 @@ base::string16 TargetPickerTableModel::GetText(int row, int /*column_id*/) { // Show "title (origin)", to disambiguate titles that are the same, and as a // security measure. - return base::UTF8ToUTF16(targets_[row].name() + " (" + - targets_[row].manifest_url().GetOrigin().spec() + - ")"); + return l10n_util::GetStringFUTF16( + IDS_WEBSHARE_TARGET_DIALOG_ITEM_TEXT, + base::UTF8ToUTF16(targets_[row].name()), + base::UTF8ToUTF16(targets_[row].manifest_url().GetOrigin().spec())); } void TargetPickerTableModel::SetObserver(ui::TableModelObserver* observer) {}
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc index 023cc2b..8155f843 100644 --- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
@@ -598,10 +598,11 @@ if (IsMinimalMigration()) minimal_migration_start_ = tick_clock_->NowTicks(); + cryptohome::MigrateToDircryptoRequest request; + request.set_minimal_migration(IsMinimalMigration()); DBusThreadManager::Get()->GetCryptohomeClient()->AddObserver(this); cryptohome::HomedirMethods::GetInstance()->MigrateToDircrypto( - cryptohome::Identification(user_context_.GetAccountId()), - IsMinimalMigration(), + cryptohome::Identification(user_context_.GetAccountId()), request, base::Bind(&EncryptionMigrationScreenHandler::OnMigrationRequested, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc index 266e5347..585736b 100644 --- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc +++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc
@@ -206,10 +206,10 @@ _ /* 1: minimal_migration*/, _ /* 2: callback */)) .WillOnce(WithArgs<1, 2>( Invoke([expect_minimal_migration]( - bool minimal_migration, + const cryptohome::MigrateToDircryptoRequest request, const cryptohome::HomedirMethods::DBusResultCallback& callback) { - EXPECT_EQ(expect_minimal_migration, minimal_migration); + EXPECT_EQ(expect_minimal_migration, request.minimal_migration()); // Call the callback immediately - actual result is sent later // using DircryptoMigrationProgressHandler. callback.Run(true /* success */);
diff --git a/chrome/browser/ui/webui/inspect_ui.cc b/chrome/browser/ui/webui/inspect_ui.cc index c37e0a9..7e460c80 100644 --- a/chrome/browser/ui/webui/inspect_ui.cc +++ b/chrome/browser/ui/webui/inspect_ui.cc
@@ -353,42 +353,35 @@ const std::string& target_id) { scoped_refptr<DevToolsAgentHost> target = FindTarget(source_id, target_id); if (target) { - const std::string target_type = target->GetType(); Profile* profile = Profile::FromBrowserContext( web_ui()->GetWebContents()->GetBrowserContext()); DevToolsWindow::OpenDevToolsWindow(target, profile); - ForceUpdateIfNeeded(source_id, target_type); } } void InspectUI::Activate(const std::string& source_id, const std::string& target_id) { scoped_refptr<DevToolsAgentHost> target = FindTarget(source_id, target_id); - if (target) { - const std::string target_type = target->GetType(); + if (target) target->Activate(); - ForceUpdateIfNeeded(source_id, target_type); - } } void InspectUI::Close(const std::string& source_id, const std::string& target_id) { scoped_refptr<DevToolsAgentHost> target = FindTarget(source_id, target_id); if (target) { - const std::string target_type = target->GetType(); target->Close(); - ForceUpdateIfNeeded(source_id, target_type); + DevToolsTargetsUIHandler* handler = FindTargetHandler(source_id); + if (handler) + handler->ForceUpdate(); } } void InspectUI::Reload(const std::string& source_id, const std::string& target_id) { scoped_refptr<DevToolsAgentHost> target = FindTarget(source_id, target_id); - if (target) { - const std::string target_type = target->GetType(); + if (target) target->Reload(); - ForceUpdateIfNeeded(source_id, target_type); - } } void InspectUI::Open(const std::string& source_id, @@ -615,17 +608,6 @@ web_ui()->CallJavascriptFunctionUnsafe("populateAdditionalTargets", targets); } -void InspectUI::ForceUpdateIfNeeded(const std::string& source_id, - const std::string& target_type) { - // TODO(dgozman): remove this after moving discovery to protocol. - // See crbug.com/398049. - if (target_type != content::DevToolsAgentHost::kTypeServiceWorker) - return; - DevToolsTargetsUIHandler* handler = FindTargetHandler(source_id); - if (handler) - handler->ForceUpdate(); -} - void InspectUI::PopulatePortStatus(const base::Value& status) { web_ui()->CallJavascriptFunctionUnsafe("populatePortStatus", status); }
diff --git a/chrome/browser/ui/webui/inspect_ui.h b/chrome/browser/ui/webui/inspect_ui.h index 8610222..a0ccc38 100644 --- a/chrome/browser/ui/webui/inspect_ui.h +++ b/chrome/browser/ui/webui/inspect_ui.h
@@ -85,9 +85,6 @@ void PopulateAdditionalTargets(const base::ListValue& targets); - void ForceUpdateIfNeeded(const std::string& source_id, - const std::string& target_type); - void PopulatePortStatus(const base::Value& status); void ShowIncognitoWarning();
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom b/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom index e852735..d66b796 100644 --- a/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom +++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom
@@ -13,6 +13,18 @@ bool enabled; }; +struct PreviewsFlag { + // The human readable description of the flag that will be displayed on + // chrome://interventions-internals. + string description; + + // The link to this flag in chrome://flags. + string link; + + // The string representation of the flag value. + string value; +}; + struct MessageLog { // The tye of event message (E.g. "Navigation"). string type; @@ -30,8 +42,13 @@ interface InterventionsInternalsPageHandler { // Returns a map of previews modes statuses. + // TODO(thanhdle): Change this to array type. crbug.com/786996. GetPreviewsEnabled() => (map<string, PreviewsStatus> statuses); + // Returns a map of previews related flags details. + // TODO(thanhdle): Change this to array type. crbug.com/786996. + GetPreviewsFlagsDetails() => (map<string, PreviewsFlag> flags); + // Inject the client side page object. SetClientPage(InterventionsInternalsPage page);
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc index 9954595..518ec96 100644 --- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc +++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc
@@ -5,30 +5,76 @@ #include "chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h" #include <unordered_map> +#include <utility> +#include "base/base_switches.h" +#include "base/command_line.h" +#include "build/build_config.h" +#include "chrome/browser/flag_descriptions.h" +#include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h" +#include "chrome/common/chrome_switches.h" #include "components/previews/core/previews_experiments.h" namespace { -// Key for status mapping. +// Keys for status mapping. These value will be used as HTML DOM ID in the +// JavaScript code. const char kAmpRedirectionPreviews[] = "ampPreviews"; const char kClientLoFiPreviews[] = "clientLoFiPreviews"; const char kNoScriptPreviews[] = "noScriptPreviews"; const char kOfflinePreviews[] = "offlinePreviews"; -// Description for statuses. +// Descriptions for previews. const char kAmpRedirectionDescription[] = "AMP Previews"; const char kClientLoFiDescription[] = "Client LoFi Previews"; const char kNoScriptDescription[] = "NoScript Previews"; const char kOfflineDesciption[] = "Offline Previews"; +// Flag feature name. +const char kNoScriptFeatureName[] = "NoScriptPreviews"; +#if defined(OS_ANDROID) +const char kOfflinePageFeatureName[] = "OfflinePreviews"; +#endif // OS_ANDROID + +// Keys for flags mapping. +const char kEctFlag[] = "ectFlag"; +const char kNoScriptFlag[] = "noScriptFlag"; +const char kOfflinePageFlag[] = "offlinePageFlag"; + +// Links to flags in chrome://flags. +// TODO(thanhdle): Refactor into vector of structs. crbug.com/787010. +const char kEctFlagLink[] = "chrome://flags/#force-effective-connection-type"; +const char kNoScriptFlagLink[] = "chrome://flags/#enable-noscript-previews"; +const char kOfflinePageFlagLink[] = "chrome://flags/#enable-offline-previews"; + +const char kDefaultFlagValue[] = "Not Forced"; + +// Check if the flag status of the flag is a forced value or not. +std::string GetFeatureFlagStatus(const std::string& feature_name) { + std::string enabled_features = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kEnableFeatures); + if (enabled_features.find(feature_name) != std::string::npos) { + return "Forced Enabled"; + } + std::string disabled_features = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kDisableFeatures); + if (disabled_features.find(feature_name) != std::string::npos) { + return "Forced Disabled"; + } + return kDefaultFlagValue; +} + } // namespace InterventionsInternalsPageHandler::InterventionsInternalsPageHandler( mojom::InterventionsInternalsPageHandlerRequest request, - previews::PreviewsUIService* previews_ui_service) + previews::PreviewsUIService* previews_ui_service, + UINetworkQualityEstimatorService* ui_nqe_service) : binding_(this, std::move(request)), previews_ui_service_(previews_ui_service), + ui_nqe_service_(ui_nqe_service), current_estimated_ect_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) { logger_ = previews_ui_service_->previews_logger(); DCHECK(logger_); @@ -37,6 +83,7 @@ InterventionsInternalsPageHandler::~InterventionsInternalsPageHandler() { DCHECK(logger_); logger_->RemoveObserver(this); + ui_nqe_service_->RemoveEffectiveConnectionTypeObserver(this); } void InterventionsInternalsPageHandler::SetClientPage( @@ -45,6 +92,7 @@ DCHECK(page_); OnEffectiveConnectionTypeChanged(current_estimated_ect_); logger_->AddAndNotifyObserver(this); + ui_nqe_service_->AddEffectiveConnectionTypeObserver(this); } void InterventionsInternalsPageHandler::OnEffectiveConnectionTypeChanged( @@ -126,3 +174,38 @@ std::move(callback).Run(std::move(statuses)); } + +void InterventionsInternalsPageHandler::GetPreviewsFlagsDetails( + GetPreviewsFlagsDetailsCallback callback) { + std::unordered_map<std::string, mojom::PreviewsFlagPtr> flags; + + auto ect_status = mojom::PreviewsFlag::New(); + ect_status->description = + flag_descriptions::kForceEffectiveConnectionTypeName; + ect_status->link = kEctFlagLink; + std::string ect_value = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kForceEffectiveConnectionType); + ect_status->value = ect_value.empty() ? kDefaultFlagValue : ect_value; + flags[kEctFlag] = std::move(ect_status); + + auto noscript_status = mojom::PreviewsFlag::New(); + noscript_status->description = flag_descriptions::kEnableNoScriptPreviewsName; + noscript_status->link = kNoScriptFlagLink; + noscript_status->value = GetFeatureFlagStatus(kNoScriptFeatureName); + flags[kNoScriptFlag] = std::move(noscript_status); + + auto offline_page_status = mojom::PreviewsFlag::New(); +#if defined(OS_ANDROID) + offline_page_status->description = + flag_descriptions::kEnableOfflinePreviewsName; + offline_page_status->value = GetFeatureFlagStatus(kOfflinePageFeatureName); +#else + offline_page_status->description = "Offline Page Previews"; + offline_page_status->value = "Only support on Android"; +#endif // OS_ANDROID + offline_page_status->link = kOfflinePageFlagLink; + flags[kOfflinePageFlag] = std::move(offline_page_status); + + std::move(callback).Run(std::move(flags)); +}
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h index bcf7246..1fe7f28 100644 --- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h +++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_UI_WEBUI_INTERVENTIONS_INTERNALS_INTERVENTIONS_INTERNALS_PAGE_HANDLER_H_ #define CHROME_BROWSER_UI_WEBUI_INTERVENTIONS_INTERNALS_INTERVENTIONS_INTERNALS_PAGE_HANDLER_H_ +#include <string> + #include "base/macros.h" #include "base/time/time.h" #include "chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom.h" @@ -16,6 +18,8 @@ #include "net/nqe/effective_connection_type.h" #include "net/nqe/effective_connection_type_observer.h" +class UINetworkQualityEstimatorService; + class InterventionsInternalsPageHandler : public previews::PreviewsLoggerObserver, public net::EffectiveConnectionTypeObserver, @@ -24,11 +28,14 @@ public: InterventionsInternalsPageHandler( mojom::InterventionsInternalsPageHandlerRequest request, - previews::PreviewsUIService* previews_ui_service); + previews::PreviewsUIService* previews_ui_service, + UINetworkQualityEstimatorService* ui_nqe_service); ~InterventionsInternalsPageHandler() override; // mojom::InterventionsInternalsPageHandler: void GetPreviewsEnabled(GetPreviewsEnabledCallback callback) override; + void GetPreviewsFlagsDetails( + GetPreviewsFlagsDetailsCallback callback) override; void SetClientPage(mojom::InterventionsInternalsPagePtr page) override; void SetIgnorePreviewsBlacklistDecision(bool ignore) override; @@ -56,6 +63,10 @@ // guaranteed to outlive |this|. previews::PreviewsUIService* previews_ui_service_; + // A pointer to the UINetworkQualityEsitmatorService, guaranteed to outlive + // |this|. + UINetworkQualityEstimatorService* ui_nqe_service_; + // The current estimated effective connection type. net::EffectiveConnectionType current_estimated_ect_;
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc index 2827ed95..96eaa1e9 100644 --- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
@@ -4,43 +4,88 @@ #include "chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h" +#include <memory> #include <string> #include <unordered_map> +#include <utility> #include <vector> +#include "base/base_switches.h" +#include "base/command_line.h" #include "base/macros.h" #include "base/run_loop.h" +#include "base/test/scoped_command_line.h" #include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" +#include "build/build_config.h" +#include "chrome/browser/flag_descriptions.h" +#include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" #include "components/previews/content/previews_io_data.h" #include "components/previews/content/previews_ui_service.h" #include "components/previews/core/previews_features.h" #include "components/previews/core/previews_logger.h" #include "components/previews/core/previews_logger_observer.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "mojo/public/cpp/bindings/binding.h" +#include "net/nqe/effective_connection_type.h" #include "testing/gtest/include/gtest/gtest.h" namespace { -// The key for the mapping for the enabled/disabled status map. +// The keys for the mapping for the enabled/disabled status map. constexpr char kAMPRedirectionPreviews[] = "ampPreviews"; constexpr char kClientLoFiPreviews[] = "clientLoFiPreviews"; constexpr char kNoScriptPreviews[] = "noScriptPreviews"; constexpr char kOfflinePreviews[] = "offlinePreviews"; -// Description for statuses. +// Descriptions for previews. constexpr char kAmpRedirectionDescription[] = "AMP Previews"; constexpr char kClientLoFiDescription[] = "Client LoFi Previews"; constexpr char kNoScriptDescription[] = "NoScript Previews"; constexpr char kOfflineDesciption[] = "Offline Previews"; -// The map that would be passed to the callback in GetPreviewsEnabledCallback. -std::unordered_map<std::string, mojom::PreviewsStatusPtr> passed_in_map; +// Keys for flags mapping. +constexpr char kEctFlag[] = "ectFlag"; +constexpr char kNoScriptFlag[] = "noScriptFlag"; +constexpr char kOfflinePageFlag[] = "offlinePageFlag"; +// Links to flags in chrome://flags. +constexpr char kNoScriptFlagLink[] = "chrome://flags/#enable-noscript-previews"; +constexpr char kEctFlagLink[] = + "chrome://flags/#force-effective-connection-type"; +constexpr char kOfflinePageFlagLink[] = + "chrome://flags/#enable-offline-previews"; + +// Flag features names. +constexpr char kNoScriptFeatureName[] = "NoScriptPreviews"; +constexpr char kOfflinePageFeatureName[] = "OfflinePreviews"; + +constexpr char kDefaultFlagValue[] = "Not Forced"; + +// The map that would be passed to the callback in GetPreviewsEnabledCallback. +std::unordered_map<std::string, mojom::PreviewsStatusPtr> passed_in_modes; + +// The map that would be passed to the callback in +// GetPreviewsFlagsDetailsCallback. +std::unordered_map<std::string, mojom::PreviewsFlagPtr> passed_in_flags; + +// Mocked call back method to test GetPreviewsEnabledCallback. void MockGetPreviewsEnabledCallback( std::unordered_map<std::string, mojom::PreviewsStatusPtr> params) { - passed_in_map = std::move(params); + passed_in_modes = std::move(params); +} + +// Mocked call back method to test GetPreviewsFlagsDetailsCallback. +void MockGetPreviewsFlagsCallback( + std::unordered_map<std::string, mojom::PreviewsFlagPtr> params) { + passed_in_flags = std::move(params); } // Dummy method for creating TestPreviewsUIService. @@ -128,6 +173,27 @@ bool remove_is_called_; }; +// Mock class to test interaction between PageHandler and the +// UINetworkQualityEstimatorService. +class TestUINetworkQualityEstimatorService + : public UINetworkQualityEstimatorService { + public: + explicit TestUINetworkQualityEstimatorService(Profile* profile) + : UINetworkQualityEstimatorService(profile), remove_is_called_(false) {} + + // UINetworkQualityEstimatorService: + void RemoveEffectiveConnectionTypeObserver( + net::EffectiveConnectionTypeObserver* observer) override { + remove_is_called_ = true; + } + + bool RemovedObserverIsCalled() const { return remove_is_called_; } + + private: + // Check if the observer removed itself from the observer list. + bool remove_is_called_; +}; + // A dummy class to setup PreviewsUIService. class TestPreviewsIOData : public previews::PreviewsIOData { public: @@ -173,13 +239,11 @@ class InterventionsInternalsPageHandlerTest : public testing::Test { public: InterventionsInternalsPageHandlerTest() - : scoped_task_environment_( - base::test::ScopedTaskEnvironment::MainThreadType::IO) {} + : profile_manager_(TestingBrowserProcess::GetGlobal()) {} ~InterventionsInternalsPageHandlerTest() override {} void SetUp() override { - scoped_task_environment_.RunUntilIdle(); TestPreviewsIOData io_data; std::unique_ptr<TestPreviewsLogger> logger = base::MakeUnique<TestPreviewsLogger>(); @@ -187,10 +251,17 @@ previews_ui_service_ = base::MakeUnique<TestPreviewsUIService>(&io_data, std::move(logger)); + ASSERT_TRUE(profile_manager_.SetUp()); + TestingProfile* test_profile = + profile_manager_.CreateTestingProfile(chrome::kInitialProfile); + ui_nqe_service_ = + base::MakeUnique<TestUINetworkQualityEstimatorService>(test_profile); + mojom::InterventionsInternalsPageHandlerPtr page_handler_ptr; handler_request_ = mojo::MakeRequest(&page_handler_ptr); page_handler_ = base::MakeUnique<InterventionsInternalsPageHandler>( - std::move(handler_request_), previews_ui_service_.get()); + std::move(handler_request_), previews_ui_service_.get(), + ui_nqe_service_.get()); mojom::InterventionsInternalsPagePtr page_ptr; page_request_ = mojo::MakeRequest(&page_ptr); @@ -202,11 +273,16 @@ scoped_feature_list_ = base::MakeUnique<base::test::ScopedFeatureList>(); } + void TearDown() override { profile_manager_.DeleteAllTestingProfiles(); } + + content::TestBrowserThreadBundle thread_bundle_; + protected: - base::test::ScopedTaskEnvironment scoped_task_environment_; + TestingProfileManager profile_manager_; TestPreviewsLogger* logger_; std::unique_ptr<TestPreviewsUIService> previews_ui_service_; + std::unique_ptr<TestUINetworkQualityEstimatorService> ui_nqe_service_; // InterventionsInternalPageHandler's variables. mojom::InterventionsInternalsPageHandlerRequest handler_request_; @@ -219,12 +295,12 @@ std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_; }; -TEST_F(InterventionsInternalsPageHandlerTest, CorrectSizeOfPassingParameters) { +TEST_F(InterventionsInternalsPageHandlerTest, GetPreviewsEnabledCount) { page_handler_->GetPreviewsEnabled( base::BindOnce(&MockGetPreviewsEnabledCallback)); constexpr size_t expected = 4; - EXPECT_EQ(expected, passed_in_map.size()); + EXPECT_EQ(expected, passed_in_modes.size()); } TEST_F(InterventionsInternalsPageHandlerTest, AMPRedirectionDisabled) { @@ -234,8 +310,8 @@ page_handler_->GetPreviewsEnabled( base::BindOnce(&MockGetPreviewsEnabledCallback)); - auto amp_redirection = passed_in_map.find(kAMPRedirectionPreviews); - ASSERT_NE(passed_in_map.end(), amp_redirection); + auto amp_redirection = passed_in_modes.find(kAMPRedirectionPreviews); + ASSERT_NE(passed_in_modes.end(), amp_redirection); EXPECT_EQ(kAmpRedirectionDescription, amp_redirection->second->description); EXPECT_FALSE(amp_redirection->second->enabled); } @@ -247,8 +323,8 @@ page_handler_->GetPreviewsEnabled( base::BindOnce(&MockGetPreviewsEnabledCallback)); - auto amp_redirection = passed_in_map.find(kAMPRedirectionPreviews); - ASSERT_NE(passed_in_map.end(), amp_redirection); + auto amp_redirection = passed_in_modes.find(kAMPRedirectionPreviews); + ASSERT_NE(passed_in_modes.end(), amp_redirection); EXPECT_EQ(kAmpRedirectionDescription, amp_redirection->second->description); EXPECT_TRUE(amp_redirection->second->enabled); } @@ -259,8 +335,8 @@ page_handler_->GetPreviewsEnabled( base::BindOnce(&MockGetPreviewsEnabledCallback)); - auto client_lofi = passed_in_map.find(kClientLoFiPreviews); - ASSERT_NE(passed_in_map.end(), client_lofi); + auto client_lofi = passed_in_modes.find(kClientLoFiPreviews); + ASSERT_NE(passed_in_modes.end(), client_lofi); EXPECT_EQ(kClientLoFiDescription, client_lofi->second->description); EXPECT_FALSE(client_lofi->second->enabled); } @@ -271,8 +347,8 @@ page_handler_->GetPreviewsEnabled( base::BindOnce(&MockGetPreviewsEnabledCallback)); - auto client_lofi = passed_in_map.find(kClientLoFiPreviews); - ASSERT_NE(passed_in_map.end(), client_lofi); + auto client_lofi = passed_in_modes.find(kClientLoFiPreviews); + ASSERT_NE(passed_in_modes.end(), client_lofi); EXPECT_EQ(kClientLoFiDescription, client_lofi->second->description); EXPECT_TRUE(client_lofi->second->enabled); } @@ -284,8 +360,8 @@ page_handler_->GetPreviewsEnabled( base::BindOnce(&MockGetPreviewsEnabledCallback)); - auto noscript = passed_in_map.find(kNoScriptPreviews); - ASSERT_NE(passed_in_map.end(), noscript); + auto noscript = passed_in_modes.find(kNoScriptPreviews); + ASSERT_NE(passed_in_modes.end(), noscript); EXPECT_EQ(kNoScriptDescription, noscript->second->description); EXPECT_FALSE(noscript->second->enabled); } @@ -297,8 +373,8 @@ page_handler_->GetPreviewsEnabled( base::BindOnce(&MockGetPreviewsEnabledCallback)); - auto noscript = passed_in_map.find(kNoScriptPreviews); - ASSERT_NE(passed_in_map.end(), noscript); + auto noscript = passed_in_modes.find(kNoScriptPreviews); + ASSERT_NE(passed_in_modes.end(), noscript); EXPECT_EQ(kNoScriptDescription, noscript->second->description); EXPECT_TRUE(noscript->second->enabled); } @@ -310,8 +386,8 @@ page_handler_->GetPreviewsEnabled( base::BindOnce(&MockGetPreviewsEnabledCallback)); - auto offline_previews = passed_in_map.find(kOfflinePreviews); - ASSERT_NE(passed_in_map.end(), offline_previews); + auto offline_previews = passed_in_modes.find(kOfflinePreviews); + ASSERT_NE(passed_in_modes.end(), offline_previews); EXPECT_EQ(kOfflineDesciption, offline_previews->second->description); EXPECT_FALSE(offline_previews->second->enabled); } @@ -323,13 +399,165 @@ page_handler_->GetPreviewsEnabled( base::BindOnce(&MockGetPreviewsEnabledCallback)); - auto offline_previews = passed_in_map.find(kOfflinePreviews); - ASSERT_NE(passed_in_map.end(), offline_previews); + auto offline_previews = passed_in_modes.find(kOfflinePreviews); + ASSERT_NE(passed_in_modes.end(), offline_previews); EXPECT_TRUE(offline_previews->second); EXPECT_EQ(kOfflineDesciption, offline_previews->second->description); EXPECT_TRUE(offline_previews->second->enabled); } +TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsCount) { + page_handler_->GetPreviewsFlagsDetails( + base::BindOnce(&MockGetPreviewsFlagsCallback)); + + constexpr size_t expected = 3; + EXPECT_EQ(expected, passed_in_flags.size()); +} + +TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsEctDefaultValue) { + page_handler_->GetPreviewsFlagsDetails( + base::BindOnce(&MockGetPreviewsFlagsCallback)); + auto ect_flag = passed_in_flags.find(kEctFlag); + + ASSERT_NE(passed_in_flags.end(), ect_flag); + EXPECT_EQ(flag_descriptions::kForceEffectiveConnectionTypeName, + ect_flag->second->description); + EXPECT_EQ(kDefaultFlagValue, ect_flag->second->value); + EXPECT_EQ(kEctFlagLink, ect_flag->second->link); +} + +TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsForceEctValue) { + std::string expected_ects[] = { + net::kEffectiveConnectionTypeUnknown, + net::kEffectiveConnectionTypeOffline, + net::kEffectiveConnectionTypeSlow2G, + net::kEffectiveConnectionType3G, + net::kEffectiveConnectionType4G, + }; + + base::test::ScopedCommandLine scoped_command_line; + base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine(); + for (auto expected_ect : expected_ects) { + command_line->AppendSwitchASCII(switches::kForceEffectiveConnectionType, + expected_ect); + page_handler_->GetPreviewsFlagsDetails( + base::BindOnce(&MockGetPreviewsFlagsCallback)); + auto ect_flag = passed_in_flags.find(kEctFlag); + + ASSERT_NE(passed_in_flags.end(), ect_flag); + EXPECT_EQ(flag_descriptions::kForceEffectiveConnectionTypeName, + ect_flag->second->description); + EXPECT_EQ(expected_ect, ect_flag->second->value); + EXPECT_EQ(kEctFlagLink, ect_flag->second->link); + } +} + +TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsNoScriptDefaultValue) { + page_handler_->GetPreviewsFlagsDetails( + base::BindOnce(&MockGetPreviewsFlagsCallback)); + auto noscript_flag = passed_in_flags.find(kNoScriptFlag); + + ASSERT_NE(passed_in_flags.end(), noscript_flag); + EXPECT_EQ(flag_descriptions::kEnableNoScriptPreviewsName, + noscript_flag->second->description); + EXPECT_EQ(kDefaultFlagValue, noscript_flag->second->value); + EXPECT_EQ(kNoScriptFlagLink, noscript_flag->second->link); +} + +TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsNoScriptEnabled) { + base::test::ScopedCommandLine scoped_command_line; + base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine(); + command_line->AppendSwitchASCII(switches::kEnableFeatures, + kNoScriptFeatureName); + + page_handler_->GetPreviewsFlagsDetails( + base::BindOnce(&MockGetPreviewsFlagsCallback)); + auto noscript_flag = passed_in_flags.find(kNoScriptFlag); + + ASSERT_NE(passed_in_flags.end(), noscript_flag); + EXPECT_EQ(flag_descriptions::kEnableNoScriptPreviewsName, + noscript_flag->second->description); + EXPECT_EQ("Forced Enabled", noscript_flag->second->value); + EXPECT_EQ(kNoScriptFlagLink, noscript_flag->second->link); +} + +TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsNoScriptDisabled) { + base::test::ScopedCommandLine scoped_command_line; + base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine(); + command_line->AppendSwitchASCII(switches::kDisableFeatures, + kNoScriptFeatureName); + + page_handler_->GetPreviewsFlagsDetails( + base::BindOnce(&MockGetPreviewsFlagsCallback)); + auto noscript_flag = passed_in_flags.find(kNoScriptFlag); + + ASSERT_NE(passed_in_flags.end(), noscript_flag); + EXPECT_EQ(flag_descriptions::kEnableNoScriptPreviewsName, + noscript_flag->second->description); + EXPECT_EQ("Forced Disabled", noscript_flag->second->value); + EXPECT_EQ(kNoScriptFlagLink, noscript_flag->second->link); +} + +#if defined(OS_ANDROID) +#define TestAndroid(x) x +#else +#define TestAndroid(x) DISABLED_##x +#endif // OS_ANDROID +TEST_F(InterventionsInternalsPageHandlerTest, + TestAndroid(GetFlagsOfflinePageDefaultValue)) { + page_handler_->GetPreviewsFlagsDetails( + base::BindOnce(&MockGetPreviewsFlagsCallback)); + auto offline_page_flag = passed_in_flags.find(kOfflinePageFlag); + + ASSERT_NE(passed_in_flags.end(), offline_page_flag); +#if defined(OS_ANDROID) + EXPECT_EQ(flag_descriptions::kEnableOfflinePreviewsName, + offline_page_flag->second->description); +#endif // OS_ANDROID + EXPECT_EQ(kDefaultFlagValue, offline_page_flag->second->value); + EXPECT_EQ(kOfflinePageFlagLink, offline_page_flag->second->link); +} + +TEST_F(InterventionsInternalsPageHandlerTest, + TestAndroid(GetFlagsOfflinePageEnabled)) { + base::test::ScopedCommandLine scoped_command_line; + base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine(); + command_line->AppendSwitchASCII(switches::kEnableFeatures, + kOfflinePageFeatureName); + + page_handler_->GetPreviewsFlagsDetails( + base::BindOnce(&MockGetPreviewsFlagsCallback)); + auto offline_page_flag = passed_in_flags.find(kOfflinePageFlag); + + ASSERT_NE(passed_in_flags.end(), offline_page_flag); +#if defined(OS_ANDROID) + EXPECT_EQ(flag_descriptions::kEnableOfflinePreviewsName, + offline_page_flag->second->description); +#endif // OS_ANDROID + EXPECT_EQ("Forced Enabled", offline_page_flag->second->value); + EXPECT_EQ(kOfflinePageFlagLink, offline_page_flag->second->link); +} + +TEST_F(InterventionsInternalsPageHandlerTest, + TestAndroid(GetFlagsOfflinePageDisabled)) { + base::test::ScopedCommandLine scoped_command_line; + base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine(); + command_line->AppendSwitchASCII(switches::kDisableFeatures, + kOfflinePageFeatureName); + + page_handler_->GetPreviewsFlagsDetails( + base::BindOnce(&MockGetPreviewsFlagsCallback)); + auto offline_page_flag = passed_in_flags.find(kOfflinePageFlag); + + ASSERT_NE(passed_in_flags.end(), offline_page_flag); +#if defined(OS_ANDROID) + EXPECT_EQ(flag_descriptions::kEnableOfflinePreviewsName, + offline_page_flag->second->description); +#endif // OS_ANDROID + EXPECT_EQ("Forced Disabled", offline_page_flag->second->value); + EXPECT_EQ(kOfflinePageFlagLink, offline_page_flag->second->link); +} + TEST_F(InterventionsInternalsPageHandlerTest, OnNewMessageLogAddedPostToPage) { const previews::PreviewsLogger::MessageLog expected_messages[] = { previews::PreviewsLogger::MessageLog("Event_a", "Some description a", @@ -358,8 +586,10 @@ TEST_F(InterventionsInternalsPageHandlerTest, ObserverIsRemovedWhenDestroyed) { EXPECT_FALSE(logger_->RemovedObserverIsCalled()); + EXPECT_FALSE(ui_nqe_service_->RemovedObserverIsCalled()); page_handler_.reset(); EXPECT_TRUE(logger_->RemovedObserverIsCalled()); + EXPECT_TRUE(ui_nqe_service_->RemovedObserverIsCalled()); } TEST_F(InterventionsInternalsPageHandlerTest, OnNewBlacklistedHostPostToPage) {
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc index 161a649..0e1930ed 100644 --- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc +++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc
@@ -5,6 +5,8 @@ #include "chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.h" #include <string> +#include <utility> +#include <vector> #include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h" #include "chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.h" @@ -60,18 +62,12 @@ UINetworkQualityEstimatorServiceFactory::GetForProfile(profile); } -InterventionsInternalsUI::~InterventionsInternalsUI() { - if (page_handler_) { - // |page_handler_| was not initialized in Guest Mode or Incognito Mode. - ui_nqe_service_->RemoveEffectiveConnectionTypeObserver(page_handler_.get()); - } -} +InterventionsInternalsUI::~InterventionsInternalsUI() {} void InterventionsInternalsUI::BindUIHandler( mojom::InterventionsInternalsPageHandlerRequest request) { DCHECK(previews_ui_service_); DCHECK(ui_nqe_service_); page_handler_.reset(new InterventionsInternalsPageHandler( - std::move(request), previews_ui_service_)); - ui_nqe_service_->AddEffectiveConnectionTypeObserver(page_handler_.get()); + std::move(request), previews_ui_service_, ui_nqe_service_)); }
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 d00c0ba..05c7f59 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
@@ -732,11 +732,33 @@ #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) void AddChromeCleanupStrings(content::WebUIDataSource* html_source) { + const wchar_t kUnwantedSoftwareProtectionWhitePaperUrl[] = + L"https://www.google.ca/chrome/browser/privacy/" + "whitepaper.html#unwantedsoftware"; + LocalizedString localized_strings[] = { - {"chromeCleanupExplanation", - IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_REMOVE}, + {"chromeCleanupPageTitle", + IDS_SETTINGS_RESET_CLEAN_UP_COMPUTER_PAGE_TITLE}, + {"chromeCleanupDetailsFilesAndPrograms", + IDS_SETTINGS_RESET_CLEANUP_DETAILS_FILES_AND_PROGRAMS}, + {"chromeCleanupDetailsRegistryEntries", + IDS_SETTINGS_RESET_CLEANUP_DETAILS_REGISTRY_ENTRIES}, {"chromeCleanupDoneButtonLabel", IDS_SETTINGS_RESET_CLEANUP_DONE_BUTTON_LABEL}, + {"chromeCleanupExplanationCleanupError", + IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_CLEANUP_ERROR}, + {"chromeCleanupExplanationFindAndRemove", + IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_FIND_AND_REMOVE}, + {"chromeCleanupExplanationNoInternet", + IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_NO_INTERNET_CONNECTION}, + {"chromeCleanupExplanationPermissionsNeeded", + IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_PERMISSIONS_NEEDED}, + {"chromeCleanupExplanationRemove", + IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_REMOVE}, + {"chromeCleanupExplanationScanError", + IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_SCAN_ERROR}, + {"chromeCleanupFindButtonLable", + IDS_SETTINGS_RESET_CLEANUP_FIND_BUTTON_LABEL}, {"chromeCleanupLinkShowFiles", IDS_SETTINGS_RESET_CLEANUP_LINK_SHOW_FILES}, {"chromeCleanupLogsUploadPermission", IDS_CHROME_CLEANUP_LOGS_PERMISSION}, @@ -744,13 +766,30 @@ IDS_SETTINGS_RESET_CLEANUP_REMOVE_BUTTON_LABEL}, {"chromeCleanupRestartButtonLabel", IDS_SETTINGS_RESET_CLEANUP_RESTART_BUTTON_LABEL}, + {"chromeCleanupTitleDone", IDS_SETTINGS_RESET_CLEANUP_TITLE_DONE}, {"chromeCleanupTitleErrorCantRemove", IDS_SETTINGS_RESET_CLEANUP_TITLE_ERROR_CANT_REMOVE}, + {"chromeCleanupTitleErrorPermissions", + IDS_SETTINGS_RESET_CLEANUP_TITLE_ERROR_PERMISSIONS_NEEDED}, + {"chromeCleanupTitleFindAndRemove", + IDS_SETTINGS_RESET_CLEANUP_TITLE_FIND_AND_REMOVE}, + {"chromeCleanupTitleNoInternet", + IDS_SETTINGS_RESET_CLEANUP_TITLE_NO_INTERNET_CONNECTION}, + {"chromeCleanupTitleNothingFound", + IDS_SETTINGS_RESET_CLEANUP_TITLE_NOTHING_FOUND}, {"chromeCleanupTitleRemove", IDS_SETTINGS_RESET_CLEANUP_TITLE_REMOVE}, {"chromeCleanupTitleRemoved", IDS_SETTINGS_RESET_CLEANUP_TITLE_REMOVED}, {"chromeCleanupTitleRemoving", IDS_SETTINGS_RESET_CLEANUP_TITLE_REMOVING}, {"chromeCleanupTitleRestart", IDS_SETTINGS_RESET_CLEANUP_TITLE_RESTART}, + {"chromeCleanupTitleScanning", IDS_SETTINGS_RESET_CLEANUP_TITLE_SCANNING}, + {"chromeCleanupTitleScanningFailed", + IDS_SETTINGS_RESET_CLEANUP_TITLE_ERROR_SCANNING_FAILED}, + {"chromeCleanupTitleTryAgainButtonLabel", + IDS_SETTINGS_RESET_CLEANUP_TRY_AGAIN_BUTTON_LABEL}, + {"chromeCleanupTitleLogsPermissionExplanation", + IDS_SETTINGS_RESET_CLEANUP_LOGS_PERMISSION_EXPLANATION}, }; + AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings)); const std::string cleanup_learn_more_url = @@ -760,15 +799,16 @@ .spec(); html_source->AddString("chromeCleanupLearnMoreUrl", cleanup_learn_more_url); - // TODO(crbug.com/776538): Localize these strings. - html_source->AddString("chromeCleanupPageTitle", "Clean up computer"); - html_source->AddString("chromeCleanupPageTriggerDescription", - "Find and remove harmful software"); - - base::string16 powered_by_html = + const base::string16 powered_by_html = l10n_util::GetStringFUTF16(IDS_SETTINGS_RESET_CLEANUP_FOOTER_POWERED_BY, L"<span id='powered-by-logo'></span>"); html_source->AddString("chromeCleanupPoweredByHtml", powered_by_html); + + const base::string16 cleanup_details_explanation = + l10n_util::GetStringFUTF16(IDS_SETTINGS_RESET_CLEANUP_DETAILS_EXPLANATION, + kUnwantedSoftwareProtectionWhitePaperUrl); + html_source->AddString("chromeCleanupDetailsExplanation", + cleanup_details_explanation); } #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) @@ -793,6 +833,14 @@ {"resetAutomatedDialogTitle", IDS_SETTINGS_RESET_AUTOMATED_DIALOG_TITLE}, {"resetProfileBannerButton", IDS_SETTINGS_RESET_BANNER_RESET_BUTTON_TEXT}, {"resetProfileBannerDescription", IDS_SETTINGS_RESET_BANNER_TEXT}, +#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) + // The page title to be used if user initiated cleanups are enabled. + {"resetAndCleanupPageTitle", IDS_SETTINGS_RESET_AND_CLEANUP}, + {"resetCleanupComputerTrigger", + IDS_SETTINGS_RESET_CLEAN_UP_COMPUTER_TRIGGER}, + {"resetCleanupComputerTriggerDescription", + IDS_SETTINGS_RESET_CLEAN_UP_COMPUTER_TRIGGER_DESCRIPTION}, +#endif }; AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings));
diff --git a/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc b/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc index 2cdebf6d..e5535f6d 100644 --- a/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc +++ b/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc
@@ -197,7 +197,7 @@ base::DictionaryValue dict; static const char* keys[] = { - prefs::kEnableTranslate, + prefs::kOfferTranslateEnabled, translate::TranslatePrefs::kPrefTranslateBlockedLanguages, translate::TranslatePrefs::kPrefTranslateSiteBlacklist, translate::TranslatePrefs::kPrefTranslateWhitelists,
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index f77e26c..4ca96015 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -122,6 +122,7 @@ "model/model.h", "model/omnibox_suggestions.cc", "model/omnibox_suggestions.h", + "model/permissions_model.h", "model/reticle_model.h", "model/speech_recognition_model.h", "model/toolbar_state.cc",
diff --git a/chrome/browser/vr/browser_ui_interface.h b/chrome/browser/vr/browser_ui_interface.h index 6ab3234..51bd1ee 100644 --- a/chrome/browser/vr/browser_ui_interface.h +++ b/chrome/browser/vr/browser_ui_interface.h
@@ -27,11 +27,11 @@ virtual void SetIsExiting() = 0; virtual void SetHistoryButtonsEnabled(bool can_go_back, bool can_go_forward) = 0; - virtual void SetVideoCapturingIndicator(bool enabled) = 0; - virtual void SetScreenCapturingIndicator(bool enabled) = 0; - virtual void SetAudioCapturingIndicator(bool enabled) = 0; - virtual void SetBluetoothConnectedIndicator(bool enabled) = 0; - virtual void SetLocationAccessIndicator(bool enabled) = 0; + virtual void SetVideoCaptureEnabled(bool enabled) = 0; + virtual void SetScreenCaptureEnabled(bool enabled) = 0; + virtual void SetAudioCaptureEnabled(bool enabled) = 0; + virtual void SetBluetoothConnected(bool enabled) = 0; + virtual void SetLocationAccess(bool enabled) = 0; virtual void SetExitVrPromptEnabled(bool enabled, UiUnsupportedMode reason) = 0; virtual void SetSpeechRecognitionEnabled(bool enabled) = 0;
diff --git a/chrome/browser/vr/color_scheme.cc b/chrome/browser/vr/color_scheme.cc index 1a80882f..9a65595 100644 --- a/chrome/browser/vr/color_scheme.cc +++ b/chrome/browser/vr/color_scheme.cc
@@ -27,7 +27,7 @@ normal_scheme.element_background = 0xCCB3B3B3; normal_scheme.element_background_hover = 0xFFCCCCCC; normal_scheme.element_background_down = 0xFFF3F3F3; - normal_scheme.button_colors.foreground = normal_scheme.element_foreground; + normal_scheme.button_colors.foreground = 0x87000000; normal_scheme.button_colors.background = normal_scheme.element_background; normal_scheme.button_colors.background_hover = normal_scheme.element_background_hover;
diff --git a/chrome/browser/vr/elements/button.cc b/chrome/browser/vr/elements/button.cc index 96057c5..37f25c3 100644 --- a/chrome/browser/vr/elements/button.cc +++ b/chrome/browser/vr/elements/button.cc
@@ -20,10 +20,6 @@ constexpr float kIconScaleFactor = 0.5; constexpr float kHitPlaneScaleFactorHovered = 1.2; -constexpr float kBackgroundZOffset = -kTextureOffset; -constexpr float kForegroundZOffset = kTextureOffset; -constexpr float kBackgroundZOffsetHover = kTextureOffset; -constexpr float kForegroundZOffsetHover = 4 * kTextureOffset; } // namespace @@ -31,8 +27,9 @@ int draw_phase, float width, float height, + float hover_offset, const gfx::VectorIcon& icon) - : click_handler_(click_handler) { + : click_handler_(click_handler), hover_offset_(hover_offset) { set_draw_phase(draw_phase); set_hit_testable(false); SetSize(width, height); @@ -45,7 +42,6 @@ background->SetTransitionedProperties({TRANSFORM}); background->set_corner_radius(width / 2); background->set_hit_testable(false); - background->SetTranslate(0.0, 0.0, kBackgroundZOffset); background_ = background.get(); AddChild(std::move(background)); @@ -57,7 +53,6 @@ vector_icon->SetSize(width * kIconScaleFactor, height * kIconScaleFactor); vector_icon->SetTransitionedProperties({TRANSFORM}); vector_icon->set_hit_testable(false); - vector_icon->SetTranslate(0.0, 0.0, kForegroundZOffset); foreground_ = vector_icon.get(); AddChild(std::move(vector_icon)); @@ -125,13 +120,13 @@ pressed_ = hovered_ ? down_ : false; if (hovered_) { - background_->SetTranslate(0.0, 0.0, kBackgroundZOffsetHover); - foreground_->SetTranslate(0.0, 0.0, kForegroundZOffsetHover); + background_->SetTranslate(0.0, 0.0, hover_offset_); + foreground_->SetTranslate(0.0, 0.0, hover_offset_); hit_plane_->SetScale(kHitPlaneScaleFactorHovered, kHitPlaneScaleFactorHovered, 1.0f); } else { - background_->SetTranslate(0.0, 0.0, kBackgroundZOffset); - foreground_->SetTranslate(0.0, 0.0, kForegroundZOffset); + background_->SetTranslate(0.0, 0.0, 0.0); + foreground_->SetTranslate(0.0, 0.0, 0.0); hit_plane_->SetScale(1.0f, 1.0f, 1.0f); }
diff --git a/chrome/browser/vr/elements/button.h b/chrome/browser/vr/elements/button.h index 5fb8416..1e5aa635 100644 --- a/chrome/browser/vr/elements/button.h +++ b/chrome/browser/vr/elements/button.h
@@ -31,6 +31,7 @@ int draw_phase, float width, float height, + float hover_offset, const gfx::VectorIcon& icon); ~Button() override; @@ -55,6 +56,7 @@ bool hovered_ = false; bool pressed_ = false; base::Callback<void()> click_handler_; + float hover_offset_; ButtonColors colors_; Rect* background_;
diff --git a/chrome/browser/vr/elements/button_unittest.cc b/chrome/browser/vr/elements/button_unittest.cc index a959633..b448134 100644 --- a/chrome/browser/vr/elements/button_unittest.cc +++ b/chrome/browser/vr/elements/button_unittest.cc
@@ -20,7 +20,7 @@ TEST(Button, HoverTest) { auto button = base::MakeUnique<Button>(base::Callback<void()>(), kPhaseForeground, 1.0, - 1.0, vector_icons::kMicrophoneIcon); + 1.0, 0.5, vector_icons::kMicrophoneIcon); cc::TransformOperation foreground_op = button->foreground()->GetTargetTransform().at(UiElement::kTranslateIndex);
diff --git a/chrome/browser/vr/elements/ui_element.cc b/chrome/browser/vr/elements/ui_element.cc index 3caefd4..e9ae8f5 100644 --- a/chrome/browser/vr/elements/ui_element.cc +++ b/chrome/browser/vr/elements/ui_element.cc
@@ -460,7 +460,7 @@ if (!child->IsVisible()) { continue; } - gfx::Point3F child_center; + gfx::Point3F child_center(child->local_origin()); child->LocalTransform().TransformPoint(&child_center); gfx::RectF local_rect = gfx::RectF(child_center.x() - 0.5 * child->size().width(),
diff --git a/chrome/browser/vr/elements/ui_element_unittest.cc b/chrome/browser/vr/elements/ui_element_unittest.cc index c6f5c008..a45be3d8 100644 --- a/chrome/browser/vr/elements/ui_element_unittest.cc +++ b/chrome/browser/vr/elements/ui_element_unittest.cc
@@ -64,6 +64,16 @@ parent->DoLayOutChildren(); EXPECT_RECT_NEAR(gfx::RectF(-0.5f, 0.5f, 9.2f, 7.4f), gfx::RectF(parent->local_origin(), parent->size()), epsilon); + + auto grand_parent = base::MakeUnique<UiElement>(); + grand_parent->set_bounds_contain_children(true); + grand_parent->set_padding(0.1, 0.2); + grand_parent->AddChild(std::move(parent)); + + grand_parent->DoLayOutChildren(); + EXPECT_RECT_NEAR( + gfx::RectF(-0.5f, 0.5f, 9.4f, 7.8f), + gfx::RectF(grand_parent->local_origin(), grand_parent->size()), epsilon); } TEST(UiElements, AnimateSize) {
diff --git a/chrome/browser/vr/model/model.h b/chrome/browser/vr/model/model.h index 6e9ea57..9e25410 100644 --- a/chrome/browser/vr/model/model.h +++ b/chrome/browser/vr/model/model.h
@@ -8,6 +8,7 @@ #include "chrome/browser/vr/model/controller_model.h" #include "chrome/browser/vr/model/modal_prompt_type.h" #include "chrome/browser/vr/model/omnibox_suggestions.h" +#include "chrome/browser/vr/model/permissions_model.h" #include "chrome/browser/vr/model/reticle_model.h" #include "chrome/browser/vr/model/speech_recognition_model.h" #include "chrome/browser/vr/model/toolbar_state.h" @@ -34,6 +35,8 @@ ModalPromptType active_modal_prompt_type = kModalPromptTypeNone; + PermissionsModel permissions; + ToolbarState toolbar_state; std::vector<OmniboxSuggestion> omnibox_suggestions; };
diff --git a/chrome/browser/vr/model/permissions_model.h b/chrome/browser/vr/model/permissions_model.h new file mode 100644 index 0000000..696aa108 --- /dev/null +++ b/chrome/browser/vr/model/permissions_model.h
@@ -0,0 +1,20 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_VR_MODEL_PERMISSIONS_MODEL_H_ +#define CHROME_BROWSER_VR_MODEL_PERMISSIONS_MODEL_H_ + +namespace vr { + +struct PermissionsModel { + bool audio_capture_enabled = false; + bool video_capture_enabled = false; + bool screen_capture_enabled = false; + bool location_access = false; + bool bluetooth_connected = false; +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_MODEL_PERMISSIONS_MODEL_H_
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc index 76b3c85..c7a2e10 100644 --- a/chrome/browser/vr/testapp/vr_test_context.cc +++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -65,6 +65,7 @@ base::i18n::InitializeICU(); ui_ = base::MakeUnique<Ui>(this, nullptr, UiInitialState()); + model_ = ui_->model_for_test(); GURL gurl("https://dangerous.com/dir/file.html"); ToolbarState state(gurl, security_state::SecurityLevel::DANGEROUS, @@ -74,11 +75,11 @@ ui_->SetHistoryButtonsEnabled(true, true); ui_->SetLoading(true); ui_->SetLoadProgress(0.4); - ui_->SetVideoCapturingIndicator(true); - ui_->SetScreenCapturingIndicator(true); - ui_->SetAudioCapturingIndicator(true); - ui_->SetBluetoothConnectedIndicator(true); - ui_->SetLocationAccessIndicator(true); + ui_->SetVideoCaptureEnabled(true); + ui_->SetScreenCaptureEnabled(true); + ui_->SetAudioCaptureEnabled(true); + ui_->SetBluetoothConnected(true); + ui_->SetLocationAccess(true); } VrTestContext::~VrTestContext() = default; @@ -127,6 +128,10 @@ case ui::DomCode::US_S: { CreateFakeOmniboxSuggestions(); break; + case ui::DomCode::US_V: + ui_->SetVideoCaptureEnabled( + !model_->permissions.video_capture_enabled); + break; } default: break;
diff --git a/chrome/browser/vr/testapp/vr_test_context.h b/chrome/browser/vr/testapp/vr_test_context.h index 10e7155e..e1604be 100644 --- a/chrome/browser/vr/testapp/vr_test_context.h +++ b/chrome/browser/vr/testapp/vr_test_context.h
@@ -21,6 +21,7 @@ namespace vr { class Ui; +struct Model; // This class provides a home for the VR UI in a testapp context, and // manipulates the UI according to user input. @@ -67,6 +68,9 @@ float view_scale_factor_ = 1.f; + // This avoids storing a duplicate of the model state here. + Model* model_; + bool fullscreen_ = false; bool incognito_ = false;
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc index 6f49bc8..6960a62 100644 --- a/chrome/browser/vr/ui.cc +++ b/chrome/browser/vr/ui.cc
@@ -86,24 +86,24 @@ scene_manager_->SetHistoryButtonsEnabled(can_go_back, can_go_forward); } -void Ui::SetVideoCapturingIndicator(bool enabled) { - scene_manager_->SetVideoCapturingIndicator(enabled); +void Ui::SetVideoCaptureEnabled(bool enabled) { + model_->permissions.video_capture_enabled = enabled; } -void Ui::SetScreenCapturingIndicator(bool enabled) { - scene_manager_->SetScreenCapturingIndicator(enabled); +void Ui::SetScreenCaptureEnabled(bool enabled) { + model_->permissions.screen_capture_enabled = enabled; } -void Ui::SetAudioCapturingIndicator(bool enabled) { - scene_manager_->SetAudioCapturingIndicator(enabled); +void Ui::SetAudioCaptureEnabled(bool enabled) { + model_->permissions.audio_capture_enabled = enabled; } -void Ui::SetBluetoothConnectedIndicator(bool enabled) { - scene_manager_->SetBluetoothConnectedIndicator(enabled); +void Ui::SetBluetoothConnected(bool enabled) { + model_->permissions.bluetooth_connected = enabled; } -void Ui::SetLocationAccessIndicator(bool enabled) { - scene_manager_->SetLocationAccessIndicator(enabled); +void Ui::SetLocationAccess(bool enabled) { + model_->permissions.location_access = enabled; } void Ui::SetExitVrPromptEnabled(bool enabled, UiUnsupportedMode reason) {
diff --git a/chrome/browser/vr/ui.h b/chrome/browser/vr/ui.h index efb4adbf..ded6cda 100644 --- a/chrome/browser/vr/ui.h +++ b/chrome/browser/vr/ui.h
@@ -64,11 +64,11 @@ void SetLoadProgress(float progress) override; void SetIsExiting() override; void SetHistoryButtonsEnabled(bool can_go_back, bool can_go_forward) override; - void SetVideoCapturingIndicator(bool enabled) override; - void SetScreenCapturingIndicator(bool enabled) override; - void SetAudioCapturingIndicator(bool enabled) override; - void SetBluetoothConnectedIndicator(bool enabled) override; - void SetLocationAccessIndicator(bool enabled) override; + void SetVideoCaptureEnabled(bool enabled) override; + void SetScreenCaptureEnabled(bool enabled) override; + void SetAudioCaptureEnabled(bool enabled) override; + void SetBluetoothConnected(bool enabled) override; + void SetLocationAccess(bool enabled) override; void SetExitVrPromptEnabled(bool enabled, UiUnsupportedMode reason) override; void SetSpeechRecognitionEnabled(bool enabled) override; void SetRecognitionResult(const base::string16& result) override; @@ -94,6 +94,8 @@ void OnContentBoundsChanged(int width, int height); void OnPlatformControllerInitialized(PlatformController* controller); + Model* model_for_test() { return model_.get(); } + private: UiBrowserInterface* browser_;
diff --git a/chrome/browser/vr/ui_scene_constants.h b/chrome/browser/vr/ui_scene_constants.h index 2bed899..3e9fb3c9 100644 --- a/chrome/browser/vr/ui_scene_constants.h +++ b/chrome/browser/vr/ui_scene_constants.h
@@ -92,6 +92,8 @@ static constexpr float kSplashScreenTextVerticalOffset = -0.18f; static constexpr float kSplashScreenMinDurationSeconds = 3; +static constexpr float kButtonZOffsetHoverDMM = 0.048; + static constexpr float kCloseButtonDistance = 2.4f; static constexpr float kCloseButtonHeight = kUrlBarHeightDMM * kCloseButtonDistance;
diff --git a/chrome/browser/vr/ui_scene_manager.cc b/chrome/browser/vr/ui_scene_manager.cc index bd05bd71..f8b9394 100644 --- a/chrome/browser/vr/ui_scene_manager.cc +++ b/chrome/browser/vr/ui_scene_manager.cc
@@ -167,7 +167,7 @@ CreateExitPrompt(model); CreateAudioPermissionPrompt(model); CreateWebVRExitWarning(); - CreateSystemIndicators(); + CreateSystemIndicators(model); CreateUrlBar(model); CreateSuggestionList(model); CreateWebVrUrlToast(model); @@ -275,26 +275,29 @@ scene_->AddUiElement(k2dBrowsingViewportAwareRoot, std::move(element)); } -void UiSceneManager::CreateSystemIndicators() { +void UiSceneManager::CreateSystemIndicators(Model* model) { std::unique_ptr<UiElement> element; struct Indicator { - UiElement** element; UiElementName name; const gfx::VectorIcon& icon; int resource_string; + bool PermissionsModel::*signal; }; const std::vector<Indicator> indicators = { - {&audio_capture_indicator_, kAudioCaptureIndicator, - vector_icons::kMicrophoneIcon, IDS_AUDIO_CALL_NOTIFICATION_TEXT_2}, - {&video_capture_indicator_, kVideoCaptureIndicator, - vector_icons::kVideocamIcon, IDS_VIDEO_CALL_NOTIFICATION_TEXT_2}, - {&screen_capture_indicator_, kScreenCaptureIndicator, - vector_icons::kScreenShareIcon, IDS_SCREEN_CAPTURE_NOTIFICATION_TEXT_2}, - {&bluetooth_connected_indicator_, kBluetoothConnectedIndicator, - vector_icons::kBluetoothConnectedIcon, 0}, - {&location_access_indicator_, kLocationAccessIndicator, - vector_icons::kLocationOnIcon, 0}, + {kAudioCaptureIndicator, vector_icons::kMicrophoneIcon, + IDS_AUDIO_CALL_NOTIFICATION_TEXT_2, + &PermissionsModel::audio_capture_enabled}, + {kVideoCaptureIndicator, vector_icons::kVideocamIcon, + IDS_VIDEO_CALL_NOTIFICATION_TEXT_2, + &PermissionsModel::video_capture_enabled}, + {kScreenCaptureIndicator, vector_icons::kScreenShareIcon, + IDS_SCREEN_CAPTURE_NOTIFICATION_TEXT_2, + &PermissionsModel::screen_capture_enabled}, + {kBluetoothConnectedIndicator, vector_icons::kBluetoothConnectedIcon, 0, + &PermissionsModel::bluetooth_connected}, + {kLocationAccessIndicator, vector_icons::kLocationOnIcon, 0, + &PermissionsModel::location_access}, }; std::unique_ptr<LinearLayout> indicator_layout = @@ -305,6 +308,9 @@ indicator_layout->SetTranslate(0, kIndicatorVerticalOffset, kIndicatorDistanceOffset); indicator_layout->set_margin(kIndicatorGap); + indicator_layout->AddBinding( + VR_BIND_FUNC(bool, UiSceneManager, this, fullscreen() == false, UiElement, + indicator_layout.get(), SetVisible)); scene_->AddUiElement(k2dBrowsingContentGroup, std::move(indicator_layout)); for (const auto& indicator : indicators) { @@ -312,9 +318,20 @@ 512, kIndicatorHeight, indicator.icon, indicator.resource_string); element->set_name(indicator.name); element->set_draw_phase(kPhaseForeground); + element->set_requires_layout(false); element->SetVisible(false); - *(indicator.element) = element.get(); - system_indicators_.push_back(element.get()); + element->AddBinding(base::MakeUnique<Binding<bool>>( + base::Bind( + [](Model* m, bool PermissionsModel::*permission) { + return m->permissions.*permission; + }, + base::Unretained(model), indicator.signal), + base::Bind( + [](UiElement* e, const bool& v) { + e->SetVisible(v); + e->set_requires_layout(v); + }, + base::Unretained(element.get())))); scene_->AddUiElement(kIndicatorLayout, std::move(element)); } } @@ -470,6 +487,7 @@ auto button = base::MakeUnique<Button>( base::Bind(&UiSceneManager::OnWebVrTimedOut, base::Unretained(this)), kPhaseOverlayForeground, kTimeoutButtonWidth, kTimeoutButtonHeight, + kButtonZOffsetHoverDMM * kTimeoutButtonDistance, vector_icons::kClose16Icon); button->set_name(kWebVrTimeoutMessageButton); button->SetVisible(false); @@ -590,7 +608,7 @@ base::Bind(&UiSceneManager::OnVoiceSearchButtonClicked, base::Unretained(this)), kPhaseForeground, kVoiceSearchButtonWidth, kVoiceSearchButtonHeight, - vector_icons::kMicrophoneIcon); + kButtonZOffsetHoverDMM * kUrlBarDistance, vector_icons::kMicrophoneIcon); voice_search_button->set_name(kVoiceSearchButton); voice_search_button->SetTranslate(0.f, -kVoiceSearchButtonYOffset, 0.f); voice_search_button->set_y_anchoring(BOTTOM); @@ -742,7 +760,8 @@ base::Bind(&UiSceneManager::OnExitRecognizingSpeechClicked, base::Unretained(this)), kPhaseForeground, kVoiceSearchCloseButtonWidth, - kVoiceSearchCloseButtonHeight, vector_icons::kClose16Icon); + kVoiceSearchCloseButtonHeight, kButtonZOffsetHoverDMM * kContentDistance, + vector_icons::kClose16Icon); close_button->set_name(kSpeechRecognitionListeningCloseButton); close_button->SetTranslate(0.0, -kVoiceSearchCloseButtonYOffset, 0.f); BindColor(this, close_button.get(), &ColorScheme::button_colors); @@ -951,6 +970,7 @@ std::unique_ptr<Button> element = base::MakeUnique<Button>( base::Bind(&UiSceneManager::OnCloseButtonClicked, base::Unretained(this)), kPhaseForeground, kCloseButtonWidth, kCloseButtonHeight, + kButtonZOffsetHoverDMM * kCloseButtonDistance, vector_icons::kClose16Icon); element->set_name(kCloseButton); element->SetTranslate(0, kContentVerticalOffset - (kContentHeight / 2) - 0.3f, @@ -1283,28 +1303,10 @@ scene_->set_reticle_rendering_enabled( !(web_vr_mode_ || exiting_ || showing_web_vr_splash_screen_)); - ConfigureIndicators(); ConfigureBackgroundColor(); scene_->set_dirty(); } -void UiSceneManager::ConfigureIndicators() { - DCHECK(configuring_scene_); - bool allowed = !web_vr_mode_ && !fullscreen_; - audio_capture_indicator_->SetVisible(allowed && audio_capturing_); - video_capture_indicator_->SetVisible(allowed && video_capturing_); - screen_capture_indicator_->SetVisible(allowed && screen_capturing_); - location_access_indicator_->SetVisible(allowed && location_access_); - bluetooth_connected_indicator_->SetVisible(allowed && bluetooth_connected_); - - audio_capture_indicator_->set_requires_layout(allowed && audio_capturing_); - video_capture_indicator_->set_requires_layout(allowed && video_capturing_); - screen_capture_indicator_->set_requires_layout(allowed && screen_capturing_); - location_access_indicator_->set_requires_layout(allowed && location_access_); - bluetooth_connected_indicator_->set_requires_layout(allowed && - bluetooth_connected_); -} - void UiSceneManager::ConfigureBackgroundColor() { DCHECK(configuring_scene_); for (Rect* panel : background_panels_) { @@ -1317,31 +1319,6 @@ floor_->SetGridColor(color_scheme().floor_grid); } -void UiSceneManager::SetAudioCapturingIndicator(bool enabled) { - audio_capturing_ = enabled; - ConfigureScene(); -} - -void UiSceneManager::SetVideoCapturingIndicator(bool enabled) { - video_capturing_ = enabled; - ConfigureScene(); -} - -void UiSceneManager::SetScreenCapturingIndicator(bool enabled) { - screen_capturing_ = enabled; - ConfigureScene(); -} - -void UiSceneManager::SetLocationAccessIndicator(bool enabled) { - location_access_ = enabled; - ConfigureScene(); -} - -void UiSceneManager::SetBluetoothConnectedIndicator(bool enabled) { - bluetooth_connected_ = enabled; - ConfigureScene(); -} - void UiSceneManager::SetIncognito(bool incognito) { if (incognito == incognito_) return;
diff --git a/chrome/browser/vr/ui_scene_manager.h b/chrome/browser/vr/ui_scene_manager.h index 98e5165..d23d6999 100644 --- a/chrome/browser/vr/ui_scene_manager.h +++ b/chrome/browser/vr/ui_scene_manager.h
@@ -126,11 +126,6 @@ void SetIncognito(bool incognito); void SetWebVrMode(bool web_vr, bool show_toast); void SetIsExiting(); - void SetVideoCapturingIndicator(bool enabled); - void SetScreenCapturingIndicator(bool enabled); - void SetAudioCapturingIndicator(bool enabled); - void SetLocationAccessIndicator(bool enabled); - void SetBluetoothConnectedIndicator(bool enabled); void SetHistoryButtonsEnabled(bool can_go_back, bool can_go_forward); bool ShouldRenderWebVr(); @@ -165,7 +160,7 @@ void CreateWebVrRoot(); void CreateScreenDimmer(); void CreateWebVRExitWarning(); - void CreateSystemIndicators(); + void CreateSystemIndicators(Model* model); void CreateContentQuad(ContentInputDelegate* delegate); void CreateSplashScreen(Model* model); void CreateUnderDevelopmentNotice(); @@ -182,7 +177,6 @@ void CreateController(Model* model); void ConfigureScene(); - void ConfigureIndicators(); void ConfigureBackgroundColor(); void OnBackButtonClicked(); void OnSecurityIconClicked(); @@ -209,11 +203,6 @@ ShowUntilSignalTransientElement* splash_screen_transient_parent_ = nullptr; UiElement* exit_warning_ = nullptr; ContentElement* main_content_ = nullptr; - UiElement* audio_capture_indicator_ = nullptr; - UiElement* bluetooth_connected_indicator_ = nullptr; - UiElement* video_capture_indicator_ = nullptr; - UiElement* screen_capture_indicator_ = nullptr; - UiElement* location_access_indicator_ = nullptr; UiElement* screen_dimmer_ = nullptr; Rect* ceiling_ = nullptr; Grid* floor_ = nullptr; @@ -222,8 +211,6 @@ TransientElement* webvr_url_toast_transient_parent_ = nullptr; WebVrUrlToast* webvr_url_toast_ = nullptr; - std::vector<UiElement*> system_indicators_; - bool in_cct_; bool web_vr_mode_; bool web_vr_show_toast_ = false; @@ -238,11 +225,6 @@ bool fullscreen_ = false; bool incognito_ = false; - bool audio_capturing_ = false; - bool video_capturing_ = false; - bool screen_capturing_ = false; - bool location_access_ = false; - bool bluetooth_connected_ = false; std::vector<Rect*> background_panels_;
diff --git a/chrome/browser/vr/ui_scene_manager_unittest.cc b/chrome/browser/vr/ui_scene_manager_unittest.cc index f0d1060b..1ca3071 100644 --- a/chrome/browser/vr/ui_scene_manager_unittest.cc +++ b/chrome/browser/vr/ui_scene_manager_unittest.cc
@@ -460,11 +460,11 @@ TEST_F(UiSceneManagerTest, UiUpdatesForWebVR) { MakeManager(kNotInCct, kInWebVr); - manager_->SetAudioCapturingIndicator(true); - manager_->SetVideoCapturingIndicator(true); - manager_->SetScreenCapturingIndicator(true); - manager_->SetLocationAccessIndicator(true); - manager_->SetBluetoothConnectedIndicator(true); + model_->permissions.audio_capture_enabled = true; + model_->permissions.video_capture_enabled = true; + model_->permissions.screen_capture_enabled = true; + model_->permissions.location_access = true; + model_->permissions.bluetooth_connected = true; auto* web_vr_root = scene_->GetUiElementByName(kWebVrRoot); for (auto& element : *web_vr_root) { @@ -480,11 +480,11 @@ TEST_F(UiSceneManagerTest, UiUpdateTransitionToWebVR) { MakeManager(kNotInCct, kNotInWebVr); - manager_->SetAudioCapturingIndicator(true); - manager_->SetVideoCapturingIndicator(true); - manager_->SetScreenCapturingIndicator(true); - manager_->SetLocationAccessIndicator(true); - manager_->SetBluetoothConnectedIndicator(true); + model_->permissions.audio_capture_enabled = true; + model_->permissions.video_capture_enabled = true; + model_->permissions.screen_capture_enabled = true; + model_->permissions.location_access = true; + model_->permissions.bluetooth_connected = true; // Transition to WebVR mode manager_->SetWebVrMode(true, false); @@ -504,22 +504,20 @@ EXPECT_TRUE(VerifyVisibility(indicators, false)); EXPECT_TRUE(VerifyRequiresLayout(indicators, false)); - manager_->SetAudioCapturingIndicator(true); - manager_->SetVideoCapturingIndicator(true); - manager_->SetScreenCapturingIndicator(true); - manager_->SetLocationAccessIndicator(true); - manager_->SetBluetoothConnectedIndicator(true); + model_->permissions.audio_capture_enabled = true; + model_->permissions.video_capture_enabled = true; + model_->permissions.screen_capture_enabled = true; + model_->permissions.location_access = true; + model_->permissions.bluetooth_connected = true; EXPECT_TRUE(VerifyVisibility(indicators, true)); EXPECT_TRUE(VerifyRequiresLayout(indicators, true)); // Go into non-browser modes and make sure all indicators are hidden. manager_->SetWebVrMode(true, false); EXPECT_TRUE(VerifyVisibility(indicators, false)); - EXPECT_TRUE(VerifyRequiresLayout(indicators, false)); manager_->SetWebVrMode(false, false); manager_->SetFullscreen(true); EXPECT_TRUE(VerifyVisibility(indicators, false)); - EXPECT_TRUE(VerifyRequiresLayout(indicators, false)); manager_->SetFullscreen(false); // Back to browser, make sure the indicators reappear. @@ -528,12 +526,11 @@ EXPECT_TRUE(VerifyRequiresLayout(indicators, true)); // Ensure they can be turned off. - manager_->SetAudioCapturingIndicator(false); - manager_->SetVideoCapturingIndicator(false); - manager_->SetScreenCapturingIndicator(false); - manager_->SetLocationAccessIndicator(false); - manager_->SetBluetoothConnectedIndicator(false); - EXPECT_TRUE(VerifyVisibility(indicators, false)); + model_->permissions.audio_capture_enabled = false; + model_->permissions.video_capture_enabled = false; + model_->permissions.screen_capture_enabled = false; + model_->permissions.location_access = false; + model_->permissions.bluetooth_connected = false; EXPECT_TRUE(VerifyRequiresLayout(indicators, false)); }
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index 5f21a871..df72a86 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -179,8 +179,6 @@ "ssl_insecure_content.h", "stack_sampling_configuration.cc", "stack_sampling_configuration.h", - "switch_utils.cc", - "switch_utils.h", "trace_event_args_whitelist.cc", "trace_event_args_whitelist.h", "tts_messages.h",
diff --git a/chrome/common/crash_keys_unittest.cc b/chrome/common/crash_keys_unittest.cc index 183d0f1..ea57a03 100644 --- a/chrome/common/crash_keys_unittest.cc +++ b/chrome/common/crash_keys_unittest.cc
@@ -14,11 +14,13 @@ #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" +#include "components/crash/core/common/crash_key.h" #include "testing/gtest/include/gtest/gtest.h" class CrashKeysTest : public testing::Test { public: void SetUp() override { + crash_reporter::InitializeCrashKeys(); self_ = this; base::debug::SetCrashKeyReportingFunctions( &SetCrashKeyValue, &ClearCrashKey);
diff --git a/chrome/common/extensions/api/input_ime/input_components_handler.cc b/chrome/common/extensions/api/input_ime/input_components_handler.cc index 89b4d61f..ea4aa9e 100644 --- a/chrome/common/extensions/api/input_ime/input_components_handler.cc +++ b/chrome/common/extensions/api/input_ime/input_components_handler.cc
@@ -124,11 +124,11 @@ // input_ime manifest specification. const base::Value* language_value = NULL; if (module_value->Get(keys::kLanguage, &language_value)) { - if (language_value->GetType() == base::Value::Type::STRING) { + if (language_value->is_string()) { std::string language_str; language_value->GetAsString(&language_str); languages.insert(language_str); - } else if (language_value->GetType() == base::Value::Type::LIST) { + } else if (language_value->is_list()) { const base::ListValue* language_list = NULL; language_value->GetAsList(&language_list); for (size_t j = 0; j < language_list->GetSize(); ++j) {
diff --git a/chrome/common/extensions/api/webrtc_logging_private.idl b/chrome/common/extensions/api/webrtc_logging_private.idl index fbeca04..70620b4 100644 --- a/chrome/common/extensions/api/webrtc_logging_private.idl +++ b/chrome/common/extensions/api/webrtc_logging_private.idl
@@ -26,6 +26,11 @@ // The guest process id for the requester, if the request is from a // webview. long? guestProcessId; + + // Use the render process of the webview in the current page. This allows an + // app to make a request for a webview it contains. If there are more or + // less than 1 webview, this will fail with a runtime error. + boolean? targetWebview; }; // This contains information about the result of audio debug recordings or
diff --git a/chrome/common/media_router/mojo/media_router.mojom b/chrome/common/media_router/mojo/media_router.mojom index 97e4a434..48ba44a3 100644 --- a/chrome/common/media_router/mojo/media_router.mojom +++ b/chrome/common/media_router/mojo/media_router.mojom
@@ -170,7 +170,7 @@ ActionType default_action; - array<ActionType>? secondary_actions; + array<ActionType> secondary_actions; // The ID of the help page to be opened if users select learn_more. int32 help_page_id;
diff --git a/chrome/common/media_router/mojo/media_router_struct_traits.cc b/chrome/common/media_router/mojo/media_router_struct_traits.cc index 00cc5bac..4dc83e0 100644 --- a/chrome/common/media_router/mojo/media_router_struct_traits.cc +++ b/chrome/common/media_router/mojo/media_router_struct_traits.cc
@@ -167,6 +167,7 @@ return true; } +// static bool StructTraits<media_router::mojom::MediaRouteDataView, media_router::MediaRoute>:: Read(media_router::mojom::MediaRouteDataView data,
diff --git a/chrome/common/media_router/mojo/media_router_struct_traits.h b/chrome/common/media_router/mojo/media_router_struct_traits.h index a94bbce..e66392f 100644 --- a/chrome/common/media_router/mojo/media_router_struct_traits.h +++ b/chrome/common/media_router/mojo/media_router_struct_traits.h
@@ -206,10 +206,8 @@ static bool Read(media_router::mojom::IssueDataView data, media_router::IssueInfo* out); - static base::Optional<std::string> route_id( - const media_router::IssueInfo& issue) { - return issue.route_id.empty() ? base::Optional<std::string>() - : base::make_optional(issue.route_id); + static const std::string& route_id(const media_router::IssueInfo& issue) { + return issue.route_id; } static media_router::IssueInfo::Severity severity( @@ -225,10 +223,8 @@ return issue.title; } - static base::Optional<std::string> message( - const media_router::IssueInfo& issue) { - return issue.message.empty() ? base::Optional<std::string>() - : base::make_optional(issue.message); + static const std::string& message(const media_router::IssueInfo& issue) { + return issue.message; } static media_router::IssueInfo::Action default_action( @@ -236,8 +232,8 @@ return issue.default_action; } - static base::Optional<std::vector<media_router::IssueInfo::Action>> - secondary_actions(const media_router::IssueInfo& issue) { + static const std::vector<media_router::IssueInfo::Action>& secondary_actions( + const media_router::IssueInfo& issue) { return issue.secondary_actions; } @@ -394,7 +390,7 @@ static base::Optional<std::string> media_source( const media_router::MediaRoute& route) { - // TODO(imcheng): If we ever convert from Mojo to C++ outside of unit tests, + // TODO(imcheng): If we ever convert from C++ to Mojo outside of unit tests, // it would be better to make the |media_source_| field on MediaRoute a // base::Optional<MediaSource::Id> instead so it can be returned directly // here. @@ -416,11 +412,9 @@ return route.is_local(); } - static base::Optional<std::string> custom_controller_path( + static const std::string& custom_controller_path( const media_router::MediaRoute& route) { - return route.custom_controller_path().empty() - ? base::Optional<std::string>() - : base::make_optional(route.custom_controller_path()); + return route.custom_controller_path(); } static bool supports_media_route_controller(
diff --git a/chrome/gpu/BUILD.gn b/chrome/gpu/BUILD.gn index 6f2c2e3..e050947 100644 --- a/chrome/gpu/BUILD.gn +++ b/chrome/gpu/BUILD.gn
@@ -16,7 +16,7 @@ if (is_chromeos) { deps += [ - "//components/arc:arc_bindings", + "//components/arc/common:media", "//components/arc/video_accelerator", "//gpu/command_buffer/service", "//services/service_manager/public/cpp",
diff --git a/chrome/installer/linux/debian/dist_package_versions.json b/chrome/installer/linux/debian/dist_package_versions.json index 54ba3050..7b9c8ec4 100644 --- a/chrome/installer/linux/debian/dist_package_versions.json +++ b/chrome/installer/linux/debian/dist_package_versions.json
@@ -6,11 +6,12 @@ "libatk1.0-0": "2.26.0-2", "libc6": "2.24-17", "libcairo2": "1.15.8-2", - "libcups2": "2.2.5-2", - "libdbus-1-3": "1.11.22-1", - "libexpat1": "2.2.3-1", + "libcups2": "2.2.6-2", + "libdbus-1-3": "1.12.0-1", + "libdconf1": "0.26.1-1", + "libexpat1": "2.2.3-2", "libfontconfig1": "2.12.3-0.2", - "libgcc1": "1:7.2.0-12", + "libgcc1": "1:7.2.0-14", "libgconf-2-4": "3.2.6-4+b1", "libgdk-pixbuf2.0-0": "2.36.11-1", "libglib2.0-0": "2.54.1-1", @@ -19,7 +20,7 @@ "libnss3": "2:3.33-1", "libpango-1.0-0": "1.40.12-1", "libpangocairo-1.0-0": "1.40.12-1", - "libstdc++6": "7.2.0-12", + "libstdc++6": "7.2.0-14", "libx11-6": "2:1.6.4-3", "libx11-xcb1": "2:1.6.4-3", "libxcb1": "1.12-1", @@ -43,6 +44,7 @@ "libcairo2": "1.14.0-2.1+deb8u2", "libcups2": "1.7.5-11+deb8u1", "libdbus-1-3": "1.8.22-0+deb8u1", + "libdconf1": "0.22.0-1", "libexpat1": "2.1.0-6+deb8u4", "libfontconfig1": "2.11.0-6.3+deb8u1", "libgcc1": "1:4.9.2-10", @@ -78,6 +80,7 @@ "libcairo2": "1.14.8-1", "libcups2": "2.2.1-8", "libdbus-1-3": "1.10.22-0+deb9u1", + "libdconf1": "0.26.0-2+b1", "libexpat1": "2.2.0-2+deb9u1", "libfontconfig1": "2.11.0-6.7+b1", "libgcc1": "1:6.3.0-18", @@ -113,6 +116,7 @@ "libcairo2": "1.13.0~20140204-0ubuntu1.1", "libcups2": "1.7.2-0ubuntu1.7", "libdbus-1-3": "1.6.18-0ubuntu4.4", + "libdconf1": "0.20.0-1", "libexpat1": "2.1.0-4ubuntu1.4", "libfontconfig1": "2.11.0-0ubuntu4.2", "libgcc1": "1:4.9.3-0ubuntu4", @@ -148,6 +152,7 @@ "libcairo2": "1.14.6-1", "libcups2": "2.1.3-4ubuntu0.3", "libdbus-1-3": "1.10.6-1ubuntu3.1", + "libdconf1": "0.24.0-2", "libexpat1": "2.1.0-7ubuntu0.16.04.3", "libfontconfig1": "2.11.94-0ubuntu1.1", "libgcc1": "1:6.0.1-0ubuntu1", @@ -183,6 +188,7 @@ "libcairo2": "1.14.8-1", "libcups2": "2.2.2-1ubuntu1", "libdbus-1-3": "1.10.10-1ubuntu2", + "libdconf1": "0.26.0-2", "libexpat1": "2.2.0-2ubuntu0.1", "libfontconfig1": "2.11.94-0ubuntu2", "libgcc1": "1:6.3.0-12ubuntu2", @@ -216,15 +222,16 @@ "libatk1.0-0": "2.26.0-2ubuntu1", "libc6": "2.26-0ubuntu2", "libcairo2": "1.14.10-1ubuntu1", - "libcups2": "2.2.4-7ubuntu2", + "libcups2": "2.2.4-7ubuntu3", "libdbus-1-3": "1.10.22-1ubuntu1", + "libdconf1": "0.26.0-2", "libexpat1": "2.2.3-1", "libfontconfig1": "2.11.94-0ubuntu2", "libgcc1": "1:7.2.0-8ubuntu3", "libgconf-2-4": "3.2.6-4ubuntu1", "libgdk-pixbuf2.0-0": "2.36.11-1", "libglib2.0-0": "2.54.1-1ubuntu1", - "libgtk-3-0": "3.22.24-0ubuntu1", + "libgtk-3-0": "3.22.25-0ubuntu0.1", "libnspr4": "2:4.16-1ubuntu2", "libnss3": "2:3.32-1ubuntu3", "libpango-1.0-0": "1.40.12-1",
diff --git a/chrome/installer/linux/debian/update_dist_package_versions.py b/chrome/installer/linux/debian/update_dist_package_versions.py index 7c33190..45df2707 100755 --- a/chrome/installer/linux/debian/update_dist_package_versions.py +++ b/chrome/installer/linux/debian/update_dist_package_versions.py
@@ -43,6 +43,7 @@ "libcairo2", "libcups2", "libdbus-1-3", + "libdconf1", "libexpat1", "libfontconfig1", "libgcc1",
diff --git a/chrome/installer/linux/rpm/dist_package_provides.json b/chrome/installer/linux/rpm/dist_package_provides.json index 7866294..6166758 100644 --- a/chrome/installer/linux/rpm/dist_package_provides.json +++ b/chrome/installer/linux/rpm/dist_package_provides.json
@@ -57,6 +57,7 @@ "libdbus-1.so.3()(64bit)", "libdbus-1.so.3(LIBDBUS_1_3)(64bit)", "libdbus-1.so.3(LIBDBUS_PRIVATE_1.11.18)(64bit)", + "libdconf.so.1()(64bit)", "libdl.so.2()(64bit)", "libdl.so.2(GLIBC_2.2.5)(64bit)", "libdl.so.2(GLIBC_2.3.3)(64bit)", @@ -297,6 +298,7 @@ "libdbus-1.so.3()(64bit)", "libdbus-1.so.3(LIBDBUS_1_3)(64bit)", "libdbus-1.so.3(LIBDBUS_PRIVATE_1.11.18)(64bit)", + "libdconf.so.1()(64bit)", "libdl.so.2()(64bit)", "libdl.so.2(GLIBC_2.2.5)(64bit)", "libdl.so.2(GLIBC_2.3.3)(64bit)", @@ -543,6 +545,7 @@ "libdbus-1.so.3()(64bit)", "libdbus-1.so.3(LIBDBUS_1_3)(64bit)", "libdbus-1.so.3(LIBDBUS_PRIVATE_1.12.0)(64bit)", + "libdconf.so.1()(64bit)", "libdl.so.2()(64bit)", "libdl.so.2(GLIBC_2.2.5)(64bit)", "libdl.so.2(GLIBC_2.3.3)(64bit)", @@ -842,6 +845,8 @@ "libcups.so.2()(64bit)", "libdbus-1.so.3", "libdbus-1.so.3()(64bit)", + "libdconf.so.1", + "libdconf.so.1()(64bit)", "libdl.so.2", "libdl.so.2()(64bit)", "libdl.so.2(GLIBC_2.0)", @@ -1295,6 +1300,8 @@ "libcups.so.2()(64bit)", "libdbus-1.so.3", "libdbus-1.so.3()(64bit)", + "libdconf.so.1", + "libdconf.so.1()(64bit)", "libdl.so.2", "libdl.so.2()(64bit)", "libdl.so.2(GLIBC_2.0)",
diff --git a/chrome/installer/linux/rpm/update_package_provides.py b/chrome/installer/linux/rpm/update_package_provides.py index feacf8da..843f215 100755 --- a/chrome/installer/linux/rpm/update_package_provides.py +++ b/chrome/installer/linux/rpm/update_package_provides.py
@@ -33,6 +33,7 @@ "libcairo.so", "libcups.so", "libdbus-1.so", + "libdconf.so", "libdl.so", "libexpat.so", "libfontconfig.so",
diff --git a/chrome/installer/util/experiment_metrics.cc b/chrome/installer/util/experiment_metrics.cc index 66d8347e..b3c59b08 100644 --- a/chrome/installer/util/experiment_metrics.cc +++ b/chrome/installer/util/experiment_metrics.cc
@@ -11,9 +11,11 @@ } bool ExperimentMetrics::InTerminalState() const { + static_assert(NUM_STATES == 18, + "update the list of terminal states when adding a new state."); return state == kSelectedNoThanks || state == kSelectedOpenChromeAndCrash || state == kSelectedOpenChromeAndNoCrash || state == kSelectedClose || - state == kUserLogOff; + state == kUserLogOff || state == kOtherLaunch || state == kOtherClose; } bool ExperimentMetrics::operator==(const ExperimentMetrics& other) const {
diff --git a/chrome/renderer/autofill/form_autocomplete_browsertest.cc b/chrome/renderer/autofill/form_autocomplete_browsertest.cc index c543dc9..225fd7f2 100644 --- a/chrome/renderer/autofill/form_autocomplete_browsertest.cc +++ b/chrome/renderer/autofill/form_autocomplete_browsertest.cc
@@ -148,8 +148,8 @@ // This call is necessary to setup the autofill agent appropriate for the // user selection; simulates the menu actually popping up. - static_cast<autofill::PageClickListener*>(autofill_agent) - ->FormControlElementClicked(element.To<WebInputElement>(), false); + autofill_agent->FormControlElementClicked(element.To<WebInputElement>(), + false); FormData data; data.name = base::ASCIIToUTF16("name"); @@ -569,8 +569,8 @@ WebInputElement* input_element = blink::ToWebInputElement(&element); ASSERT_TRUE(input_element); // Select this element in |autofill_agent_|. - static_cast<autofill::PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(element.To<WebInputElement>(), false); + autofill_agent_->FormControlElementClicked(element.To<WebInputElement>(), + false); autofill_agent_->AcceptDataListSuggestion(kSuggestion); EXPECT_EQ(c.expected, input_element->Value().Utf8()) << "Case id: " << c.id;
diff --git a/chrome/renderer/autofill/form_control_click_detection_browsertest.cc b/chrome/renderer/autofill/form_control_click_detection_browsertest.cc new file mode 100644 index 0000000..827f5528 --- /dev/null +++ b/chrome/renderer/autofill/form_control_click_detection_browsertest.cc
@@ -0,0 +1,246 @@ +// 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 <memory> + +#include "chrome/test/base/chrome_render_view_test.h" +#include "components/autofill/content/renderer/autofill_agent.h" +#include "content/public/renderer/render_view.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/platform/WebFloatPoint.h" +#include "third_party/WebKit/public/platform/WebSize.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebInputElement.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/WebKit/public/web/WebSettings.h" +#include "third_party/WebKit/public/web/WebView.h" +#include "ui/events/keycodes/keyboard_codes.h" + +namespace autofill { + +class FormControlClickDetectionTest : public ChromeRenderViewTest { + protected: + void SetUp() override { + ChromeRenderViewTest::SetUp(); + // Must be set before loading HTML. + view_->GetWebView()->SetDefaultPageScaleLimits(1, 4); + + LoadHTML( + "<form>" + " <input type='text' id='text_1'></input><br>" + " <input type='text' id='text_2'></input><br>" + " <textarea id='textarea_1'></textarea><br>" + " <textarea id='textarea_2'></textarea><br>" + " <input type='button' id='button'></input><br>" + " <input type='button' id='button_2' disabled></input><br>" + "</form>"); + GetWebWidget()->Resize(blink::WebSize(500, 500)); + GetWebWidget()->SetFocus(true); + blink::WebDocument document = GetMainFrame()->GetDocument(); + text_ = document.GetElementById("text_1"); + textarea_ = document.GetElementById("textarea_1"); + ASSERT_FALSE(text_.IsNull()); + ASSERT_FALSE(textarea_.IsNull()); + + // Enable show-ime event when element is focused by indicating that a user + // gesture has been processed since load. + EXPECT_TRUE(SimulateElementClick("button")); + } + + void TearDown() override { + text_.Reset(); + textarea_.Reset(); + ChromeRenderViewTest::TearDown(); + } + + void ClearAutofillAgentTestState() { + autofill_agent_->last_clicked_form_control_element_for_testing_ = + blink::WebFormControlElement(); + autofill_agent_ + ->last_clicked_form_control_element_was_focused_for_testing_ = false; + } + + const blink::WebFormControlElement& last_clicked_form_control_element() + const { + return autofill_agent_->last_clicked_form_control_element_for_testing_; + } + + bool last_clicked_form_control_element_was_focused() const { + return autofill_agent_ + ->last_clicked_form_control_element_was_focused_for_testing_; + } + + bool form_control_element_clicked_called() const { + return !last_clicked_form_control_element().IsNull(); + } + + blink::WebElement text_; + blink::WebElement textarea_; +}; + +// Tests that a clicked input call is properly handled by AutofillAgent. +TEST_F(FormControlClickDetectionTest, InputClicked) { + ClearAutofillAgentTestState(); + EXPECT_NE(text_, text_.GetDocument().FocusedElement()); + // Click the text field once. + EXPECT_TRUE(SimulateElementClick("text_1")); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_FALSE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(text_, last_clicked_form_control_element()); + ClearAutofillAgentTestState(); + + // Click the text field again and verify that AutofillAgent knows about its + // focus. + EXPECT_TRUE(SimulateElementClick("text_1")); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_TRUE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(text_, last_clicked_form_control_element()); + ClearAutofillAgentTestState(); + + // Click the button, no notification should happen (this is not a text-input). + EXPECT_TRUE(SimulateElementClick("button")); + EXPECT_FALSE(form_control_element_clicked_called()); +} + +// Tests that AutofillAgent ignores a right click. +TEST_F(FormControlClickDetectionTest, InputRightClicked) { + ClearAutofillAgentTestState(); + EXPECT_NE(text_, text_.GetDocument().FocusedElement()); + // Right click the text field once. + EXPECT_TRUE(SimulateElementRightClick("text_1")); + EXPECT_FALSE(form_control_element_clicked_called()); + EXPECT_FALSE(last_clicked_form_control_element_was_focused()); + EXPECT_NE(text_, last_clicked_form_control_element()); +} + +TEST_F(FormControlClickDetectionTest, InputFocusedAndClicked) { + ClearAutofillAgentTestState(); + // Focus the text field without a click. + ExecuteJavaScriptForTests("document.getElementById('text_1').focus();"); + EXPECT_FALSE(form_control_element_clicked_called()); + ClearAutofillAgentTestState(); + + // Click the focused text field to test that was_focused_ is set correctly. + EXPECT_TRUE(SimulateElementClick("text_1")); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_TRUE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(text_, last_clicked_form_control_element()); +} + +// Tests that AutofillAgent accepts form clicks for a textarea element which is +// clicked. +TEST_F(FormControlClickDetectionTest, TextAreaClicked) { + ClearAutofillAgentTestState(); + // Click the textarea field once. + EXPECT_TRUE(SimulateElementClick("textarea_1")); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_FALSE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(textarea_, last_clicked_form_control_element()); + ClearAutofillAgentTestState(); + + // Click the text field again and verify that AutofillAgent knows about its + // focus. + EXPECT_TRUE(SimulateElementClick("textarea_1")); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_TRUE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(textarea_, last_clicked_form_control_element()); + ClearAutofillAgentTestState(); + + // Click the button, no notification should happen (this is not a text-input). + EXPECT_TRUE(SimulateElementClick("button")); + EXPECT_FALSE(form_control_element_clicked_called()); +} + +TEST_F(FormControlClickDetectionTest, TextAreaFocusedAndClicked) { + ClearAutofillAgentTestState(); + // Focus the textarea without a click. + ExecuteJavaScriptForTests("document.getElementById('textarea_1').focus();"); + EXPECT_FALSE(form_control_element_clicked_called()); + ClearAutofillAgentTestState(); + + // Click the text field again and verify that AutofillAgent knows about its + // focus. + EXPECT_TRUE(SimulateElementClick("textarea_1")); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_TRUE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(textarea_, last_clicked_form_control_element()); + ClearAutofillAgentTestState(); +} + +TEST_F(FormControlClickDetectionTest, ScaledTextareaClicked) { + ClearAutofillAgentTestState(); + EXPECT_NE(textarea_, textarea_.GetDocument().FocusedElement()); + view_->GetWebView()->SetPageScaleFactor(3); + view_->GetWebView()->SetVisualViewportOffset(blink::WebFloatPoint(50, 50)); + + // Click textarea_1. + SimulatePointClick(gfx::Point(30, 30)); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_FALSE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(textarea_, last_clicked_form_control_element()); +} + +TEST_F(FormControlClickDetectionTest, ScaledTextareaTapped) { + ClearAutofillAgentTestState(); + EXPECT_NE(textarea_, textarea_.GetDocument().FocusedElement()); + view_->GetWebView()->SetPageScaleFactor(3); + view_->GetWebView()->SetVisualViewportOffset(blink::WebFloatPoint(50, 50)); + + // Tap textarea_1. + SimulateRectTap(gfx::Rect(30, 30, 30, 30)); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_FALSE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(textarea_, last_clicked_form_control_element()); +} + +TEST_F(FormControlClickDetectionTest, DisabledInputClickedNoEvent) { + ClearAutofillAgentTestState(); + EXPECT_NE(text_, text_.GetDocument().FocusedElement()); + // Click the text field once. + EXPECT_TRUE(SimulateElementClick("text_1")); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_FALSE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(text_, last_clicked_form_control_element()); + ClearAutofillAgentTestState(); + + // Click the disabled element. + EXPECT_TRUE(SimulateElementClick("button_2")); + EXPECT_FALSE(form_control_element_clicked_called()); +} + +TEST_F(FormControlClickDetectionTest, + ClickDisabledInputDoesNotResetClickCounter) { + EXPECT_NE(text_, text_.GetDocument().FocusedElement()); + // Click the text field once. + EXPECT_TRUE(SimulateElementClick("text_1")); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_FALSE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(text_, last_clicked_form_control_element()); + ClearAutofillAgentTestState(); + + // Click the disabled element. + EXPECT_TRUE(SimulateElementClick("button_2")); + EXPECT_FALSE(form_control_element_clicked_called()); + ClearAutofillAgentTestState(); + + // Click the text field second time. AutofillClient should know that this is + // the second click. + EXPECT_TRUE(SimulateElementClick("text_1")); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_TRUE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(text_, last_clicked_form_control_element()); +} + +TEST_F(FormControlClickDetectionTest, TapNearEdgeIsPageClick) { + EXPECT_NE(text_, text_.GetDocument().FocusedElement()); + // Tap outside of element bounds, but tap width is overlapping the field. + gfx::Rect element_bounds = GetElementBounds("text_1"); + SimulateRectTap(element_bounds - + gfx::Vector2d(element_bounds.width() / 2 + 1, 0)); + EXPECT_TRUE(form_control_element_clicked_called()); + EXPECT_FALSE(last_clicked_form_control_element_was_focused()); + EXPECT_EQ(text_, last_clicked_form_control_element()); +} + +} // namespace autofill
diff --git a/chrome/renderer/autofill/page_click_tracker_browsertest.cc b/chrome/renderer/autofill/page_click_tracker_browsertest.cc deleted file mode 100644 index 8602495..0000000 --- a/chrome/renderer/autofill/page_click_tracker_browsertest.cc +++ /dev/null
@@ -1,251 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <memory> - -#include "chrome/test/base/chrome_render_view_test.h" -#include "components/autofill/content/renderer/autofill_agent.h" -#include "components/autofill/content/renderer/page_click_listener.h" -#include "components/autofill/content/renderer/page_click_tracker.h" -#include "content/public/renderer/render_view.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/public/platform/WebFloatPoint.h" -#include "third_party/WebKit/public/platform/WebSize.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebInputElement.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebSettings.h" -#include "third_party/WebKit/public/web/WebView.h" -#include "ui/events/keycodes/keyboard_codes.h" - -namespace autofill { - -class TestPageClickListener : public PageClickListener { - public: - TestPageClickListener() - : form_control_element_clicked_called_(false), - was_focused_(false) {} - - void FormControlElementClicked(const blink::WebFormControlElement& element, - bool was_focused) override { - form_control_element_clicked_called_ = true; - form_control_element_clicked_ = element; - was_focused_ = was_focused; - } - - void ClearResults() { - form_control_element_clicked_called_ = false; - form_control_element_clicked_.Reset(); - was_focused_ = false; - } - - bool form_control_element_clicked_called_; - blink::WebFormControlElement form_control_element_clicked_; - bool was_focused_; -}; - -class PageClickTrackerTest : public ChromeRenderViewTest { - protected: - void SetUp() override { - ChromeRenderViewTest::SetUp(); - - // PageClickTracker is created and owned by AutofillAgent. To setup our test - // listener we need to use our copy of PageClickTracker and set it up for - // testing. The ownership will be transfered to AutofillAgent. - auto page_click_tracker = base::MakeUnique<PageClickTracker>( - view_->GetMainRenderFrame(), &test_listener_); - autofill_agent_->set_page_click_tracker_for_testing( - std::move(page_click_tracker)); - - // Must be set before loading HTML. - view_->GetWebView()->SetDefaultPageScaleLimits(1, 4); - - LoadHTML("<form>" - " <input type='text' id='text_1'></input><br>" - " <input type='text' id='text_2'></input><br>" - " <textarea id='textarea_1'></textarea><br>" - " <textarea id='textarea_2'></textarea><br>" - " <input type='button' id='button'></input><br>" - " <input type='button' id='button_2' disabled></input><br>" - "</form>"); - GetWebWidget()->Resize(blink::WebSize(500, 500)); - GetWebWidget()->SetFocus(true); - blink::WebDocument document = GetMainFrame()->GetDocument(); - text_ = document.GetElementById("text_1"); - textarea_ = document.GetElementById("textarea_1"); - ASSERT_FALSE(text_.IsNull()); - ASSERT_FALSE(textarea_.IsNull()); - - // Enable show-ime event when element is focused by indicating that a user - // gesture has been processed since load. - EXPECT_TRUE(SimulateElementClick("button")); - } - - void TearDown() override { - text_.Reset(); - textarea_.Reset(); - test_listener_.ClearResults(); - ChromeRenderViewTest::TearDown(); - } - - TestPageClickListener test_listener_; - blink::WebElement text_; - blink::WebElement textarea_; -}; - -// Tests that PageClickTracker does notify correctly when an input -// node is clicked. -TEST_F(PageClickTrackerTest, PageClickTrackerInputClicked) { - EXPECT_NE(text_, text_.GetDocument().FocusedElement()); - // Click the text field once. - EXPECT_TRUE(SimulateElementClick("text_1")); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_FALSE(test_listener_.was_focused_); - EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_); - test_listener_.ClearResults(); - - // Click the text field again to test that was_focused_ is set correctly. - EXPECT_TRUE(SimulateElementClick("text_1")); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_TRUE(test_listener_.was_focused_); - EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_); - test_listener_.ClearResults(); - - // Click the button, no notification should happen (this is not a text-input). - EXPECT_TRUE(SimulateElementClick("button")); - EXPECT_FALSE(test_listener_.form_control_element_clicked_called_); -} - -// Tests that PageClickTracker does not notify when there is right click. -TEST_F(PageClickTrackerTest, PageClickTrackerInputRightClicked) { - EXPECT_NE(text_, text_.GetDocument().FocusedElement()); - // Right click the text field once. - EXPECT_TRUE(SimulateElementRightClick("text_1")); - EXPECT_FALSE(test_listener_.form_control_element_clicked_called_); - EXPECT_FALSE(test_listener_.was_focused_); - EXPECT_NE(text_, test_listener_.form_control_element_clicked_); -} - -TEST_F(PageClickTrackerTest, PageClickTrackerInputFocusedAndClicked) { - // Focus the text field without a click. - ExecuteJavaScriptForTests("document.getElementById('text_1').focus();"); - EXPECT_FALSE(test_listener_.form_control_element_clicked_called_); - test_listener_.ClearResults(); - - // Click the focused text field to test that was_focused_ is set correctly. - EXPECT_TRUE(SimulateElementClick("text_1")); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_TRUE(test_listener_.was_focused_); - EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_); -} - -// Tests that PageClickTracker does notify correctly when a textarea -// node is clicked. -TEST_F(PageClickTrackerTest, PageClickTrackerTextAreaClicked) { - // Click the textarea field once. - EXPECT_TRUE(SimulateElementClick("textarea_1")); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_FALSE(test_listener_.was_focused_); - EXPECT_TRUE(textarea_ == test_listener_.form_control_element_clicked_); - test_listener_.ClearResults(); - - // Click the textarea field again to test that was_focused_ is set correctly. - EXPECT_TRUE(SimulateElementClick("textarea_1")); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_TRUE(test_listener_.was_focused_); - EXPECT_TRUE(textarea_ == test_listener_.form_control_element_clicked_); - test_listener_.ClearResults(); - - // Click the button, no notification should happen (this is not a text-input). - EXPECT_TRUE(SimulateElementClick("button")); - EXPECT_FALSE(test_listener_.form_control_element_clicked_called_); -} - -TEST_F(PageClickTrackerTest, PageClickTrackerTextAreaFocusedAndClicked) { - // Focus the textarea without a click. - ExecuteJavaScriptForTests("document.getElementById('textarea_1').focus();"); - EXPECT_FALSE(test_listener_.form_control_element_clicked_called_); - test_listener_.ClearResults(); - - // Click the focused text field to test that was_focused_ is set correctly. - EXPECT_TRUE(SimulateElementClick("textarea_1")); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_TRUE(test_listener_.was_focused_); - EXPECT_TRUE(textarea_ == test_listener_.form_control_element_clicked_); - test_listener_.ClearResults(); -} - -TEST_F(PageClickTrackerTest, PageClickTrackerScaledTextareaClicked) { - EXPECT_NE(textarea_, textarea_.GetDocument().FocusedElement()); - view_->GetWebView()->SetPageScaleFactor(3); - view_->GetWebView()->SetVisualViewportOffset(blink::WebFloatPoint(50, 50)); - - // Click textarea_1. - SimulatePointClick(gfx::Point(30, 30)); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_FALSE(test_listener_.was_focused_); - EXPECT_TRUE(textarea_ == test_listener_.form_control_element_clicked_); -} - -TEST_F(PageClickTrackerTest, PageClickTrackerScaledTextareaTapped) { - EXPECT_NE(textarea_, textarea_.GetDocument().FocusedElement()); - view_->GetWebView()->SetPageScaleFactor(3); - view_->GetWebView()->SetVisualViewportOffset(blink::WebFloatPoint(50, 50)); - - // Tap textarea_1. - SimulateRectTap(gfx::Rect(30, 30, 30, 30)); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_FALSE(test_listener_.was_focused_); - EXPECT_TRUE(textarea_ == test_listener_.form_control_element_clicked_); -} - -TEST_F(PageClickTrackerTest, PageClickTrackerDisabledInputClickedNoEvent) { - EXPECT_NE(text_, text_.GetDocument().FocusedElement()); - // Click the text field once. - EXPECT_TRUE(SimulateElementClick("text_1")); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_FALSE(test_listener_.was_focused_); - EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_); - test_listener_.ClearResults(); - - // Click the disabled element. - EXPECT_TRUE(SimulateElementClick("button_2")); - EXPECT_FALSE(test_listener_.form_control_element_clicked_called_); -} - -TEST_F(PageClickTrackerTest, - PageClickTrackerClickDisabledInputDoesNotResetClickCounter) { - EXPECT_NE(text_, text_.GetDocument().FocusedElement()); - // Click the text field once. - EXPECT_TRUE(SimulateElementClick("text_1")); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_FALSE(test_listener_.was_focused_); - EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_); - test_listener_.ClearResults(); - - // Click the disabled element. - EXPECT_TRUE(SimulateElementClick("button_2")); - EXPECT_FALSE(test_listener_.form_control_element_clicked_called_); - test_listener_.ClearResults(); - - // Click the text field second time. Page click tracker should know that this - // is the second click. - EXPECT_TRUE(SimulateElementClick("text_1")); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_TRUE(test_listener_.was_focused_); - EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_); -} - -TEST_F(PageClickTrackerTest, PageClickTrackerTapNearEdgeIsPageClick) { - EXPECT_NE(text_, text_.GetDocument().FocusedElement()); - // Tap outside of element bounds, but tap width is overlapping the field. - gfx::Rect element_bounds = GetElementBounds("text_1"); - SimulateRectTap(element_bounds - - gfx::Vector2d(element_bounds.width() / 2 + 1, 0)); - EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); - EXPECT_FALSE(test_listener_.was_focused_); - EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_); -} - -} // namespace autofill
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc index 6c060f3..1001499 100644 --- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -424,8 +424,7 @@ const base::string16& password) { // This call is necessary to setup the autofill agent appropriate for the // user selection; simulates the menu actually popping up. - static_cast<autofill::PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(input, false); + autofill_agent_->FormControlElementClicked(input, false); autofill_agent_->FillPasswordSuggestion(username, password); } @@ -1613,16 +1612,14 @@ // Simulate a user clicking on the username element. This should produce a // message with all the usernames. - static_cast<PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(username_element_, false); + autofill_agent_->FormControlElementClicked(username_element_, false); CheckSuggestions(std::string(), false); // Now simulate a user typing in an unrecognized username and then // clicking on the username element. This should also produce a message with // all the usernames. SimulateUsernameTyping("baz"); - static_cast<PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(username_element_, true); + autofill_agent_->FormControlElementClicked(username_element_, true); CheckSuggestions("baz", true); ClearUsernameAndPasswordFields(); } @@ -1646,8 +1643,7 @@ // Simulate a user clicking on the password element. This should produce no // message. fake_driver_.reset_show_pw_suggestions(); - static_cast<PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(password_element_, false); + autofill_agent_->FormControlElementClicked(password_element_, false); EXPECT_TRUE(GetCalledShowPasswordSuggestions()); } @@ -1679,8 +1675,7 @@ // Simulate a user clicking on the password element. This should produce a // dropdown with suggestion of all available usernames and so username // filter will be the empty string. - static_cast<PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(password_element_, false); + autofill_agent_->FormControlElementClicked(password_element_, false); CheckSuggestions("", false); } @@ -1700,8 +1695,7 @@ // Simulate a user clicking on the password element. This should produce no // message. fake_driver_.reset_show_pw_suggestions(); - static_cast<PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(password_element_, false); + autofill_agent_->FormControlElementClicked(password_element_, false); EXPECT_TRUE(GetCalledShowPasswordSuggestions()); } @@ -2404,8 +2398,7 @@ SimulateOnFillPasswordForm(fill_data_); // Simulate a user clicking on the username element. This should produce a // message. - static_cast<PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(username_element_, true); + autofill_agent_->FormControlElementClicked(username_element_, true); CheckSuggestions("", true); } @@ -2423,8 +2416,7 @@ SimulateOnFillPasswordForm(fill_data_); // Simulate a user clicking on the password element. This should produce a // message. - static_cast<PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(password_element_, true); + autofill_agent_->FormControlElementClicked(password_element_, true); CheckSuggestions("", false); } @@ -2955,8 +2947,7 @@ // Simulate a user clicking on the password element. This should produce a // dropdown with suggestion of all available usernames. - static_cast<PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(password_element_, false); + autofill_agent_->FormControlElementClicked(password_element_, false); CheckSuggestions("", false); } @@ -3068,8 +3059,7 @@ // Simulate a user clicking on the password element. This should produce a // dropdown with suggestion of all available usernames. - static_cast<PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(password_element_, false); + autofill_agent_->FormControlElementClicked(password_element_, false); CheckSuggestions("", false); } @@ -3253,8 +3243,7 @@ UpdateOnlyPasswordElement(); // Simulate a user clicking on the password element. - static_cast<PageClickListener*>(autofill_agent_) - ->FormControlElementClicked(password_element_, false); + autofill_agent_->FormControlElementClicked(password_element_, false); // Check that no information about Gaia reauthentication is not sent. EXPECT_FALSE(fake_driver_.called_password_forms_parsed());
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 969b11c..cba61aa 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1175,6 +1175,10 @@ return SearchBouncer::GetInstance()->IsNewTabPage(url); } +bool ChromeContentRendererClient::ShouldTrackUseCounter(const GURL& url) { + return !SearchBouncer::GetInstance()->IsNewTabPage(url); +} + void ChromeContentRendererClient::GetNavigationErrorStrings( content::RenderFrame* render_frame, const WebURLRequest& failed_request,
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index 649f56c..9427391 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -128,6 +128,7 @@ bool HasErrorPage(int http_status_code) override; bool ShouldSuppressErrorPage(content::RenderFrame* render_frame, const GURL& url) override; + bool ShouldTrackUseCounter(const GURL& url) override; void GetNavigationErrorStrings(content::RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const blink::WebURLError& error,
diff --git a/chrome/renderer/chrome_content_renderer_client_unittest.cc b/chrome/renderer/chrome_content_renderer_client_unittest.cc index 1bab231..8ea1c74 100644 --- a/chrome/renderer/chrome_content_renderer_client_unittest.cc +++ b/chrome/renderer/chrome_content_renderer_client_unittest.cc
@@ -384,6 +384,14 @@ SearchBouncer::GetInstance()->SetNewTabPageURL(GURL::EmptyGURL()); } +TEST_F(ChromeContentRendererClientTest, ShouldTrackUseCounter) { + ChromeContentRendererClient client; + SearchBouncer::GetInstance()->SetNewTabPageURL(GURL("http://example.com/n")); + EXPECT_TRUE(client.ShouldTrackUseCounter(GURL("http://example.com"))); + EXPECT_FALSE(client.ShouldTrackUseCounter(GURL("http://example.com/n"))); + SearchBouncer::GetInstance()->SetNewTabPageURL(GURL::EmptyGURL()); +} + TEST_F(ChromeContentRendererClientTest, AddImageContextMenuPropertiesForLoFi) { ChromeContentRendererClient client; blink::WebURLResponse web_url_response;
diff --git a/chrome/renderer/resources/extensions/media_router_bindings.js b/chrome/renderer/resources/extensions/media_router_bindings.js index 6474f580..9251258 100644 --- a/chrome/renderer/resources/extensions/media_router_bindings.js +++ b/chrome/renderer/resources/extensions/media_router_bindings.js
@@ -90,7 +90,7 @@ 'description': route.description, 'icon_url': route.iconUrl, 'is_local': route.isLocal, - 'custom_controller_path': route.customControllerPath, + 'custom_controller_path': route.customControllerPath || '', 'for_display': route.forDisplay, 'is_incognito': route.offTheRecord, 'is_local_presentation': route.isOffscreenPresentation, @@ -393,10 +393,10 @@ return issueActionToMojo_(e); }); this.service_.onIssue(new mediaRouterMojom.Issue({ - 'route_id': issue.routeId, + 'route_id': issue.routeId || '', 'severity': issueSeverityToMojo_(issue.severity), 'title': issue.title, - 'message': issue.message, + 'message': issue.message || '', 'default_action': issueActionToMojo_(issue.defaultAction), 'secondary_actions': secondaryActions, 'help_page_id': issue.helpPageId,
diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc index ef8ca3a..000f6f9 100644 --- a/chrome/renderer/searchbox/searchbox.cc +++ b/chrome/renderer/searchbox/searchbox.cc
@@ -230,13 +230,10 @@ SearchBox::~SearchBox() = default; void SearchBox::LogEvent(NTPLoggingEventType event) { - // navigation_start in ms. - uint64_t start = - 1000 * (render_frame()->GetWebFrame()->Performance().NavigationStart()); - uint64_t now = - (base::TimeTicks::Now() - base::TimeTicks::UnixEpoch()).InMilliseconds(); - DCHECK(now >= start); - base::TimeDelta delta = base::TimeDelta::FromMilliseconds(now - start); + base::Time navigation_start = base::Time::FromDoubleT( + render_frame()->GetWebFrame()->Performance().NavigationStart()); + base::Time now = base::Time::Now(); + base::TimeDelta delta = now - navigation_start; embedded_search_service_->LogEvent(page_seq_no_, event, delta); }
diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc index 937cd2ff..42017b26 100644 --- a/chrome/service/cloud_print/printer_job_handler.cc +++ b/chrome/service/cloud_print/printer_job_handler.cc
@@ -57,7 +57,7 @@ JOB_HANDLER_MAX, }; -net::PartialNetworkTrafficAnnotationTag kPartialTrafficAnnotation = +constexpr net::PartialNetworkTrafficAnnotationTag kPartialTrafficAnnotation = net::DefinePartialNetworkTrafficAnnotation("printer_job_handler", "cloud_print", R"(
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index fd0f8c56..82d350f1 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -428,6 +428,7 @@ "../browser/apps/service_worker_browsertest.cc", "../browser/autocomplete/autocomplete_browsertest.cc", "../browser/autofill/autofill_browsertest.cc", + "../browser/autofill/autofill_metrics_browsertest.cc", "../browser/autofill/autofill_server_browsertest.cc", "../browser/autofill/content_autofill_driver_browsertest.cc", "../browser/autofill/form_structure_browsertest.cc", @@ -821,7 +822,7 @@ "../renderer/autofill/form_autocomplete_browsertest.cc", "../renderer/autofill/form_autofill_browsertest.cc", "../renderer/autofill/form_classifier_browsertest.cc", - "../renderer/autofill/page_click_tracker_browsertest.cc", + "../renderer/autofill/form_control_click_detection_browsertest.cc", "../renderer/autofill/page_passwords_analyser_browsertest.cc", "../renderer/autofill/password_autofill_agent_browsertest.cc", "../renderer/autofill/password_generation_agent_browsertest.cc", @@ -1654,6 +1655,7 @@ sources += [ "../browser/safe_browsing/certificate_reporting_service_browsertest.cc", "../browser/safe_browsing/chrome_password_protection_service_browsertest.cc", + "../browser/safe_browsing/client_side_detection_host_browsertest.cc", "../browser/safe_browsing/permission_reporter_browsertest.cc", "../browser/safe_browsing/safe_browsing_blocking_page_test.cc", "../browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc", @@ -2471,7 +2473,6 @@ "../common/pref_names_util_unittest.cc", "../common/search/search_urls_unittest.cc", "../common/secure_origin_whitelist_unittest.cc", - "../common/switch_utils_unittest.cc", "../renderer/app_categorizer_unittest.cc", "../renderer/chrome_content_renderer_client_unittest.cc", "../renderer/content_settings_observer_unittest.cc", @@ -3395,11 +3396,12 @@ sources += [ "../browser/media/protected_media_identifier_permission_context_unittest.cc" ] } else { sources += [ + "../browser/lifetime/switch_utils_unittest.cc", "../browser/net/disk_cache_dir_policy_handler_unittest.cc", - "//chrome/browser/profiles/profile_list_desktop_unittest.cc", - "//chrome/browser/profiles/profile_statistics_unittest.cc", - "//chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc", - "//chrome/browser/ui/startup/startup_tab_provider_unittest.cc", + "../browser/profiles/profile_list_desktop_unittest.cc", + "../browser/profiles/profile_statistics_unittest.cc", + "../browser/ui/startup/startup_browser_creator_impl_unittest.cc", + "../browser/ui/startup/startup_tab_provider_unittest.cc", ] } if (use_gio) {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java index 0f19e3e..6f19fc5 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -411,9 +411,11 @@ * Waits for the activity to fully finish it's native initialization. */ public void waitForActivityNativeInitializationComplete() { - CriteriaHelper.pollUiThread(() -> ChromeBrowserInitializer.getInstance( - getActivity()).hasNativeInitializationCompleted(), - "Native initialization never finished", 2 * CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL, + CriteriaHelper.pollUiThread(() + -> ChromeBrowserInitializer.getInstance(getActivity()) + .hasNativeInitializationCompleted(), + "Native initialization never finished", + 20 * CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL, CriteriaHelper.DEFAULT_POLLING_INTERVAL); CriteriaHelper.pollUiThread(() -> getActivity().didFinishNativeInitialization(),
diff --git a/chrome/test/base/extension_js_browser_test.cc b/chrome/test/base/extension_js_browser_test.cc index f1d3030..fdc027e0 100644 --- a/chrome/test/base/extension_js_browser_test.cc +++ b/chrome/test/base/extension_js_browser_test.cc
@@ -54,7 +54,7 @@ script); std::unique_ptr<base::Value> value_result = base::JSONReader::Read(result); - CHECK_EQ(base::Value::Type::DICTIONARY, value_result->GetType()); + CHECK_EQ(base::Value::Type::DICTIONARY, value_result->type()); base::DictionaryValue* dict_value = static_cast<base::DictionaryValue*>(value_result.get()); bool test_result;
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index a696c0f9..29b4169 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -75,6 +75,10 @@ 'PerfTest.testColdExecuteScript', # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1819 'ChromeExtensionsCapabilityTest.testIFrameWithExtensionsSource', + # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2144 + 'MobileEmulationCapabilityTest.testClickElement', + 'MobileEmulationCapabilityTest.testNetworkConnectionTypeIsAppliedToAllTabs', + 'MobileEmulationCapabilityTest.testNetworkConnectionTypeIsAppliedToAllTabsImmediately', ] _VERSION_SPECIFIC_FILTER = {}
diff --git a/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/appwindow.html b/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/appwindow.html new file mode 100644 index 0000000..a780eea --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/appwindow.html
@@ -0,0 +1,5 @@ +<html> + <script src="appwindow.js"></script> + <body> + </body> +</html>
diff --git a/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/appwindow.js b/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/appwindow.js new file mode 100644 index 0000000..8281197 --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/appwindow.js
@@ -0,0 +1,26 @@ +// 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. + +// Making it explicit that this is exposed for the background page to call. +window.attemptAudioDebugRecording = function(succeed, fail) { + // The API calls must be made in the window that hosts the webview. + chrome.webrtcLoggingPrivate.startAudioDebugRecordings( + {targetWebview: true}, '', 0, + function(startResult) { + if (chrome.runtime.lastError) { + fail('startAudioDebugRecordings: ' + + chrome.runtime.lastError.message); + return; + } + chrome.webrtcLoggingPrivate.stopAudioDebugRecordings( + {targetWebview: true}, '', function(stopResult) { + if (chrome.runtime.lastError) { + fail('stopAudioDebugRecordings: ' + + chrome.runtime.lastError.message); + return; + } + succeed(); + }); + }); +};
diff --git a/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/manifest.json b/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/manifest.json new file mode 100644 index 0000000..caa3049 --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/manifest.json
@@ -0,0 +1,15 @@ +{ + // This app id is whitelisted for webrtcLoggingPrivate. + // Extension ID: knldjmfmopnpolahpmmgbagdohdnhkik + "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB", + "name": "webrtcLoggingPrivate webview in RequestInfo test", + "version": "0.1", + "manifest_version": 2, + "description": "Tests initiation of WebRTC audio debug recordings on behalf of a webview with an app using webrtcLoggingPrivate", + "app": { + "background": { + "scripts": ["test.js"] + } + }, + "permissions": ["webrtcLoggingPrivate", "webview"] +}
diff --git a/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/test.js b/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/test.js new file mode 100644 index 0000000..664a1f3 --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrtc_logging_private/audio_debug/start_audio_debug_recordings_for_webview_from_app/test.js
@@ -0,0 +1,91 @@ +// 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. + +function assertNoLastError(message) { + if (chrome.runtime.lastError) { + message += ': ' + chrome.runtime.lastError.message; + } + chrome.test.assertFalse(!!chrome.runtime.lastError, message); +} + +function executeWindowTest(testBody) { + chrome.app.window.create( + 'appwindow.html', {}, function(appWindow) { + assertNoLastError('window.create'); + appWindow.contentWindow.onload = function() { + testBody(appWindow.contentWindow); + }; + }); +} + +function createWebviews(doc, numWebviews, onWebviewsLoaded) { + var webviewStates = {}; + for (var i = 0; i < numWebviews; i++) { + // Initialize object with mapping from id to isLoaded boolean. + webviewStates['webview' + i] = false; + } + function allLoaded() { + return Object.values(webviewStates).every(function(isLoaded) { + return isLoaded; + }); + } + function onLoadStop(e) { + var webview = e.target; + e.target.removeEventListener('loadstop', onLoadStop); + var wasLoaded = allLoaded(); + webviewStates[webview.id] = true; + var isLoaded = allLoaded(); + if (!wasLoaded && isLoaded) { + onWebviewsLoaded(); + } + } + Object.keys(webviewStates).forEach(function(webviewId) { + var webview = doc.createElement('webview'); + webview.src = 'data:text/plain, test'; + webview.addEventListener('loadstop', onLoadStop); + webview.id = webviewId; + doc.body.appendChild(webview); + }); +} + +function testStartStopWithOneWebview() { + executeWindowTest(function(win) { + createWebviews(win.document, 1, function() { + win.attemptAudioDebugRecording( + function() { + chrome.test.succeed('Started and stopped with 1 webview'); + }, chrome.test.fail); + }); + }); +} + +function testFailWithMoreThanOneWebview() { + executeWindowTest(function(win) { + createWebviews(win.document, 2, function() { + win.attemptAudioDebugRecording( + function() { + chrome.test.fail('Expected runtime error'); + }, + chrome.test.succeed); + }); + }); +} + +function testFailWithZeroWebviews() { + executeWindowTest(function(win) { + win.attemptAudioDebugRecording( + function() { + chrome.test.fail('Expected runtime error'); + }, + chrome.test.succeed); + }); +} + +chrome.app.runtime.onLaunched.addListener(function() { + chrome.test.runTests([ + testStartStopWithOneWebview, + testFailWithMoreThanOneWebview, + testFailWithZeroWebviews, + ]); +});
diff --git a/chrome/test/data/webui/interventions_internals_browsertest.js b/chrome/test/data/webui/interventions_internals_browsertest.js index abf9b465..0899ab4 100644 --- a/chrome/test/data/webui/interventions_internals_browsertest.js +++ b/chrome/test/data/webui/interventions_internals_browsertest.js
@@ -44,25 +44,38 @@ */ class TestPageHandler extends TestBrowserProxy { constructor() { - super(['getPreviewsEnabled']); + super(['getPreviewsEnabled', 'getPreviewsFlagsDetails']); /** @private {!Map} */ - this.statuses_ = new Map(); + this.previewsModeStatuses_ = new Map(); + this.previewsFlagsStatuses_ = new Map(); } /** - * Setup testing map. + * Setup testing map for getPreviewsEnabled. * @param {!Map} map The testing status map. */ - setTestingMap(map) { - this.statuses_ = map; + setTestingPreviewsModeMap(map) { + this.previewsModeStatuses_ = map; + } + + setTestingPreviewsFlagsMap(map) { + this.previewsFlagsStatuses_ = map; } /** @override **/ getPreviewsEnabled() { this.methodCalled('getPreviewsEnabled'); return Promise.resolve({ - statuses: this.statuses_, + statuses: this.previewsModeStatuses_, + }); + } + + /** @override **/ + getPreviewsFlagsDetails() { + this.methodCalled('getPreviewsFlagsDetails'); + return Promise.resolve({ + flags: this.previewsFlagsStatuses_, }); } } @@ -98,7 +111,7 @@ }, }; -TEST_F('InterventionsInternalsUITest', 'DisplayCorrectStatuses', function() { +TEST_F('InterventionsInternalsUITest', 'GetPreviewsEnabled', function() { let setupFnResolver = this.setupFnResolver; test('DisplayCorrectStatuses', () => { @@ -117,7 +130,7 @@ enabled: true, }); - window.testPageHandler.setTestingMap(testMap); + window.testPageHandler.setTestingPreviewsModeMap(testMap); this.setupFnResolver.resolve(); return setupFnResolver.promise @@ -143,6 +156,56 @@ mocha.run(); }); +TEST_F('InterventionsInternalsUITest', 'GetPreviewsFlagsDetails', function() { + let setupFnResolver = this.setupFnResolver; + + test('DisplayCorrectStatuses', () => { + // Setup testPageHandler behavior. + let testMap = new Map(); + testMap.set('params2', { + description: 'Params 2', + link: 'Link 2', + value: 'Value 2', + }); + testMap.set('params3', { + description: 'Param 3', + link: 'Link 3', + value: 'Value 3', + }); + testMap.set('params1', { + description: 'Params 1', + link: 'Link 1', + value: 'Value 1', + }); + + window.testPageHandler.setTestingPreviewsFlagsMap(testMap); + this.setupFnResolver.resolve(); + + return setupFnResolver.promise + .then(() => { + return window.testPageHandler.whenCalled('getPreviewsFlagsDetails'); + }) + .then(() => { + testMap.forEach((value, key) => { + let actualDescription = + document.querySelector('#' + key + 'Description'); + let actualValue = document.querySelector('#' + key + 'Value'); + expectEquals(value.description, actualDescription.textContent); + expectEquals(value.link, actualDescription.getAttribute('href')); + expectEquals(value.value, actualValue.textContent); + }); + + // Test correct order of flags displayed on page. + let flags = document.querySelectorAll('.previews-status-value'); + for (let i = 1; i < flags.length; i++) { + expectGE(flags[i].textContent, flags[i - 1].textContent); + } + }); + }); + + mocha.run(); +}); + TEST_F('InterventionsInternalsUITest', 'LogNewMessage', function() { test('LogMessageIsPostedCorrectly', () => { let pageImpl = new InterventionsInternalPageImpl(null);
diff --git a/chrome/test/data/webui/settings/languages_page_tests.js b/chrome/test/data/webui/settings/languages_page_tests.js index d44b823..ae251e4 100644 --- a/chrome/test/data/webui/settings/languages_page_tests.js +++ b/chrome/test/data/webui/settings/languages_page_tests.js
@@ -428,7 +428,7 @@ // Disable spellcheck for en-US. var spellcheckLanguageToggle = - spellCheckCollapse.querySelector('paper-toggle-button[checked]'); + spellCheckCollapse.querySelector('cr-toggle[checked]'); assertTrue(!!spellcheckLanguageToggle); MockInteractions.tap(spellcheckLanguageToggle); assertFalse(spellcheckLanguageToggle.checked);
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.js b/chrome/test/data/webui/settings/people_page_sync_page_test.js index fbced73..649f9a6 100644 --- a/chrome/test/data/webui/settings/people_page_sync_page_test.js +++ b/chrome/test/data/webui/settings/people_page_sync_page_test.js
@@ -195,8 +195,7 @@ // Assert that all the individual datatype controls are disabled. var datatypeControls = syncPage - .$$('#configure') - .querySelectorAll('.list-item paper-toggle-button'); + .$$('#configure').querySelectorAll('.list-item cr-toggle'); for (var control of datatypeControls) { assertTrue(control.disabled); assertTrue(control.checked);
diff --git a/chrome/test/media_router/media_router_integration_ui_browsertest.cc b/chrome/test/media_router/media_router_integration_ui_browsertest.cc index ecf58df..b8fe114 100644 --- a/chrome/test/media_router/media_router_integration_ui_browsertest.cc +++ b/chrome/test/media_router/media_router_integration_ui_browsertest.cc
@@ -85,10 +85,10 @@ "domAutomationController.send(" "window.document.getElementById('media-router-container').shadowRoot." "getElementById('route-details').shadowRoot.getElementById(" - "'route-information').getElementsByTagName('span')[0].innerText)"); + "'route-description').innerText)"); std::string route_information = ExecuteScriptAndExtractString( dialog_contents, route_script); - ASSERT_EQ("Casting: Test Route", route_information); + ASSERT_EQ("Test Route", route_information); std::string sink_script; // Verify the container header is not undefined.
diff --git a/chromecast/app/BUILD.gn b/chromecast/app/BUILD.gn index 82fff72a..7f742ed3 100644 --- a/chromecast/app/BUILD.gn +++ b/chromecast/app/BUILD.gn
@@ -20,6 +20,7 @@ "//chromecast/common", "//chromecast/renderer", "//chromecast/utility", + "//components/crash/core/common:crash_key", "//content/public/app:both", "//content/public/browser", "//content/public/common",
diff --git a/chromecast/app/cast_main_delegate.cc b/chromecast/app/cast_main_delegate.cc index d651604..5c529490 100644 --- a/chromecast/app/cast_main_delegate.cc +++ b/chromecast/app/cast_main_delegate.cc
@@ -25,6 +25,7 @@ #include "chromecast/renderer/cast_content_renderer_client.h" #include "chromecast/utility/cast_content_utility_client.h" #include "components/crash/content/app/crash_reporter_client.h" +#include "components/crash/core/common/crash_key.h" #include "content/public/browser/browser_main_runner.h" #include "content/public/common/content_switches.h" #include "ui/base/resource/resource_bundle.h" @@ -145,6 +146,8 @@ } #endif // defined(OS_LINUX) + crash_reporter::InitializeCrashKeys(); + InitializeResourceBundle(); }
diff --git a/chromecast/browser/android/BUILD.gn b/chromecast/browser/android/BUILD.gn index 277e691..9374666d 100644 --- a/chromecast/browser/android/BUILD.gn +++ b/chromecast/browser/android/BUILD.gn
@@ -32,6 +32,9 @@ if (display_web_contents_in_service) { defines += [ "_DISPLAY_WEB_CONTENTS_IN_SERVICE" ] } + + # Set the logcat extractor size in lines. + defines += [ "_LOGCAT_EXTRACTOR_SIZE=${logcat_extractor_size}" ] } android_resources("cast_shell_android_resources") {
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/LogcatExtractor.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/LogcatExtractor.java index 35e185f..2429a9a 100644 --- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/LogcatExtractor.java +++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/LogcatExtractor.java
@@ -33,7 +33,6 @@ class LogcatExtractor { private static final String TAG = "LogcatExtractor"; private static final long HALF_SECOND = 500; - protected static final int LOGCAT_SIZE = 512; // Number of lines. protected static final String EMAIL_ELISION = "XXX@EMAIL.ELIDED"; @VisibleForTesting protected static final String URL_ELISION = "HTTP://WEBADDRESS.ELIDED"; @@ -118,7 +117,7 @@ while ((logLn = bReader.readLine()) != null) { // Add each new string to the end of the queue. rawLogcat.add(logLn); - if (rawLogcat.size() > LOGCAT_SIZE) { + if (rawLogcat.size() > BuildConfig.LOGCAT_SIZE) { // Remove the head of the queue when it gets too large. rawLogcat.remove(); }
diff --git a/chromecast/browser/android/apk/templates/BuildConfig.template b/chromecast/browser/android/apk/templates/BuildConfig.template index 4f8b551..91e5e89 100644 --- a/chromecast/browser/android/apk/templates/BuildConfig.template +++ b/chromecast/browser/android/apk/templates/BuildConfig.template
@@ -11,4 +11,6 @@ false; #endif -} \ No newline at end of file + // Set the number of lines for LogcatExtractor to send. + public static final int LOGCAT_SIZE = _LOGCAT_EXTRACTOR_SIZE; +}
diff --git a/chromecast/chromecast.gni b/chromecast/chromecast.gni index de07990..28cb596 100644 --- a/chromecast/chromecast.gni +++ b/chromecast/chromecast.gni
@@ -54,6 +54,9 @@ # Set to true to keep Android activities alive when they are moved to the # background. enable_background_activities = false + + # Set the number of lines for LogcatExtractor to send. + logcat_extractor_size = 512 } declare_args() {
diff --git a/chromecast/crash/OWNERS b/chromecast/crash/OWNERS new file mode 100644 index 0000000..38324cc --- /dev/null +++ b/chromecast/crash/OWNERS
@@ -0,0 +1 @@ +per-file crash_keys*=rsesek@chromium.org
diff --git a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java index bad9902..6a2ee68d 100644 --- a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java +++ b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java
@@ -336,7 +336,7 @@ Math.min(mTotalFramesWritten, mAudioTrack.getBufferSizeInFrames()); playtimeLeftNsecs = SEC_IN_NSEC * most_frames_left / mSampleRateInHz; } - return playtimeLeftNsecs / 1000; // return usecs + return (playtimeLeftNsecs < 0) ? 0 : playtimeLeftNsecs / 1000; // return usecs } @CalledByNative
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc index 9d5b72d7..88e3fd67 100644 --- a/chromeos/audio/cras_audio_handler.cc +++ b/chromeos/audio/cras_audio_handler.cc
@@ -1655,14 +1655,14 @@ weak_ptr_factory_.GetWeakPtr())); } -void CrasAudioHandler::HandleGetDefaultOutputBufferSize(int32_t buffer_size, - bool success) { - if (!success) { +void CrasAudioHandler::HandleGetDefaultOutputBufferSize( + base::Optional<int> buffer_size) { + if (!buffer_size.has_value()) { LOG(ERROR) << "Failed to retrieve output buffer size"; return; } - default_output_buffer_size_ = buffer_size; + default_output_buffer_size_ = buffer_size.value(); } } // namespace chromeos
diff --git a/chromeos/audio/cras_audio_handler.h b/chromeos/audio/cras_audio_handler.h index 647709b..af34f473 100644 --- a/chromeos/audio/cras_audio_handler.h +++ b/chromeos/audio/cras_audio_handler.h
@@ -472,7 +472,7 @@ void GetDefaultOutputBufferSizeInternal(); // Handle dbus callback for GetDefaultOutputBufferSize. - void HandleGetDefaultOutputBufferSize(int buffer_size, bool success); + void HandleGetDefaultOutputBufferSize(base::Optional<int> buffer_size); void OnVideoCaptureStartedOnMainThread(media::VideoFacingMode facing); void OnVideoCaptureStoppedOnMainThread(media::VideoFacingMode facing);
diff --git a/chromeos/cryptohome/homedir_methods.cc b/chromeos/cryptohome/homedir_methods.cc index a9b16350..d1877e75 100644 --- a/chromeos/cryptohome/homedir_methods.cc +++ b/chromeos/cryptohome/homedir_methods.cc
@@ -139,31 +139,21 @@ } void RemoveKeyEx(const Identification& id, - const Authorization& auth, - const std::string& label, + const AuthorizationRequest& auth, + const RemoveKeyRequest& request, const Callback& callback) override { - cryptohome::RemoveKeyRequest request; - - request.mutable_key()->mutable_data()->set_label(label); - DBusThreadManager::Get()->GetCryptohomeClient()->RemoveKeyEx( - id, CreateAuthorizationRequest(auth.label, auth.key), request, + id, auth, request, base::BindOnce(&HomedirMethodsImpl::OnBaseReplyCallback, weak_ptr_factory_.GetWeakPtr(), callback)); } void UpdateKeyEx(const Identification& id, - const Authorization& auth, - const KeyDefinition& new_key, - const std::string& signature, + const AuthorizationRequest& auth, + const UpdateKeyRequest& request, const Callback& callback) override { - cryptohome::UpdateKeyRequest pb_update_key; - - KeyDefinitionToKey(new_key, pb_update_key.mutable_changes()); - pb_update_key.set_authorization_signature(signature); - DBusThreadManager::Get()->GetCryptohomeClient()->UpdateKeyEx( - id, CreateAuthorizationRequest(auth.label, auth.key), pb_update_key, + id, auth, request, base::BindOnce(&HomedirMethodsImpl::OnBaseReplyCallback, weak_ptr_factory_.GetWeakPtr(), callback)); } @@ -186,10 +176,8 @@ } void MigrateToDircrypto(const Identification& id, - bool minimal_migration, + const cryptohome::MigrateToDircryptoRequest& request, const DBusResultCallback& callback) override { - cryptohome::MigrateToDircryptoRequest request; - request.set_minimal_migration(minimal_migration); DBusThreadManager::Get()->GetCryptohomeClient()->MigrateToDircrypto( id, request, base::Bind(&HomedirMethodsImpl::OnDBusResultCallback,
diff --git a/chromeos/cryptohome/homedir_methods.h b/chromeos/cryptohome/homedir_methods.h index d69db62..7648423 100644 --- a/chromeos/cryptohome/homedir_methods.h +++ b/chromeos/cryptohome/homedir_methods.h
@@ -83,23 +83,20 @@ const AddKeyRequest& request, const Callback& callback) = 0; - // Asks cryptohomed to update |key| for user identified by |id| using |auth| - // to unlock the key. - // Label for |auth| and |key| have to be the same. - // Key used in |auth| should have PRIV_AUTHORIZED_UPDATE privilege. - // |signature| is used by cryptohome to verify the authentity of new key. + // Asks cryptohomed to update the key for the user identified by |id| using + // |auth| to unlock the key. Label for |auth| and the requested key have to be + // the same. Key used in |auth| should have PRIV_AUTHORIZED_UPDATE privilege. // |callback| will be called with status info on completion. virtual void UpdateKeyEx(const Identification& id, - const Authorization& auth, - const KeyDefinition& key, - const std::string& signature, + const AuthorizationRequest& auth, + const UpdateKeyRequest& request, const Callback& callback) = 0; - // Asks cryptohomed to remove specific key labeled with |label| for user - // identified by |id| using |auth|. + // Asks cryptohomed to remove a specific key for the user identified by |id| + // using |auth|. virtual void RemoveKeyEx(const Identification& id, - const Authorization& auth, - const std::string& label, + const AuthorizationRequest& auth, + const RemoveKeyRequest& request, const Callback& callback) = 0; // Asks cryptohomed to change cryptohome identification |id_from| to |id_to|, @@ -117,7 +114,7 @@ // Asks cryptohomed to migrate the cryptohome to the new encryption method // for the user specified by |id|. virtual void MigrateToDircrypto(const Identification& id, - bool minimal_migration, + const MigrateToDircryptoRequest& request, const DBusResultCallback& callback) = 0; // Creates the global HomedirMethods instance.
diff --git a/chromeos/cryptohome/mock_homedir_methods.cc b/chromeos/cryptohome/mock_homedir_methods.cc index 2c42d54..4bf1edc 100644 --- a/chromeos/cryptohome/mock_homedir_methods.cc +++ b/chromeos/cryptohome/mock_homedir_methods.cc
@@ -32,8 +32,9 @@ ON_CALL(*this, AddKeyEx(_, _, _, _)) .WillByDefault( WithArgs<3>(Invoke(this, &MockHomedirMethods::DoAddKeyCallback))); - ON_CALL(*this, UpdateKeyEx(_, _, _, _, _)).WillByDefault( - WithArgs<4>(Invoke(this, &MockHomedirMethods::DoCallback))); + ON_CALL(*this, UpdateKeyEx(_, _, _, _)) + .WillByDefault( + WithArgs<3>(Invoke(this, &MockHomedirMethods::DoCallback))); ON_CALL(*this, RemoveKeyEx(_, _, _, _)).WillByDefault( WithArgs<3>(Invoke(this, &MockHomedirMethods::DoCallback))); }
diff --git a/chromeos/cryptohome/mock_homedir_methods.h b/chromeos/cryptohome/mock_homedir_methods.h index 21abd274..0c9d6bb9 100644 --- a/chromeos/cryptohome/mock_homedir_methods.h +++ b/chromeos/cryptohome/mock_homedir_methods.h
@@ -44,14 +44,13 @@ const Callback& callback)); MOCK_METHOD4(RemoveKeyEx, void(const Identification& id, - const Authorization& auth, - const std::string& label, + const AuthorizationRequest& auth, + const RemoveKeyRequest& request, const Callback& callback)); - MOCK_METHOD5(UpdateKeyEx, + MOCK_METHOD4(UpdateKeyEx, void(const Identification& id, - const Authorization& auth, - const KeyDefinition& key, - const std::string& signature, + const AuthorizationRequest& auth, + const UpdateKeyRequest& request, const Callback& callback)); MOCK_METHOD3(RenameCryptohome, void(const Identification& id_from, @@ -62,7 +61,7 @@ const GetAccountDiskUsageCallback& callback)); MOCK_METHOD3(MigrateToDircrypto, void(const Identification& id, - bool minimal_migration, + const MigrateToDircryptoRequest& request, const DBusResultCallback& callback)); void set_mount_callback(const base::Closure& callback) {
diff --git a/chromeos/dbus/cras_audio_client.cc b/chromeos/dbus/cras_audio_client.cc index b4061631..92fd51c73 100644 --- a/chromeos/dbus/cras_audio_client.cc +++ b/chromeos/dbus/cras_audio_client.cc
@@ -40,23 +40,22 @@ return observers_.HasObserver(observer); } - void GetVolumeState(const GetVolumeStateCallback& callback) override { + void GetVolumeState(DBusMethodCallback<VolumeState> callback) override { dbus::MethodCall method_call(cras::kCrasControlInterface, cras::kGetVolumeState); cras_proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::BindOnce(&CrasAudioClientImpl::OnGetVolumeState, - weak_ptr_factory_.GetWeakPtr(), callback)); + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } - void GetDefaultOutputBufferSize( - const GetDefaultOutputBufferSizeCallback& callback) override { + void GetDefaultOutputBufferSize(DBusMethodCallback<int> callback) override { dbus::MethodCall method_call(cras::kCrasControlInterface, cras::kGetDefaultOutputBufferSize); cras_proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::BindOnce(&CrasAudioClientImpl::OnGetDefaultOutputBufferSize, - weak_ptr_factory_.GetWeakPtr(), callback)); + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } void GetNodes(DBusMethodCallback<AudioNodeList> callback) override { @@ -379,48 +378,47 @@ observer.HotwordTriggered(tv_sec, tv_nsec); } - void OnGetVolumeState(const GetVolumeStateCallback& callback, + void OnGetVolumeState(DBusMethodCallback<VolumeState> callback, dbus::Response* response) { - bool success = true; - VolumeState volume_state; - if (response) { - dbus::MessageReader reader(response); - if (!reader.PopInt32(&volume_state.output_volume) || - !reader.PopBool(&volume_state.output_system_mute) || - !reader.PopInt32(&volume_state.input_gain) || - !reader.PopBool(&volume_state.input_mute) || - !reader.PopBool(&volume_state.output_user_mute)) { - success = false; - LOG(ERROR) << "Error reading response from cras: " - << response->ToString(); - } - } else { - success = false; + if (!response) { LOG(ERROR) << "Error calling " << cras::kGetVolumeState; + std::move(callback).Run(base::nullopt); + return; } - callback.Run(volume_state, success); + VolumeState volume_state; + dbus::MessageReader reader(response); + if (!reader.PopInt32(&volume_state.output_volume) || + !reader.PopBool(&volume_state.output_system_mute) || + !reader.PopInt32(&volume_state.input_gain) || + !reader.PopBool(&volume_state.input_mute) || + !reader.PopBool(&volume_state.output_user_mute)) { + LOG(ERROR) << "Error reading response from cras: " + << response->ToString(); + std::move(callback).Run(base::nullopt); + return; + } + + std::move(callback).Run(std::move(volume_state)); } - void OnGetDefaultOutputBufferSize( - const GetDefaultOutputBufferSizeCallback& callback, - dbus::Response* response) { - bool success = true; - int32_t buffer_size = 0; - - if (response) { - dbus::MessageReader reader(response); - if (!reader.PopInt32(&buffer_size)) { - success = false; - LOG(ERROR) << "Error reading response from cras: " - << response->ToString(); - } - } else { - success = false; + void OnGetDefaultOutputBufferSize(DBusMethodCallback<int> callback, + dbus::Response* response) { + if (!response) { LOG(ERROR) << "Error calling " << cras::kGetDefaultOutputBufferSize; + std::move(callback).Run(base::nullopt); + return; + } + int32_t buffer_size = 0; + dbus::MessageReader reader(response); + if (!reader.PopInt32(&buffer_size)) { + LOG(ERROR) << "Error reading response from cras: " + << response->ToString(); + std::move(callback).Run(base::nullopt); + return; } - callback.Run(buffer_size, success); + std::move(callback).Run(buffer_size); } void OnGetNodes(DBusMethodCallback<AudioNodeList> callback,
diff --git a/chromeos/dbus/cras_audio_client.h b/chromeos/dbus/cras_audio_client.h index 3d23707..2d400e31 100644 --- a/chromeos/dbus/cras_audio_client.h +++ b/chromeos/dbus/cras_audio_client.h
@@ -64,24 +64,11 @@ // Returns true if this object has the given observer. virtual bool HasObserver(const Observer* observer) const = 0; - // GetVolumeStateCallback is used for GetVolumeState method. It receives - // 2 arguments, |volume_state| which containing both input and output volume - // state data, and |success| which indicates whether or not the request - // succeeded. - typedef base::Callback<void(const VolumeState&, bool)> GetVolumeStateCallback; - - // Used for GetDefaultOutputBufferSize method. The first argument is the - // default output buffer size. The second argument indicates whether the - // request succeeded. The first argument is valid only when the request - // succeeded. - typedef base::Callback<void(int, bool)> GetDefaultOutputBufferSizeCallback; - // Gets the volume state, asynchronously. - virtual void GetVolumeState(const GetVolumeStateCallback& callback) = 0; + virtual void GetVolumeState(DBusMethodCallback<VolumeState> callback) = 0; // Gets the default output buffer size in frames. - virtual void GetDefaultOutputBufferSize( - const GetDefaultOutputBufferSizeCallback& callback) = 0; + virtual void GetDefaultOutputBufferSize(DBusMethodCallback<int> callback) = 0; // Gets an array of audio input and output nodes. virtual void GetNodes(DBusMethodCallback<AudioNodeList> callback) = 0;
diff --git a/chromeos/dbus/fake_cras_audio_client.cc b/chromeos/dbus/fake_cras_audio_client.cc index c6ab7c3..ad45915 100644 --- a/chromeos/dbus/fake_cras_audio_client.cc +++ b/chromeos/dbus/fake_cras_audio_client.cc
@@ -98,13 +98,13 @@ } void FakeCrasAudioClient::GetVolumeState( - const GetVolumeStateCallback& callback) { - callback.Run(volume_state_, true); + DBusMethodCallback<VolumeState> callback) { + std::move(callback).Run(volume_state_); } void FakeCrasAudioClient::GetDefaultOutputBufferSize( - const GetDefaultOutputBufferSizeCallback& callback) { - callback.Run(512, true); + DBusMethodCallback<int> callback) { + std::move(callback).Run(512); } void FakeCrasAudioClient::GetNodes(DBusMethodCallback<AudioNodeList> callback) {
diff --git a/chromeos/dbus/fake_cras_audio_client.h b/chromeos/dbus/fake_cras_audio_client.h index 868e72f..7bab901 100644 --- a/chromeos/dbus/fake_cras_audio_client.h +++ b/chromeos/dbus/fake_cras_audio_client.h
@@ -26,9 +26,8 @@ void AddObserver(Observer* observer) override; void RemoveObserver(Observer* observer) override; bool HasObserver(const Observer* observer) const override; - void GetVolumeState(const GetVolumeStateCallback& callback) override; - void GetDefaultOutputBufferSize( - const GetDefaultOutputBufferSizeCallback& callback) override; + void GetVolumeState(DBusMethodCallback<VolumeState> callback) override; + void GetDefaultOutputBufferSize(DBusMethodCallback<int> callback) override; void GetNodes(DBusMethodCallback<AudioNodeList> callback) override; void SetOutputNodeVolume(uint64_t node_id, int32_t volume) override; void SetOutputUserMute(bool mute_on) override;
diff --git a/chromeos/dbus/fake_shill_service_client.cc b/chromeos/dbus/fake_shill_service_client.cc index b92d611..9ae9a97 100644 --- a/chromeos/dbus/fake_shill_service_client.cc +++ b/chromeos/dbus/fake_shill_service_client.cc
@@ -406,7 +406,7 @@ shill::kProviderProperty, base::Value(base::Value::Type::DICTIONARY)); provider->SetKey(key, value.Clone()); changed_property = shill::kProviderProperty; - } else if (value.GetType() == base::Value::Type::DICTIONARY) { + } else if (value.is_dict()) { const base::DictionaryValue* new_dict = NULL; value.GetAsDictionary(&new_dict); CHECK(new_dict);
diff --git a/chromeos/dbus/shill_client_helper.cc b/chromeos/dbus/shill_client_helper.cc index 2439dbc3..e61444c 100644 --- a/chromeos/dbus/shill_client_helper.cc +++ b/chromeos/dbus/shill_client_helper.cc
@@ -398,7 +398,7 @@ const base::Value& value, DictionaryType dictionary_type) { // Support basic types and string-to-string dictionary. - switch (value.GetType()) { + switch (value.type()) { case base::Value::Type::DICTIONARY: { const base::DictionaryValue* dictionary = NULL; value.GetAsDictionary(&dictionary); @@ -439,7 +439,7 @@ dbus::AppendBasicTypeValueDataAsVariant(writer, value); break; default: - NET_LOG(ERROR) << "Unexpected value type: " << value.GetType(); + NET_LOG(ERROR) << "Unexpected value type: " << value.type(); } }
diff --git a/chromeos/dbus/shill_ipconfig_client.cc b/chromeos/dbus/shill_ipconfig_client.cc index 6c98528..b3071e1 100644 --- a/chromeos/dbus/shill_ipconfig_client.cc +++ b/chromeos/dbus/shill_ipconfig_client.cc
@@ -113,7 +113,7 @@ dbus::MessageWriter writer(&method_call); writer.AppendString(name); // IPConfig supports writing basic type and string array properties. - switch (value.GetType()) { + switch (value.type()) { case base::Value::Type::LIST: { const base::ListValue* list_value = NULL; value.GetAsList(&list_value); @@ -124,8 +124,7 @@ for (base::ListValue::const_iterator it = list_value->begin(); it != list_value->end(); ++it) { - DLOG_IF(ERROR, it->GetType() != base::Value::Type::STRING) - << "Unexpected type " << it->GetType(); + DLOG_IF(ERROR, !it->is_string()) << "Unexpected type " << it->type(); std::string str; it->GetAsString(&str); array_writer.AppendString(str); @@ -140,7 +139,7 @@ dbus::AppendBasicTypeValueDataAsVariant(&writer, value); break; default: - DLOG(ERROR) << "Unexpected type " << value.GetType(); + DLOG(ERROR) << "Unexpected type " << value.type(); } GetHelper(ipconfig_path)->CallVoidMethod(&method_call, std::move(callback)); }
diff --git a/chromeos/geolocation/simple_geolocation_request.cc b/chromeos/geolocation/simple_geolocation_request.cc index 513b612..791b1fc 100644 --- a/chromeos/geolocation/simple_geolocation_request.cc +++ b/chromeos/geolocation/simple_geolocation_request.cc
@@ -208,7 +208,7 @@ server_url, "Unexpected response type : " + base::StringPrintf( - "%u", static_cast<unsigned int>(response_value->GetType())), + "%u", static_cast<unsigned int>(response_value->type())), position); RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_MALFORMED); return false;
diff --git a/chromeos/login/auth/extended_authenticator_impl.cc b/chromeos/login/auth/extended_authenticator_impl.cc index 89f5c1e..650050f 100644 --- a/chromeos/login/auth/extended_authenticator_impl.cc +++ b/chromeos/login/auth/extended_authenticator_impl.cc
@@ -236,20 +236,17 @@ const UserContext& user_context) { RecordStartMarker("UpdateKeyAuthorized"); - cryptohome::Identification id(user_context.GetAccountId()); const Key* const auth_key = user_context.GetKey(); - cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel()); - + cryptohome::UpdateKeyRequest request; + cryptohome::KeyDefinitionToKey(key, request.mutable_changes()); + request.set_authorization_signature(signature); cryptohome::HomedirMethods::GetInstance()->UpdateKeyEx( - id, - auth, - key, - signature, - base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete, - this, - "UpdateKeyAuthorized", - user_context, - success_callback)); + cryptohome::Identification(user_context.GetAccountId()), + cryptohome::CreateAuthorizationRequest(auth_key->GetLabel(), + auth_key->GetSecret()), + request, + base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete, this, + "UpdateKeyAuthorized", user_context, success_callback)); } void ExtendedAuthenticatorImpl::DoRemoveKey(const std::string& key_to_remove, @@ -257,19 +254,16 @@ const UserContext& user_context) { RecordStartMarker("RemoveKeyEx"); - cryptohome::Identification id(user_context.GetAccountId()); + cryptohome::RemoveKeyRequest request; + request.mutable_key()->mutable_data()->set_label(key_to_remove); const Key* const auth_key = user_context.GetKey(); - cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel()); - cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx( - id, - auth, - key_to_remove, - base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete, - this, - "RemoveKeyEx", - user_context, - success_callback)); + cryptohome::Identification(user_context.GetAccountId()), + cryptohome::CreateAuthorizationRequest(auth_key->GetLabel(), + auth_key->GetSecret()), + request, + base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete, this, + "RemoveKeyEx", user_context, success_callback)); } void ExtendedAuthenticatorImpl::OnMountComplete(
diff --git a/chromeos/network/network_sms_handler.cc b/chromeos/network/network_sms_handler.cc index efacb0df..d5d2fde 100644 --- a/chromeos/network/network_sms_handler.cc +++ b/chromeos/network/network_sms_handler.cc
@@ -406,7 +406,7 @@ } const base::Value* value; if (!properties.GetWithoutPathExpansion(shill::kDevicesProperty, &value) || - value->GetType() != base::Value::Type::LIST) { + !value->is_list()) { LOG(ERROR) << "NetworkSmsHandler: No list value for: " << shill::kDevicesProperty; return;
diff --git a/chromeos/network/onc/onc_mapper.cc b/chromeos/network/onc/onc_mapper.cc index d7417595..7c9f78df 100644 --- a/chromeos/network/onc/onc_mapper.cc +++ b/chromeos/network/onc/onc_mapper.cc
@@ -25,7 +25,7 @@ const base::Value& onc_value, bool* error) { std::unique_ptr<base::Value> result_value; - switch (onc_value.GetType()) { + switch (onc_value.type()) { case base::Value::Type::DICTIONARY: { const base::DictionaryValue* dict = NULL; onc_value.GetAsDictionary(&dict);
diff --git a/chromeos/network/onc/onc_test_utils.cc b/chromeos/network/onc/onc_test_utils.cc index 11ae0ad..1243415 100644 --- a/chromeos/network/onc/onc_test_utils.cc +++ b/chromeos/network/onc/onc_test_utils.cc
@@ -63,7 +63,7 @@ dict = base::DictionaryValue::From(std::move(content)); CHECK(dict) << "File '" << filename << "' does not contain a dictionary as expected, but type " - << content->GetType(); + << content->type(); return dict; }
diff --git a/chromeos/network/onc/onc_translator_onc_to_shill.cc b/chromeos/network/onc/onc_translator_onc_to_shill.cc index 7c3e2d7d..8258be7 100644 --- a/chromeos/network/onc/onc_translator_onc_to_shill.cc +++ b/chromeos/network/onc/onc_translator_onc_to_shill.cc
@@ -383,9 +383,9 @@ if (field_signature) { base::Value::Type expected_type = field_signature->value_signature->onc_type; - if (value->GetType() != expected_type) { + if (value->type() != expected_type) { LOG(ERROR) << "Found field " << onc_field_name << " of type " - << value->GetType() << " but expected type " << expected_type; + << value->type() << " but expected type " << expected_type; return; } } else {
diff --git a/chromeos/network/onc/onc_translator_shill_to_onc.cc b/chromeos/network/onc/onc_translator_shill_to_onc.cc index 2198fd2..432240d 100644 --- a/chromeos/network/onc/onc_translator_shill_to_onc.cc +++ b/chromeos/network/onc/onc_translator_shill_to_onc.cc
@@ -38,7 +38,7 @@ } else { value = base::JSONReader::Read(str); } - if (value && value->GetType() != type) + if (value && value->type() != type) return nullptr; return value; @@ -797,10 +797,10 @@ return; } - if (shill_value->GetType() != field_signature->value_signature->onc_type) { + if (shill_value->type() != field_signature->value_signature->onc_type) { LOG(ERROR) << "Shill property '" << shill_property_name << "' with value " << *shill_value << " has base::Value::Type " - << shill_value->GetType() << " but ONC field '" + << shill_value->type() << " but ONC field '" << field_signature->onc_field_name << "' requires type " << field_signature->value_signature->onc_type << ": " << GetName();
diff --git a/chromeos/network/onc/onc_validator.cc b/chromeos/network/onc/onc_validator.cc index d2f69fd..6248bc1 100644 --- a/chromeos/network/onc/onc_validator.cc +++ b/chromeos/network/onc/onc_validator.cc
@@ -71,9 +71,9 @@ const OncValueSignature& signature, const base::Value& onc_value, bool* error) { - if (onc_value.GetType() != signature.onc_type) { + if (onc_value.type() != signature.onc_type) { LOG(ERROR) << MessageHeader() << "Found value '" << onc_value - << "' of type '" << base::Value::GetTypeName(onc_value.GetType()) + << "' of type '" << base::Value::GetTypeName(onc_value.type()) << "', but type '" << base::Value::GetTypeName(signature.onc_type) << "' is required."; @@ -84,7 +84,7 @@ std::unique_ptr<base::Value> repaired = Mapper::MapValue(signature, onc_value, error); if (repaired) - CHECK_EQ(repaired->GetType(), signature.onc_type); + CHECK_EQ(repaired->type(), signature.onc_type); return repaired; }
diff --git a/chromeos/timezone/timezone_request.cc b/chromeos/timezone/timezone_request.cc index df1ef21e..a918b08e 100644 --- a/chromeos/timezone/timezone_request.cc +++ b/chromeos/timezone/timezone_request.cc
@@ -192,7 +192,7 @@ server_url, "Unexpected response type : " + base::StringPrintf( - "%u", static_cast<unsigned int>(response_value->GetType())), + "%u", static_cast<unsigned int>(response_value->type())), timezone); RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_MALFORMED); return false;
diff --git a/components/BUILD.gn b/components/BUILD.gn index 756dc5f5..8204331 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -448,7 +448,9 @@ "//ipc:test_support", "//net:test_support", "//printing/features", + "//services/device/public/interfaces", "//services/service_manager/public/cpp", + "//services/service_manager/public/interfaces", "//testing/gmock", "//testing/gtest", "//ui/base",
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn index 7eb22fc8..425c697 100644 --- a/components/arc/BUILD.gn +++ b/components/arc/BUILD.gn
@@ -2,7 +2,6 @@ # 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") import("//testing/test.gni") static_library("arc") { @@ -62,7 +61,7 @@ deps = [ "//ash:ash", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//chromeos", "//chromeos:login_manager_proto", @@ -138,7 +137,7 @@ ] deps = [ - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//chromeos", "//components/keyed_service/content", @@ -150,63 +149,8 @@ ] public_deps = [ - ":arc_bindings", ":prefs", - ] -} - -mojom("arc_bindings") { - sources = [ - "common/accessibility_helper.mojom", - "common/app.mojom", - "common/arc_bridge.mojom", - "common/audio.mojom", - "common/auth.mojom", - "common/backup_settings.mojom", - "common/bitmap.mojom", - "common/bluetooth.mojom", - "common/boot_phase_monitor.mojom", - "common/cast_receiver.mojom", - "common/cert_store.mojom", - "common/clipboard.mojom", - "common/crash_collector.mojom", - "common/enterprise_reporting.mojom", - "common/file_system.mojom", - "common/gfx.mojom", - "common/ime.mojom", - "common/intent_helper.mojom", - "common/kiosk.mojom", - "common/lock_screen.mojom", - "common/metrics.mojom", - "common/midis.mojom", - "common/net.mojom", - "common/notifications.mojom", - "common/obb_mounter.mojom", - "common/oemcrypto.mojom", - "common/oemcrypto_daemon.mojom", - "common/policy.mojom", - "common/power.mojom", - "common/print.mojom", - "common/process.mojom", - "common/protected_buffer_manager.mojom", - "common/rotation_lock.mojom", - "common/scale_factor.mojom", - "common/storage_manager.mojom", - "common/tracing.mojom", - "common/tts.mojom", - "common/video.mojom", - "common/video_common.mojom", - "common/video_decode_accelerator.mojom", - "common/video_encode_accelerator.mojom", - "common/voice_interaction_arc_home.mojom", - "common/voice_interaction_framework.mojom", - "common/volume_mounter.mojom", - "common/wallpaper.mojom", - ] - - public_deps = [ - "//mojo/common:common_custom_types", - "//ui/gfx/geometry/mojo", + "//components/arc/common", ] } @@ -266,7 +210,7 @@ deps = [ ":arc_test_support", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//base/test:test_support", "//chromeos",
diff --git a/components/arc/arc_util.cc b/components/arc/arc_util.cc index 83436fe..f0033f47 100644 --- a/components/arc/arc_util.cc +++ b/components/arc/arc_util.cc
@@ -172,6 +172,11 @@ return false; } + if (user->GetType() == user_manager::USER_TYPE_CHILD) { + VLOG(1) << "ARC usage by Child users is prohibited"; + return false; + } + return true; }
diff --git a/components/arc/arc_util_unittest.cc b/components/arc/arc_util_unittest.cc index 486d81d5..c739f35 100644 --- a/components/arc/arc_util_unittest.cc +++ b/components/arc/arc_util_unittest.cc
@@ -197,7 +197,7 @@ {user_manager::USER_TYPE_PUBLIC_ACCOUNT, false}, {user_manager::USER_TYPE_SUPERVISED, false}, {user_manager::USER_TYPE_KIOSK_APP, false}, - {user_manager::USER_TYPE_CHILD, true}, + {user_manager::USER_TYPE_CHILD, false}, {user_manager::USER_TYPE_ARC_KIOSK_APP, true}, {user_manager::USER_TYPE_ACTIVE_DIRECTORY, true}, };
diff --git a/components/arc/common/BUILD.gn b/components/arc/common/BUILD.gn new file mode 100644 index 0000000..a60852bb --- /dev/null +++ b/components/arc/common/BUILD.gn
@@ -0,0 +1,76 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/tools/bindings/mojom.gni") + +if (is_chromeos) { + mojom("common") { + sources = [ + "accessibility_helper.mojom", + "app.mojom", + "arc_bridge.mojom", + "audio.mojom", + "auth.mojom", + "backup_settings.mojom", + "bitmap.mojom", + "bluetooth.mojom", + "boot_phase_monitor.mojom", + "cast_receiver.mojom", + "cert_store.mojom", + "clipboard.mojom", + "crash_collector.mojom", + "enterprise_reporting.mojom", + "file_system.mojom", + "gfx.mojom", + "ime.mojom", + "intent_helper.mojom", + "kiosk.mojom", + "lock_screen.mojom", + "metrics.mojom", + "midis.mojom", + "net.mojom", + "notifications.mojom", + "obb_mounter.mojom", + "oemcrypto.mojom", + "oemcrypto_daemon.mojom", + "policy.mojom", + "power.mojom", + "print.mojom", + "process.mojom", + "rotation_lock.mojom", + "scale_factor.mojom", + "storage_manager.mojom", + "tracing.mojom", + "tts.mojom", + "voice_interaction_arc_home.mojom", + "voice_interaction_framework.mojom", + "volume_mounter.mojom", + "wallpaper.mojom", + ] + + public_deps = [ + ":media", + "//mojo/common:common_custom_types", + "//ui/gfx/geometry/mojo", + ] + } +} + +# Media related mojo interfaces. There are used by +# //services/ui/public/interfaces. We have this separate mojom target to avoid +# pulling in unnecessary interfaces, +mojom("media") { + sources = [ + "protected_buffer_manager.mojom", + "video.mojom", + "video_common.mojom", + "video_decode_accelerator.mojom", + "video_encode_accelerator.mojom", + ] + + public_deps = [ + "//mojo/common:common_custom_types", + "//ui/gfx/geometry/mojo", + ] +}
diff --git a/components/arc/common/video_common.typemap b/components/arc/common/video_common.typemap index 3bff538..3bc56045 100644 --- a/components/arc/common/video_common.typemap +++ b/components/arc/common/video_common.typemap
@@ -11,6 +11,9 @@ sources = [ "//components/arc/common/video_accelerator_struct_traits.cc", ] +deps = [ + "//ui/gfx/geometry", +] type_mappings = [ "arc.mojom.VideoFramePlane=arc::VideoFramePlane[move_only]", "arc.mojom.Size=gfx::Size",
diff --git a/components/arc/common/video_encode_accelerator.typemap b/components/arc/common/video_encode_accelerator.typemap index 1957e525..a7453766 100644 --- a/components/arc/common/video_encode_accelerator.typemap +++ b/components/arc/common/video_encode_accelerator.typemap
@@ -5,7 +5,7 @@ mojom = "//components/arc/common/video_encode_accelerator.mojom" public_headers = [ "//media/video/video_encode_accelerator.h" ] public_deps = [ - "//media", + "//media/gpu", ] traits_headers = [ "//components/arc/common/video_encode_accelerator_struct_traits.h" ]
diff --git a/components/arc/common/voice_interaction_framework.mojom b/components/arc/common/voice_interaction_framework.mojom index 6a2cba6..098bf02 100644 --- a/components/arc/common/voice_interaction_framework.mojom +++ b/components/arc/common/voice_interaction_framework.mojom
@@ -23,18 +23,12 @@ // Handles voice interaction queries from Android. // Next method ID: 6 -// Deprecated method ID: 0, 4 +// Deprecated method ID: 0, 2, 3, 4 interface VoiceInteractionFrameworkHost { // Returns a fullscreen screenshot of the primary display. // |data| represents the image encoded in JPEG format. [MinVersion=1]CaptureFullscreen@1() => (array<uint8> data); - // Notifies the host that the metalayer has closed or could not open. - [MinVersion=2]OnMetalayerClosed@2(); - - // Enables/disables screenshot taking. - [MinVersion=3]SetMetalayerEnabled@3(bool enabled); - // Notifies Chrome the state of voice interaction session. [MinVersion=8]SetVoiceInteractionState@5(VoiceInteractionState state); };
diff --git a/components/arc/common/volume_mounter.typemap b/components/arc/common/volume_mounter.typemap index 6198166d..0b905728 100644 --- a/components/arc/common/volume_mounter.typemap +++ b/components/arc/common/volume_mounter.typemap
@@ -3,14 +3,16 @@ # found in the LICENSE file. mojom = "//components/arc/common/volume_mounter.mojom" -public_headers = [ "//chromeos/disks/disk_mount_manager.h" ] +public_headers = [ + "//chromeos/chromeos_export.h", + "//chromeos/dbus/cros_disks_client.h", + "//chromeos/dbus/dbus_client_implementation_type.h", + "//chromeos/disks/disk_mount_manager.h", +] traits_headers = [ "//components/arc/volume_mounter/volume_mounter_traits.h" ] sources = [ "//components/arc/volume_mounter/volume_mounter_traits.cc", ] -deps = [ - "//chromeos", -] type_mappings = [ "arc.mojom.DeviceType=chromeos::DeviceType", "arc.mojom.MountEvent=chromeos::disks::DiskMountManager::MountEvent",
diff --git a/components/arc/video_accelerator/BUILD.gn b/components/arc/video_accelerator/BUILD.gn index b4df8bfd8..49683a0 100644 --- a/components/arc/video_accelerator/BUILD.gn +++ b/components/arc/video_accelerator/BUILD.gn
@@ -18,7 +18,7 @@ ] deps = [ - "//components/arc:arc_bindings", + "//components/arc/common:media", "//media/gpu", "//ui/ozone", ]
diff --git a/components/autofill/content/browser/BUILD.gn b/components/autofill/content/browser/BUILD.gn index ef84caa..e2d7717 100644 --- a/components/autofill/content/browser/BUILD.gn +++ b/components/autofill/content/browser/BUILD.gn
@@ -38,8 +38,10 @@ "//device/geolocation/public/interfaces", "//gpu/config", "//mojo/common:common_base", + "//mojo/public/cpp/bindings", "//net", "//ppapi/features", + "//services/device/public/interfaces", "//services/service_manager/public/cpp", "//sql", "//ui/base",
diff --git a/components/autofill/content/browser/DEPS b/components/autofill/content/browser/DEPS index 302796c..e6b2b02 100644 --- a/components/autofill/content/browser/DEPS +++ b/components/autofill/content/browser/DEPS
@@ -1,8 +1,10 @@ include_rules = [ "+content/public/browser", "+crypto/random.h", - "+device/geolocation", + "+device/geolocation/public", "+gpu/config/gpu_info.h", + "+services/device/public", + "+services/service_manager/public/interfaces", "+third_party/WebKit/public/platform/WebRect.h", ]
diff --git a/components/autofill/content/browser/risk/fingerprint.cc b/components/autofill/content/browser/risk/fingerprint.cc index 9264eb6..3a97366f 100644 --- a/components/autofill/content/browser/risk/fingerprint.cc +++ b/components/autofill/content/browser/risk/fingerprint.cc
@@ -38,11 +38,15 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/screen_info.h" #include "content/public/common/webplugininfo.h" -#include "device/geolocation/geolocation_provider.h" #include "device/geolocation/public/cpp/geoposition.h" +#include "device/geolocation/public/interfaces/geolocation.mojom.h" +#include "device/geolocation/public/interfaces/geolocation_context.mojom.h" #include "device/geolocation/public/interfaces/geoposition.mojom.h" #include "gpu/config/gpu_info.h" +#include "mojo/public/cpp/bindings/interface_request.h" #include "ppapi/features/features.h" +#include "services/device/public/interfaces/constants.mojom.h" +#include "services/service_manager/public/cpp/connector.h" #include "third_party/WebKit/public/platform/WebRect.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -189,7 +193,8 @@ const std::string& app_locale, const std::string& user_agent, const base::TimeDelta& timeout, - const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback); + const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback, + service_manager::Connector* connector); private: ~FingerprintDataLoader() override {} @@ -200,7 +205,10 @@ // Callbacks for asynchronously loaded data. void OnGotFonts(std::unique_ptr<base::ListValue> fonts); void OnGotPlugins(const std::vector<content::WebPluginInfo>& plugins); - void OnGotGeoposition(const device::mojom::Geoposition& geoposition); + void OnGotGeoposition( + device::mojom::GeolocationContextPtr geolocation_context, + device::mojom::GeolocationPtr geolocation, + device::mojom::GeopositionPtr geoposition); // If all of the asynchronous data has been loaded, calls |callback_| with // the fingerprint data. @@ -243,10 +251,6 @@ // The callback that will be called once all the data is available. base::Callback<void(std::unique_ptr<Fingerprint>)> callback_; - // The callback used as an "observer" of the GeolocationProvider. - std::unique_ptr<device::GeolocationProvider::Subscription> - geolocation_subscription_; - // For invalidating asynchronous callbacks that might arrive after |this| // instance is destroyed. base::WeakPtrFactory<FingerprintDataLoader> weak_ptr_factory_; @@ -266,7 +270,8 @@ const std::string& app_locale, const std::string& user_agent, const base::TimeDelta& timeout, - const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback) + const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback, + service_manager::Connector* connector) : gpu_data_manager_(content::GpuDataManager::GetInstance()), gpu_observer_(this), obfuscated_gaia_id_(obfuscated_gaia_id), @@ -310,11 +315,19 @@ weak_ptr_factory_.GetWeakPtr())); // Load geolocation data. - geolocation_subscription_ = device::GeolocationProvider::GetInstance()-> - AddLocationUpdateCallback( - base::Bind(&FingerprintDataLoader::OnGotGeoposition, - weak_ptr_factory_.GetWeakPtr()), - false); + DCHECK(connector); + device::mojom::GeolocationContextPtr geolocation_context; + device::mojom::GeolocationPtr geolocation; + connector->BindInterface(device::mojom::kServiceName, + mojo::MakeRequest(&geolocation_context)); + geolocation_context->BindGeolocation(mojo::MakeRequest(&geolocation)); + geolocation->SetHighAccuracy(false); + geolocation->QueryNextPosition( + // Pass the ownership of |geolocation_context| and |geolocation| to ensure + // the connections are kept alive until the callback is received. + base::BindOnce(&FingerprintDataLoader::OnGotGeoposition, + weak_ptr_factory_.GetWeakPtr(), + std::move(geolocation_context), std::move(geolocation))); } void FingerprintDataLoader::OnGpuInfoUpdate() { @@ -340,14 +353,15 @@ } void FingerprintDataLoader::OnGotGeoposition( - const device::mojom::Geoposition& geoposition) { + device::mojom::GeolocationContextPtr geolocation_context, + device::mojom::GeolocationPtr geolocation, + device::mojom::GeopositionPtr geoposition) { DCHECK(!device::ValidateGeoposition(geoposition_)); - geoposition_ = geoposition; + geoposition_ = *geoposition; DCHECK(device::ValidateGeoposition(geoposition_) || geoposition_.error_code != device::mojom::Geoposition::ErrorCode::NONE); - geolocation_subscription_.reset(); MaybeFillFingerprint(); } @@ -447,13 +461,14 @@ const std::string& app_locale, const std::string& user_agent, const base::TimeDelta& timeout, - const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback) { + const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback, + service_manager::Connector* connector) { // Begin loading all of the data that we need to load asynchronously. // This class is responsible for freeing its own memory. new FingerprintDataLoader(obfuscated_gaia_id, window_bounds, content_bounds, screen_info, version, charset, accept_languages, install_time, app_locale, user_agent, timeout, - callback); + callback, connector); } } // namespace internal @@ -468,7 +483,8 @@ const base::Time& install_time, const std::string& app_locale, const std::string& user_agent, - const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback) { + const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback, + service_manager::Connector* connector) { gfx::Rect content_bounds = web_contents->GetContainerBounds(); content::ScreenInfo screen_info; @@ -480,7 +496,7 @@ internal::GetFingerprintInternal( obfuscated_gaia_id, window_bounds, content_bounds, screen_info, version, charset, accept_languages, install_time, app_locale, user_agent, - base::TimeDelta::FromSeconds(kTimeoutSeconds), callback); + base::TimeDelta::FromSeconds(kTimeoutSeconds), callback, connector); } } // namespace risk
diff --git a/components/autofill/content/browser/risk/fingerprint.h b/components/autofill/content/browser/risk/fingerprint.h index 870743d..7b45019d 100644 --- a/components/autofill/content/browser/risk/fingerprint.h +++ b/components/autofill/content/browser/risk/fingerprint.h
@@ -28,6 +28,10 @@ class WebContents; } +namespace service_manager { +class Connector; +} + namespace gfx { class Rect; } @@ -55,7 +59,8 @@ const base::Time& install_time, const std::string& app_locale, const std::string& user_agent, - const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback); + const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback, + service_manager::Connector* connector); } // namespace risk } // namespace autofill
diff --git a/components/autofill/content/browser/risk/fingerprint_browsertest.cc b/components/autofill/content/browser/risk/fingerprint_browsertest.cc index 2c8d155..4ff4ce5 100644 --- a/components/autofill/content/browser/risk/fingerprint_browsertest.cc +++ b/components/autofill/content/browser/risk/fingerprint_browsertest.cc
@@ -17,8 +17,13 @@ #include "content/public/common/screen_info.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/test_utils.h" -#include "device/geolocation/geolocation_provider.h" +#include "device/geolocation/public/interfaces/geolocation.mojom.h" +#include "device/geolocation/public/interfaces/geolocation_context.mojom.h" #include "device/geolocation/public/interfaces/geoposition.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "services/device/public/interfaces/constants.mojom.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/interfaces/connector.mojom.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebRect.h" @@ -26,6 +31,41 @@ using testing::ElementsAre; +namespace { + +class FakeGeolocation : public device::mojom::GeolocationContext, + public device::mojom::Geolocation { + public: + explicit FakeGeolocation(device::mojom::Geoposition& position) + : binding_context_(this), binding_(this), position_(position) {} + ~FakeGeolocation() override {} + + void Bind(mojo::ScopedMessagePipeHandle handle) { + binding_context_.Bind( + device::mojom::GeolocationContextRequest(std::move(handle))); + } + + // device::mojom::Geolocation implementation: + void QueryNextPosition(QueryNextPositionCallback callback) override { + std::move(callback).Run(position_.Clone()); + } + void SetHighAccuracy(bool high_accuracy) override {} + + // device::mojom::GeolocationContext implementation: + void BindGeolocation(device::mojom::GeolocationRequest request) override { + binding_.Bind(std::move(request)); + } + void SetOverride(device::mojom::GeopositionPtr geoposition) override {} + void ClearOverride() override {} + + private: + mojo::Binding<device::mojom::GeolocationContext> binding_context_; + mojo::Binding<device::mojom::Geolocation> binding_; + device::mojom::Geoposition position_; +}; + +} // namespace + namespace autofill { namespace risk { @@ -44,7 +84,8 @@ const std::string& app_locale, const std::string& user_agent, const base::TimeDelta& timeout, - const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback); + const base::Callback<void(std::unique_ptr<Fingerprint>)>& callback, + service_manager::Connector* connector); } // namespace internal @@ -74,6 +115,25 @@ available_screen_bounds_(0, 11, 101, 60), unavailable_screen_bounds_(0, 0, 101, 11) {} + void SetUpOnMainThread() override { + device::mojom::Geoposition position; + position.latitude = kLatitude; + position.longitude = kLongitude; + position.altitude = kAltitude; + position.accuracy = kAccuracy; + position.timestamp = base::Time::UnixEpoch() + + base::TimeDelta::FromMilliseconds(kGeolocationTime); + fake_geolocation_ = std::make_unique<FakeGeolocation>(position); + + service_manager::mojom::ConnectorRequest request; + connector_ = service_manager::Connector::Create(&request); + service_manager::Connector::TestApi test_api(connector_.get()); + test_api.OverrideBinderForTesting( + device::mojom::kServiceName, device::mojom::GeolocationContext::Name_, + base::Bind(&FakeGeolocation::Bind, + base::Unretained(fake_geolocation_.get()))); + } + void GetFingerprintTestCallback(base::OnceClosure continuation_callback, std::unique_ptr<Fingerprint> fingerprint) { // Verify that all fields Chrome can fill have been filled. @@ -182,23 +242,15 @@ const gfx::Rect available_screen_bounds_; const gfx::Rect unavailable_screen_bounds_; + std::unique_ptr<service_manager::Connector> connector_; + std::unique_ptr<FakeGeolocation> fake_geolocation_; + // A message loop to block on the asynchronous loading of the fingerprint. base::MessageLoopForUI message_loop_; }; // Test that getting a fingerprint works on some basic level. IN_PROC_BROWSER_TEST_F(AutofillRiskFingerprintTest, GetFingerprint) { - device::mojom::Geoposition position; - position.latitude = kLatitude; - position.longitude = kLongitude; - position.altitude = kAltitude; - position.accuracy = kAccuracy; - position.timestamp = base::Time::UnixEpoch() + - base::TimeDelta::FromMilliseconds(kGeolocationTime); - - device::GeolocationProvider::GetInstance()->OverrideLocationForTesting( - position); - content::ScreenInfo screen_info; screen_info.depth = kScreenColorDepth; screen_info.rect = screen_bounds_; @@ -211,7 +263,8 @@ kUserAgent, base::TimeDelta::FromDays(1), // Ought to be longer than any test run. base::Bind(&AutofillRiskFingerprintTest::GetFingerprintTestCallback, - base::Unretained(this), run_loop.QuitWhenIdleClosure())); + base::Unretained(this), run_loop.QuitWhenIdleClosure()), + connector_.get()); // Wait for the callback to be called. run_loop.Run();
diff --git a/components/autofill/content/common/autofill_param_traits_macros.h b/components/autofill/content/common/autofill_param_traits_macros.h index e738b99b..76bd83d 100644 --- a/components/autofill/content/common/autofill_param_traits_macros.h +++ b/components/autofill/content/common/autofill_param_traits_macros.h
@@ -50,6 +50,7 @@ IPC_STRUCT_TRAITS_MEMBER(name) IPC_STRUCT_TRAITS_MEMBER(origin) IPC_STRUCT_TRAITS_MEMBER(action) + IPC_STRUCT_TRAITS_MEMBER(main_frame_origin) IPC_STRUCT_TRAITS_MEMBER(is_form_tag) IPC_STRUCT_TRAITS_MEMBER(is_formless_checkout) IPC_STRUCT_TRAITS_MEMBER(fields)
diff --git a/components/autofill/content/common/autofill_types.mojom b/components/autofill/content/common/autofill_types.mojom index fe2c8782..6351ef75 100644 --- a/components/autofill/content/common/autofill_types.mojom +++ b/components/autofill/content/common/autofill_types.mojom
@@ -104,6 +104,7 @@ string name; url.mojom.Url origin; url.mojom.Url action; + url.mojom.Url main_frame_origin; bool is_form_tag; bool is_formless_checkout; array<FormFieldData> fields;
diff --git a/components/autofill/content/common/autofill_types_struct_traits.cc b/components/autofill/content/common/autofill_types_struct_traits.cc index a15b41f..ccfdf58 100644 --- a/components/autofill/content/common/autofill_types_struct_traits.cc +++ b/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -476,6 +476,8 @@ return false; if (!data.ReadAction(&out->action)) return false; + if (!data.ReadMainFrameOrigin(&out->main_frame_origin)) + return false; out->is_form_tag = data.is_form_tag(); out->is_formless_checkout = data.is_formless_checkout();
diff --git a/components/autofill/content/common/autofill_types_struct_traits.h b/components/autofill/content/common/autofill_types_struct_traits.h index f0b9c0e..0ba55934 100644 --- a/components/autofill/content/common/autofill_types_struct_traits.h +++ b/components/autofill/content/common/autofill_types_struct_traits.h
@@ -191,6 +191,10 @@ static const GURL& action(const autofill::FormData& r) { return r.action; } + static const GURL& main_frame_origin(const autofill::FormData& r) { + return r.main_frame_origin; + } + static bool is_form_tag(const autofill::FormData& r) { return r.is_form_tag; } static bool is_formless_checkout(const autofill::FormData& r) {
diff --git a/components/autofill/content/renderer/BUILD.gn b/components/autofill/content/renderer/BUILD.gn index 9ef7d0e..4150ff5 100644 --- a/components/autofill/content/renderer/BUILD.gn +++ b/components/autofill/content/renderer/BUILD.gn
@@ -14,9 +14,6 @@ "form_classifier.h", "html_based_username_detector.cc", "html_based_username_detector.h", - "page_click_listener.h", - "page_click_tracker.cc", - "page_click_tracker.h", "page_form_analyser_logger.cc", "page_form_analyser_logger.h", "page_passwords_analyser.cc",
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index 3cd27b20e..b06ffb7 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -156,7 +156,6 @@ is_generation_popup_possibly_visible_(false), is_user_gesture_required_(true), is_secure_context_required_(false), - page_click_tracker_(new PageClickTracker(render_frame, this)), binding_(this), weak_ptr_factory_(this) { render_frame->GetWebFrame()->SetAutofillClient(this); @@ -227,7 +226,14 @@ } void AutofillAgent::FocusedNodeChanged(const WebNode& node) { - page_click_tracker_->FocusedNodeChanged(node); + was_focused_before_now_ = false; + + if (IsKeyboardAccessoryEnabled() && + WebUserGestureIndicator::IsProcessingUserGesture( + node.IsNull() ? nullptr : node.GetDocument().GetFrame())) { + focused_node_was_last_clicked_ = true; + HandleFocusChangeComplete(); + } HidePopup(); @@ -301,28 +307,6 @@ weak_ptr_factory_.InvalidateWeakPtrs(); } - -void AutofillAgent::FormControlElementClicked( - const WebFormControlElement& element, - bool was_focused) { - const WebInputElement* input_element = ToWebInputElement(&element); - if (!input_element && !form_util::IsTextAreaElement(element)) - return; - - ShowSuggestionsOptions options; - options.autofill_on_empty_values = true; - options.show_full_suggestion_list = element.IsAutofilled(); - - if (!IsSingleClickEnabled()) { - // Show full suggestions when clicking on an already-focused form field. On - // the initial click (not focused yet), only show password suggestions. - options.show_full_suggestion_list = - options.show_full_suggestion_list || was_focused; - options.show_password_suggestions_only = !was_focused; - } - ShowSuggestions(element, options); -} - void AutofillAgent::TextFieldDidEndEditing(const WebInputElement& element) { GetAutofillDriver()->DidEndTextFieldEditing(); } @@ -806,14 +790,57 @@ if (!focused_element.IsNull() && password_autofill_agent_) password_autofill_agent_->FocusedNodeHasChanged(focused_element); - // PageClickTracker needs to be notified after - // |is_generation_popup_possibly_visible_| has been updated. - page_click_tracker_->DidCompleteFocusChangeInFrame(); + if (!IsKeyboardAccessoryEnabled()) + HandleFocusChangeComplete(); } void AutofillAgent::DidReceiveLeftMouseDownOrGestureTapInNode( const WebNode& node) { - page_click_tracker_->DidReceiveLeftMouseDownOrGestureTapInNode(node); + DCHECK(!node.IsNull()); + focused_node_was_last_clicked_ = node.Focused(); + + if (IsKeyboardAccessoryEnabled()) + HandleFocusChangeComplete(); +} + +void AutofillAgent::FormControlElementClicked( + const WebFormControlElement& element, + bool was_focused) { + last_clicked_form_control_element_for_testing_ = element; + last_clicked_form_control_element_was_focused_for_testing_ = was_focused; + + const WebInputElement* input_element = ToWebInputElement(&element); + if (!input_element && !form_util::IsTextAreaElement(element)) + return; + + ShowSuggestionsOptions options; + options.autofill_on_empty_values = true; + options.show_full_suggestion_list = element.IsAutofilled(); + + if (!IsSingleClickEnabled()) { + // Show full suggestions when clicking on an already-focused form field. On + // the initial click (not focused yet), only show password suggestions. + options.show_full_suggestion_list = + options.show_full_suggestion_list || was_focused; + options.show_password_suggestions_only = !was_focused; + } + ShowSuggestions(element, options); +} + +void AutofillAgent::HandleFocusChangeComplete() { + WebElement focused_element = + render_frame()->GetWebFrame()->GetDocument().FocusedElement(); + + if (focused_node_was_last_clicked_ && !focused_element.IsNull() && + focused_element.IsFormControlElement() && + (form_util::IsTextInput(blink::ToWebInputElement(&focused_element)) || + focused_element.HasHTMLTagName("textarea"))) { + FormControlElementClicked(focused_element.ToConst<WebFormControlElement>(), + was_focused_before_now_); + } + + was_focused_before_now_ = true; + focused_node_was_last_clicked_ = false; } void AutofillAgent::AjaxSucceeded() {
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h index e242130..c5691fe3 100644 --- a/components/autofill/content/renderer/autofill_agent.h +++ b/components/autofill/content/renderer/autofill_agent.h
@@ -16,8 +16,6 @@ #include "components/autofill/content/common/autofill_agent.mojom.h" #include "components/autofill/content/common/autofill_driver.mojom.h" #include "components/autofill/content/renderer/form_cache.h" -#include "components/autofill/content/renderer/page_click_listener.h" -#include "components/autofill/content/renderer/page_click_tracker.h" #include "content/public/renderer/render_frame_observer.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/service_manager/public/cpp/binder_registry.h" @@ -47,7 +45,6 @@ // - entire form fill based on one field entry, referred to as Form Autofill. class AutofillAgent : public content::RenderFrameObserver, - public PageClickListener, public blink::WebAutofillClient, public mojom::AutofillAgent { public: @@ -88,16 +85,16 @@ void ShowNotSecureWarning(const blink::WebInputElement& element); - void set_page_click_tracker_for_testing( - std::unique_ptr<PageClickTracker> page_click_tracker) { - page_click_tracker_ = std::move(page_click_tracker); - } + void FormControlElementClicked(const blink::WebFormControlElement& element, + bool was_focused); protected: // blink::WebAutofillClient: void DidAssociateFormControlsDynamically() override; private: + friend class FormControlClickDetectionTest; + // Functor used as a simplified comparison function for FormData. Only // compares forms at a high level (notably name, origin, action). struct FormDataCompare { @@ -155,10 +152,6 @@ // times. void Shutdown(); - // PageClickListener: - void FormControlElementClicked(const blink::WebFormControlElement& element, - bool was_focused) override; - // blink::WebAutofillClient: void TextFieldDidEndEditing(const blink::WebInputElement& element) override; void TextFieldDidChange(const blink::WebFormControlElement& element) override; @@ -173,6 +166,8 @@ void DidReceiveLeftMouseDownOrGestureTapInNode( const blink::WebNode& node) override; + void HandleFocusChangeComplete(); + // Called when a same-document navigation is detected. void OnSameDocumentNavigationCompleted(); // Helper method which collects unowned elements (i.e., those not inside a @@ -200,10 +195,9 @@ // Fills |form| and |field| with the FormData and FormField corresponding to // |node|. Returns true if the data was found; and false otherwise. - bool FindFormAndFieldForNode( - const blink::WebNode& node, - FormData* form, - FormFieldData* field) WARN_UNUSED_RESULT; + bool FindFormAndFieldForNode(const blink::WebNode& node, + FormData* form, + FormFieldData* field) WARN_UNUSED_RESULT; // Set |node| to display the given |value|. void DoFillFieldWithValue(const base::string16& value, @@ -241,7 +235,7 @@ // this frame's current load. We use a simplified comparison function. std::set<FormData, FormDataCompare> submitted_forms_; - PasswordAutofillAgent* password_autofill_agent_; // Weak reference. + PasswordAutofillAgent* password_autofill_agent_; // Weak reference. PasswordGenerationAgent* password_generation_agent_; // Weak reference. // The ID of the last request sent for form field Autofill. Used to ignore @@ -288,7 +282,10 @@ // Default to false. bool is_secure_context_required_; - std::unique_ptr<PageClickTracker> page_click_tracker_; + bool focused_node_was_last_clicked_ = false; + bool was_focused_before_now_ = false; + blink::WebFormControlElement last_clicked_form_control_element_for_testing_; + bool last_clicked_form_control_element_was_focused_for_testing_ = false; mojo::Binding<mojom::AutofillAgent> binding_;
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index 013581f..c92cff6 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -1145,6 +1145,11 @@ FormData* form, FormFieldData* field) { form->origin = GetCanonicalOriginForDocument(document); + DCHECK(document.GetFrame()->Top()); + url::Origin main_frame_origin = + document.GetFrame()->Top()->GetSecurityOrigin(); + form->main_frame_origin = main_frame_origin.GetURL(); + form->is_form_tag = false; return FormOrFieldsetsToFormData( @@ -1463,14 +1468,16 @@ ExtractMask extract_mask, FormData* form, FormFieldData* field) { - const WebLocalFrame* frame = form_element.GetDocument().GetFrame(); + WebLocalFrame* frame = form_element.GetDocument().GetFrame(); if (!frame) return false; form->name = GetFormIdentifier(form_element); form->origin = GetCanonicalOriginForDocument(frame->GetDocument()); form->action = frame->GetDocument().CompleteURL(form_element.Action()); - + DCHECK(frame->Top()); + url::Origin main_frame_origin = frame->Top()->GetSecurityOrigin(); + form->main_frame_origin = main_frame_origin.GetURL(); // If the completed URL is not valid, just use the action we get from // WebKit. if (!form->action.is_valid())
diff --git a/components/autofill/content/renderer/page_click_listener.h b/components/autofill/content/renderer/page_click_listener.h deleted file mode 100644 index ad93cb8..0000000 --- a/components/autofill/content/renderer/page_click_listener.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_AUTOFILL_CONTENT_RENDERER_PAGE_CLICK_LISTENER_H_ -#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_PAGE_CLICK_LISTENER_H_ - -namespace blink { -class WebFormControlElement; -} - -namespace autofill { - -// Interface that should be implemented by classes interested in getting -// notifications for clicks or taps on a page. -// Register on the PageListenerTracker object. -class PageClickListener { - public: - // Notification that |element| was clicked. - // |was_focused| is true if |element| had focus BEFORE the click. - virtual void FormControlElementClicked( - const blink::WebFormControlElement& element, - bool was_focused) = 0; - - protected: - virtual ~PageClickListener() {} -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_PAGE_CLICK_LISTENER_H_
diff --git a/components/autofill/content/renderer/page_click_tracker.cc b/components/autofill/content/renderer/page_click_tracker.cc deleted file mode 100644 index e405131..0000000 --- a/components/autofill/content/renderer/page_click_tracker.cc +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/autofill/content/renderer/page_click_tracker.h" - -#include "base/command_line.h" -#include "components/autofill/content/renderer/form_autofill_util.h" -#include "components/autofill/content/renderer/page_click_listener.h" -#include "components/autofill/core/common/autofill_util.h" -#include "content/public/renderer/render_frame.h" -#include "content/public/renderer/render_view.h" -#include "third_party/WebKit/public/platform/WebPoint.h" -#include "third_party/WebKit/public/platform/WebSize.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebFormControlElement.h" -#include "third_party/WebKit/public/web/WebHitTestResult.h" -#include "third_party/WebKit/public/web/WebInputElement.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebUserGestureIndicator.h" -#include "third_party/WebKit/public/web/WebView.h" - -using blink::WebElement; -using blink::WebFormControlElement; -using blink::WebInputElement; -using blink::WebNode; -using blink::WebPoint; -using blink::WebSize; -using blink::WebUserGestureIndicator; - -namespace autofill { - -namespace { - -// Casts |element| to a WebFormControlElement, but only if it's a text field. -// Returns an empty (IsNull()) wrapper otherwise. -const WebFormControlElement GetTextFormControlElement( - const WebElement& element) { - if (!element.IsFormControlElement()) - return WebFormControlElement(); - if (form_util::IsTextInput(blink::ToWebInputElement(&element)) || - element.HasHTMLTagName("textarea")) - return element.ToConst<WebFormControlElement>(); - return WebFormControlElement(); -} - -} // namespace - -PageClickTracker::PageClickTracker(content::RenderFrame* render_frame, - PageClickListener* listener) - : focused_node_was_last_clicked_(false), - was_focused_before_now_(false), - listener_(listener), - render_frame_(render_frame) {} - -PageClickTracker::~PageClickTracker() { -} - -void PageClickTracker::FocusedNodeChanged(const WebNode& node) { - was_focused_before_now_ = false; - - if (IsKeyboardAccessoryEnabled() && - WebUserGestureIndicator::IsProcessingUserGesture( - node.IsNull() ? nullptr : node.GetDocument().GetFrame())) { - focused_node_was_last_clicked_ = true; - DoFocusChangeComplete(); - } -} - -void PageClickTracker::DidCompleteFocusChangeInFrame() { - if (IsKeyboardAccessoryEnabled()) - return; - - DoFocusChangeComplete(); -} - -void PageClickTracker::DidReceiveLeftMouseDownOrGestureTapInNode( - const blink::WebNode& node) { - DCHECK(!node.IsNull()); - focused_node_was_last_clicked_ = node.Focused(); - - if (IsKeyboardAccessoryEnabled()) - DoFocusChangeComplete(); -} - -void PageClickTracker::DoFocusChangeComplete() { - WebElement focused_element = - render_frame()->GetWebFrame()->GetDocument().FocusedElement(); - if (focused_node_was_last_clicked_ && !focused_element.IsNull()) { - const WebFormControlElement control = - GetTextFormControlElement(focused_element); - if (!control.IsNull()) { - listener_->FormControlElementClicked(control, - was_focused_before_now_); - } - } - - was_focused_before_now_ = true; - focused_node_was_last_clicked_ = false; -} - -} // namespace autofill
diff --git a/components/autofill/content/renderer/page_click_tracker.h b/components/autofill/content/renderer/page_click_tracker.h deleted file mode 100644 index 3b1dda44..0000000 --- a/components/autofill/content/renderer/page_click_tracker.h +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_AUTOFILL_CONTENT_RENDERER_PAGE_CLICK_TRACKER_H_ -#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_PAGE_CLICK_TRACKER_H_ - -#include <vector> - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "third_party/WebKit/public/web/WebNode.h" - -namespace content { -class RenderFrame; -} - -namespace autofill { - -class PageClickListener; - -// This class is responsible notifying the associated listener when a node is -// clicked or tapped. It also tracks whether a node was focused before the event -// was handled. -// -// This is useful for password/form autofill where we want to trigger a -// suggestion popup when a text input is clicked. -// -// There is one PageClickTracker per AutofillAgent. -class PageClickTracker { - public: - // The |listener| will be notified when an element is clicked. It must - // outlive this class. - PageClickTracker(content::RenderFrame* render_frame, - PageClickListener* listener); - ~PageClickTracker(); - - void FocusedNodeChanged(const blink::WebNode& node); - void DidCompleteFocusChangeInFrame(); - void DidReceiveLeftMouseDownOrGestureTapInNode(const blink::WebNode& node); - - content::RenderFrame* render_frame() const { return render_frame_; } - - private: - void DoFocusChangeComplete(); - - // True when the last click was on the focused node. - bool focused_node_was_last_clicked_; - - // This is set to false when the focus changes, then set back to true soon - // afterwards. This helps track whether an event happened after a node was - // already focused, or if it caused the focus to change. - bool was_focused_before_now_; - - // The listener getting the actual notifications. - PageClickListener* listener_; - - content::RenderFrame* const render_frame_; - - DISALLOW_COPY_AND_ASSIGN(PageClickTracker); -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_PAGE_CLICK_TRACKER_H_
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index 2f0fdeb..594d888 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -1602,7 +1602,7 @@ return; // Setup the url for metrics that we will collect for this form. - form_interactions_ukm_logger_->OnFormsParsed(forms[0].origin); + form_interactions_ukm_logger_->OnFormsParsed(forms[0].main_frame_origin); std::vector<FormStructure*> non_queryable_forms; std::vector<FormStructure*> queryable_forms;
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc index f059758..5a79b70 100644 --- a/components/autofill/core/browser/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -306,7 +306,7 @@ form_structure->set_form_parsed_timestamp(TimeTicks::Now()); form_structures()->push_back(std::move(form_structure)); - form_interactions_ukm_logger()->OnFormsParsed(form.origin); + form_interactions_ukm_logger()->OnFormsParsed(form.main_frame_origin); } // Calls AutofillManager::OnWillSubmitForm and waits for it to complete. @@ -366,7 +366,7 @@ const ukm::UkmSource* source = ukm_recorder.GetSourceForSourceId(entry->source_id); ASSERT_NE(nullptr, source); - EXPECT_EQ(form.origin, source->url()); + EXPECT_EQ(form.main_frame_origin, source->url()); int expected_metric_value = 0; for (const auto it : expected_metric_values) @@ -403,7 +403,7 @@ const ukm::UkmSource* source = ukm_recorder.GetSourceForSourceId(entry->source_id); ASSERT_NE(nullptr, source); - EXPECT_EQ(form.origin, source->url()); + EXPECT_EQ(form.main_frame_origin, source->url()); ASSERT_LT(expected_metrics_index, expected_metrics.size()); EXPECT_THAT( @@ -572,6 +572,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); std::vector<ServerFieldType> heuristic_types, server_types; FormFieldData field; @@ -881,6 +882,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); std::vector<ServerFieldType> heuristic_types, server_types, actual_types; AutofillField field; @@ -1049,6 +1051,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Autofilled", "autofilled", "Elvis Aaron Presley", @@ -1088,6 +1091,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); std::vector<ServerFieldType> heuristic_types, server_types; FormFieldData field; @@ -1275,6 +1279,7 @@ form.name = ASCIIToUTF16("MyForm"); form.origin = GURL("http://myform.com/form.html"); form.action = GURL("http://myform.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; // Heuristic value will match with Autocomplete attribute. @@ -1385,6 +1390,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); std::vector<ServerFieldType> heuristic_types, server_types; FormFieldData field; @@ -1433,6 +1439,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field1; test::CreateTestFormField("Select", "select", "USA", "select-one", &field1); @@ -1500,6 +1507,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); std::vector<ServerFieldType> heuristic_types, server_types; @@ -1596,6 +1604,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); // Three fields is enough to make it an autofillable form. FormFieldData field; @@ -1627,6 +1636,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); // Two fields is not enough to make it an autofillable form. FormFieldData field; @@ -1656,6 +1666,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); std::vector<ServerFieldType> heuristic_types, server_types; @@ -1707,6 +1718,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); std::vector<ServerFieldType> heuristic_types, server_types; @@ -1757,6 +1769,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Name", "name", "", "text", &field); @@ -1846,6 +1859,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Name", "name", "", "text", &field); @@ -1890,6 +1904,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Name", "name", "", "text", &field); @@ -1939,6 +1954,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Name", "name", "", "text", &field); @@ -2218,6 +2234,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -2289,6 +2306,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -2401,6 +2419,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -2573,6 +2592,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); autofill_client_.set_form_origin(form.origin); FormFieldData field; @@ -2591,6 +2611,7 @@ // Simulate having seen this insecure form on page load. form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); autofill_manager_->AddSeenForm(form, field_types, field_types); // Simulate an Autofill query on a credit card field (HTTP, non-secure @@ -2607,6 +2628,7 @@ autofill_manager_->Reset(); form.origin = GURL("https://example.com/form.html"); form.action = GURL("https://example.com/submit.html"); + form.main_frame_origin = GURL("https://example_root.com/form.html"); autofill_client_.set_form_origin(form.origin); autofill_manager_->AddSeenForm(form, field_types, field_types); @@ -2629,6 +2651,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -2681,6 +2704,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -2729,6 +2753,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -2869,6 +2894,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -2940,6 +2966,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -3110,6 +3137,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -3183,6 +3211,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -3225,6 +3254,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -3269,6 +3299,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -3313,6 +3344,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -3366,6 +3398,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -3407,6 +3440,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -3754,6 +3788,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -3975,6 +4010,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -4026,6 +4062,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -4115,6 +4152,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -4180,6 +4218,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -4380,6 +4419,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -4551,6 +4591,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -4659,6 +4700,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types; @@ -4744,6 +4786,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Name", "name", "", "text", &field); @@ -4992,6 +5035,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Name", "name", "", "text", &field); @@ -5114,6 +5158,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); std::vector<FormData> forms(1, form); @@ -5140,6 +5185,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("https://example.com/form.html"); form.action = GURL("https://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); // Construct a valid credit card form with minimal fields. FormFieldData field; @@ -5299,6 +5345,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Name", "name", "", "text", &field); @@ -5511,6 +5558,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Name", "name", "", "text", &field); @@ -5902,6 +5950,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); // Create the form's fields. FormFieldData field; @@ -6021,6 +6070,7 @@ void SetUp() override { FormData form; form.origin = GURL("http://foo.com"); + form.main_frame_origin = GURL("http://foo_root.com"); FormFieldData field; field.form_control_type = "text"; @@ -6154,6 +6204,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("http://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); autofill_client_.set_form_origin(form.origin); FormFieldData field; @@ -6210,6 +6261,7 @@ form.name = ASCIIToUTF16("TestForm"); form.origin = GURL("https://example.com/form.html"); form.action = GURL("http://example.com/submit.html"); + form.main_frame_origin = GURL("http://example_root.com/form.html"); FormFieldData field; std::vector<ServerFieldType> field_types;
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc index 17ec57f2..cf5b0a1 100644 --- a/components/autofill/core/browser/autofill_test_utils.cc +++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -132,6 +132,7 @@ form->name = ASCIIToUTF16("MyForm"); form->origin = GURL("http://myform.com/form.html"); form->action = GURL("http://myform.com/submit.html"); + form->main_frame_origin = GURL("http://myform_root.com/form.html"); types->clear(); FormFieldData field;
diff --git a/components/autofill/core/browser/credit_card_save_manager.cc b/components/autofill/core/browser/credit_card_save_manager.cc index 845f3b4..dd2f892 100644 --- a/components/autofill/core/browser/credit_card_save_manager.cc +++ b/components/autofill/core/browser/credit_card_save_manager.cc
@@ -139,7 +139,7 @@ int upload_decision_metrics = SetProfilesForCreditCardUpload(card, &upload_request_); - pending_upload_request_url_ = GURL(submitted_form.source_url()); + pending_upload_request_url_ = GURL(submitted_form.main_frame_url()); should_cvc_be_requested_ = false; if (upload_request_.cvc.empty()) {
diff --git a/components/autofill/core/browser/credit_card_save_manager.h b/components/autofill/core/browser/credit_card_save_manager.h index eda8e83..91af0795 100644 --- a/components/autofill/core/browser/credit_card_save_manager.h +++ b/components/autofill/core/browser/credit_card_save_manager.h
@@ -125,6 +125,7 @@ // determined to be a CVC field via heuristics has a valid CVC |value|. bool found_cvc_value_in_non_cvc_field_ = false; + // The origin of the top level frame from which a form is uploaded. GURL pending_upload_request_url_; base::WeakPtrFactory<CreditCardSaveManager> weak_ptr_factory_;
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 5e11400..fc03fd5 100644 --- a/components/autofill/core/browser/credit_card_save_manager_unittest.cc +++ b/components/autofill/core/browser/credit_card_save_manager_unittest.cc
@@ -652,9 +652,11 @@ if (is_https) { form->origin = GURL("https://myform.com/form.html"); form->action = GURL("https://myform.com/submit.html"); + form->main_frame_origin = GURL("https://myform_root.com/form.html"); } else { form->origin = GURL("http://myform.com/form.html"); form->action = GURL("http://myform.com/submit.html"); + form->main_frame_origin = GURL("http://myform_root.com/form.html"); } FormFieldData field; @@ -1196,6 +1198,8 @@ credit_card_form.name = ASCIIToUTF16("MyForm"); credit_card_form.origin = GURL("https://myform.com/form.html"); credit_card_form.action = GURL("https://myform.com/submit.html"); + credit_card_form.main_frame_origin = + GURL("https://myform_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Card Name", "cardname", "", "text", &field); @@ -1256,6 +1260,8 @@ credit_card_form.name = ASCIIToUTF16("MyForm"); credit_card_form.origin = GURL("https://myform.com/form.html"); credit_card_form.action = GURL("https://myform.com/submit.html"); + credit_card_form.main_frame_origin = + GURL("https://myform_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Card Name", "cardname", "", "text", &field); @@ -1311,6 +1317,8 @@ credit_card_form.name = ASCIIToUTF16("MyForm"); credit_card_form.origin = GURL("https://myform.com/form.html"); credit_card_form.action = GURL("https://myform.com/submit.html"); + credit_card_form.main_frame_origin = + GURL("https://myform_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Card Name", "cardname", "", "text", &field); @@ -1369,6 +1377,8 @@ credit_card_form.name = ASCIIToUTF16("MyForm"); credit_card_form.origin = GURL("https://myform.com/form.html"); credit_card_form.action = GURL("https://myform.com/submit.html"); + credit_card_form.main_frame_origin = + GURL("https://myform_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Card Name", "cardname", "", "text", &field); @@ -1429,6 +1439,8 @@ credit_card_form.name = ASCIIToUTF16("MyForm"); credit_card_form.origin = GURL("https://myform.com/form.html"); credit_card_form.action = GURL("https://myform.com/submit.html"); + credit_card_form.main_frame_origin = + GURL("https://myform_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Card Name", "cardname", "", "text", &field); @@ -1496,6 +1508,8 @@ credit_card_form.name = ASCIIToUTF16("MyForm"); credit_card_form.origin = GURL("https://myform.com/form.html"); credit_card_form.action = GURL("https://myform.com/submit.html"); + credit_card_form.main_frame_origin = + GURL("https://myform_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Card Name", "cardname", "", "text", &field); @@ -1558,6 +1572,8 @@ credit_card_form.name = ASCIIToUTF16("MyForm"); credit_card_form.origin = GURL("https://myform.com/form.html"); credit_card_form.action = GURL("https://myform.com/submit.html"); + credit_card_form.main_frame_origin = + GURL("https://myform_root.com/form.html"); FormFieldData field; test::CreateTestFormField("Card Name", "cardname", "", "text", &field);
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 14d243a..ab6d479b 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -310,6 +310,7 @@ : form_name_(form.name), source_url_(form.origin), target_url_(form.action), + main_frame_url_(form.main_frame_origin), autofill_count_(0), active_field_count_(0), upload_required_(USE_UPLOAD_RATES), @@ -392,7 +393,7 @@ } if (developer_engagement_metrics) - AutofillMetrics::LogDeveloperEngagementUkm(ukm_recorder, source_url(), + AutofillMetrics::LogDeveloperEngagementUkm(ukm_recorder, main_frame_url(), developer_engagement_metrics); if (base::FeatureList::IsEnabled(kAutofillRationalizeFieldTypePredictions)) @@ -564,6 +565,7 @@ form.data.name = form_structure->form_name_; form.data.origin = form_structure->source_url_; form.data.action = form_structure->target_url_; + form.data.main_frame_origin = form_structure->main_frame_url_; form.data.is_form_tag = form_structure->is_form_tag_; form.data.is_formless_checkout = form_structure->is_formless_checkout_; form.signature = form_structure->FormSignatureAsStr(); @@ -811,8 +813,8 @@ GetFormTypes(), did_autofill_some_possible_fields, elapsed); } } - if (form_interactions_ukm_logger->url() != source_url()) - form_interactions_ukm_logger->UpdateSourceURL(source_url()); + if (form_interactions_ukm_logger->url() != main_frame_url()) + form_interactions_ukm_logger->UpdateSourceURL(main_frame_url()); AutofillMetrics::LogAutofillFormSubmittedState( state, form_parsed_timestamp_, form_interactions_ukm_logger); } @@ -1015,6 +1017,7 @@ data.name = form_name_; data.origin = source_url_; data.action = target_url_; + data.main_frame_origin = main_frame_url_; for (size_t i = 0; i < fields_.size(); ++i) { data.fields.push_back(FormFieldData(*fields_[i]));
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index 7339fb1..823455b 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -192,6 +192,8 @@ const GURL& target_url() const { return target_url_; } + const GURL& main_frame_url() const { return main_frame_url_; } + bool has_author_specified_types() const { return has_author_specified_types_; } @@ -292,6 +294,9 @@ // The target URL. GURL target_url_; + // The source URL of the main frame of this form. + GURL main_frame_url_; + // The number of fields able to be auto-filled. size_t autofill_count_;
diff --git a/components/autofill/core/common/form_data.cc b/components/autofill/core/common/form_data.cc index 81de550a..11c6513 100644 --- a/components/autofill/core/common/form_data.cc +++ b/components/autofill/core/common/form_data.cc
@@ -5,7 +5,6 @@ #include "components/autofill/core/common/form_data.h" #include <stddef.h> - #include <tuple> #include "base/base64.h" @@ -18,7 +17,7 @@ namespace { -const int kPickleVersion = 5; +const int kPickleVersion = 6; bool ReadGURL(base::PickleIterator* iter, GURL* url) { std::string spec; @@ -66,6 +65,7 @@ : name(data.name), origin(data.origin), action(data.action), + main_frame_origin(data.main_frame_origin), is_form_tag(data.is_form_tag), is_formless_checkout(data.is_formless_checkout), fields(data.fields) {} @@ -119,7 +119,8 @@ std::ostream& operator<<(std::ostream& os, const FormData& form) { os << base::UTF16ToUTF8(form.name) << " " << form.origin << " " << form.action - << " " << form.is_form_tag << " " << form.is_formless_checkout << " " + << " " << form.main_frame_origin << " " << form.is_form_tag << " " + << form.is_formless_checkout << " " << "Fields:"; for (size_t i = 0; i < form.fields.size(); ++i) { os << form.fields[i] << ","; @@ -135,6 +136,7 @@ SerializeFormFieldDataVector(form_data.fields, pickle); pickle->WriteBool(form_data.is_form_tag); pickle->WriteBool(form_data.is_formless_checkout); + pickle->WriteString(form_data.main_frame_origin.spec()); } void SerializeFormDataToBase64String(const FormData& form_data, @@ -198,6 +200,13 @@ } } + if (version >= 6) { + if (!ReadGURL(iter, &temp_form_data.main_frame_origin)) { + LogDeserializationError(version); + return false; + } + } + *form_data = temp_form_data; return true; }
diff --git a/components/autofill/core/common/form_data.h b/components/autofill/core/common/form_data.h index 5e5a429..c706480 100644 --- a/components/autofill/core/common/form_data.h +++ b/components/autofill/core/common/form_data.h
@@ -41,6 +41,8 @@ GURL origin; // The action target of the form. GURL action; + // The URL of main frame containing this form. + GURL main_frame_origin; // True if this form is a form tag. bool is_form_tag; // True if the form is made of unowned fields in a non checkout flow.
diff --git a/components/autofill/core/common/form_data_unittest.cc b/components/autofill/core/common/form_data_unittest.cc index ee174b715..c6dee3b 100644 --- a/components/autofill/core/common/form_data_unittest.cc +++ b/components/autofill/core/common/form_data_unittest.cc
@@ -87,6 +87,21 @@ pickle->WriteBool(form_data.is_formless_checkout); } +void SerializeInVersion6Format(const FormData& form_data, + base::Pickle* pickle) { + pickle->WriteInt(6); + pickle->WriteString16(form_data.name); + pickle->WriteString(form_data.origin.spec()); + pickle->WriteString(form_data.action.spec()); + pickle->WriteInt(static_cast<int>(form_data.fields.size())); + for (size_t i = 0; i < form_data.fields.size(); ++i) { + SerializeFormFieldData(form_data.fields[i], pickle); + } + pickle->WriteBool(form_data.is_form_tag); + pickle->WriteBool(form_data.is_formless_checkout); + pickle->WriteString(form_data.main_frame_origin.spec()); +} + // This function serializes the form data into the pickle in incorrect format // (no version number). void SerializeIncorrectFormat(const FormData& form_data, base::Pickle* pickle) { @@ -102,8 +117,9 @@ void FillInDummyFormData(FormData* data) { data->name = base::ASCIIToUTF16("name"); - data->origin = GURL("origin"); - data->action = GURL("action"); + data->origin = GURL("https://example.com"); + data->action = GURL("https://example.com/action"); + data->main_frame_origin = GURL("https://origin-example.com"); data->is_form_tag = true; // Default value. data->is_formless_checkout = false; // Default value. @@ -249,6 +265,21 @@ EXPECT_TRUE(actual.SameFormAs(data)); } +TEST(FormDataTest, Serialize_v6_Deserialize_vCurrent) { + FormData data; + FillInDummyFormData(&data); + data.is_formless_checkout = true; + + base::Pickle pickle; + SerializeInVersion6Format(data, &pickle); + + base::PickleIterator iter(pickle); + FormData actual; + EXPECT_TRUE(DeserializeFormData(&iter, &actual)); + + EXPECT_TRUE(actual.SameFormAs(data)); +} + TEST(FormDataTest, SerializeIncorrectFormatAndDeserialize) { FormData data; FillInDummyFormData(&data);
diff --git a/components/crash/core/common/crash_keys.cc b/components/crash/core/common/crash_keys.cc index 9e3346bfd..513a85c4 100644 --- a/components/crash/core/common/crash_keys.cc +++ b/components/crash/core/common/crash_keys.cc
@@ -13,6 +13,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "components/crash/core/common/crash_key.h" namespace crash_keys { @@ -38,7 +39,6 @@ const char kVariations[] = "variations"; const char kSwitchFormat[] = "switch-%" PRIuS; -const char kNumSwitches[] = "num-switches"; const char kBug464926CrashKey[] = "bug-464926-info"; @@ -110,8 +110,6 @@ void GetCrashKeysForCommandLineSwitches( std::vector<base::debug::CrashKey>* keys) { DCHECK(keys); - base::debug::CrashKey crash_key = { kNumSwitches, kSmallSize }; - keys->push_back(crash_key); // Use static storage for formatted key names, since they will persist for // the duration of the program. @@ -139,8 +137,9 @@ const base::CommandLine::StringVector& argv = command_line.argv(); // Set the number of switches in case size > kNumSwitches. - base::debug::SetCrashKeyValue(kNumSwitches, - base::StringPrintf("%" PRIuS, argv.size() - 1)); + // num-switches is capped at 15 entries, so only two digits are stored. + static crash_reporter::CrashKeyString<2> num_switches_key("num-switches"); + num_switches_key.Set(base::StringPrintf("%" PRIuS, argv.size() - 1)); size_t key_i = 1; // Key names are 1-indexed.
diff --git a/components/crash/core/common/crash_keys.h b/components/crash/core/common/crash_keys.h index 4596fce..2d3d5cda 100644 --- a/components/crash/core/common/crash_keys.h +++ b/components/crash/core/common/crash_keys.h
@@ -36,7 +36,7 @@ // of crash keys. using SwitchFilterFunction = bool (*)(const std::string& flag); -// Sets the kNumSwitches key and a set of keys named using kSwitchFormat based +// Sets the "num-switches" key and a set of keys named using kSwitchFormat based // on the given |command_line|. If |skip_filter| is not null, ignore any switch // for which it returns true. void SetSwitchesFromCommandLine(const base::CommandLine& command_line, @@ -104,10 +104,6 @@ // at most |kSwitchesMaxCount| command line switches. extern const char kSwitchFormat[]; -// The total number of switches, used to report the total in case more than -// |kSwitchesMaxCount| are present. -extern const char kNumSwitches[]; - // Used to help investigate bug 464926. extern const char kBug464926CrashKey[];
diff --git a/components/crash/core/common/crash_keys_unittest.cc b/components/crash/core/common/crash_keys_unittest.cc index be4f3fc..466c5fe 100644 --- a/components/crash/core/common/crash_keys_unittest.cc +++ b/components/crash/core/common/crash_keys_unittest.cc
@@ -15,11 +15,13 @@ #include "base/format_macros.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" +#include "components/crash/core/common/crash_key.h" #include "testing/gtest/include/gtest/gtest.h" class CrashKeysTest : public testing::Test { public: void SetUp() override { + crash_reporter::InitializeCrashKeys(); self_ = this; base::debug::SetCrashKeyReportingFunctions( &SetCrashKeyValue, &ClearCrashKey);
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc index 67debd51..842cbb51 100644 --- a/components/cronet/android/cronet_url_request_context_adapter.cc +++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -166,7 +166,7 @@ } bool OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) override { // Disallow saving cookies by default. return false;
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc index 2327a8c..0bbc94a 100644 --- a/components/cronet/url_request_context_config.cc +++ b/components/cronet/url_request_context_config.cc
@@ -57,6 +57,7 @@ const char kQuicDisableBidirectionalStreams[] = "quic_disable_bidirectional_streams"; const char kQuicRaceCertVerification[] = "race_cert_verification"; +const char kQuicHostWhitelist[] = "host_whitelist"; // AsyncDNS experiment dictionary name. const char kAsyncDnsFieldTrialName[] = "AsyncDNS"; @@ -284,6 +285,17 @@ quic_race_cert_verification; } + std::string quic_host_whitelist; + if (quic_args->GetString(kQuicHostWhitelist, &quic_host_whitelist)) { + std::vector<std::string> host_vector = + base::SplitString(quic_host_whitelist, ",", base::TRIM_WHITESPACE, + base::SPLIT_WANT_ALL); + session_params->quic_host_whitelist.clear(); + for (const std::string& host : host_vector) { + session_params->quic_host_whitelist.insert(host); + } + } + } else if (it.key() == kAsyncDnsFieldTrialName) { const base::DictionaryValue* async_dns_args = nullptr; if (!it.value().GetAsDictionary(&async_dns_args)) {
diff --git a/components/cronet/url_request_context_config_unittest.cc b/components/cronet/url_request_context_config_unittest.cc index 064c156..6447879 100644 --- a/components/cronet/url_request_context_config_unittest.cc +++ b/components/cronet/url_request_context_config_unittest.cc
@@ -160,7 +160,7 @@ EXPECT_TRUE(params->quic_migrate_sessions_early); } -TEST(URLRequestContextConfigTest, SetQuicConnectionMigrationiV2Options) { +TEST(URLRequestContextConfigTest, SetQuicConnectionMigrationV2Options) { base::test::ScopedTaskEnvironment scoped_task_environment_( base::test::ScopedTaskEnvironment::MainThreadType::IO); @@ -209,6 +209,58 @@ EXPECT_TRUE(params->quic_migrate_sessions_on_network_change_v2); } +TEST(URLRequestContextConfigTest, SetQuicHostWhitelist) { + base::test::ScopedTaskEnvironment scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::IO); + + URLRequestContextConfig config( + // Enable QUIC. + true, + // QUIC User Agent ID. + "Default QUIC User Agent ID", + // Enable SPDY. + true, + // Enable Brotli. + false, + // Type of http cache. + URLRequestContextConfig::HttpCacheType::DISK, + // Max size of http cache in bytes. + 1024000, + // Disable caching for HTTP responses. Other information may be stored in + // the cache. + false, + // Storage path for http cache and cookie storage. + "/data/data/org.chromium.net/app_cronet_test/test_storage", + // User-Agent request header field. + "fake agent", + // JSON encoded experimental options. + "{\"QUIC\":{\"host_whitelist\":\"www.example.com,www.example.org\"}}", + // MockCertVerifier to use for testing purposes. + std::unique_ptr<net::CertVerifier>(), + // Enable network quality estimator. + false, + // Enable Public Key Pinning bypass for local trust anchors. + true, + // Certificate verifier cache data. + ""); + + net::URLRequestContextBuilder builder; + net::NetLog net_log; + config.ConfigureURLRequestContextBuilder(&builder, &net_log); + // Set a ProxyConfigService to avoid DCHECK failure when building. + builder.set_proxy_config_service( + base::MakeUnique<net::ProxyConfigServiceFixed>( + net::ProxyConfig::CreateDirect())); + std::unique_ptr<net::URLRequestContext> context(builder.Build()); + const net::HttpNetworkSession::Params* params = + context->GetNetworkSessionParams(); + + EXPECT_TRUE( + base::ContainsKey(params->quic_host_whitelist, "www.example.com")); + EXPECT_TRUE( + base::ContainsKey(params->quic_host_whitelist, "www.example.org")); +} + // See stale_host_resolver_unittest.cc for test of StaleDNS options. } // namespace cronet
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.cc index fc0b8e7..510671ff 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.cc
@@ -20,7 +20,16 @@ // The Chrome-Proxy "exp" directive value used by data reduction proxy to // receive an alternative back end implementation. -const char kDataReductionProxyServerAlternative[] = "alternative"; +const char kDataReductionProxyServerAlternative1[] = "alt1"; +const char kDataReductionProxyServerAlternative2[] = "alt2"; +const char kDataReductionProxyServerAlternative3[] = "alt3"; +const char kDataReductionProxyServerAlternative4[] = "alt4"; +const char kDataReductionProxyServerAlternative5[] = "alt5"; +const char kDataReductionProxyServerAlternative6[] = "alt6"; +const char kDataReductionProxyServerAlternative7[] = "alt7"; +const char kDataReductionProxyServerAlternative8[] = "alt8"; +const char kDataReductionProxyServerAlternative9[] = "alt9"; +const char kDataReductionProxyServerAlternative10[] = "alt10"; // The origin of the data reduction proxy fallback. const char kDataReductionProxyFallback[] = "spdy-proxy-auth-fallback";
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h index 7a57599..4d3f0ea 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h
@@ -25,7 +25,16 @@ extern const char kDataReductionProxyLoFiValueSlowConnectionsOnly[]; extern const char kDataReductionProxySecureProxyCheckURL[]; extern const char kDataReductionProxyServerExperimentsDisabled[]; -extern const char kDataReductionProxyServerAlternative[]; +extern const char kDataReductionProxyServerAlternative1[]; +extern const char kDataReductionProxyServerAlternative2[]; +extern const char kDataReductionProxyServerAlternative3[]; +extern const char kDataReductionProxyServerAlternative4[]; +extern const char kDataReductionProxyServerAlternative5[]; +extern const char kDataReductionProxyServerAlternative6[]; +extern const char kDataReductionProxyServerAlternative7[]; +extern const char kDataReductionProxyServerAlternative8[]; +extern const char kDataReductionProxyServerAlternative9[]; +extern const char kDataReductionProxyServerAlternative10[]; extern const char kEnableDataReductionProxy[]; extern const char kEnableDataReductionProxyBypassWarning[]; extern const char kEnableDataReductionProxyForcePingback[];
diff --git a/components/download/BUILD.gn b/components/download/BUILD.gn index 2bd5bb6..985df7bab 100644 --- a/components/download/BUILD.gn +++ b/components/download/BUILD.gn
@@ -13,6 +13,7 @@ deps += [ "//components/download/content/internal:unit_tests", "//components/download/content/public:unit_tests", + "//components/download/downloader/in_progress:unit_tests", ] }
diff --git a/components/download/downloader/in_progress/BUILD.gn b/components/download/downloader/in_progress/BUILD.gn index 63ff415..6f45a44 100644 --- a/components/download/downloader/in_progress/BUILD.gn +++ b/components/download/downloader/in_progress/BUILD.gn
@@ -22,3 +22,19 @@ "//components/download/downloader/in_progress/proto", ] } + +source_set("unit_tests") { + testonly = true + + sources = [ + "in_progress_conversions_unittest.cc", + ] + + deps = [ + ":in_progress", + "//base/test:test_support", + "//components/download/downloader/in_progress/proto", + "//testing/gmock", + "//testing/gtest", + ] +}
diff --git a/components/download/downloader/in_progress/download_entry.cc b/components/download/downloader/in_progress/download_entry.cc index a9fb01e6..ffd31057 100644 --- a/components/download/downloader/in_progress/download_entry.cc +++ b/components/download/downloader/in_progress/download_entry.cc
@@ -16,4 +16,8 @@ DownloadEntry::~DownloadEntry() = default; +bool DownloadEntry::operator==(const DownloadEntry& other) const { + return guid == other.guid && request_origin == other.request_origin; +} + } // namespace download
diff --git a/components/download/downloader/in_progress/download_entry.h b/components/download/downloader/in_progress/download_entry.h index 238d2ef..3e2271b 100644 --- a/components/download/downloader/in_progress/download_entry.h +++ b/components/download/downloader/in_progress/download_entry.h
@@ -17,6 +17,8 @@ DownloadEntry(const std::string& guid, const std::string& request_origin); ~DownloadEntry(); + bool operator==(const DownloadEntry& other) const; + // A unique GUID that represents this download. std::string guid;
diff --git a/components/download/downloader/in_progress/in_progress_conversions.h b/components/download/downloader/in_progress/in_progress_conversions.h index d0b66a2..81c6f91 100644 --- a/components/download/downloader/in_progress/in_progress_conversions.h +++ b/components/download/downloader/in_progress/in_progress_conversions.h
@@ -24,9 +24,6 @@ static metadata_pb::DownloadEntries DownloadEntriesToProto( const std::vector<DownloadEntry>& entries); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(InProgressConversions); }; } // namespace download
diff --git a/components/download/downloader/in_progress/in_progress_conversions_unittest.cc b/components/download/downloader/in_progress/in_progress_conversions_unittest.cc new file mode 100644 index 0000000..ef2b2f6 --- /dev/null +++ b/components/download/downloader/in_progress/in_progress_conversions_unittest.cc
@@ -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. + +#include "components/download/downloader/in_progress/in_progress_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace download { + +class InProgressConversionsTest : public testing::Test, + public InProgressConversions { + public: + ~InProgressConversionsTest() override {} +}; + +TEST_F(InProgressConversionsTest, DownloadEntry) { + // Entry with no fields. + DownloadEntry entry; + EXPECT_EQ(entry, DownloadEntryFromProto(DownloadEntryToProto(entry))); + + // Entry with guid and request origin. + entry.guid = "guid"; + entry.request_origin = "request origin"; + EXPECT_EQ(entry, DownloadEntryFromProto(DownloadEntryToProto(entry))); +} + +TEST_F(InProgressConversionsTest, DownloadEntries) { + // Entries vector with no entries. + std::vector<DownloadEntry> entries; + EXPECT_EQ(entries, DownloadEntriesFromProto(DownloadEntriesToProto(entries))); + + // Entries vector with one entry. + entries.push_back(DownloadEntry("guid", "request origin")); + EXPECT_EQ(entries, DownloadEntriesFromProto(DownloadEntriesToProto(entries))); + + // Entries vector with multiple entries. + entries.push_back(DownloadEntry("guid2", "request origin")); + EXPECT_EQ(entries, DownloadEntriesFromProto(DownloadEntriesToProto(entries))); +} + +} // namespace download
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn index dea6b1c2..d3d8bc5 100644 --- a/components/exo/BUILD.gn +++ b/components/exo/BUILD.gn
@@ -60,7 +60,7 @@ ] deps = [ - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//cc", "//components/viz/service", @@ -103,7 +103,7 @@ deps = [ ":exo", "//ash:test_support_without_content", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//gpu", "//skia", @@ -141,7 +141,7 @@ ":test_support", "//ash", "//ash:test_support_without_content", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//base/test:test_support", "//cc", @@ -181,7 +181,7 @@ deps = [ ":unit_tests", "//ash:test_support_without_content", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//base/test:test_support", "//cc:test_support",
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index bd3f776b..47d552b 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -63,7 +63,7 @@ deps = [ ":aura_shell_protocol", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//components/exo", "//device/gamepad", @@ -313,7 +313,7 @@ ":wayland", "//ash", "//ash:test_support_without_content", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//base/test:test_support", "//cc:test_support",
diff --git a/components/leveldb/leveldb_database_impl.cc b/components/leveldb/leveldb_database_impl.cc index 1605a7f..f285c92 100644 --- a/components/leveldb/leveldb_database_impl.cc +++ b/components/leveldb/leveldb_database_impl.cc
@@ -5,6 +5,7 @@ #include "components/leveldb/leveldb_database_impl.h" #include <inttypes.h> +#include <algorithm> #include <map> #include <string> #include <utility> @@ -45,9 +46,9 @@ } // namespace LevelDBDatabaseImpl::LevelDBDatabaseImpl( - std::unique_ptr<leveldb::Env> environment, - std::unique_ptr<leveldb::DB> db, - std::unique_ptr<leveldb::Cache> cache, + std::unique_ptr<Env> environment, + std::unique_ptr<DB> db, + std::unique_ptr<Cache> cache, base::Optional<base::trace_event::MemoryAllocatorDumpGuid> memory_dump_id) : environment_(std::move(environment)), cache_(std::move(cache)), @@ -71,23 +72,21 @@ void LevelDBDatabaseImpl::Put(const std::vector<uint8_t>& key, const std::vector<uint8_t>& value, PutCallback callback) { - leveldb::Status status = + Status status = db_->Put(leveldb::WriteOptions(), GetSliceFor(key), GetSliceFor(value)); std::move(callback).Run(LeveldbStatusToError(status)); } void LevelDBDatabaseImpl::Delete(const std::vector<uint8_t>& key, DeleteCallback callback) { - leveldb::Status status = - db_->Delete(leveldb::WriteOptions(), GetSliceFor(key)); + Status status = db_->Delete(leveldb::WriteOptions(), GetSliceFor(key)); std::move(callback).Run(LeveldbStatusToError(status)); } void LevelDBDatabaseImpl::DeletePrefixed(const std::vector<uint8_t>& key_prefix, DeletePrefixedCallback callback) { - leveldb::WriteBatch batch; - leveldb::Status status = DeletePrefixedHelper( - GetSliceFor(key_prefix), &batch); + WriteBatch batch; + Status status = DeletePrefixedHelper(GetSliceFor(key_prefix), &batch); if (status.ok()) status = db_->Write(leveldb::WriteOptions(), &batch); std::move(callback).Run(LeveldbStatusToError(status)); @@ -96,7 +95,7 @@ void LevelDBDatabaseImpl::Write( std::vector<mojom::BatchedOperationPtr> operations, WriteCallback callback) { - leveldb::WriteBatch batch; + WriteBatch batch; for (size_t i = 0; i < operations.size(); ++i) { switch (operations[i]->type) { @@ -105,7 +104,7 @@ batch.Put(GetSliceFor(operations[i]->key), GetSliceFor(*(operations[i]->value))); } else { - batch.Put(GetSliceFor(operations[i]->key), leveldb::Slice()); + batch.Put(GetSliceFor(operations[i]->key), Slice()); } break; } @@ -117,18 +116,27 @@ DeletePrefixedHelper(GetSliceFor(operations[i]->key), &batch); break; } + case mojom::BatchOperationType::COPY_PREFIXED_KEY: { + if (!operations[i]->value) { + mojo::ReportBadMessage( + "COPY_PREFIXED_KEY operation must provide a value."); + std::move(callback).Run(mojom::DatabaseError::INVALID_ARGUMENT); + return; + } + CopyPrefixedHelper(operations[i]->key, *(operations[i]->value), &batch); + break; + } } } - leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); + Status status = db_->Write(leveldb::WriteOptions(), &batch); std::move(callback).Run(LeveldbStatusToError(status)); } void LevelDBDatabaseImpl::Get(const std::vector<uint8_t>& key, GetCallback callback) { std::string value; - leveldb::Status status = - db_->Get(leveldb::ReadOptions(), GetSliceFor(key), &value); + Status status = db_->Get(leveldb::ReadOptions(), GetSliceFor(key), &value); std::move(callback).Run(LeveldbStatusToError(status), StdStringToUint8Vector(value)); } @@ -136,17 +144,29 @@ void LevelDBDatabaseImpl::GetPrefixed(const std::vector<uint8_t>& key_prefix, GetPrefixedCallback callback) { std::vector<mojom::KeyValuePtr> data; - leveldb::Status status = ForEachWithPrefix( - db_.get(), GetSliceFor(key_prefix), - [&data](const leveldb::Slice& key, const leveldb::Slice& value) { - mojom::KeyValuePtr kv = mojom::KeyValue::New(); - kv->key = GetVectorFor(key); - kv->value = GetVectorFor(value); - data.push_back(std::move(kv)); - }); + Status status = + ForEachWithPrefix(db_.get(), GetSliceFor(key_prefix), + [&data](const Slice& key, const Slice& value) { + mojom::KeyValuePtr kv = mojom::KeyValue::New(); + kv->key = GetVectorFor(key); + kv->value = GetVectorFor(value); + data.push_back(std::move(kv)); + }); std::move(callback).Run(LeveldbStatusToError(status), std::move(data)); } +void LevelDBDatabaseImpl::CopyPrefixed( + const std::vector<uint8_t>& source_key_prefix, + const std::vector<uint8_t>& destination_key_prefix, + CopyPrefixedCallback callback) { + WriteBatch batch; + Status status = + CopyPrefixedHelper(source_key_prefix, destination_key_prefix, &batch); + if (status.ok()) + status = db_->Write(leveldb::WriteOptions(), &batch); + std::move(callback).Run(LeveldbStatusToError(status)); +} + void LevelDBDatabaseImpl::GetSnapshot(GetSnapshotCallback callback) { const Snapshot* s = db_->GetSnapshot(); base::UnguessableToken token = base::UnguessableToken::Create(); @@ -178,7 +198,7 @@ std::string value; leveldb::ReadOptions options; options.snapshot = it->second; - leveldb::Status status = db_->Get(options, GetSliceFor(key), &value); + Status status = db_->Get(options, GetSliceFor(key), &value); std::move(callback).Run(LeveldbStatusToError(status), StdStringToUint8Vector(value)); } @@ -320,12 +340,30 @@ GetVectorFor(it->key()), GetVectorFor(it->value())); } -leveldb::Status LevelDBDatabaseImpl::DeletePrefixedHelper( - const leveldb::Slice& key_prefix, +Status LevelDBDatabaseImpl::DeletePrefixedHelper(const Slice& key_prefix, + WriteBatch* batch) { + Status status = ForEachWithPrefix( + db_.get(), key_prefix, + [batch](const Slice& key, const Slice& value) { batch->Delete(key); }); + return status; +} + +Status LevelDBDatabaseImpl::CopyPrefixedHelper( + const std::vector<uint8_t>& source_key_prefix, + const std::vector<uint8_t>& destination_key_prefix, leveldb::WriteBatch* batch) { - leveldb::Status status = ForEachWithPrefix(db_.get(), key_prefix, - [batch](const leveldb::Slice& key, const leveldb::Slice& value) { - batch->Delete(key); + std::vector<uint8_t> new_prefix = destination_key_prefix; + size_t source_key_prefix_size = source_key_prefix.size(); + size_t destination_key_prefix_size = destination_key_prefix.size(); + Status status = ForEachWithPrefix( + db_.get(), GetSliceFor(source_key_prefix), + [&batch, &new_prefix, source_key_prefix_size, + destination_key_prefix_size](const Slice& key, const Slice& value) { + size_t excess_key = key.size() - source_key_prefix_size; + new_prefix.resize(destination_key_prefix_size + excess_key); + std::copy(key.data() + source_key_prefix_size, key.data() + key.size(), + new_prefix.begin() + destination_key_prefix_size); + batch->Put(GetSliceFor(new_prefix), value); }); return status; }
diff --git a/components/leveldb/leveldb_database_impl.h b/components/leveldb/leveldb_database_impl.h index 31c9cbab..757c61e1 100644 --- a/components/leveldb/leveldb_database_impl.h +++ b/components/leveldb/leveldb_database_impl.h
@@ -6,6 +6,7 @@ #define COMPONENTS_LEVELDB_LEVELDB_DATABASE_IMPL_H_ #include <memory> +#include <vector> #include "base/trace_event/memory_dump_provider.h" #include "base/unguessable_token.h" @@ -40,6 +41,9 @@ void Get(const std::vector<uint8_t>& key, GetCallback callback) override; void GetPrefixed(const std::vector<uint8_t>& key_prefix, GetPrefixedCallback callback) override; + void CopyPrefixed(const std::vector<uint8_t>& source_key_prefix, + const std::vector<uint8_t>& destination_key_prefix, + CopyPrefixedCallback callback) override; void GetSnapshot(GetSnapshotCallback callback) override; void ReleaseSnapshot(const base::UnguessableToken& snapshot) override; void GetFromSnapshot(const base::UnguessableToken& snapshot, @@ -76,6 +80,11 @@ leveldb::Status DeletePrefixedHelper(const leveldb::Slice& key_prefix, leveldb::WriteBatch* batch); + leveldb::Status CopyPrefixedHelper( + const std::vector<uint8_t>& source_key_prefix, + const std::vector<uint8_t>& destination_key_prefix, + leveldb::WriteBatch* batch); + std::unique_ptr<leveldb::Env> environment_; std::unique_ptr<leveldb::Cache> cache_; std::unique_ptr<leveldb::DB> db_;
diff --git a/components/leveldb/leveldb_service_unittest.cc b/components/leveldb/leveldb_service_unittest.cc index 2c9192d..ef65336 100644 --- a/components/leveldb/leveldb_service_unittest.cc +++ b/components/leveldb/leveldb_service_unittest.cc
@@ -85,6 +85,17 @@ run_loop.Run(); } +void DatabaseSyncCopyPrefixed(mojom::LevelDBDatabase* database, + const std::string& source_key_prefix, + const std::string& destination_key_prefix, + mojom::DatabaseError* out_error) { + base::RunLoop run_loop; + database->CopyPrefixed(StdStringToUint8Vector(source_key_prefix), + StdStringToUint8Vector(destination_key_prefix), + Capture(out_error, run_loop.QuitClosure())); + run_loop.Run(); +} + void DatabaseSyncDeletePrefixed(mojom::LevelDBDatabase* database, const std::string& key_prefix, mojom::DatabaseError* out_error) { @@ -223,9 +234,14 @@ DatabaseSyncPut(database.get(), "prefix-key2", "value", &error); EXPECT_EQ(mojom::DatabaseError::OK, error); - // Create a batched operation to delete them. + // Create batched operations to copy and then delete the 'prefix' data. operations.clear(); item = mojom::BatchedOperation::New(); + item->type = mojom::BatchOperationType::COPY_PREFIXED_KEY; + item->key = StdStringToUint8Vector("prefix"); + item->value = StdStringToUint8Vector("copy-prefix"); + operations.push_back(std::move(item)); + item = mojom::BatchedOperation::New(); item->type = mojom::BatchOperationType::DELETE_PREFIXED_KEY; item->key = StdStringToUint8Vector("prefix"); operations.push_back(std::move(item)); @@ -247,6 +263,71 @@ DatabaseSyncGet(database.get(), "prefix-key2", &error, &value); EXPECT_EQ(mojom::DatabaseError::NOT_FOUND, error); EXPECT_EQ("", Uint8VectorToStdString(value)); + + // Prefix keys should have been copied to 'copy-prefix' before deletion. + error = mojom::DatabaseError::INVALID_ARGUMENT; + DatabaseSyncGet(database.get(), "copy-prefix-key1", &error, &value); + EXPECT_EQ(mojom::DatabaseError::OK, error); + EXPECT_EQ("value", Uint8VectorToStdString(value)); + error = mojom::DatabaseError::INVALID_ARGUMENT; + DatabaseSyncGet(database.get(), "copy-prefix-key2", &error, &value); + EXPECT_EQ(mojom::DatabaseError::OK, error); + EXPECT_EQ("value", Uint8VectorToStdString(value)); +} + +TEST_F(LevelDBServiceTest, WriteBatchPrefixesAndDeletes) { + // This test makes sure that prefixes & deletes happen before all other batch + // operations. + mojom::DatabaseError error; + mojom::LevelDBDatabaseAssociatedPtr database; + LevelDBSyncOpenInMemory(leveldb().get(), MakeRequest(&database), &error); + EXPECT_EQ(mojom::DatabaseError::OK, error); + + // Write a key to the database. + DatabaseSyncPut(database.get(), "key", "value", &error); + EXPECT_EQ(mojom::DatabaseError::OK, error); + + // The copy applies as if it happens before this write batch. + // The delete applies to all keys that existed before these changes. + std::vector<mojom::BatchedOperationPtr> operations; + mojom::BatchedOperationPtr item = mojom::BatchedOperation::New(); + item->type = mojom::BatchOperationType::PUT_KEY; + item->key = StdStringToUint8Vector("key"); + item->value = StdStringToUint8Vector("new_value"); + operations.push_back(std::move(item)); + + item = mojom::BatchedOperation::New(); + item->type = mojom::BatchOperationType::PUT_KEY; + item->key = StdStringToUint8Vector("key2"); + item->value = StdStringToUint8Vector("value2"); + operations.push_back(std::move(item)); + + item = mojom::BatchedOperation::New(); + item->type = mojom::BatchOperationType::DELETE_PREFIXED_KEY; + item->key = StdStringToUint8Vector("k"); + operations.push_back(std::move(item)); + + item = mojom::BatchedOperation::New(); + item->type = mojom::BatchOperationType::COPY_PREFIXED_KEY; + item->key = StdStringToUint8Vector("k"); + item->value = StdStringToUint8Vector("f"); + operations.push_back(std::move(item)); + base::RunLoop run_loop; + database->Write(std::move(operations), + Capture(&error, run_loop.QuitClosure())); + run_loop.Run(); + EXPECT_EQ(mojom::DatabaseError::OK, error); + + std::vector<uint8_t> value; + error = mojom::DatabaseError::INVALID_ARGUMENT; + DatabaseSyncGet(database.get(), "key", &error, &value); + EXPECT_EQ(mojom::DatabaseError::NOT_FOUND, error); + DatabaseSyncGet(database.get(), "key2", &error, &value); + EXPECT_EQ("value2", Uint8VectorToStdString(value)); + error = mojom::DatabaseError::INVALID_ARGUMENT; + DatabaseSyncGet(database.get(), "fey", &error, &value); + EXPECT_EQ(mojom::DatabaseError::OK, error); + EXPECT_EQ("value", Uint8VectorToStdString(value)); } TEST_F(LevelDBServiceTest, Reconnect) { @@ -483,6 +564,7 @@ EXPECT_EQ(mojom::DatabaseError::OK, error); const std::string prefix("prefix"); + const std::string copy_prefix("foo"); std::vector<mojom::KeyValuePtr> key_values; // Completely empty database. @@ -528,6 +610,17 @@ EXPECT_EQ("prefix2", Uint8VectorToStdString(key_values[1]->key)); EXPECT_EQ("value2", Uint8VectorToStdString(key_values[1]->value)); + // Copy to a different prefix + DatabaseSyncCopyPrefixed(database.get(), prefix, copy_prefix, &error); + EXPECT_EQ(mojom::DatabaseError::OK, error); + DatabaseSyncGetPrefixed(database.get(), copy_prefix, &error, &key_values); + EXPECT_EQ(mojom::DatabaseError::OK, error); + ASSERT_EQ(2u, key_values.size()); + EXPECT_EQ("foo", Uint8VectorToStdString(key_values[0]->key)); + EXPECT_EQ("value", Uint8VectorToStdString(key_values[0]->value)); + EXPECT_EQ("foo2", Uint8VectorToStdString(key_values[1]->key)); + EXPECT_EQ("value2", Uint8VectorToStdString(key_values[1]->value)); + // Delete the prefixed values. error = mojom::DatabaseError::INVALID_ARGUMENT; DatabaseSyncDeletePrefixed(database.get(), prefix, &error); @@ -547,6 +640,9 @@ DatabaseSyncGet(database.get(), "z-after-prefix", &error, &value); EXPECT_EQ(mojom::DatabaseError::OK, error); EXPECT_EQ("value", Uint8VectorToStdString(value)); + DatabaseSyncGetPrefixed(database.get(), copy_prefix, &error, &key_values); + EXPECT_EQ(mojom::DatabaseError::OK, error); + EXPECT_EQ(2u, key_values.size()); // A key having our prefix, but no key matching it exactly. // Even thought there is no exact matching key, GetPrefixed
diff --git a/components/leveldb/public/interfaces/leveldb.mojom b/components/leveldb/public/interfaces/leveldb.mojom index 061c81f..1dcca48 100644 --- a/components/leveldb/public/interfaces/leveldb.mojom +++ b/components/leveldb/public/interfaces/leveldb.mojom
@@ -20,12 +20,16 @@ enum BatchOperationType { PUT_KEY, DELETE_KEY, - DELETE_PREFIXED_KEY + DELETE_PREFIXED_KEY, + // |key| is source prefixed key, |value| is destination prefixed key. + COPY_PREFIXED_KEY }; +// TODO(dmurph): change to a union type for value population. struct BatchedOperation { BatchOperationType type; array<uint8> key; + // Populated for operations of types PUT_KEY and COPY_PREFIXED_KEY. array<uint8>? value; }; @@ -110,6 +114,12 @@ DeletePrefixed(array<uint8> key_prefix) => (DatabaseError status); // Atomically performs all |operations|. + // The DELETE_PREFIXED_KEY applies to all keys that exist before these + // operations execute. If a 'put' operation precedes a delete prefix, then it + // will only be deleted if it was a previously-populated key in the database. + // The COPY_PREFIXED_KEY operations will always ignore all other changes in + // the operations batch. It will not copy records that were inserted earlier + // in the operations list. Write(array<BatchedOperation> operations) => (DatabaseError status); Get(array<uint8> key) => (DatabaseError status, array<uint8> value); @@ -117,6 +127,12 @@ GetPrefixed(array<uint8> key_prefix) => (DatabaseError status, array<KeyValue> data); + // Copies all data from the source prefix to the destination prefix. Useful + // for deep copies. + CopyPrefixed(array<uint8> source_key_prefix, + array<uint8> destination_key_prefix) + => (DatabaseError status); + // Snapshots ------------------------------------------------------------- // Returns a handle to the current database state.
diff --git a/components/network_session_configurator/browser/network_session_configurator.cc b/components/network_session_configurator/browser/network_session_configurator.cc index d38d7d6..41dade2 100644 --- a/components/network_session_configurator/browser/network_session_configurator.cc +++ b/components/network_session_configurator/browser/network_session_configurator.cc
@@ -267,6 +267,15 @@ GetVariationParam(quic_trial_params, "allow_server_migration"), "true"); } +base::flat_set<std::string> GetQuicHostWhitelist( + const VariationParameters& quic_trial_params) { + std::string host_whitelist = + GetVariationParam(quic_trial_params, "host_whitelist"); + std::vector<std::string> host_vector = base::SplitString( + host_whitelist, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + return base::flat_set<std::string>(std::move(host_vector)); +} + size_t GetQuicMaxPacketLength(const VariationParameters& quic_trial_params) { unsigned value; if (base::StringToUint( @@ -353,6 +362,7 @@ ShouldQuicMigrateSessionsEarly(quic_trial_params); params->quic_allow_server_migration = ShouldQuicAllowServerMigration(quic_trial_params); + params->quic_host_whitelist = GetQuicHostWhitelist(quic_trial_params); } size_t max_packet_length = GetQuicMaxPacketLength(quic_trial_params);
diff --git a/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/components/network_session_configurator/browser/network_session_configurator_unittest.cc index 4bceaf2f6..59cd1efc 100644 --- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -106,6 +106,7 @@ EXPECT_FALSE(params_.quic_migrate_sessions_on_network_change_v2); EXPECT_FALSE(params_.quic_migrate_sessions_early); EXPECT_FALSE(params_.quic_allow_server_migration); + EXPECT_TRUE(params_.quic_host_whitelist.empty()); net::HttpNetworkSession::Params default_params; EXPECT_EQ(default_params.quic_supported_versions, @@ -438,6 +439,32 @@ EXPECT_EQ(options, params_.quic_client_connection_options); } +TEST_F(NetworkSessionConfiguratorTest, QuicHostWhitelist) { + std::map<std::string, std::string> field_trial_params; + field_trial_params["host_whitelist"] = "www.example.org, www.example.com"; + variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); + base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); + + ParseFieldTrials(); + + EXPECT_EQ(2u, params_.quic_host_whitelist.size()); + EXPECT_TRUE( + base::ContainsKey(params_.quic_host_whitelist, "www.example.com")); + EXPECT_TRUE( + base::ContainsKey(params_.quic_host_whitelist, "www.example.org")); +} + +TEST_F(NetworkSessionConfiguratorTest, QuicHostWhitelistEmpty) { + std::map<std::string, std::string> field_trial_params; + field_trial_params["host_whitelist"] = ""; + variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); + base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); + + ParseFieldTrials(); + + EXPECT_TRUE(params_.quic_host_whitelist.empty()); +} + TEST_F(NetworkSessionConfiguratorTest, Http2SettingsFromFieldTrialParams) { std::map<std::string, std::string> field_trial_params; field_trial_params["http2_settings"] = "7:1234,25:5678";
diff --git a/components/offline_pages/core/BUILD.gn b/components/offline_pages/core/BUILD.gn index bbdeb4c4..290cb5c6 100644 --- a/components/offline_pages/core/BUILD.gn +++ b/components/offline_pages/core/BUILD.gn
@@ -20,6 +20,8 @@ "model/add_page_task.h", "model/clear_digest_task.cc", "model/clear_digest_task.h", + "model/clear_legacy_temporary_pages_task.cc", + "model/clear_legacy_temporary_pages_task.h", "model/clear_storage_task.cc", "model/clear_storage_task.h", "model/create_archive_task.cc", @@ -32,6 +34,8 @@ "model/mark_page_accessed_task.h", "model/offline_page_model_taskified.cc", "model/offline_page_model_taskified.h", + "model/persistent_pages_consistency_check_task.cc", + "model/persistent_pages_consistency_check_task.h", "model/temporary_pages_consistency_check_task.cc", "model/temporary_pages_consistency_check_task.h", "offline_event_logger.cc", @@ -86,6 +90,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", "offline_page_metadata_store_test_util.cc", "offline_page_metadata_store_test_util.h", "offline_page_test_archiver.cc", @@ -131,12 +137,14 @@ "client_policy_controller_unittest.cc", "model/add_page_task_unittest.cc", "model/clear_digest_task_unittest.cc", + "model/clear_legacy_temporary_pages_task_unittest.cc", "model/clear_storage_task_unittest.cc", "model/create_archive_task_unittest.cc", "model/delete_page_task_unittest.cc", "model/get_pages_task_unittest.cc", "model/mark_page_accessed_task_unittest.cc", "model/offline_page_model_taskified_unittest.cc", + "model/persistent_pages_consistency_check_task_unittest.cc", "model/temporary_pages_consistency_check_task_unittest.cc", "offline_event_logger_unittest.cc", "offline_page_feature_unittest.cc",
diff --git a/components/offline_pages/core/model/clear_legacy_temporary_pages_task.cc b/components/offline_pages/core/model/clear_legacy_temporary_pages_task.cc new file mode 100644 index 0000000..b844290e --- /dev/null +++ b/components/offline_pages/core/model/clear_legacy_temporary_pages_task.cc
@@ -0,0 +1,147 @@ +// 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 "components/offline_pages/core/model/clear_legacy_temporary_pages_task.h" + +#include <memory> +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/files/file_util.h" +#include "components/offline_pages/core/client_policy_controller.h" +#include "components/offline_pages/core/offline_page_metadata_store_sql.h" +#include "components/offline_pages/core/offline_store_utils.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "sql/transaction.h" + +namespace offline_pages { + +namespace { + +#define OFFLINE_PAGES_TABLE_NAME "offlinepages_v1" + +struct PageInfo { + int64_t offline_id; + base::FilePath file_path; +}; + +std::vector<PageInfo> GetAllTemporaryPageInfos( + const std::vector<std::string>& temp_namespaces, + sql::Connection* db) { + std::vector<PageInfo> result; + + static const char kSql[] = + "SELECT offline_id, file_path" + " FROM " OFFLINE_PAGES_TABLE_NAME " WHERE client_namespace = ?"; + + for (const auto& temp_namespace : temp_namespaces) { + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindString(0, temp_namespace); + while (statement.Step()) { + result.push_back( + {statement.ColumnInt64(0), + store_utils::FromDatabaseFilePath(statement.ColumnString(1))}); + } + } + + return result; +} + +bool DeletePagesByOfflineIds(const std::vector<int64_t>& offline_ids, + sql::Connection* db) { + static const char kSql[] = + "DELETE FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id = ?"; + + for (const auto& offline_id : offline_ids) { + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt64(0, offline_id); + if (!statement.Run()) + return false; + } + return true; +} + +bool DeleteFiles(const std::vector<base::FilePath>& file_paths) { + bool result = true; + for (const auto& file_path : file_paths) + result = base::DeleteFile(file_path, false) && result; + return result; +} + +bool ClearLegacyTempPagesSync(const std::vector<std::string>& namespaces, + const base::FilePath& legacy_archives_dir, + sql::Connection* db) { + if (!db) + return false; + + // One large database transaction that will: + // 1. Get temporary page infos from the database. + // 2. Decide which pages to delete. + // 3. Delete metadata entries from the database. + sql::Transaction transaction(db); + if (!transaction.Begin()) + return false; + + auto temp_page_infos = GetAllTemporaryPageInfos(namespaces, db); + + std::vector<int64_t> offline_ids_to_delete; + std::vector<base::FilePath> files_to_delete; + for (const auto& page_info : temp_page_infos) { + // Get pages whose archive files are still in the legacy archives directory. + if (legacy_archives_dir.IsParent(page_info.file_path)) { + offline_ids_to_delete.push_back(page_info.offline_id); + files_to_delete.push_back(page_info.file_path); + continue; + } + } + + // Try to delete the pages by offline ids collected above. + // If there's any database related errors, the function will return false, + // and the database operations will be rolled back since the transaction will + // not be committed. + if (!DeletePagesByOfflineIds(offline_ids_to_delete, db)) + return false; + + if (!transaction.Commit()) + return false; + + return DeleteFiles(files_to_delete); +} + +} // namespace + +ClearLegacyTemporaryPagesTask::ClearLegacyTemporaryPagesTask( + OfflinePageMetadataStoreSQL* store, + ClientPolicyController* policy_controller, + const base::FilePath& legacy_archives_dir) + : store_(store), + policy_controller_(policy_controller), + legacy_archives_dir_(legacy_archives_dir), + weak_ptr_factory_(this) {} + +ClearLegacyTemporaryPagesTask::~ClearLegacyTemporaryPagesTask() {} + +void ClearLegacyTemporaryPagesTask::Run() { + std::vector<std::string> temp_namespaces = + policy_controller_->GetNamespacesRemovedOnCacheReset(); + store_->Execute( + base::BindOnce(&ClearLegacyTempPagesSync, temp_namespaces, + legacy_archives_dir_), + base::BindOnce( + &ClearLegacyTemporaryPagesTask::OnClearLegacyTemporaryPagesDone, + weak_ptr_factory_.GetWeakPtr())); +} + +void ClearLegacyTemporaryPagesTask::OnClearLegacyTemporaryPagesDone( + bool result) { + // TODO(romax): https://crbug.com/772204. Replace the DVLOG with UMA + // collecting. If there's a need, introduce more detailed local enums + // indicating which part failed. + DVLOG(1) << "ClearLegacyTemporaryPagesTask returns with result: " << result; + TaskComplete(); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/model/clear_legacy_temporary_pages_task.h b/components/offline_pages/core/model/clear_legacy_temporary_pages_task.h new file mode 100644 index 0000000..4c08b33 --- /dev/null +++ b/components/offline_pages/core/model/clear_legacy_temporary_pages_task.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 COMPONENTS_OFFLINE_PAGES_CORE_MODEL_CLEAR_LEGACY_TEMPORARY_PAGES_TASK_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_MODEL_CLEAR_LEGACY_TEMPORARY_PAGES_TASK_H_ + +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/offline_pages/core/task.h" + +namespace offline_pages { + +class ClientPolicyController; +class OfflinePageMetadataStoreSQL; + +// Task that delete all temporary pages and their files if the files are in the +// legacy archives directory. +// This task is supposed to be executed only when Chrome starts, in order to +// complete the consistency check for temporary pages in legacy archives +// directory. +class ClearLegacyTemporaryPagesTask : public Task { + public: + ClearLegacyTemporaryPagesTask(OfflinePageMetadataStoreSQL* store, + ClientPolicyController* policy_controller, + const base::FilePath& legacy_archives_dir); + ~ClearLegacyTemporaryPagesTask() override; + + // Task implementation + void Run() override; + + private: + void OnClearLegacyTemporaryPagesDone(bool result); + + // The store for clearing legacy pages. Not owned. + OfflinePageMetadataStoreSQL* store_; + // The client policy controller to get temporary namespaces. Not owned. + ClientPolicyController* policy_controller_; + base::FilePath legacy_archives_dir_; + + base::WeakPtrFactory<ClearLegacyTemporaryPagesTask> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(ClearLegacyTemporaryPagesTask); +}; + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_MODEL_CLEAR_LEGACY_TEMPORARY_PAGES_TASK_H_
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 new file mode 100644 index 0000000..245c73b5 --- /dev/null +++ b/components/offline_pages/core/model/clear_legacy_temporary_pages_task_unittest.cc
@@ -0,0 +1,116 @@ +// 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 "components/offline_pages/core/model/clear_legacy_temporary_pages_task.h" + +#include "base/bind.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_util.h" +#include "base/test/test_simple_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.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_test_util.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" + +namespace offline_pages { + +class ClearLegacyTemporaryPagesTaskTest : public testing::Test { + public: + ClearLegacyTemporaryPagesTaskTest(); + ~ClearLegacyTemporaryPagesTaskTest() override; + + void SetUp() override; + void TearDown() override; + + OfflinePageItem AddPage(const std::string& name_space, + const base::FilePath& archive_dir); + + OfflinePageMetadataStoreSQL* store() { return store_test_util_.store(); } + OfflinePageMetadataStoreTestUtil* store_test_util() { + return &store_test_util_; + } + OfflinePageItemGenerator* generator() { return &generator_; } + TestTaskRunner* runner() { return &runner_; } + ClientPolicyController* policy_controller() { + return policy_controller_.get(); + } + + const base::FilePath& legacy_archives_dir() { + return legacy_archives_dir_.GetPath(); + } + + private: + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + base::ThreadTaskRunnerHandle task_runner_handle_; + + OfflinePageMetadataStoreTestUtil store_test_util_; + OfflinePageItemGenerator generator_; + TestTaskRunner runner_; + std::unique_ptr<ClientPolicyController> policy_controller_; + + base::ScopedTempDir legacy_archives_dir_; +}; + +ClearLegacyTemporaryPagesTaskTest::ClearLegacyTemporaryPagesTaskTest() + : task_runner_(new base::TestSimpleTaskRunner()), + task_runner_handle_(task_runner_), + store_test_util_(task_runner_), + runner_(task_runner_) {} + +ClearLegacyTemporaryPagesTaskTest::~ClearLegacyTemporaryPagesTaskTest() {} + +void ClearLegacyTemporaryPagesTaskTest::SetUp() { + store_test_util_.BuildStoreInMemory(); + ASSERT_TRUE(legacy_archives_dir_.CreateUniqueTempDir()); + policy_controller_ = base::MakeUnique<ClientPolicyController>(); +} + +void ClearLegacyTemporaryPagesTaskTest::TearDown() { + store_test_util_.DeleteStore(); + if (!legacy_archives_dir_.Delete()) + DVLOG(1) << "ScopedTempDir deletion failed."; +} + +OfflinePageItem ClearLegacyTemporaryPagesTaskTest::AddPage( + const std::string& name_space, + const base::FilePath& archive_dir) { + generator()->SetNamespace(name_space); + generator()->SetArchiveDirectory(archive_dir); + OfflinePageItem page = generator()->CreateItemWithTempFile(); + store_test_util()->InsertItem(page); + return page; +} + +// This test is affected by https://crbug.com/725685, which only affects windows +// platform. +#if defined(OS_WIN) +#define MAYBE_TestDeletePageInLegacyArchivesDir \ + DISABLED_TestDeletePageInLegacyArchivesDir +#else +#define MAYBE_TestDeletePageInLegacyArchivesDir \ + TestDeletePageInLegacyArchivesDir +#endif +TEST_F(ClearLegacyTemporaryPagesTaskTest, + MAYBE_TestDeletePageInLegacyArchivesDir) { + OfflinePageItem page1 = AddPage(kLastNNamespace, legacy_archives_dir()); + OfflinePageItem page2 = AddPage(kDownloadNamespace, legacy_archives_dir()); + + EXPECT_EQ(2LL, store_test_util()->GetPageCount()); + EXPECT_EQ(2UL, test_util::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_FALSE(store_test_util()->GetPageByOfflineId(page1.offline_id)); +} + +} // namespace offline_pages
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 d2de071..f4c0155b 100644 --- a/components/offline_pages/core/model/clear_storage_task_unittest.cc +++ b/components/offline_pages/core/model/clear_storage_task_unittest.cc
@@ -15,6 +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/offline_page_metadata_store_test_util.h" #include "components/offline_pages/core/test_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" @@ -41,16 +42,6 @@ int expired_page_count; }; -int64_t GetFileCountInDir(const base::FilePath& dir) { - base::FileEnumerator file_enumerator(dir, false, base::FileEnumerator::FILES); - int64_t count = 0; - for (base::FilePath path = file_enumerator.Next(); !path.empty(); - path = file_enumerator.Next()) { - count++; - } - return count; -} - class TestArchiveManager : public ArchiveManager { public: explicit TestArchiveManager(OfflinePageMetadataStoreTestUtil* store_test_util) @@ -219,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(2LL, GetFileCountInDir(temp_dir_path())); + EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temp_dir_path())); } TEST_F(ClearStorageTaskTest, ClearPagesMoreFreshPages) { @@ -240,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(130LL, GetFileCountInDir(temp_dir_path())); + EXPECT_EQ(130UL, test_util::GetFileCountInDirectory(temp_dir_path())); } TEST_F(ClearStorageTaskTest, TryClearPersistentPages) { @@ -259,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(20LL, GetFileCountInDir(temp_dir_path())); + EXPECT_EQ(20UL, test_util::GetFileCountInDirectory(temp_dir_path())); } TEST_F(ClearStorageTaskTest, TryClearPersistentPagesWithStoragePressure) { @@ -280,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(20LL, GetFileCountInDir(temp_dir_path())); + EXPECT_EQ(20UL, test_util::GetFileCountInDirectory(temp_dir_path())); } TEST_F(ClearStorageTaskTest, ClearMultipleTimes) { @@ -305,7 +296,7 @@ EXPECT_EQ(1, total_cleared_times()); EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result()); EXPECT_EQ(90LL, store_test_util()->GetPageCount()); - EXPECT_EQ(90LL, GetFileCountInDir(temp_dir_path())); + EXPECT_EQ(90UL, test_util::GetFileCountInDirectory(temp_dir_path())); clock->SetNow(start_time); // Advance the clock by the expiration period of last_n namespace, all pages @@ -323,7 +314,7 @@ EXPECT_EQ(2, total_cleared_times()); EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result()); EXPECT_EQ(70LL, store_test_util()->GetPageCount()); - EXPECT_EQ(70LL, GetFileCountInDir(temp_dir_path())); + EXPECT_EQ(70UL, test_util::GetFileCountInDirectory(temp_dir_path())); clock->SetNow(start_time); // Advance the clock by 1 ms, there's no change in pages so the attempt to @@ -338,7 +329,7 @@ EXPECT_EQ(3, total_cleared_times()); EXPECT_EQ(ClearStorageResult::UNNECESSARY, last_clear_storage_result()); EXPECT_EQ(70LL, store_test_util()->GetPageCount()); - EXPECT_EQ(70LL, GetFileCountInDir(temp_dir_path())); + EXPECT_EQ(70UL, test_util::GetFileCountInDirectory(temp_dir_path())); clock->SetNow(start_time); // Adding more fresh pages in bookmark namespace to make storage usage exceed @@ -362,7 +353,7 @@ EXPECT_EQ(4, total_cleared_times()); EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result()); EXPECT_EQ(107LL, store_test_util()->GetPageCount()); - EXPECT_EQ(107LL, GetFileCountInDir(temp_dir_path())); + EXPECT_EQ(107UL, test_util::GetFileCountInDirectory(temp_dir_path())); clock->SetNow(start_time); // Advance the clock by 300 days, in order to expire all temporary pages. Only @@ -377,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(40LL, GetFileCountInDir(temp_dir_path())); + EXPECT_EQ(40UL, test_util::GetFileCountInDirectory(temp_dir_path())); } } // namespace offline_pages
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 273970b27..7aa8bac 100644 --- a/components/offline_pages/core/model/offline_page_item_generator.cc +++ b/components/offline_pages/core/model/offline_page_item_generator.cc
@@ -39,7 +39,9 @@ OfflinePageItem item = CreateItem(); base::FilePath path; base::CreateTemporaryFileInDir(archive_dir_, &path); - item.file_path = path; + base::FilePath mhtml_path = path.AddExtension(FILE_PATH_LITERAL("mhtml")); + DCHECK(base::Move(path, mhtml_path)); + item.file_path = mhtml_path; return item; }
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 43e38d5e..0b1ec406 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
@@ -17,6 +17,7 @@ #include "build/build_config.h" #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_test_util.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" @@ -57,16 +58,6 @@ const std::string kTestRequestOrigin("abc.xyz"); const std::string kEmptyRequestOrigin(""); -int64_t GetFileCountInDir(const base::FilePath& dir) { - base::FileEnumerator file_enumerator(dir, false, base::FileEnumerator::FILES); - int64_t count = 0; - for (base::FilePath path = file_enumerator.Next(); !path.empty(); - path = file_enumerator.Next()) { - count++; - } - return count; -} - } // namespace class OfflinePageModelTaskifiedTest @@ -289,7 +280,7 @@ kTestUrl, kTestClientId1, kTestUrl2, kEmptyRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); - EXPECT_EQ(1LL, GetFileCountInDir(temporary_dir_path())); + EXPECT_EQ(1UL, test_util::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); @@ -314,7 +305,7 @@ kTestUrl, kTestClientId1, kTestUrl, kEmptyRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); - EXPECT_EQ(1LL, GetFileCountInDir(temporary_dir_path())); + EXPECT_EQ(1UL, test_util::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); @@ -330,7 +321,7 @@ kTestUrl, kTestClientId1, kTestUrl2, kTestRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); - EXPECT_EQ(1LL, GetFileCountInDir(temporary_dir_path())); + EXPECT_EQ(1UL, test_util::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); @@ -427,7 +418,7 @@ SavePageWithCallback(kTestUrl2, kTestClientId2, GURL(), kTestRequestOrigin, std::move(archiver), callback.Get()); - EXPECT_EQ(1LL, GetFileCountInDir(temporary_dir_path())); + EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); base::FilePath saved_file_path1 = last_path_created_by_archiver(); @@ -438,7 +429,7 @@ PumpLoop(); // Check that offline_id1 refers to the second save page request. - EXPECT_EQ(2LL, GetFileCountInDir(temporary_dir_path())); + EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); base::FilePath saved_file_path2 = last_path_created_by_archiver(); @@ -530,7 +521,7 @@ OfflinePageItem page2 = page_generator()->CreateItemWithTempFile(); InsertPageIntoStore(page1); InsertPageIntoStore(page2); - EXPECT_EQ(2LL, GetFileCountInDir(temporary_dir_path())); + EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); base::MockCallback<DeletePageCallback> callback; @@ -543,7 +534,7 @@ PumpLoop(); EXPECT_TRUE(observer_delete_page_called()); EXPECT_EQ(last_deleted_page_info().offline_id, page1.offline_id); - EXPECT_EQ(1LL, GetFileCountInDir(temporary_dir_path())); + EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); CheckTaskQueueIdle(); } @@ -556,7 +547,7 @@ OfflinePageItem page2 = page_generator()->CreateItemWithTempFile(); InsertPageIntoStore(page1); InsertPageIntoStore(page2); - EXPECT_EQ(2LL, GetFileCountInDir(temporary_dir_path())); + EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); base::MockCallback<DeletePageCallback> callback; @@ -574,7 +565,7 @@ PumpLoop(); EXPECT_TRUE(observer_delete_page_called()); EXPECT_EQ(last_deleted_page_info().offline_id, page1.offline_id); - EXPECT_EQ(1LL, GetFileCountInDir(temporary_dir_path())); + EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); CheckTaskQueueIdle(); } @@ -738,7 +729,7 @@ OfflinePageItem page2 = page_generator()->CreateItemWithTempFile(); InsertPageIntoStore(page1); InsertPageIntoStore(page2); - EXPECT_EQ(2LL, GetFileCountInDir(temporary_dir_path())); + EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); base::MockCallback<DeletePageCallback> callback; @@ -751,7 +742,7 @@ PumpLoop(); EXPECT_TRUE(observer_delete_page_called()); EXPECT_EQ(last_deleted_page_info().client_id, page1.client_id); - EXPECT_EQ(1LL, GetFileCountInDir(temporary_dir_path())); + EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); CheckTaskQueueIdle(); }
diff --git a/components/offline_pages/core/model/offline_page_test_util.cc b/components/offline_pages/core/model/offline_page_test_util.cc new file mode 100644 index 0000000..5867ac1 --- /dev/null +++ b/components/offline_pages/core/model/offline_page_test_util.cc
@@ -0,0 +1,26 @@ +// 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 "components/offline_pages/core/offline_store_utils.h" + +#include "base/files/file_enumerator.h" + +namespace offline_pages { + +namespace test_util { + +size_t GetFileCountInDirectory(const base::FilePath& directory) { + base::FileEnumerator file_enumerator(directory, false, + base::FileEnumerator::FILES); + size_t count = 0; + for (base::FilePath path = file_enumerator.Next(); !path.empty(); + path = file_enumerator.Next()) { + count++; + } + return count; +} + +} // namespace test_util + +} // 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_util.h new file mode 100644 index 0000000..958e7bb --- /dev/null +++ b/components/offline_pages/core/model/offline_page_test_util.h
@@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_TEST_UTILS_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_TEST_UTILS_H_ + +#include <stdint.h> + +#include <string> + +namespace base { + +class FilePath; + +} // namespace base + +namespace offline_pages { + +// The test_util namespace within offline_pages namespace contains helper +// methods that are common and shared among all Offline Pages tests. +namespace test_util { + +// Get number of files in the given |dir|. +size_t GetFileCountInDirectory(const base::FilePath& directory); + +} // namespace test_util + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_TEST_UTILS_H_
diff --git a/components/offline_pages/core/model/persistent_pages_consistency_check_task.cc b/components/offline_pages/core/model/persistent_pages_consistency_check_task.cc new file mode 100644 index 0000000..629551c --- /dev/null +++ b/components/offline_pages/core/model/persistent_pages_consistency_check_task.cc
@@ -0,0 +1,186 @@ +// 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 "components/offline_pages/core/model/persistent_pages_consistency_check_task.h" + +#include <stdint.h> + +#include <memory> +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_util.h" +#include "base/memory/ptr_util.h" +#include "components/offline_pages/core/client_policy_controller.h" +#include "components/offline_pages/core/offline_page_metadata_store_sql.h" +#include "components/offline_pages/core/offline_page_types.h" +#include "components/offline_pages/core/offline_store_utils.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "sql/transaction.h" + +namespace offline_pages { + +namespace { + +#define OFFLINE_PAGES_TABLE_NAME "offlinepages_v1" + +struct PageInfo { + int64_t offline_id; + base::FilePath file_path; +}; + +std::vector<PageInfo> GetAllPersistentPageInfos( + const std::vector<std::string>& namespaces, + sql::Connection* db) { + std::vector<PageInfo> result; + + const char kSql[] = + "SELECT offline_id, file_path" + " FROM " OFFLINE_PAGES_TABLE_NAME " WHERE client_namespace = ?"; + + for (const auto& persistent_namespace : namespaces) { + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindString(0, persistent_namespace); + while (statement.Step()) + result.push_back( + {statement.ColumnInt64(0), + store_utils::FromDatabaseFilePath(statement.ColumnString(1))}); + } + + return result; +} + +std::set<base::FilePath> GetAllArchives(const base::FilePath& archives_dir) { + std::set<base::FilePath> result; + base::FileEnumerator file_enumerator(archives_dir, false, + base::FileEnumerator::FILES); + for (auto archive_path = file_enumerator.Next(); !archive_path.empty(); + archive_path = file_enumerator.Next()) { + if (file_enumerator.GetInfo().GetName().MatchesExtension( + FILE_PATH_LITERAL(".mhtml"))) { + result.insert(archive_path); + } + } + return result; +} + +bool DeletePagesByOfflineIds(const std::vector<int64_t>& offline_ids, + sql::Connection* db) { + static const char kSql[] = + "DELETE FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id = ?"; + + for (const auto& offline_id : offline_ids) { + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt64(0, offline_id); + if (!statement.Run()) + return false; + } + return true; +} + +bool DeleteFiles(const std::vector<base::FilePath>& file_paths) { + bool result = true; + for (const auto& file_path : file_paths) + result = base::DeleteFile(file_path, false) && result; + return result; +} + +// The method will return false if: +// - An invalid database pointer is provided by the store, which indicates store +// failure, or +// - The transaction of database operations fails at start or commit, or +// - At least one deletion of an offline page entry failed, or +// - At least one file deletion failed +bool CheckConsistencySync(const base::FilePath& archives_dir, + const std::vector<std::string>& namespaces, + sql::Connection* db) { + if (!db) + return false; + + std::vector<int64_t> offline_ids_to_delete; + std::vector<base::FilePath> files_to_delete; + + // One large database transaction that will: + // 1. Gets persistent page infos from the database. + // 2. Decide which pages to delete. + // 3. Delete metadata entries from the database. + sql::Transaction transaction(db); + if (!transaction.Begin()) + return false; + + auto persistent_page_infos = GetAllPersistentPageInfos(namespaces, db); + + for (const auto& page_info : persistent_page_infos) { + // Get pages whose archive files does not exist and delete. + if (!base::PathExists(page_info.file_path)) { + offline_ids_to_delete.push_back(page_info.offline_id); + continue; + } + } + // Try to delete the pages by offline ids collected above. + // If there's any database related errors, the function will return false, + // and the database operations will be rolled back since the transaction will + // not be committed. + if (!DeletePagesByOfflineIds(offline_ids_to_delete, db)) + return false; + + if (!transaction.Commit()) + return false; + + // Delete any files in the persistent archive directory that no longer have + // associated entries in the database. + // TODO(romax): https://crbug.com/786240. + std::set<base::FilePath> archive_paths = GetAllArchives(archives_dir); + for (const auto& archive_path : archive_paths) { + if (std::find_if(persistent_page_infos.begin(), persistent_page_infos.end(), + [&archive_path](const PageInfo& page_info) -> bool { + return page_info.file_path == archive_path; + }) == persistent_page_infos.end()) { + files_to_delete.push_back(archive_path); + } + } + + return DeleteFiles(files_to_delete); +} + +} // namespace + +PersistentPagesConsistencyCheckTask::PersistentPagesConsistencyCheckTask( + OfflinePageMetadataStoreSQL* store, + ClientPolicyController* policy_controller, + const base::FilePath& archives_dir) + : store_(store), + policy_controller_(policy_controller), + archives_dir_(archives_dir), + weak_ptr_factory_(this) {} + +PersistentPagesConsistencyCheckTask::~PersistentPagesConsistencyCheckTask() {} + +void PersistentPagesConsistencyCheckTask::Run() { + std::vector<std::string> namespaces = policy_controller_->GetAllNamespaces(); + std::vector<std::string> persistent_namespace_names; + for (const auto& name_space : namespaces) { + if (!policy_controller_->IsRemovedOnCacheReset(name_space)) + persistent_namespace_names.push_back(name_space); + } + store_->Execute( + base::BindOnce(&CheckConsistencySync, archives_dir_, + persistent_namespace_names), + base::BindOnce( + &PersistentPagesConsistencyCheckTask::OnCheckConsistencyDone, + weak_ptr_factory_.GetWeakPtr())); +} + +void PersistentPagesConsistencyCheckTask::OnCheckConsistencyDone(bool result) { + // TODO(romax): https://crbug.com/772204. Replace the DVLOG with UMA + // collecting. If there's a need, introduce more detailed local enums + // indicating which part failed. + DVLOG(1) << "PersistentPagesConsistencyCheck returns with result: " << result; + TaskComplete(); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/model/persistent_pages_consistency_check_task.h b/components/offline_pages/core/model/persistent_pages_consistency_check_task.h new file mode 100644 index 0000000..358b5721 --- /dev/null +++ b/components/offline_pages/core/model/persistent_pages_consistency_check_task.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 COMPONENTS_OFFINE_PAGES_CORE_MODEL_PERSISTENT_PAGES_CONSISTENCY_CHECK_TASK_H_ +#define COMPONENTS_OFFINE_PAGES_CORE_MODEL_PERSISTENT_PAGES_CONSISTENCY_CHECK_TASK_H_ + +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/offline_pages/core/task.h" + +namespace offline_pages { + +class ClientPolicyController; +class OfflinePageMetadataStoreSQL; + +// Task that does consistency check between persistent pages stored in metadata +// store and persistent archive files. No callback is required for this task. +// The task includes 2 steps: +// 1. Iterate through all persistent entries in the DB, delete the ones that +// do not have associated files. +// 2. Iterate through all MHTML files in the persistent archives directory, +// delete the ones that do not have associated DB entries. +class PersistentPagesConsistencyCheckTask : public Task { + public: + PersistentPagesConsistencyCheckTask(OfflinePageMetadataStoreSQL* store, + ClientPolicyController* policy_controller, + const base::FilePath& archives_dir); + ~PersistentPagesConsistencyCheckTask() override; + + // Task implementation + void Run() override; + + private: + void OnCheckConsistencyDone(bool result); + + // The store for consistency check. Not owned. + OfflinePageMetadataStoreSQL* store_; + // The client policy controller to get policies for persistent namespaces. + // Not owned. + ClientPolicyController* policy_controller_; + base::FilePath archives_dir_; + + base::WeakPtrFactory<PersistentPagesConsistencyCheckTask> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(PersistentPagesConsistencyCheckTask); +}; + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_MODEL_PERSISTENT_PAGES_CONSISTENCY_CHECK_TASK_H_
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 new file mode 100644 index 0000000..619b7de --- /dev/null +++ b/components/offline_pages/core/model/persistent_pages_consistency_check_task_unittest.cc
@@ -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. + +#include "components/offline_pages/core/model/persistent_pages_consistency_check_task.h" + +#include "base/bind.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_util.h" +#include "base/test/test_simple_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.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/offline_page_metadata_store_test_util.h" +#include "components/offline_pages/core/test_task_runner.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace offline_pages { + +namespace { + +int64_t GetFileCountInDir(const base::FilePath& dir) { + base::FileEnumerator file_enumerator(dir, false, base::FileEnumerator::FILES); + int64_t count = 0; + for (base::FilePath path = file_enumerator.Next(); !path.empty(); + path = file_enumerator.Next()) { + count++; + } + return count; +} + +} // namespace + +class PersistentPagesConsistencyCheckTaskTest : public testing::Test { + public: + PersistentPagesConsistencyCheckTaskTest(); + ~PersistentPagesConsistencyCheckTaskTest() override; + + void SetUp() override; + void TearDown() override; + + OfflinePageItem AddPage(const std::string& name_space, + const base::FilePath& archive_dir); + void SetShouldCreateDbEntry(bool should_create_db_entry); + void SetShouldCreateFile(bool should_create_file); + bool IsPageRemovedFromBothPlaces(const OfflinePageItem& page); + + OfflinePageMetadataStoreSQL* store() { return store_test_util_.store(); } + OfflinePageMetadataStoreTestUtil* store_test_util() { + return &store_test_util_; + } + OfflinePageItemGenerator* generator() { return &generator_; } + TestTaskRunner* runner() { return &runner_; } + ClientPolicyController* policy_controller() { + return policy_controller_.get(); + } + + const base::FilePath& persistent_dir() { return persistent_dir_.GetPath(); } + + private: + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + base::ThreadTaskRunnerHandle task_runner_handle_; + + OfflinePageMetadataStoreTestUtil store_test_util_; + OfflinePageItemGenerator generator_; + TestTaskRunner runner_; + std::unique_ptr<ClientPolicyController> policy_controller_; + + base::ScopedTempDir persistent_dir_; + bool should_create_db_entry_; + bool should_create_file_; +}; + +PersistentPagesConsistencyCheckTaskTest:: + PersistentPagesConsistencyCheckTaskTest() + : task_runner_(new base::TestSimpleTaskRunner()), + task_runner_handle_(task_runner_), + store_test_util_(task_runner_), + runner_(task_runner_), + should_create_db_entry_(false), + should_create_file_(false) {} + +PersistentPagesConsistencyCheckTaskTest:: + ~PersistentPagesConsistencyCheckTaskTest() {} + +void PersistentPagesConsistencyCheckTaskTest::SetUp() { + store_test_util_.BuildStoreInMemory(); + ASSERT_TRUE(persistent_dir_.CreateUniqueTempDir()); + policy_controller_ = base::MakeUnique<ClientPolicyController>(); +} + +void PersistentPagesConsistencyCheckTaskTest::TearDown() { + store_test_util_.DeleteStore(); + if (!persistent_dir_.Delete()) + DVLOG(1) << "ScopedTempDir deletion failed."; + task_runner_->RunUntilIdle(); +} + +OfflinePageItem PersistentPagesConsistencyCheckTaskTest::AddPage( + const std::string& name_space, + const base::FilePath& archive_dir) { + generator()->SetNamespace(name_space); + generator()->SetArchiveDirectory(archive_dir); + OfflinePageItem page = generator()->CreateItemWithTempFile(); + if (should_create_db_entry_) + store_test_util()->InsertItem(page); + if (!should_create_file_) + EXPECT_TRUE(base::DeleteFile(page.file_path, false)); + return page; +} + +void PersistentPagesConsistencyCheckTaskTest::SetShouldCreateDbEntry( + bool should_create_db_entry) { + should_create_db_entry_ = should_create_db_entry; +} + +void PersistentPagesConsistencyCheckTaskTest::SetShouldCreateFile( + bool should_create_file) { + should_create_file_ = should_create_file; +} + +bool PersistentPagesConsistencyCheckTaskTest::IsPageRemovedFromBothPlaces( + const OfflinePageItem& page) { + return !base::PathExists(page.file_path) && + !store_test_util()->GetPageByOfflineId(page.offline_id); +} + +// This test is affected by https://crbug.com/725685, which only affects windows +// platform. +#if defined(OS_WIN) +#define MAYBE_TestDeleteFileWithoutDbEntry DISABLED_TestDeleteFileWithoutDbEntry +#else +#define MAYBE_TestDeleteFileWithoutDbEntry TestDeleteFileWithoutDbEntry +#endif +TEST_F(PersistentPagesConsistencyCheckTaskTest, + MAYBE_TestDeleteFileWithoutDbEntry) { + // Only the files without DB entry and in persistent archive directory will + // be deleted. + SetShouldCreateFile(true); + + SetShouldCreateDbEntry(true); + OfflinePageItem page1 = AddPage(kDownloadNamespace, persistent_dir()); + SetShouldCreateDbEntry(false); + OfflinePageItem page2 = AddPage(kDownloadNamespace, persistent_dir()); + + EXPECT_EQ(1LL, store_test_util()->GetPageCount()); + EXPECT_EQ(2LL, GetFileCountInDir(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(1LL, GetFileCountInDir(persistent_dir())); + EXPECT_FALSE(IsPageRemovedFromBothPlaces(page1)); + EXPECT_TRUE(IsPageRemovedFromBothPlaces(page2)); +} + +// This test is affected by https://crbug.com/725685, which only affects windows +// platform. +#if defined(OS_WIN) +#define MAYBE_TestDeleteDbEntryWithoutFile DISABLED_TestDeleteDbEntryWithoutFile +#else +#define MAYBE_TestDeleteDbEntryWithoutFile TestDeleteDbEntryWithoutFile +#endif +TEST_F(PersistentPagesConsistencyCheckTaskTest, + MAYBE_TestDeleteDbEntryWithoutFile) { + // The persistent pages will be deleted from DB if their DB entries exist but + // files are missing. + SetShouldCreateDbEntry(true); + + SetShouldCreateFile(true); + OfflinePageItem page1 = AddPage(kDownloadNamespace, persistent_dir()); + SetShouldCreateFile(false); + OfflinePageItem page2 = AddPage(kDownloadNamespace, persistent_dir()); + + EXPECT_EQ(2LL, store_test_util()->GetPageCount()); + EXPECT_EQ(1LL, GetFileCountInDir(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(1LL, GetFileCountInDir(persistent_dir())); + EXPECT_FALSE(IsPageRemovedFromBothPlaces(page1)); + EXPECT_TRUE(IsPageRemovedFromBothPlaces(page2)); +} + +// This test is affected by https://crbug.com/725685, which only affects windows +// platform. +#if defined(OS_WIN) +#define MAYBE_CombinedTest DISABLED_CombinedTest +#else +#define MAYBE_CombinedTest CombinedTest +#endif +TEST_F(PersistentPagesConsistencyCheckTaskTest, MAYBE_CombinedTest) { + // Adding a bunch of pages with different setups. + // After the consistency check, only page1 will exist. + SetShouldCreateDbEntry(true); + SetShouldCreateFile(true); + OfflinePageItem page1 = AddPage(kDownloadNamespace, persistent_dir()); + SetShouldCreateDbEntry(false); + SetShouldCreateFile(true); + OfflinePageItem page2 = AddPage(kDownloadNamespace, persistent_dir()); + SetShouldCreateDbEntry(true); + SetShouldCreateFile(false); + OfflinePageItem page3 = AddPage(kDownloadNamespace, persistent_dir()); + + EXPECT_EQ(2LL, store_test_util()->GetPageCount()); + EXPECT_EQ(2LL, GetFileCountInDir(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(1LL, GetFileCountInDir(persistent_dir())); + EXPECT_FALSE(IsPageRemovedFromBothPlaces(page1)); + EXPECT_TRUE(IsPageRemovedFromBothPlaces(page2)); + EXPECT_TRUE(IsPageRemovedFromBothPlaces(page3)); +} + +TEST_F(PersistentPagesConsistencyCheckTaskTest, TestKeepingNonMhtmlFile) { + // The persistent pages will be deleted from DB if their DB entries exist but + // files are missing. + SetShouldCreateDbEntry(false); + SetShouldCreateFile(true); + OfflinePageItem page1 = AddPage(kDownloadNamespace, persistent_dir()); + // Create a file with non-mhtml extension. + base::FilePath path; + base::CreateTemporaryFileInDir(persistent_dir(), &path); + base::FilePath mp3_path = path.AddExtension(FILE_PATH_LITERAL("mp3")); + EXPECT_TRUE(base::Move(path, mp3_path)); + + EXPECT_EQ(0LL, store_test_util()->GetPageCount()); + EXPECT_EQ(2LL, GetFileCountInDir(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(1LL, GetFileCountInDir(persistent_dir())); + EXPECT_TRUE(IsPageRemovedFromBothPlaces(page1)); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/model/temporary_pages_consistency_check_task.cc b/components/offline_pages/core/model/temporary_pages_consistency_check_task.cc index 6c622d2..17373528 100644 --- a/components/offline_pages/core/model/temporary_pages_consistency_check_task.cc +++ b/components/offline_pages/core/model/temporary_pages_consistency_check_task.cc
@@ -13,10 +13,10 @@ #include "base/bind.h" #include "base/files/file_enumerator.h" #include "base/files/file_util.h" -#include "base/memory/ptr_util.h" #include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_page_metadata_store_sql.h" #include "components/offline_pages/core/offline_page_types.h" +#include "components/offline_pages/core/offline_store_utils.h" #include "sql/connection.h" #include "sql/statement.h" #include "sql/transaction.h" @@ -25,35 +25,29 @@ namespace { -// The define, struct and the MakePageInfo should be kept in sync on the fields. -#define PAGE_INFO_PROJECTION " offline_id, file_path" struct PageInfo { int64_t offline_id; base::FilePath file_path; }; -PageInfo MakePageInfo(sql::Statement* statement) { - PageInfo page_info; - page_info.offline_id = statement->ColumnInt64(0); - page_info.file_path = - base::FilePath::FromUTF8Unsafe(statement->ColumnString(1)); - return page_info; -} - std::vector<PageInfo> GetAllTemporaryPageInfos( const std::vector<std::string>& temp_namespaces, sql::Connection* db) { std::vector<PageInfo> result; - const char kSql[] = "SELECT" PAGE_INFO_PROJECTION - " FROM offlinepages_v1" - " WHERE client_namespace = ?"; + const char kSql[] = + "SELECT offline_id, file_path" + " FROM offlinepages_v1" + " WHERE client_namespace = ?"; for (const auto& temp_namespace : temp_namespaces) { sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindString(0, temp_namespace); - while (statement.Step()) - result.emplace_back(MakePageInfo(&statement)); + while (statement.Step()) { + result.push_back( + {statement.ColumnInt64(0), + store_utils::FromDatabaseFilePath(statement.ColumnString(1))}); + } } return result; @@ -72,15 +66,15 @@ bool DeletePagesByOfflineIds(const std::vector<int64_t>& offline_ids, sql::Connection* db) { - bool result = true; static const char kSql[] = "DELETE FROM offlinepages_v1 WHERE offline_id = ?"; for (const auto& offline_id : offline_ids) { sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindInt64(0, offline_id); - result = statement.Run() && result; + if (!statement.Run()) + return false; } - return result; + return true; } bool DeleteFiles(const std::vector<base::FilePath>& file_paths) { @@ -97,17 +91,13 @@ // - At least one deletion of an offline page entry failed, or // - At least one file deletion failed bool CheckConsistencySync(const base::FilePath& archives_dir, - const base::FilePath& legacy_archives_dir, const std::vector<std::string>& namespaces, sql::Connection* db) { if (!db) return false; - std::vector<int64_t> offline_ids_to_delete; - std::vector<base::FilePath> files_to_delete; - // One large database transaction that will: - // 1. Gets temporary page infos from the database. + // 1. Get temporary page infos from the database. // 2. Decide which pages to delete. // 3. Delete metadata entries from the database. sql::Transaction transaction(db); @@ -116,13 +106,8 @@ auto temp_page_infos = GetAllTemporaryPageInfos(namespaces, db); + std::vector<int64_t> offline_ids_to_delete; for (const auto& page_info : temp_page_infos) { - // Get pages whose archive files are still in the legacy archives directory. - if (legacy_archives_dir.IsParent(page_info.file_path)) { - offline_ids_to_delete.push_back(page_info.offline_id); - files_to_delete.push_back(page_info.file_path); - continue; - } // Get pages whose archive files does not exist and delete. if (!base::PathExists(page_info.file_path)) { offline_ids_to_delete.push_back(page_info.offline_id); @@ -141,7 +126,9 @@ // Delete any files in the temporary archive directory that no longer have // associated entries in the database. + // TODO(romax): https://crbug.com/786240. std::set<base::FilePath> archive_paths = GetAllArchives(archives_dir); + std::vector<base::FilePath> files_to_delete; for (const auto& archive_path : archive_paths) { if (std::find_if(temp_page_infos.begin(), temp_page_infos.end(), [&archive_path](const PageInfo& page_info) -> bool { @@ -159,22 +146,19 @@ TemporaryPagesConsistencyCheckTask::TemporaryPagesConsistencyCheckTask( OfflinePageMetadataStoreSQL* store, ClientPolicyController* policy_controller, - const base::FilePath& archives_dir, - const base::FilePath& legacy_archives_dir) + const base::FilePath& archives_dir) : store_(store), policy_controller_(policy_controller), archives_dir_(archives_dir), - legacy_archives_dir_(legacy_archives_dir), weak_ptr_factory_(this) {} TemporaryPagesConsistencyCheckTask::~TemporaryPagesConsistencyCheckTask() {} void TemporaryPagesConsistencyCheckTask::Run() { - std::vector<std::string> temp_namespace_names = + std::vector<std::string> temp_namespaces = policy_controller_->GetNamespacesRemovedOnCacheReset(); store_->Execute( - base::BindOnce(&CheckConsistencySync, archives_dir_, legacy_archives_dir_, - temp_namespace_names), + base::BindOnce(&CheckConsistencySync, archives_dir_, temp_namespaces), base::BindOnce( &TemporaryPagesConsistencyCheckTask::OnCheckConsistencyDone, weak_ptr_factory_.GetWeakPtr()));
diff --git a/components/offline_pages/core/model/temporary_pages_consistency_check_task.h b/components/offline_pages/core/model/temporary_pages_consistency_check_task.h index cb362df..680ef6d 100644 --- a/components/offline_pages/core/model/temporary_pages_consistency_check_task.h +++ b/components/offline_pages/core/model/temporary_pages_consistency_check_task.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_OFFINE_PAGES_CORE_MODEL_TEMPORARY_PAGES_CONSISTENCY_CHECK_TASK_H_ -#define COMPONENTS_OFFINE_PAGES_CORE_MODEL_TEMPORARY_PAGES_CONSISTENCY_CHECK_TASK_H_ +#ifndef COMPONENTS_OFFLINE_PAGES_CORE_MODEL_TEMPORARY_PAGES_CONSISTENCY_CHECK_TASK_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_MODEL_TEMPORARY_PAGES_CONSISTENCY_CHECK_TASK_H_ #include "base/files/file_path.h" #include "base/macros.h" @@ -17,25 +17,16 @@ // Task that does consistency check between temporary pages stored in metadata // store and temporary archive files. No callback is required for this task. -// The task includes 3 steps: -// TODO(romax): https://crbug.com/770871. Move step 1 into a separate task -// since it's not supposed to run when Chrome is running. -// 1. Delete all temporary pages and their files if the files are in the -// previous temporary archives directory (the abandoned directory). -// 2. Iterate through all temporary entries in the DB, delete the ones that +// The task includes two steps: +// 1. Iterate through all temporary entries in the DB, delete the ones that // do not have associated files. -// 3. Iterate through all files in the temporary archives directory, delete the +// 2. Iterate through all files in the temporary archives directory, delete the // ones that do not have associated DB entries. -// NOTE: if the temporary archives directory is empty, only step 1 will be -// executed. -// TODO(romax): https://crbug.com/772171. This also needs to be revised during -// P2P sharing implementation. class TemporaryPagesConsistencyCheckTask : public Task { public: TemporaryPagesConsistencyCheckTask(OfflinePageMetadataStoreSQL* store, ClientPolicyController* policy_controller, - const base::FilePath& archives_dir, - const base::FilePath& legacy_archives_dir); + const base::FilePath& archives_dir); ~TemporaryPagesConsistencyCheckTask() override; // Task implementation @@ -49,8 +40,8 @@ // The client policy controller to get policies for temporary namespaces. // Not owned. ClientPolicyController* policy_controller_; + // TODO(romax): Make the name more explicit to show it's for temp pages. base::FilePath archives_dir_; - base::FilePath legacy_archives_dir_; base::WeakPtrFactory<TemporaryPagesConsistencyCheckTask> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(TemporaryPagesConsistencyCheckTask);
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 40d76a7..70b1c49f 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
@@ -13,26 +13,13 @@ #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/offline_page_metadata_store_test_util.h" #include "components/offline_pages/core/test_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { -namespace { - -int64_t GetFileCountInDir(const base::FilePath& dir) { - base::FileEnumerator file_enumerator(dir, false, base::FileEnumerator::FILES); - int64_t count = 0; - for (base::FilePath path = file_enumerator.Next(); !path.empty(); - path = file_enumerator.Next()) { - count++; - } - return count; -} - -} // namespace - class TemporaryPagesConsistencyCheckTaskTest : public testing::Test { public: TemporaryPagesConsistencyCheckTaskTest(); @@ -44,6 +31,7 @@ OfflinePageItem AddPage(const std::string& name_space, const base::FilePath& archive_dir); void SetRemoveDbEntryAndFile(bool remove_db_entry, bool remove_file); + bool IsPageRemoved(const OfflinePageItem& page); OfflinePageMetadataStoreSQL* store() { return store_test_util_.store(); } OfflinePageMetadataStoreTestUtil* store_test_util() { @@ -54,10 +42,6 @@ ClientPolicyController* policy_controller() { return policy_controller_.get(); } - - const base::FilePath& legacy_archives_dir() { - return legacy_archives_dir_.GetPath(); - } const base::FilePath& temporary_dir() { return temporary_dir_.GetPath(); } private: @@ -69,7 +53,6 @@ TestTaskRunner runner_; std::unique_ptr<ClientPolicyController> policy_controller_; - base::ScopedTempDir legacy_archives_dir_; base::ScopedTempDir temporary_dir_; bool remove_db_entry_; bool remove_file_; @@ -88,15 +71,12 @@ void TemporaryPagesConsistencyCheckTaskTest::SetUp() { store_test_util_.BuildStoreInMemory(); - ASSERT_TRUE(legacy_archives_dir_.CreateUniqueTempDir()); ASSERT_TRUE(temporary_dir_.CreateUniqueTempDir()); policy_controller_ = base::MakeUnique<ClientPolicyController>(); } void TemporaryPagesConsistencyCheckTaskTest::TearDown() { store_test_util_.DeleteStore(); - if (!legacy_archives_dir_.Delete()) - DVLOG(1) << "ScopedTempDir deletion failed."; if (!temporary_dir_.Delete()) DVLOG(1) << "ScopedTempDir deletion failed."; task_runner_->RunUntilIdle(); @@ -122,86 +102,67 @@ remove_file_ = remove_file; } +bool TemporaryPagesConsistencyCheckTaskTest::IsPageRemoved( + const OfflinePageItem& page) { + return !base::PathExists(page.file_path) && + !store_test_util()->GetPageByOfflineId(page.offline_id); +} + // This test is affected by https://crbug.com/725685, which only affects windows // platform. #if defined(OS_WIN) -#define MAYBE_TestDeletePageInLegacyArchivesDir \ - DISABLED_TestDeletePageInLegacyArchivesDir +#define MAYBE_TestDeleteFileWithoutDbEntry DISABLED_TestDeleteFileWithoutDbEntry #else -#define MAYBE_TestDeletePageInLegacyArchivesDir \ - TestDeletePageInLegacyArchivesDir +#define MAYBE_TestDeleteFileWithoutDbEntry TestDeleteFileWithoutDbEntry #endif TEST_F(TemporaryPagesConsistencyCheckTaskTest, - MAYBE_TestDeletePageInLegacyArchivesDir) { - // The temporary pages in legacy archives directory will be deleted from both - // DB and disk. + MAYBE_TestDeleteFileWithoutDbEntry) { + // Only the file without DB entry and in temporary directory will be deleted. SetRemoveDbEntryAndFile(false, false); - OfflinePageItem page1 = AddPage(kLastNNamespace, legacy_archives_dir()); - OfflinePageItem page2 = AddPage(kDownloadNamespace, legacy_archives_dir()); - OfflinePageItem page3 = AddPage(kLastNNamespace, temporary_dir()); - - EXPECT_EQ(3LL, store_test_util()->GetPageCount()); - EXPECT_EQ(2LL, GetFileCountInDir(legacy_archives_dir())); - - auto task = base::MakeUnique<TemporaryPagesConsistencyCheckTask>( - store(), policy_controller(), temporary_dir(), legacy_archives_dir()); - runner()->RunTask(std::move(task)); - - EXPECT_EQ(2LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1LL, GetFileCountInDir(legacy_archives_dir())); - EXPECT_EQ(1LL, GetFileCountInDir(temporary_dir())); - EXPECT_FALSE(store_test_util()->GetPageByOfflineId(page1.offline_id)); -} - -TEST_F(TemporaryPagesConsistencyCheckTaskTest, TestDeleteFileWithoutDbEntry) { - // Since the files in legacy archives directory are missing DB entries, - // there's no way to know if the pages were temporary or persistent. So - // they'll not be removed, only the file without DB entry and in temporary - // directory will be deleted. + OfflinePageItem page1 = AddPage(kLastNNamespace, temporary_dir()); SetRemoveDbEntryAndFile(true, false); - OfflinePageItem page1 = AddPage(kLastNNamespace, legacy_archives_dir()); - OfflinePageItem page2 = AddPage(kDownloadNamespace, legacy_archives_dir()); - OfflinePageItem page3 = AddPage(kLastNNamespace, temporary_dir()); + OfflinePageItem page2 = AddPage(kLastNNamespace, temporary_dir()); - EXPECT_EQ(0LL, store_test_util()->GetPageCount()); - EXPECT_EQ(2LL, GetFileCountInDir(legacy_archives_dir())); - EXPECT_EQ(1LL, GetFileCountInDir(temporary_dir())); + EXPECT_EQ(1LL, store_test_util()->GetPageCount()); + EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir())); auto task = base::MakeUnique<TemporaryPagesConsistencyCheckTask>( - store(), policy_controller(), temporary_dir(), legacy_archives_dir()); - runner()->RunTask(std::move(task)); - - EXPECT_EQ(0LL, store_test_util()->GetPageCount()); - EXPECT_EQ(2LL, GetFileCountInDir(legacy_archives_dir())); - EXPECT_EQ(0LL, GetFileCountInDir(temporary_dir())); - EXPECT_TRUE(base::PathExists(page2.file_path)); -} - -TEST_F(TemporaryPagesConsistencyCheckTaskTest, TestDeleteDBEntryWithoutFile) { - // The temporary pages will be deleted from DB if their DB entries exist but - // files are missing. - // In this test case, page1 and page3 will be deleted from DB. page2 will be - // left behind in DB since it's a persistent page. - SetRemoveDbEntryAndFile(false, true); - OfflinePageItem page1 = AddPage(kLastNNamespace, legacy_archives_dir()); - OfflinePageItem page2 = AddPage(kDownloadNamespace, legacy_archives_dir()); - OfflinePageItem page3 = AddPage(kLastNNamespace, temporary_dir()); - - EXPECT_EQ(3LL, store_test_util()->GetPageCount()); - EXPECT_EQ(0LL, GetFileCountInDir(legacy_archives_dir())); - EXPECT_EQ(0LL, GetFileCountInDir(temporary_dir())); - - auto task = base::MakeUnique<TemporaryPagesConsistencyCheckTask>( - store(), policy_controller(), temporary_dir(), legacy_archives_dir()); + store(), policy_controller(), temporary_dir()); runner()->RunTask(std::move(task)); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); - EXPECT_EQ(0LL, GetFileCountInDir(legacy_archives_dir())); - EXPECT_EQ(0LL, GetFileCountInDir(temporary_dir())); - EXPECT_FALSE(store_test_util()->GetPageByOfflineId(page1.offline_id)); - EXPECT_EQ(page2.file_path, - store_test_util()->GetPageByOfflineId(page2.offline_id)->file_path); - EXPECT_FALSE(store_test_util()->GetPageByOfflineId(page3.offline_id)); + EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir())); + EXPECT_FALSE(IsPageRemoved(page1)); + EXPECT_TRUE(IsPageRemoved(page2)); +} + +// This test is affected by https://crbug.com/725685, which only affects windows +// platform. +#if defined(OS_WIN) +#define MAYBE_TestDeleteDbEntryWithoutFile DISABLED_TestDeleteDbEntryWithoutFile +#else +#define MAYBE_TestDeleteDbEntryWithoutFile TestDeleteDbEntryWithoutFile +#endif +TEST_F(TemporaryPagesConsistencyCheckTaskTest, + MAYBE_TestDeleteDbEntryWithoutFile) { + // The temporary pages will be deleted from DB if their DB entries exist but + // files are missing. + SetRemoveDbEntryAndFile(false, false); + OfflinePageItem page1 = AddPage(kLastNNamespace, temporary_dir()); + SetRemoveDbEntryAndFile(false, true); + OfflinePageItem page2 = AddPage(kLastNNamespace, temporary_dir()); + + EXPECT_EQ(2LL, store_test_util()->GetPageCount()); + EXPECT_EQ(1UL, test_util::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_FALSE(IsPageRemoved(page1)); + EXPECT_TRUE(IsPageRemoved(page2)); } // This test is affected by https://crbug.com/725685, which only affects windows @@ -213,32 +174,26 @@ #endif TEST_F(TemporaryPagesConsistencyCheckTaskTest, MAYBE_CombinedTest) { // Adding a bunch of pages with different setups. - // After the consistency check, DB will contain page2, page3, page8. - // The files of page2, page3, page4, page5, page9 will still exist. + // After the consistency check, only page1 will exist. SetRemoveDbEntryAndFile(false, false); - OfflinePageItem page1 = AddPage(kLastNNamespace, legacy_archives_dir()); - OfflinePageItem page2 = AddPage(kDownloadNamespace, legacy_archives_dir()); - OfflinePageItem page3 = AddPage(kLastNNamespace, temporary_dir()); + OfflinePageItem page1 = AddPage(kLastNNamespace, temporary_dir()); SetRemoveDbEntryAndFile(true, false); - OfflinePageItem page4 = AddPage(kLastNNamespace, legacy_archives_dir()); - OfflinePageItem page5 = AddPage(kDownloadNamespace, legacy_archives_dir()); - OfflinePageItem page6 = AddPage(kLastNNamespace, temporary_dir()); + OfflinePageItem page2 = AddPage(kLastNNamespace, temporary_dir()); SetRemoveDbEntryAndFile(false, true); - OfflinePageItem page7 = AddPage(kLastNNamespace, legacy_archives_dir()); - OfflinePageItem page8 = AddPage(kDownloadNamespace, legacy_archives_dir()); - OfflinePageItem page9 = AddPage(kLastNNamespace, temporary_dir()); + OfflinePageItem page3 = AddPage(kLastNNamespace, temporary_dir()); - EXPECT_EQ(6LL, store_test_util()->GetPageCount()); - EXPECT_EQ(4LL, GetFileCountInDir(legacy_archives_dir())); - EXPECT_EQ(2LL, GetFileCountInDir(temporary_dir())); + EXPECT_EQ(2LL, store_test_util()->GetPageCount()); + EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir())); auto task = base::MakeUnique<TemporaryPagesConsistencyCheckTask>( - store(), policy_controller(), temporary_dir(), legacy_archives_dir()); + store(), policy_controller(), temporary_dir()); runner()->RunTask(std::move(task)); - EXPECT_EQ(3LL, store_test_util()->GetPageCount()); - EXPECT_EQ(3LL, GetFileCountInDir(legacy_archives_dir())); - EXPECT_EQ(1LL, GetFileCountInDir(temporary_dir())); + EXPECT_EQ(1LL, store_test_util()->GetPageCount()); + EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir())); + EXPECT_FALSE(IsPageRemoved(page1)); + EXPECT_TRUE(IsPageRemoved(page2)); + EXPECT_TRUE(IsPageRemoved(page3)); } } // namespace offline_pages
diff --git a/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.cc b/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.cc index dbc15a0..a4501adc 100644 --- a/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.cc +++ b/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" +#include "base/strings/string_number_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/offline_page_model.h"
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn index 669c1885..7529b0e 100644 --- a/components/omnibox/browser/BUILD.gn +++ b/components/omnibox/browser/BUILD.gn
@@ -279,6 +279,7 @@ "bookmark_provider_unittest.cc", "builtin_provider_unittest.cc", "clipboard_url_provider_unittest.cc", + "history_provider_unittest.cc", "history_quick_provider_unittest.cc", "history_url_provider_unittest.cc", "in_memory_url_index_types_unittest.cc",
diff --git a/components/omnibox/browser/autocomplete_match_type.cc b/components/omnibox/browser/autocomplete_match_type.cc index 53ae042..4915017a 100644 --- a/components/omnibox/browser/autocomplete_match_type.cc +++ b/components/omnibox/browser/autocomplete_match_type.cc
@@ -4,6 +4,7 @@ #include "components/omnibox/browser/autocomplete_match_type.h" +#include "base/logging.h" #include "base/macros.h" #include "components/strings/grit/components_strings.h" #include "ui/base/l10n/l10n_util.h" @@ -45,7 +46,8 @@ base::string16 AutocompleteMatchType::ToAccessibilityLabel( AutocompleteMatchType::Type type, - const base::string16& descriptive_text) { + const base::string16& match_text, + const base::string16& additional_descriptive_text) { // Types with a message ID of zero get |text| returned as-is. static constexpr int message_ids[] = { 0, // URL_WHAT_YOU_TYPED @@ -80,11 +82,30 @@ 0, // VOICE_SUGGEST 0, // PHYSICAL_WEB 0, // PHYSICAL_WEB_OVERFLOW - 0, // TAB_SEARCH + IDS_ACC_AUTOCOMPLETE_HISTORY, // TAB_SEARCH }; static_assert(arraysize(message_ids) == AutocompleteMatchType::NUM_TYPES, "message_ids must have NUM_TYPES elements"); - if (!message_ids[type]) - return descriptive_text; - return l10n_util::GetStringFUTF16(message_ids[type], descriptive_text); + int message = message_ids[type]; + if (!message) + return match_text; + + switch (message) { + case IDS_ACC_AUTOCOMPLETE_SEARCH_HISTORY: + case IDS_ACC_AUTOCOMPLETE_SEARCH: + case IDS_ACC_AUTOCOMPLETE_SUGGESTED_SEARCH: + // Additional descriptive text NOT relevant. + return l10n_util::GetStringFUTF16(message_ids[type], match_text); + + case IDS_ACC_AUTOCOMPLETE_HISTORY: + case IDS_ACC_AUTOCOMPLETE_BOOKMARK: + case IDS_ACC_AUTOCOMPLETE_CLIPBOARD: + // Additional descriptive text relevant. + return l10n_util::GetStringFUTF16(message_ids[type], match_text, + additional_descriptive_text); + default: + break; + } + NOTREACHED(); + return match_text; }
diff --git a/components/omnibox/browser/autocomplete_match_type.h b/components/omnibox/browser/autocomplete_match_type.h index da088dc..6f60d677 100644 --- a/components/omnibox/browser/autocomplete_match_type.h +++ b/components/omnibox/browser/autocomplete_match_type.h
@@ -67,11 +67,13 @@ static std::string ToString(AutocompleteMatchType::Type type); // Returns the accessibility label for an AutocompleteMatch of type |type| - // whose text is |descriptive_text|. The accessibility label describes the + // whose text is |match_text| and which may have friendly descriptive text in + // |additional_descriptive_text_|. The accessibility label describes the // match for use in a screenreader or other assistive technology. static base::string16 ToAccessibilityLabel( AutocompleteMatchType::Type type, - const base::string16& descriptive_text); + const base::string16& match_text, + const base::string16& additional_descriptive_text); }; #endif // COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_MATCH_TYPE_H_
diff --git a/components/omnibox/browser/autocomplete_match_type_unittest.cc b/components/omnibox/browser/autocomplete_match_type_unittest.cc index c53036b..afc5914 100644 --- a/components/omnibox/browser/autocomplete_match_type_unittest.cc +++ b/components/omnibox/browser/autocomplete_match_type_unittest.cc
@@ -10,9 +10,13 @@ TEST(AutocompleteMatchTypeTest, AccessibilityLabels) { const base::string16& kTestUrl = base::UTF8ToUTF16("https://www.chromium.org"); + const base::string16& kTestTitle = base::UTF8ToUTF16("The Chromium Projects"); + EXPECT_EQ(kTestUrl, AutocompleteMatchType::ToAccessibilityLabel( - AutocompleteMatchType::URL_WHAT_YOU_TYPED, kTestUrl)); - EXPECT_EQ(base::UTF8ToUTF16("URL from history: ") + kTestUrl, + AutocompleteMatchType::URL_WHAT_YOU_TYPED, kTestUrl, + kTestTitle)); + EXPECT_EQ(kTestTitle + base::UTF8ToUTF16(" ") + kTestUrl + + base::UTF8ToUTF16(" location from history"), AutocompleteMatchType::ToAccessibilityLabel( - AutocompleteMatchType::HISTORY_URL, kTestUrl)); + AutocompleteMatchType::HISTORY_URL, kTestUrl, kTestTitle)); }
diff --git a/components/omnibox/browser/fake_autocomplete_provider_client.cc b/components/omnibox/browser/fake_autocomplete_provider_client.cc index 2e25c29..999a1bc 100644 --- a/components/omnibox/browser/fake_autocomplete_provider_client.cc +++ b/components/omnibox/browser/fake_autocomplete_provider_client.cc
@@ -5,6 +5,7 @@ #include "components/omnibox/browser/fake_autocomplete_provider_client.h" #include "base/memory/ptr_util.h" +#include "base/run_loop.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/test/test_bookmark_client.h" #include "components/history/core/browser/history_service.h" @@ -12,7 +13,8 @@ #include "components/omnibox/browser/in_memory_url_index.h" #include "components/omnibox/browser/in_memory_url_index_test_util.h" -FakeAutocompleteProviderClient::FakeAutocompleteProviderClient() { +FakeAutocompleteProviderClient::FakeAutocompleteProviderClient() + : is_tab_open_with_url_(false) { bookmark_model_ = bookmarks::TestBookmarkClient::CreateModel(); CHECK(history_dir_.CreateUniqueTempDir()); @@ -25,7 +27,16 @@ in_memory_url_index_->Init(); } -FakeAutocompleteProviderClient::~FakeAutocompleteProviderClient() = default; +FakeAutocompleteProviderClient::~FakeAutocompleteProviderClient() { + // The InMemoryURLIndex must be explicitly shut down or it will DCHECK() in + // its destructor. + GetInMemoryURLIndex()->Shutdown(); + set_in_memory_url_index(nullptr); + // History index rebuild task is created from main thread during SetUp, + // performed on DB thread and must be deleted on main thread. + // Run main loop to process delete task, to prevent leaks. + base::RunLoop().RunUntilIdle(); +} const AutocompleteSchemeClassifier& FakeAutocompleteProviderClient::GetSchemeClassifier() const { @@ -48,3 +59,7 @@ InMemoryURLIndex* FakeAutocompleteProviderClient::GetInMemoryURLIndex() { return in_memory_url_index_.get(); } + +bool FakeAutocompleteProviderClient::IsTabOpenWithURL(const GURL& url) { + return is_tab_open_with_url_; +}
diff --git a/components/omnibox/browser/fake_autocomplete_provider_client.h b/components/omnibox/browser/fake_autocomplete_provider_client.h index d574b21..a9aa057 100644 --- a/components/omnibox/browser/fake_autocomplete_provider_client.h +++ b/components/omnibox/browser/fake_autocomplete_provider_client.h
@@ -9,6 +9,7 @@ #include <utility> #include "base/files/scoped_temp_dir.h" +#include "components/omnibox/browser/in_memory_url_index.h" #include "components/omnibox/browser/mock_autocomplete_provider_client.h" #include "components/omnibox/browser/test_scheme_classifier.h" @@ -38,6 +39,11 @@ in_memory_url_index_ = std::move(index); } + bool IsTabOpenWithURL(const GURL& url) override; + void set_is_tab_open_with_url(bool is_open) { + is_tab_open_with_url_ = is_open; + } + private: base::ScopedTempDir history_dir_; std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_; @@ -45,6 +51,7 @@ SearchTermsData search_terms_data_; std::unique_ptr<InMemoryURLIndex> in_memory_url_index_; std::unique_ptr<history::HistoryService> history_service_; + bool is_tab_open_with_url_; DISALLOW_COPY_AND_ASSIGN(FakeAutocompleteProviderClient); };
diff --git a/components/omnibox/browser/history_provider.cc b/components/omnibox/browser/history_provider.cc index 945682e..527eac0 100644 --- a/components/omnibox/browser/history_provider.cc +++ b/components/omnibox/browser/history_provider.cc
@@ -112,7 +112,7 @@ match.type = AutocompleteMatchType::TAB_SEARCH; const base::string16 switch_tab_message = l10n_util::GetStringUTF16(IDS_OMNIBOX_TAB_SUGGEST_HINT) + - base::UTF8ToUTF16(" - "); + base::UTF8ToUTF16(match.description.empty() ? "" : " - "); match.description = switch_tab_message + match.description; // Add classfication for the prefix. if (match.description_class.empty()) {
diff --git a/components/omnibox/browser/history_provider.h b/components/omnibox/browser/history_provider.h index 8e8b654..2527ac1 100644 --- a/components/omnibox/browser/history_provider.h +++ b/components/omnibox/browser/history_provider.h
@@ -50,6 +50,7 @@ void ConvertOpenTabMatches(); private: + FRIEND_TEST_ALL_PREFIXES(HistoryProviderTest, ConvertsOpenTabsCorrectly); AutocompleteProviderClient* client_; DISALLOW_COPY_AND_ASSIGN(HistoryProvider);
diff --git a/components/omnibox/browser/history_provider_unittest.cc b/components/omnibox/browser/history_provider_unittest.cc new file mode 100644 index 0000000..f542a0a --- /dev/null +++ b/components/omnibox/browser/history_provider_unittest.cc
@@ -0,0 +1,81 @@ +// 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 <memory> + +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" +#include "components/omnibox/browser/fake_autocomplete_provider_client.h" +#include "components/omnibox/browser/history_provider.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class TestHistoryProvider : public HistoryProvider { + public: + explicit TestHistoryProvider(AutocompleteProviderClient* client) + : HistoryProvider(AutocompleteProvider::TYPE_HISTORY_QUICK, client) {} + + void Start(const AutocompleteInput& input, bool minimal_changes) override; + + private: + ~TestHistoryProvider() override; + + DISALLOW_COPY_AND_ASSIGN(TestHistoryProvider); +}; + +void TestHistoryProvider::Start(const AutocompleteInput& input, + bool minimal_changes) {} + +TestHistoryProvider::~TestHistoryProvider() {} + +class HistoryProviderTest : public testing::Test { + public: + HistoryProviderTest() = default; + + protected: + void SetUp() override; + void TearDown() override; + + FakeAutocompleteProviderClient* client() { return &(*client_); } + HistoryProvider* provider() { return &(*provider_); } + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + std::unique_ptr<FakeAutocompleteProviderClient> client_; + scoped_refptr<TestHistoryProvider> provider_; + + DISALLOW_COPY_AND_ASSIGN(HistoryProviderTest); +}; + +void HistoryProviderTest::SetUp() { + client_ = std::make_unique<FakeAutocompleteProviderClient>(); + provider_ = new TestHistoryProvider(client_.get()); +} + +void HistoryProviderTest::TearDown() { + provider_ = nullptr; + client_.reset(); +} + +} // namespace + +TEST_F(HistoryProviderTest, ConvertsOpenTabsCorrectly) { + AutocompleteMatch match; + match.contents = base::UTF8ToUTF16("some-url.com"); + provider()->matches_.push_back(match); + match.contents = base::UTF8ToUTF16("some-other-url.com"); + match.description = base::UTF8ToUTF16("Some Other Site"); + provider()->matches_.push_back(match); + + // Have IsTabOpenWithURL() return true. + client()->set_is_tab_open_with_url(true); + + provider()->ConvertOpenTabMatches(); + + EXPECT_EQ(base::UTF8ToUTF16("Switch to tab"), + provider()->matches_[0].description); + EXPECT_EQ(base::UTF8ToUTF16("Switch to tab - Some Other Site"), + provider()->matches_[1].description); +}
diff --git a/components/omnibox/browser/history_quick_provider_performance_unittest.cc b/components/omnibox/browser/history_quick_provider_performance_unittest.cc index 12bc421..7e2ff77 100644 --- a/components/omnibox/browser/history_quick_provider_performance_unittest.cc +++ b/components/omnibox/browser/history_quick_provider_performance_unittest.cc
@@ -109,21 +109,14 @@ void HQPPerfTestOnePopularURL::SetUp() { if (base::ThreadTicks::IsSupported()) base::ThreadTicks::WaitUntilInitialized(); - client_.reset(new FakeAutocompleteProviderClient()); + client_ = std::make_unique<FakeAutocompleteProviderClient>(); ASSERT_TRUE(client_->GetHistoryService()); ASSERT_NO_FATAL_FAILURE(PrepareData()); } void HQPPerfTestOnePopularURL::TearDown() { provider_ = nullptr; - // The InMemoryURLIndex must be explicitly shut down or it will DCHECK() in - // its destructor. - client_->GetInMemoryURLIndex()->Shutdown(); - client_->set_in_memory_url_index(nullptr); - // History index rebuild task is created from main thread during SetUp, - // performed on DB thread and must be deleted on main thread. - // Run main loop to process delete task, to prevent leaks. - base::RunLoop().RunUntilIdle(); + client_.reset(); } void HQPPerfTestOnePopularURL::PrepareData() {
diff --git a/components/omnibox/browser/history_quick_provider_unittest.cc b/components/omnibox/browser/history_quick_provider_unittest.cc index b03f13e6..4b605827 100644 --- a/components/omnibox/browser/history_quick_provider_unittest.cc +++ b/components/omnibox/browser/history_quick_provider_unittest.cc
@@ -197,7 +197,7 @@ }; void HistoryQuickProviderTest::SetUp() { - client_.reset(new FakeAutocompleteProviderClient()); + client_ = std::make_unique<FakeAutocompleteProviderClient>(); ASSERT_TRUE(client_->GetHistoryService()); ASSERT_NO_FATAL_FAILURE(FillData()); @@ -218,14 +218,7 @@ void HistoryQuickProviderTest::TearDown() { provider_ = nullptr; - // The InMemoryURLIndex must be explicitly shut down or it will DCHECK() in - // its destructor. - client_->GetInMemoryURLIndex()->Shutdown(); - client_->set_in_memory_url_index(nullptr); - // History index rebuild task is created from main thread during SetUp, - // performed on DB thread and must be deleted on main thread. - // Run main loop to process delete task, to prevent leaks. - base::RunLoop().RunUntilIdle(); + client_.reset(); } std::vector<HistoryQuickProviderTest::TestURLInfo>
diff --git a/components/omnibox/browser/history_url_provider_unittest.cc b/components/omnibox/browser/history_url_provider_unittest.cc index a07a29a1..e3984f5 100644 --- a/components/omnibox/browser/history_url_provider_unittest.cc +++ b/components/omnibox/browser/history_url_provider_unittest.cc
@@ -171,9 +171,10 @@ {"https://www.wytih/file", "What you typed in history www file", 7, 7, 80}, }; -class FakeAutocompleteProviderClient : public MockAutocompleteProviderClient { +class AnonFakeAutocompleteProviderClient + : public MockAutocompleteProviderClient { public: - explicit FakeAutocompleteProviderClient(bool create_history_db) { + explicit AnonFakeAutocompleteProviderClient(bool create_history_db) { set_template_url_service(base::MakeUnique<TemplateURLService>(nullptr, 0)); if (history_dir_.CreateUniqueTempDir()) { history_service_ = history::CreateHistoryService(history_dir_.GetPath(), @@ -199,7 +200,7 @@ base::ScopedTempDir history_dir_; std::unique_ptr<history::HistoryService> history_service_; - DISALLOW_COPY_AND_ASSIGN(FakeAutocompleteProviderClient); + DISALLOW_COPY_AND_ASSIGN(AnonFakeAutocompleteProviderClient); }; } // namespace @@ -266,7 +267,7 @@ base::MessageLoop message_loop_; ACMatches matches_; - std::unique_ptr<FakeAutocompleteProviderClient> client_; + std::unique_ptr<AnonFakeAutocompleteProviderClient> client_; scoped_refptr<HistoryURLProvider> autocomplete_; // Should the matches be sorted and duplicates removed? bool sort_matches_; @@ -299,7 +300,8 @@ } bool HistoryURLProviderTest::SetUpImpl(bool create_history_db) { - client_.reset(new FakeAutocompleteProviderClient(create_history_db)); + client_ = + std::make_unique<AnonFakeAutocompleteProviderClient>(create_history_db); if (!client_->GetHistoryService()) return false; autocomplete_ = new HistoryURLProvider(client_.get(), this);
diff --git a/components/omnibox/browser/in_memory_url_index.h b/components/omnibox/browser/in_memory_url_index.h index 426c9c7..d62ba3d 100644 --- a/components/omnibox/browser/in_memory_url_index.h +++ b/components/omnibox/browser/in_memory_url_index.h
@@ -28,6 +28,7 @@ #include "components/omnibox/browser/scored_history_match.h" #include "components/search_engines/template_url_service.h" +class FakeAutocompleteProviderClient; class HistoryQuickProviderTest; namespace base { @@ -142,6 +143,7 @@ } private: + friend class ::FakeAutocompleteProviderClient; friend class ::HistoryQuickProviderTest; friend class history::HQPPerfTestOnePopularURL; friend class InMemoryURLIndexTest;
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc index b9d7dd6..20d1d421 100644 --- a/components/omnibox/browser/omnibox_edit_model.cc +++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -765,11 +765,10 @@ const AutocompleteMatch& match = CurrentMatch(nullptr); original_url_ = match.destination_url; view_->OnTemporaryTextMaybeChanged(MaybeStripKeyword(match.fill_into_edit), - match.type, save_original_selection, - true); + match, save_original_selection, true); } else { const AutocompleteMatch& match = CurrentMatch(nullptr); - view_->OnTemporaryTextMaybeChanged(user_text_, match.type, false, true); + view_->OnTemporaryTextMaybeChanged(user_text_, match, false, true); } base::RecordAction(base::UserMetricsAction("AcceptedKeywordHint")); @@ -1066,7 +1065,7 @@ // right answer here :( } const AutocompleteMatch& match = CurrentMatch(nullptr); - view_->OnTemporaryTextMaybeChanged(MaybeStripKeyword(text), match.type, + view_->OnTemporaryTextMaybeChanged(MaybeStripKeyword(text), match, save_original_selection, true); return; }
diff --git a/components/omnibox/browser/omnibox_edit_unittest.cc b/components/omnibox/browser/omnibox_edit_unittest.cc index a97a427..49326c3 100644 --- a/components/omnibox/browser/omnibox_edit_unittest.cc +++ b/components/omnibox/browser/omnibox_edit_unittest.cc
@@ -63,7 +63,7 @@ void SetFocus() override {} void ApplyCaretVisibility() override {} void OnTemporaryTextMaybeChanged(const base::string16& display_text, - AutocompleteMatch::Type match_type, + const AutocompleteMatch& match, bool save_original_selection, bool notify_text_changed) override { text_ = display_text;
diff --git a/components/omnibox/browser/omnibox_view.h b/components/omnibox/browser/omnibox_view.h index 1b67ba5..dfa4012 100644 --- a/components/omnibox/browser/omnibox_view.h +++ b/components/omnibox/browser/omnibox_view.h
@@ -152,7 +152,7 @@ // existing selection. |notify_text_changed| is true if the model should be // notified of the change. virtual void OnTemporaryTextMaybeChanged(const base::string16& display_text, - AutocompleteMatch::Type match_type, + const AutocompleteMatch& match, bool save_original_selection, bool notify_text_changed) = 0;
diff --git a/components/omnibox/browser/shortcuts_provider_unittest.cc b/components/omnibox/browser/shortcuts_provider_unittest.cc index 9d0814f..43cfbbc 100644 --- a/components/omnibox/browser/shortcuts_provider_unittest.cc +++ b/components/omnibox/browser/shortcuts_provider_unittest.cc
@@ -179,10 +179,10 @@ AutocompleteMatchType::HISTORY_URL, "", 1, 100 }, }; -class FakeAutocompleteProviderClient +class AnonFakeAutocompleteProviderClient : public testing::NiceMock<MockAutocompleteProviderClient> { public: - FakeAutocompleteProviderClient() : pool_owner_(3, "Background Pool") { + AnonFakeAutocompleteProviderClient() : pool_owner_(3, "Background Pool") { set_template_url_service(base::MakeUnique<TemplateURLService>(nullptr, 0)); if (history_dir_.CreateUniqueTempDir()) { history_service_ = @@ -213,7 +213,7 @@ std::unique_ptr<history::HistoryService> history_service_; scoped_refptr<ShortcutsBackend> shortcuts_backend_; - DISALLOW_COPY_AND_ASSIGN(FakeAutocompleteProviderClient); + DISALLOW_COPY_AND_ASSIGN(AnonFakeAutocompleteProviderClient); }; } // namespace @@ -266,14 +266,14 @@ int max_relevance); base::test::ScopedTaskEnvironment scoped_task_environment_; - std::unique_ptr<FakeAutocompleteProviderClient> client_; + std::unique_ptr<AnonFakeAutocompleteProviderClient> client_; scoped_refptr<ShortcutsProvider> provider_; }; ShortcutsProviderTest::ShortcutsProviderTest() {} void ShortcutsProviderTest::SetUp() { - client_.reset(new FakeAutocompleteProviderClient()); + client_ = std::make_unique<AnonFakeAutocompleteProviderClient>(); ASSERT_TRUE(client_->GetShortcutsBackend()); provider_ = new ShortcutsProvider(client_.get());
diff --git a/components/omnibox_strings.grdp b/components/omnibox_strings.grdp index 68c01eb..1ae33d8 100644 --- a/components/omnibox_strings.grdp +++ b/components/omnibox_strings.grdp
@@ -57,21 +57,21 @@ These are parameterized on the text being completed into the omnibox. --> <message name="IDS_ACC_AUTOCOMPLETE_HISTORY" desc="Text for screenreaders describing a URL from history."> - URL from history: <ph name="TEXT">$1<ex>https://www.chromium.org</ex></ph> + <ph name="LOCATION_TITLE">$2<ex>The Chromium Projects</ex></ph> <ph name="SHORT_URL">$1<ex>www.chromium.org</ex> location from history</ph> </message> <message name="IDS_ACC_AUTOCOMPLETE_SEARCH_HISTORY" desc="Text for screenreaders describing a search from history."> - Search from history for <ph name="TEXT">$1<ex>dogs</ex></ph> + <ph name="TEXT">$1<ex>dogs</ex> search from history</ph> </message> <message name="IDS_ACC_AUTOCOMPLETE_SEARCH" desc="Text for screenreaders describing a generic search."> - Search for <ph name="TEXT">$1<ex>dogs</ex></ph> + <ph name="TEXT">$1<ex>dogs</ex> search</ph> </message> <message name="IDS_ACC_AUTOCOMPLETE_SUGGESTED_SEARCH" desc="Text for screenreaders describing a suggested search."> - Suggested search for <ph name="TEXT">$1<ex>dogs</ex></ph> + <ph name="TEXT">$1<ex>dogs</ex> search suggestion</ph> </message> <message name="IDS_ACC_AUTOCOMPLETE_BOOKMARK" desc="Text for screenreaders describing a URL from a bookmark."> - URL from bookmark: <ph name="TEXT">$1<ex>https://www.chromium.org</ex></ph> + <ph name="LOCATION_TITLE">$2<ex>The Chromium Projects</ex></ph> <ph name="SHORT_URL">$1<ex>www.chromium.org</ex> bookmark</ph> </message> <message name="IDS_ACC_AUTOCOMPLETE_CLIPBOARD" desc="Text for screenreaders describing a URL from a clipboard."> - URL from clipboard: <ph name="TEXT">$1<ex>https://www.chromium.org</ex></ph> + <ph name="LOCATION_TITLE">$2<ex>The Chromium Projects</ex></ph> <ph name="SHORT_URL">$1<ex>www.chromium.org</ex> location from clipboard</ph> </message> </grit-part>
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index f6792e2..f62e366 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -935,12 +935,6 @@ return true; } -#if defined(OS_MACOSX) -bool PrintRenderFrameHelper::Delegate::UseSingleMetafile() { - return false; -} -#endif - PrintRenderFrameHelper::PrintRenderFrameHelper( content::RenderFrame* render_frame, std::unique_ptr<Delegate> delegate)
diff --git a/components/printing/renderer/print_render_frame_helper.h b/components/printing/renderer/print_render_frame_helper.h index a9fe8cb7..24674f95 100644 --- a/components/printing/renderer/print_render_frame_helper.h +++ b/components/printing/renderer/print_render_frame_helper.h
@@ -110,15 +110,6 @@ // Returns true if printing is overridden and the default behavior should be // skipped for |frame|. virtual bool OverridePrint(blink::WebLocalFrame* frame) = 0; - -#if defined(OS_MACOSX) - // If true, all the printed pages are returned in the first - // PrintHostMsg_DidPrintPage metafile, like on Linux and Windows. - // NOTE: PrintHostMsg_DidPrintPage messages for all pages contain the same - // page and content area, which may lead to bug when these two parameters - // are different per page. - virtual bool UseSingleMetafile(); -#endif }; PrintRenderFrameHelper(content::RenderFrame* render_frame, @@ -284,6 +275,7 @@ #endif // BUILDFLAG(ENABLE_BASIC_PRINTING) // Page Printing / Rendering ------------------------------------------------ + #if BUILDFLAG(ENABLE_BASIC_PRINTING) void OnFramePreparedForPrintPages(); void PrintPages(); @@ -294,13 +286,18 @@ const blink::WebNode& node); #endif // BUILDFLAG(ENABLE_BASIC_PRINTING) - // Prints the page listed in |params|. #if defined(OS_MACOSX) - void PrintPagesInternal(const PrintMsg_Print_Params& params, - const std::vector<int>& printed_pages, - int page_count, - blink::WebLocalFrame* frame); + // Platform-specific helper function for rendering page(s) to |metafile|. + void RenderPage(const PrintMsg_Print_Params& params, + int page_number, + int page_count, + blink::WebLocalFrame* frame, + PdfMetafileSkia* metafile, + gfx::Size* page_size, + gfx::Rect* content_rect); #else + // Same as RenderPage() above, but for non-Mac. + // TODO(thestig): Try to merge this with RenderPage(). void PrintPageInternal(const PrintMsg_Print_Params& params, int page_number, int page_count, @@ -311,18 +308,6 @@ gfx::Rect* printable_area_in_dpi); #endif // defined(OS_MACOSX) - // Platform specific helper function for rendering page(s) to |metafile|. -#if defined(OS_MACOSX) - void RenderPage(const PrintMsg_Print_Params& params, - int page_number, - int page_count, - blink::WebLocalFrame* frame, - bool is_preview, - PdfMetafileSkia* metafile, - gfx::Size* page_size, - gfx::Rect* content_rect); -#endif // defined(OS_MACOSX) - // Renders page contents from |frame| to |content_area| of |canvas|. // |page_number| is zero-based. // When method is called, canvas should be setup to draw to |canvas_area|
diff --git a/components/printing/renderer/print_render_frame_helper_mac.mm b/components/printing/renderer/print_render_frame_helper_mac.mm index 4214995..a856628 100644 --- a/components/printing/renderer/print_render_frame_helper_mac.mm +++ b/components/printing/renderer/print_render_frame_helper_mac.mm
@@ -28,53 +28,43 @@ if (printed_pages.empty()) return false; - if (delegate_->UseSingleMetafile()) { - PrintPagesInternal(print_params, printed_pages, page_count, frame); - return true; - } - - for (int page_number : printed_pages) - PrintPagesInternal(print_params, std::vector<int>{page_number}, page_count, - frame); - return true; -} -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) - -void PrintRenderFrameHelper::PrintPagesInternal( - const PrintMsg_Print_Params& params, - const std::vector<int>& printed_pages, - int page_count, - blink::WebLocalFrame* frame) { - PdfMetafileSkia metafile(params.printed_doc_type); + PdfMetafileSkia metafile(print_params.printed_doc_type); CHECK(metafile.Init()); - gfx::Size page_size_in_dpi; - gfx::Rect content_area_in_dpi; - for (int page_number : printed_pages) { - RenderPage(params, page_number, page_count, frame, false, &metafile, - &page_size_in_dpi, &content_area_in_dpi); + std::vector<gfx::Size> page_size_in_dpi(printed_pages.size()); + std::vector<gfx::Rect> content_area_in_dpi(printed_pages.size()); + for (size_t i = 0; i < printed_pages.size(); ++i) { + RenderPage(print_params, printed_pages[i], page_count, frame, &metafile, + &page_size_in_dpi[i], &content_area_in_dpi[i]); } + + // blink::printEnd() for PDF should be called before metafile is closed. + FinishFramePrinting(); + metafile.FinishDocument(); PrintHostMsg_DidPrintPage_Params page_params; - page_params.data_size = metafile.GetDataSize(); - page_params.document_cookie = params.document_cookie; - page_params.page_size = page_size_in_dpi; - page_params.content_area = content_area_in_dpi; - - // Ask the browser to create the shared memory for us. if (!CopyMetafileDataToSharedMem(metafile, &page_params.metafile_data_handle)) { - // TODO(thestig): Fail and return false instead. - page_params.data_size = 0; + return false; } + page_params.data_size = metafile.GetDataSize(); + page_params.document_cookie = print_params.document_cookie; - for (int page_number : printed_pages) { - page_params.page_number = page_number; + for (size_t i = 0; i < printed_pages.size(); ++i) { + page_params.page_number = printed_pages[i]; + page_params.page_size = page_size_in_dpi[i]; + page_params.content_area = content_area_in_dpi[i]; Send(new PrintHostMsg_DidPrintPage(routing_id(), page_params)); - page_params.metafile_data_handle = base::SharedMemoryHandle(); + // Send the rest of the pages with an invalid metafile handle of size 0. + if (page_params.metafile_data_handle.IsValid()) { + page_params.metafile_data_handle = base::SharedMemoryHandle(); + page_params.data_size = 0; + } } + return true; } +#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) #if BUILDFLAG(ENABLE_PRINT_PREVIEW) bool PrintRenderFrameHelper::RenderPreviewPage( @@ -97,8 +87,8 @@ gfx::Size page_size; RenderPage(print_params, page_number, print_preview_context_.total_page_count(), - print_preview_context_.prepared_frame(), true, - initial_render_metafile, &page_size, NULL); + print_preview_context_.prepared_frame(), initial_render_metafile, + &page_size, nullptr); print_preview_context_.RenderedPreviewPage(base::TimeTicks::Now() - begin_time); @@ -121,7 +111,6 @@ int page_number, int page_count, blink::WebLocalFrame* frame, - bool is_preview, PdfMetafileSkia* metafile, gfx::Size* page_size, gfx::Rect* content_rect) { @@ -151,17 +140,14 @@ return; MetafileSkiaWrapper::SetMetafileOnCanvas(canvas, metafile); - cc::SetIsPreviewMetafile(canvas, is_preview); if (params.display_header_footer) { - PrintHeaderAndFooter(static_cast<blink::WebCanvas*>(canvas), - page_number + 1, page_count, *frame, scale_factor, - page_layout_in_points, params); + PrintHeaderAndFooter(canvas, page_number + 1, page_count, *frame, + scale_factor, page_layout_in_points, params); } RenderPageContent(frame, page_number, canvas_area, content_area, - scale_factor, static_cast<blink::WebCanvas*>(canvas)); + scale_factor, canvas); } - // Done printing. Close the device context to retrieve the compiled metafile. metafile->FinishPage(); }
diff --git a/components/printing/renderer/print_render_frame_helper_pdf_win.cc b/components/printing/renderer/print_render_frame_helper_pdf_win.cc index a746fd9..378e4b1a 100644 --- a/components/printing/renderer/print_render_frame_helper_pdf_win.cc +++ b/components/printing/renderer/print_render_frame_helper_pdf_win.cc
@@ -22,13 +22,12 @@ if (printed_pages.empty()) return false; - std::vector<gfx::Size> page_size_in_dpi(printed_pages.size()); - std::vector<gfx::Rect> content_area_in_dpi(printed_pages.size()); - std::vector<gfx::Rect> printable_area_in_dpi(printed_pages.size()); - PdfMetafileSkia metafile(params.params.printed_doc_type); CHECK(metafile.Init()); + std::vector<gfx::Size> page_size_in_dpi(printed_pages.size()); + std::vector<gfx::Rect> content_area_in_dpi(printed_pages.size()); + std::vector<gfx::Rect> printable_area_in_dpi(printed_pages.size()); for (size_t i = 0; i < printed_pages.size(); ++i) { PrintPageInternal(params.params, printed_pages[i], page_count, frame, &metafile, &page_size_in_dpi[i], &content_area_in_dpi[i], @@ -40,28 +39,27 @@ metafile.FinishDocument(); - PrintHostMsg_DidPrintPage_Params printed_page_params; + PrintHostMsg_DidPrintPage_Params page_params; if (!CopyMetafileDataToSharedMem(metafile, - &printed_page_params.metafile_data_handle)) { + &page_params.metafile_data_handle)) { return false; } - - printed_page_params.content_area = params.params.printable_area; - printed_page_params.data_size = metafile.GetDataSize(); - printed_page_params.document_cookie = params.params.document_cookie; - printed_page_params.page_size = params.params.page_size; + page_params.data_size = metafile.GetDataSize(); + page_params.document_cookie = params.params.document_cookie; for (size_t i = 0; i < printed_pages.size(); ++i) { - printed_page_params.page_number = printed_pages[i]; - printed_page_params.page_size = page_size_in_dpi[i]; - printed_page_params.content_area = content_area_in_dpi[i]; - printed_page_params.physical_offsets = + page_params.page_number = printed_pages[i]; + page_params.page_size = page_size_in_dpi[i]; + page_params.content_area = content_area_in_dpi[i]; + page_params.physical_offsets = gfx::Point(printable_area_in_dpi[i].x(), printable_area_in_dpi[i].y()); - Send(new PrintHostMsg_DidPrintPage(routing_id(), printed_page_params)); + Send(new PrintHostMsg_DidPrintPage(routing_id(), page_params)); // Send the rest of the pages with an invalid metafile handle. // TODO(erikchen): Fix semantics. See https://crbug.com/640840 - if (printed_page_params.metafile_data_handle.IsValid()) - printed_page_params.metafile_data_handle = base::SharedMemoryHandle(); + if (page_params.metafile_data_handle.IsValid()) { + page_params.metafile_data_handle = base::SharedMemoryHandle(); + page_params.data_size = 0; + } } return true; }
diff --git a/components/security_state/OWNERS b/components/security_state/OWNERS index 03ba2881..96886d35 100644 --- a/components/security_state/OWNERS +++ b/components/security_state/OWNERS
@@ -1,3 +1,4 @@ +elawrence@chromium.org estark@chromium.org felt@chromium.org
diff --git a/components/security_state/content/content_utils.cc b/components/security_state/content/content_utils.cc index e8ac0d9..e76a210 100644 --- a/components/security_state/content/content_utils.cc +++ b/components/security_state/content/content_utils.cc
@@ -20,6 +20,7 @@ #include "content/public/browser/security_style_explanations.h" #include "content/public/browser/ssl_status.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/url_constants.h" #include "net/base/net_errors.h" #include "net/cert/x509_certificate.h" #include "net/ssl/ssl_cipher_suite_names.h" @@ -362,13 +363,17 @@ content::NavigationEntry* entry = web_contents->GetController().GetVisibleEntry(); - state->is_error_page = - entry && (entry->GetPageType() == content::PAGE_TYPE_ERROR); - if (!entry || !entry->GetSSL().initialized) + if (!entry) return state; - - state->connection_info_initialized = true; + // Set fields that are not dependent on the connection info. + state->is_error_page = entry->GetPageType() == content::PAGE_TYPE_ERROR; + state->is_view_source = + entry->GetVirtualURL().SchemeIs(content::kViewSourceScheme); state->url = entry->GetURL(); + + if (!entry->GetSSL().initialized) + return state; + state->connection_info_initialized = true; const content::SSLStatus& ssl = entry->GetSSL(); state->certificate = ssl.certificate; state->cert_status = ssl.cert_status;
diff --git a/components/security_state/core/security_state.cc b/components/security_state/core/security_state.cc index 74fa518..9570210 100644 --- a/components/security_state/core/security_state.cc +++ b/components/security_state/core/security_state.cc
@@ -185,6 +185,10 @@ return NONE; } + if (visible_security_state.is_view_source) { + return NONE; + } + if ((visible_security_state.cert_status & net::CERT_STATUS_IS_EV) && visible_security_state.certificate) { return EV_SECURE; @@ -320,7 +324,8 @@ ran_content_with_cert_errors(false), pkp_bypassed(false), is_incognito(false), - is_error_page(false) {} + is_error_page(false), + is_view_source(false) {} VisibleSecurityState::~VisibleSecurityState() {}
diff --git a/components/security_state/core/security_state.h b/components/security_state/core/security_state.h index b2742690..7860f80 100644 --- a/components/security_state/core/security_state.h +++ b/components/security_state/core/security_state.h
@@ -189,6 +189,8 @@ // True if the page was an error page. // TODO(estark): this field is not populated on iOS. https://crbug.com/760647 bool is_error_page; + // True if the page is a view-source page. + bool is_view_source; // Contains information about input events that may impact the security // level of the page. InsecureInputEventData insecure_input_events;
diff --git a/components/security_state/core/security_state_unittest.cc b/components/security_state/core/security_state_unittest.cc index 4868bcb..2a7b1a0 100644 --- a/components/security_state/core/security_state_unittest.cc +++ b/components/security_state/core/security_state_unittest.cc
@@ -57,7 +57,9 @@ ran_mixed_content_(false), malicious_content_status_(MALICIOUS_CONTENT_STATUS_NONE), is_incognito_(false), - is_error_page_(false) {} + is_error_page_(false), + is_view_source_(false) {} + virtual ~TestSecurityStateHelper() {} void SetCertificate(scoped_refptr<net::X509Certificate> cert) { @@ -72,6 +74,9 @@ void AddCertStatus(net::CertStatus cert_status) { cert_status_ |= cert_status; } + void set_cert_status(net::CertStatus cert_status) { + cert_status_ = cert_status; + } void set_displayed_mixed_content(bool displayed_mixed_content) { displayed_mixed_content_ = displayed_mixed_content; } @@ -95,6 +100,10 @@ void set_is_error_page(bool is_error_page) { is_error_page_ = is_error_page; } + void set_is_view_source(bool is_view_source) { + is_view_source_ = is_view_source; + } + void set_insecure_field_edit(bool insecure_field_edit) { insecure_input_events_.insecure_field_edited = insecure_field_edit; } @@ -115,6 +124,7 @@ state->malicious_content_status = malicious_content_status_; state->is_incognito = is_incognito_; state->is_error_page = is_error_page_; + state->is_view_source = is_view_source_; state->insecure_input_events = insecure_input_events_; return state; } @@ -137,6 +147,7 @@ MaliciousContentStatus malicious_content_status_; bool is_incognito_; bool is_error_page_; + bool is_view_source_; InsecureInputEventData insecure_input_events_; }; @@ -381,6 +392,32 @@ } } +// Tests that if |is_view_source| NONE is returned for a secure site. +TEST(SecurityStateTest, ViewSourceRemovesSecure) { + TestSecurityStateHelper helper; + SecurityInfo security_info; + helper.set_cert_status(0); + helper.GetSecurityInfo(&security_info); + EXPECT_EQ(SECURE, security_info.security_level); + helper.set_is_view_source(true); + helper.GetSecurityInfo(&security_info); + EXPECT_EQ(NONE, security_info.security_level); +} + +// Tests that if |is_view_source|, DANGEROUS is still returned for a site +// flagged by SafeBrowsing. +TEST(SecurityStateTest, ViewSourceKeepsWarning) { + TestSecurityStateHelper helper; + helper.set_malicious_content_status( + MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING); + helper.set_is_view_source(true); + SecurityInfo security_info; + helper.GetSecurityInfo(&security_info); + EXPECT_EQ(MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING, + security_info.malicious_content_status); + EXPECT_EQ(DANGEROUS, security_info.security_level); +} + // Tests that |incognito_downgraded_security_level| is set only when the // corresponding VisibleSecurityState flag is set and the HTTPBad Phase 2 // experiment is enabled.
diff --git a/components/sync/driver/about_sync_util_unittest.cc b/components/sync/driver/about_sync_util_unittest.cc index 7170a48..0b71431b 100644 --- a/components/sync/driver/about_sync_util_unittest.cc +++ b/components/sync/driver/about_sync_util_unittest.cc
@@ -34,9 +34,8 @@ TEST(SyncUIUtilTestAbout, ConstructAboutInformationWithUnrecoverableErrorTest) { SyncServiceMock service; - std::unique_ptr<base::DictionaryValue> strings( - ConstructAboutInformation_DEPRECATED(&service, - version_info::Channel::UNKNOWN)); + std::unique_ptr<base::DictionaryValue> strings(ConstructAboutInformation( + &service, AccountInfo(), version_info::Channel::UNKNOWN)); EXPECT_TRUE(strings->HasKey("unrecoverable_error_detected")); }
diff --git a/components/test/data/autofill/autofill_address_form.html b/components/test/data/autofill/autofill_address_form.html new file mode 100644 index 0000000..69ac3e2 --- /dev/null +++ b/components/test/data/autofill/autofill_address_form.html
@@ -0,0 +1,21 @@ +<form name="addr1.1" id="form1" action="https://example.com/" method="post"> + Name: <input type="text" name="name" id="profile_autofill_name"><br> + Address: <input type="text" name="address"><br> + City: <input type="text" name="city"><br> + State: <select name="state"> + <option value="CA">CA</option> + <option value="MA">MA</option> + <option value="NY">NY</option> + <option value="MD">MD</option> + <option value="OR">OR</option> + <option value="OH">OH</option> + <option value="IL">IL</option> + <option value="DC">DC</option> + </select> <br> + Zip: <input name="zip" id="form_zip"> <br> + Country: <input name="country" id="form_country"> <br> + Email: <input name="email" id="form_email"> <br> + Phone: <input name="phone" id="form_phone"> <br> + <input type="reset" value="Reset"> + <input type="submit" value="Submit" id="profile_submit"> +</form> \ No newline at end of file
diff --git a/components/test/data/autofill/autofill_credit_card_form.html b/components/test/data/autofill/autofill_credit_card_form.html new file mode 100644 index 0000000..f3ea33d --- /dev/null +++ b/components/test/data/autofill/autofill_credit_card_form.html
@@ -0,0 +1,40 @@ +<form name="cc1.1" id="cc1" action="https://example.com/" method="post"> + Name on card: <input autofocus="" type="text" name="name" id="credit_card_name"><br> + Credit card number: <input type="text" name="CCNo" id="credit_card_number"><br> + Expiry Date: <select name="CCExpiresMonth"> + <option value="01">01</option> + <option value="02">02</option> + <option value="03">03</option> + <option value="04">04</option> + <option value="05">05</option> + <option value="06">06</option> + <option value="07">07</option> + <option value="08">08</option> + <option value="09">09</option> + <option value="10">10</option> + <option value="11">11</option> + <option value="12">12</option> + </select> + / +<select name="CCExpiresYear"> + <option value="2010">2010</option> + <option value="2011">2011</option> + <option value="2012">2012</option> + <option value="2013">2013</option> + <option value="2014">2014</option> + <option value="2015">2015</option> + <option value="2016">2016</option> + <option value="2017">2017</option> + <option value="2018">2018</option> + <option value="2019">2019</option> + <option value="2020">2020</option> + <option value="2021">2021</option> + <option value="2022">2022</option> + <option value="2023">2023</option> + </select> + <br> + CVC: <input name="cvc"> +<br> + <input type="reset" value="Reset"> + <input type="submit" value="Submit" id="credit_card_submit"> +</form> \ No newline at end of file
diff --git a/components/test/data/autofill/autofill_iframe_embedder.html b/components/test/data/autofill/autofill_iframe_embedder.html new file mode 100644 index 0000000..41942bb --- /dev/null +++ b/components/test/data/autofill/autofill_iframe_embedder.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<iframe id="test"></iframe>
diff --git a/components/test/data/payments/payment_request_iframe.html b/components/test/data/payments/payment_request_iframe.html index ee9ec95..208d957 100644 --- a/components/test/data/payments/payment_request_iframe.html +++ b/components/test/data/payments/payment_request_iframe.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <script> new PaymentRequest( - [{supportedMethods: ["foo"]}], - {total: {label: "Tots", amount: {currency: "USD", value: "1.00"}}}); + [{supportedMethods: ["basic-card"]}], + {total: {label: "Tots", amount: {currency: "USD", value: "1.00"}}}).show(); </script>
diff --git a/components/translate/core/browser/translate_download_manager.cc b/components/translate/core/browser/translate_download_manager.cc index 7143a145..a776e50 100644 --- a/components/translate/core/browser/translate_download_manager.cc +++ b/components/translate/core/browser/translate_download_manager.cc
@@ -34,7 +34,7 @@ void TranslateDownloadManager::RequestLanguageList(PrefService* prefs) { // We don't want to do this when translate is disabled. DCHECK(prefs != nullptr); - if (!prefs->GetBoolean(prefs::kEnableTranslate)) + if (!prefs->GetBoolean(prefs::kOfferTranslateEnabled)) return; TranslateLanguageList* language_list = GetInstance()->language_list();
diff --git a/components/translate/core/browser/translate_download_manager.h b/components/translate/core/browser/translate_download_manager.h index fe6c66d0..2cf8cb03 100644 --- a/components/translate/core/browser/translate_download_manager.h +++ b/components/translate/core/browser/translate_download_manager.h
@@ -64,8 +64,8 @@ } // Let the caller decide if and when we should fetch the language list from - // the translate server. This is a NOOP if prefs::kEnableTranslate is set to - // false. + // the translate server. This is a NOOP if prefs::kOfferTranslateEnabled is + // set to false. static void RequestLanguageList(PrefService* prefs); // Fills |languages| with the list of languages that the translate server can
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc index 014ce2e..2c069e0 100644 --- a/components/translate/core/browser/translate_manager.cc +++ b/components/translate/core/browser/translate_manager.cc
@@ -103,8 +103,8 @@ return; if (!ignore_missing_key_for_testing_ && !::google_apis::HasKeysConfigured()) { - // Without an API key, translate won't work, so don't offer to translate - // in the first place. Leave prefs::kEnableTranslate on, though, because + // Without an API key, translate won't work, so don't offer to translate in + // the first place. Leave prefs::kOfferTranslateEnabled on, though, because // that settings syncs and we don't want to turn off translate everywhere // else. TranslateBrowserMetrics::ReportInitiationStatus( @@ -115,7 +115,7 @@ std::unique_ptr<TranslatePrefs> translate_prefs( translate_client_->GetTranslatePrefs()); - if (!translate_prefs->IsEnabled()) { + if (!translate_prefs->IsOfferTranslateEnabled()) { TranslateBrowserMetrics::ReportInitiationStatus( TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_PREFS); std::string target_lang =
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc index 88d491e..5831c09 100644 --- a/components/translate/core/browser/translate_manager_unittest.cc +++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -127,7 +127,7 @@ TranslatePrefs::RegisterProfilePrefs(prefs_.registry()); // TODO(groby): Figure out RegisterProfilePrefs() should register this. prefs_.registry()->RegisterBooleanPref( - prefs::kEnableTranslate, true, + prefs::kOfferTranslateEnabled, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); manager_->ResetForTesting(); } @@ -294,7 +294,7 @@ // reached after the early-out tests including IsOffline() passed. base::HistogramTester histogram_tester; - prefs_.SetBoolean(prefs::kEnableTranslate, false); + prefs_.SetBoolean(prefs::kOfferTranslateEnabled, false); translate_manager_->GetLanguageState().LanguageDetermined("de", true);
diff --git a/components/translate/core/browser/translate_pref_names.cc b/components/translate/core/browser/translate_pref_names.cc index 30988ed8..96fe2c1 100644 --- a/components/translate/core/browser/translate_pref_names.cc +++ b/components/translate/core/browser/translate_pref_names.cc
@@ -6,7 +6,9 @@ namespace prefs { -// Boolean that is true when the translate feature is enabled. -const char kEnableTranslate[] = "translate.enabled"; +// Boolean that is true when offering translate (i.e. the automatic translate +// bubble) is enabled. Even when this is false, the user can force translate +// from the right-click context menu unless translate is disabled by policy. +const char kOfferTranslateEnabled[] = "translate.enabled"; } // namespace prefs
diff --git a/components/translate/core/browser/translate_pref_names.h b/components/translate/core/browser/translate_pref_names.h index 24c3fa23..b33849e 100644 --- a/components/translate/core/browser/translate_pref_names.h +++ b/components/translate/core/browser/translate_pref_names.h
@@ -7,7 +7,7 @@ namespace prefs { -extern const char kEnableTranslate[]; +extern const char kOfferTranslateEnabled[]; } // namespace prefs
diff --git a/components/translate/core/browser/translate_prefs.cc b/components/translate/core/browser/translate_prefs.cc index 3210bb71..123bccd 100644 --- a/components/translate/core/browser/translate_prefs.cc +++ b/components/translate/core/browser/translate_prefs.cc
@@ -175,8 +175,17 @@ #endif } -bool TranslatePrefs::IsEnabled() const { - return prefs_->GetBoolean(prefs::kEnableTranslate); +bool TranslatePrefs::IsOfferTranslateEnabled() const { + return prefs_->GetBoolean(prefs::kOfferTranslateEnabled); +} + +bool TranslatePrefs::IsTranslateAllowedByPolicy() const { + const PrefService::Preference* const pref = + prefs_->FindPreference(prefs::kOfferTranslateEnabled); + DCHECK(pref); + DCHECK(pref->GetValue()->is_bool()); + + return pref->GetValue()->GetBool() || !pref->IsManaged(); } void TranslatePrefs::SetCountry(const std::string& country) {
diff --git a/components/translate/core/browser/translate_prefs.h b/components/translate/core/browser/translate_prefs.h index c63a848..a6cb3243 100644 --- a/components/translate/core/browser/translate_prefs.h +++ b/components/translate/core/browser/translate_prefs.h
@@ -129,8 +129,12 @@ const char* accept_languages_pref, const char* preferred_languages_pref); - // Checks if the translate feature is enabled. - bool IsEnabled() const; + // Checks if the "offer translate" (i.e. automatic translate bubble) feature + // is enabled. + bool IsOfferTranslateEnabled() const; + + // Checks if translate is allowed by policy. + bool IsTranslateAllowedByPolicy() const; // Sets the country that the application is run in. Determined by the // VariationsService, can be left empty. Used by the TranslateRanker.
diff --git a/components/translate/ios/browser/language_detection_controller.mm b/components/translate/ios/browser/language_detection_controller.mm index 8a43328..da13076 100644 --- a/components/translate/ios/browser/language_detection_controller.mm +++ b/components/translate/ios/browser/language_detection_controller.mm
@@ -43,7 +43,8 @@ : web_state_(web_state), js_manager_(manager), weak_method_factory_(this) { DCHECK(web_state_); DCHECK(js_manager_); - translate_enabled_.Init(prefs::kEnableTranslate, prefs); + + translate_enabled_.Init(prefs::kOfferTranslateEnabled, prefs); web_state_->AddObserver(this); web_state_->AddScriptCommandCallback( base::Bind(&LanguageDetectionController::OnTextCaptured,
diff --git a/components/translate/ios/browser/language_detection_controller_unittest.mm b/components/translate/ios/browser/language_detection_controller_unittest.mm index 48167acd..c61adad8 100644 --- a/components/translate/ios/browser/language_detection_controller_unittest.mm +++ b/components/translate/ios/browser/language_detection_controller_unittest.mm
@@ -41,7 +41,7 @@ class LanguageDetectionControllerTest : public PlatformTest { protected: LanguageDetectionControllerTest() : details_(nullptr) { - prefs_.registry()->RegisterBooleanPref(prefs::kEnableTranslate, true); + prefs_.registry()->RegisterBooleanPref(prefs::kOfferTranslateEnabled, true); language::IOSLanguageDetectionTabHelper::CreateForWebState( &web_state_,
diff --git a/components/ui_devtools/views/dom_agent.h b/components/ui_devtools/views/dom_agent.h index 55350354..440f7b9d 100644 --- a/components/ui_devtools/views/dom_agent.h +++ b/components/ui_devtools/views/dom_agent.h
@@ -97,7 +97,6 @@ private: // ui::LayerDelegate: void OnPaintLayer(const ui::PaintContext& context) override; - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {}
diff --git a/components/viz/common/quads/DEPS b/components/viz/common/quads/DEPS index a7e480ee..1e6ce77b 100644 --- a/components/viz/common/quads/DEPS +++ b/components/viz/common/quads/DEPS
@@ -11,7 +11,10 @@ ] specific_include_rules = { + "texture_mailbox\.cc": [ + "+third_party/khronos/GLES2", + ], ".*_unittest\.cc": [ "+cc/test", - ] + ], }
diff --git a/components/viz/common/quads/texture_mailbox.cc b/components/viz/common/quads/texture_mailbox.cc index f17a798..a529b91 100644 --- a/components/viz/common/quads/texture_mailbox.cc +++ b/components/viz/common/quads/texture_mailbox.cc
@@ -9,6 +9,8 @@ #include "base/logging.h" #include "components/viz/common/quads/shared_bitmap.h" +#include "components/viz/common/resources/transferable_resource.h" +#include "third_party/khronos/GLES2/gl2.h" namespace viz { @@ -77,4 +79,29 @@ return SharedBitmap::UncheckedSizeInBytes(size_in_pixels_); } +TransferableResource TextureMailbox::ToTransferableResource() const { + DCHECK(IsValid()); + + TransferableResource resource; + if (IsTexture()) { + GLuint filter = nearest_neighbor() ? GL_NEAREST : GL_LINEAR; + + if (!is_overlay_candidate()) { + resource = TransferableResource::MakeGL(mailbox(), filter, target(), + sync_token()); + } else { + resource = TransferableResource::MakeGLOverlay( + mailbox(), filter, target(), sync_token(), size_in_pixels(), + is_overlay_candidate()); + } + } else { + resource = TransferableResource::MakeSoftware( + shared_bitmap()->id(), shared_bitmap()->sequence_number(), + size_in_pixels()); + } + resource.color_space = color_space(); + + return resource; +} + } // namespace viz
diff --git a/components/viz/common/quads/texture_mailbox.h b/components/viz/common/quads/texture_mailbox.h index 4932283..5860707 100644 --- a/components/viz/common/quads/texture_mailbox.h +++ b/components/viz/common/quads/texture_mailbox.h
@@ -19,7 +19,7 @@ #include "ui/gfx/geometry/size.h" namespace viz { - +struct TransferableResource; namespace mojom { class TextureMailboxDataView; } @@ -83,6 +83,8 @@ SharedBitmap* shared_bitmap() const { return shared_bitmap_; } size_t SharedMemorySizeInBytes() const; + TransferableResource ToTransferableResource() const; + private: friend struct mojo::StructTraits<mojom::TextureMailboxDataView, TextureMailbox>;
diff --git a/components/viz/common/resources/resource.h b/components/viz/common/resources/resource.h index 0d0db897..cc5a88576 100644 --- a/components/viz/common/resources/resource.h +++ b/components/viz/common/resources/resource.h
@@ -39,7 +39,7 @@ // for client and service libraries and should not be used directly from // external client code. struct VIZ_COMMON_EXPORT Resource { - enum Origin { INTERNAL, EXTERNAL, DELEGATED }; + enum Origin { INTERNAL, DELEGATED }; enum SynchronizationState { // The LOCALLY_USED state is the state each resource defaults to when // constructed or modified or read. This state indicates that the @@ -149,12 +149,10 @@ ResourceId id_in_child = 0; // Texture id for texture-backed resources. GLuint gl_id = 0; - // The mailbox associated with resources received from an external source, or - // sent from the client to the service. The mailbox has the IPC-capable data - // for sharing the resource backing between modules/GL contexts/processes. + // The mailbox associated with resources received from the client to the + // service. The mailbox has the IPC-capable data for sharing the resource + // backing between modules/GL contexts/processes. gpu::Mailbox mailbox; - // Callback to run when the resource is deleted and not in use by the service. - ReleaseCallback release_callback; // Non-owning pointer to a software-backed resource when mapped. uint8_t* pixels = nullptr; // Reference-counts to know when a resource can be released through the @@ -172,8 +170,7 @@ // Size of the resource in pixels. gfx::Size size; // Where the resource was originally allocated. Either internally by the - // ResourceProvider instance, externally and given to the ResourceProvider - // via in-process methods, or in a client and given to the ResourceProvider + // ResourceProvider instance, or in a client and given to the ResourceProvider // via IPC. Origin origin = INTERNAL; // The texture target for GpuMemoryBuffer- and texture-backed resources. @@ -228,9 +225,8 @@ // Tracks if a sync token needs to be waited on before using the resource. SynchronizationState synchronization_state_ = SYNCHRONIZED; // A SyncToken associated with a texture-backed or GpuMemoryBuffer-backed - // resource. It can be from an external source and waited on in order to use - // the resource, or generated internally in order to send the resource from - // client to service, and this is tracked by the |synchronization_state_|. + // resource. It is given from a child to the service, and waited on in order + // to use the resource, and this is tracked by the |synchronization_state_|. gpu::SyncToken sync_token_; DISALLOW_COPY_AND_ASSIGN(Resource);
diff --git a/components/viz/common/resources/transferable_resource.cc b/components/viz/common/resources/transferable_resource.cc index 7d44148c..2064f15a 100644 --- a/components/viz/common/resources/transferable_resource.cc +++ b/components/viz/common/resources/transferable_resource.cc
@@ -7,25 +7,13 @@ namespace viz { -TransferableResource::TransferableResource() - : id(0), - format(RGBA_8888), - buffer_format(gfx::BufferFormat::RGBA_8888), - filter(0), - read_lock_fences_enabled(false), - is_software(false), - shared_bitmap_sequence_number(0), -#if defined(OS_ANDROID) - is_backed_by_surface_texture(false), - wants_promotion_hint(false), -#endif - is_overlay_candidate(false) { -} +TransferableResource::TransferableResource() = default; +TransferableResource::~TransferableResource() = default; TransferableResource::TransferableResource(const TransferableResource& other) = default; - -TransferableResource::~TransferableResource() {} +TransferableResource& TransferableResource::operator=( + const TransferableResource& other) = default; ReturnedResource TransferableResource::ToReturnedResource() const { ReturnedResource returned;
diff --git a/components/viz/common/resources/transferable_resource.h b/components/viz/common/resources/transferable_resource.h index 6becc63a..b4e5ba07 100644 --- a/components/viz/common/resources/transferable_resource.h +++ b/components/viz/common/resources/transferable_resource.h
@@ -25,9 +25,11 @@ struct VIZ_COMMON_EXPORT TransferableResource { TransferableResource(); - TransferableResource(const TransferableResource& other); ~TransferableResource(); + TransferableResource(const TransferableResource& other); + TransferableResource& operator=(const TransferableResource& other); + ReturnedResource ToReturnedResource() const; static std::vector<ReturnedResource> ReturnResources( const std::vector<TransferableResource>& input); @@ -70,16 +72,56 @@ return r; } - ResourceId id; - // Refer to ResourceProvider::Resource for the meaning of the following data. - ResourceFormat format; - gfx::BufferFormat buffer_format; - uint32_t filter; + // TODO(danakj): Some of these fiends are only GL, some are only Software, + // some are both but used for different purposes (like the mailbox name). + // It would be nice to group things together and make it more clear when + // they will be used or not, and provide easier access to fields such as the + // mailbox that also show the intent for software for GL. + // An |id| field that can be unique to this resource. For resources + // generated by compositor clients, this |id| may be used for their + // own book-keeping but need not be set at all. + ResourceId id = 0; + + // Indicates if the resource is gpu or software backed. If gpu, the + // mailbox field is a gpu::Mailbox, else it is a SharedBitmapId. + bool is_software = false; + + // The number of pixels in the gpu mailbox/software bitmap. This must + // be set for software bitmaps, and must also be set for gpu mailboxes + // when they are an overlay candidate. Otherwise it will not be used + // and may be unset. gfx::Size size; + + // The format of the pixels in the gpu mailbox/software bitmap. This should + // almost always be RGBA_8888 for resources generted by compositor clients, + // and must be RGBA_8888 always for software resources. + ResourceFormat format = RGBA_8888; + + // The |mailbox| inside here holds the gpu::Mailbox when this is a gpu + // resource, or the SharedBitmapId when it is a software resource. + // The |texture_target| and sync_token| inside here only apply for gpu + // resources. gpu::MailboxHolder mailbox_holder; - bool read_lock_fences_enabled; - bool is_software; - uint32_t shared_bitmap_sequence_number; + + // The color space of the pixels in the resource. + gfx::ColorSpace color_space; + + // Sequence number for the shared bitmap in software resources, used for + // synchronization to not display the bitmap before it is ready. + uint32_t shared_bitmap_sequence_number = 0; + + // A gpu resource may be possible to use directly in an overlay if this is + // true. + bool is_overlay_candidate = false; + // For a gpu resource, the filter to use when scaling the resource when + // drawing it. Typically GL_LINEAR, or GL_NEAREST if no anti-aliasing + // during scaling is desired. + uint32_t filter = 0; + // If a gpu resource is backed by a GpuMemoryBuffer, this specifies the + // format of that buffer, which may not match the |format|. + gfx::BufferFormat buffer_format = gfx::BufferFormat::RGBA_8888; + // Whether a gpu fence needs to be used for reading a gpu resource. + bool read_lock_fences_enabled = false; #if defined(OS_ANDROID) // Indicates whether this resource may not be overlayed on Android, since // it's not backed by a SurfaceView. This may be set in combination with @@ -90,12 +132,29 @@ // promote SurfaceTexture via the overlay path, even if one ended up just // drawing a quad in the compositor. However, for now, we use this flag to // refuse to promote so that the compositor will draw the quad. - bool is_backed_by_surface_texture; + bool is_backed_by_surface_texture = false; // Indicates that this resource would like a promotion hint. - bool wants_promotion_hint; + bool wants_promotion_hint = false; #endif - bool is_overlay_candidate; - gfx::ColorSpace color_space; + + bool operator==(const TransferableResource& o) const { + return id == o.id && format == o.format && + buffer_format == o.buffer_format && filter == o.filter && + size == o.size && + mailbox_holder.mailbox == o.mailbox_holder.mailbox && + mailbox_holder.sync_token == o.mailbox_holder.sync_token && + mailbox_holder.texture_target == o.mailbox_holder.texture_target && + read_lock_fences_enabled == o.read_lock_fences_enabled && + is_software == o.is_software && + shared_bitmap_sequence_number == o.shared_bitmap_sequence_number && +#if defined(OS_ANDROID) + is_backed_by_surface_texture == o.is_backed_by_surface_texture && + wants_promotion_hint == o.wants_promotion_hint && +#endif + is_overlay_candidate == o.is_overlay_candidate && + color_space == o.color_space; + } + bool operator!=(const TransferableResource& o) const { return !(*this == o); } }; } // namespace viz
diff --git a/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc b/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc index eac8e27..9fd99bc 100644 --- a/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc +++ b/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc
@@ -59,6 +59,15 @@ void CloseChannel(int32_t client_id) override {} + void CreateArcVideoDecodeAccelerator( + arc::mojom::VideoDecodeAcceleratorRequest vda_request) override {} + + void CreateArcVideoEncodeAccelerator( + arc::mojom::VideoEncodeAcceleratorRequest vea_request) override {} + + void CreateArcProtectedBufferManager( + arc::mojom::ProtectedBufferManagerRequest pbm_request) override {} + void CreateJpegDecodeAccelerator( media::mojom::GpuJpegDecodeAcceleratorRequest jda_request) override {}
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index bc9f5e5b..3c07364 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -192,6 +192,10 @@ deps += [ "//ui/gfx/x" ] } + if (is_chromeos) { + deps += [ "//components/arc/video_accelerator" ] + } + if (is_mac) { sources += [ "display_embedder/compositor_overlay_candidate_validator_mac.h",
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc index 7ce85ca7..b32a714 100644 --- a/components/viz/service/display/display.cc +++ b/components/viz/service/display/display.cc
@@ -397,6 +397,12 @@ } client_->DisplayDidDrawAndSwap(); + + // Garbage collection can lead to sync IPCs to the GPU service to verify sync + // tokens. We defer garbage collection until the end of DrawAndSwap to avoid + // stalling the critical path for compositing. + surface_manager_->GarbageCollectSurfaces(); + return true; } @@ -479,6 +485,7 @@ } void Display::SurfaceDiscarded(const SurfaceId& surface_id) { + TRACE_EVENT0("viz", "Display::SurfaceDiscarded"); if (aggregator_) aggregator_->ReleaseResources(surface_id); }
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc index 045e8b9..2b18297 100644 --- a/components/viz/service/display/gl_renderer_unittest.cc +++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -30,6 +30,7 @@ #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/copy_output_result.h" #include "components/viz/common/quads/texture_draw_quad.h" +#include "components/viz/common/resources/transferable_resource.h" #include "components/viz/service/display/overlay_strategy_single_on_top.h" #include "components/viz/service/display/overlay_strategy_underlay.h" #include "components/viz/service/display/texture_mailbox_deleter.h" @@ -1958,13 +1959,13 @@ cc::FakeResourceProvider::CreateLayerTreeResourceProvider( child_context_provider.get(), shared_bitmap_manager.get()); - TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), - GL_TEXTURE_2D, gfx::Size(256, 256), true); + auto transfer_resource = TransferableResource::MakeGLOverlay( + gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(), + gfx::Size(256, 256), true); auto release_callback = SingleReleaseCallback::Create(base::Bind(&MailboxReleased)); - ResourceId resource_id = - child_resource_provider->CreateResourceFromTextureMailbox( - mailbox, std::move(release_callback)); + ResourceId resource_id = child_resource_provider->ImportResource( + transfer_resource, std::move(release_callback)); std::vector<ReturnedResource> returned_to_child; int child_id = parent_resource_provider->CreateChild( @@ -2154,13 +2155,13 @@ gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, gpu::CommandBufferId::FromUnsafeValue(0x123), 29); - TextureMailbox mailbox(gpu::Mailbox::Generate(), sync_token, GL_TEXTURE_2D, - gfx::Size(256, 256), true); + auto transfer_resource = TransferableResource::MakeGLOverlay( + gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, sync_token, + gfx::Size(256, 256), true); auto release_callback = SingleReleaseCallback::Create(base::Bind(&MailboxReleased)); - ResourceId resource_id = - child_resource_provider->CreateResourceFromTextureMailbox( - mailbox, std::move(release_callback)); + ResourceId resource_id = child_resource_provider->ImportResource( + transfer_resource, std::move(release_callback)); std::vector<ReturnedResource> returned_to_child; int child_id = parent_resource_provider->CreateChild( @@ -2396,13 +2397,13 @@ cc::FakeResourceProvider::CreateLayerTreeResourceProvider( child_context_provider.get(), nullptr); - TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), - GL_TEXTURE_2D, gfx::Size(256, 256), true); + auto transfer_resource = TransferableResource::MakeGLOverlay( + gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(), + gfx::Size(256, 256), true); auto release_callback = SingleReleaseCallback::Create(base::Bind(&MailboxReleased)); - ResourceId resource_id = - child_resource_provider->CreateResourceFromTextureMailbox( - mailbox, std::move(release_callback)); + ResourceId resource_id = child_resource_provider->ImportResource( + transfer_resource, std::move(release_callback)); std::vector<ReturnedResource> returned_to_child; int child_id = parent_resource_provider->CreateChild(
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc index a06fbb7..06b8a8b 100644 --- a/components/viz/service/display/overlay_unittest.cc +++ b/components/viz/service/display/overlay_unittest.cc
@@ -23,7 +23,7 @@ #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/stream_video_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" -#include "components/viz/common/quads/texture_mailbox.h" +#include "components/viz/common/resources/transferable_resource.h" #include "components/viz/service/display/ca_layer_overlay.h" #include "components/viz/service/display/gl_renderer.h" #include "components/viz/service/display/output_surface.h" @@ -265,14 +265,14 @@ cc::LayerTreeResourceProvider* child_resource_provider, const gfx::Size& size, bool is_overlay_candidate) { - TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), - GL_TEXTURE_2D, size, is_overlay_candidate); + auto resource = TransferableResource::MakeGLOverlay( + gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(), + size, is_overlay_candidate); auto release_callback = SingleReleaseCallback::Create(base::Bind(&MailboxReleased)); - ResourceId resource_id = - child_resource_provider->CreateResourceFromTextureMailbox( - mailbox, std::move(release_callback)); + ResourceId resource_id = child_resource_provider->ImportResource( + resource, std::move(release_callback)); std::vector<ReturnedResource> returned_to_child; int child_id = parent_resource_provider->CreateChild(
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc index d6ba416..4083eb56 100644 --- a/components/viz/service/display/surface_aggregator_unittest.cc +++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -2545,6 +2545,7 @@ // associated with |surface_id1| to get garbage collected. SubmitCompositorFrameWithResources(nullptr, 0u, true, SurfaceId(), support.get(), surface_id2); + manager_.surface_manager()->GarbageCollectSurfaces(); frame = aggregator_->Aggregate(surface_id2);
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc index 6797339..99263a0 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -116,9 +116,19 @@ void CompositorFrameSinkSupport::EvictCurrentSurface() { if (!current_surface_id_.is_valid()) return; + SurfaceId to_destroy_surface_id = current_surface_id_; current_surface_id_ = SurfaceId(); surface_manager_->DestroySurface(to_destroy_surface_id); + + // For display root surfaces the surface is no longer going to be visible. + // Make it unreachable from the top-level root. + if (referenced_local_surface_id_.has_value()) { + auto reference = MakeTopLevelRootReference( + SurfaceId(frame_sink_id_, referenced_local_surface_id_.value())); + surface_manager_->RemoveSurfaceReferences({reference}); + referenced_local_surface_id_.reset(); + } } void CompositorFrameSinkSupport::SetNeedsBeginFrame(bool needs_begin_frame) {
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h index f81641a..b8e3be5 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -25,12 +25,6 @@ #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h" #include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h" -namespace { -// The frame index starts at 2 so that empty frames will be treated as -// completely damaged the first time they're drawn from. -constexpr int kFrameIndexStart = 2; -} // namespace - namespace viz { class FrameSinkManagerImpl; @@ -49,6 +43,8 @@ base::RepeatingCallback<void(const LocalSurfaceId& local_surface_id, const gfx::Rect& damage_rect)>; + static const uint64_t kFrameIndexStart = 2; + static std::unique_ptr<CompositorFrameSinkSupport> Create( mojom::CompositorFrameSinkClient* client, FrameSinkManagerImpl* frame_sink_manager,
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc index eb22f3f..8dd1b690 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -507,10 +507,13 @@ LocalSurfaceId local_surface_id(6, kArbitraryToken); support->SubmitCompositorFrame(local_surface_id, test::MakeCompositorFrame()); + SurfaceManager* surface_manager = manager_.surface_manager(); + EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(_)) - .WillOnce(testing::InvokeWithoutArgs([&support, &mock_client]() { + .WillOnce(testing::InvokeWithoutArgs([&]() { LocalSurfaceId new_id(7, base::UnguessableToken::Create()); support->SubmitCompositorFrame(new_id, test::MakeCompositorFrame()); + surface_manager->GarbageCollectSurfaces(); })) .WillRepeatedly(testing::Return()); support->EvictCurrentSurface(); @@ -545,6 +548,7 @@ EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resources)) .Times(1); support->EvictCurrentSurface(); + manager_.surface_manager()->GarbageCollectSurfaces(); EXPECT_FALSE(GetSurfaceForId(id)); manager_.InvalidateFrameSinkId(kAnotherArbitraryFrameSinkId); } @@ -626,6 +630,7 @@ support_->EvictCurrentSurface(); local_surface_id_ = LocalSurfaceId(); + manager_.surface_manager()->GarbageCollectSurfaces(); EXPECT_TRUE(called1); EXPECT_TRUE(called2); EXPECT_TRUE(called3); @@ -698,6 +703,7 @@ frame.render_pass_list.push_back(std::move(pass)); EXPECT_FALSE( support_->SubmitCompositorFrame(local_surface_id_, std::move(frame))); + manager_.surface_manager()->GarbageCollectSurfaces(); EXPECT_FALSE(GetSurfaceForId(id)); } @@ -720,6 +726,7 @@ frame.metadata.device_scale_factor = 0.4f; EXPECT_FALSE( support_->SubmitCompositorFrame(local_surface_id_, std::move(frame))); + manager_.surface_manager()->GarbageCollectSurfaces(); EXPECT_FALSE(GetSurfaceForId(id)); }
diff --git a/components/viz/service/frame_sinks/surface_references_unittest.cc b/components/viz/service/frame_sinks/surface_references_unittest.cc index 39bc903..235cef49e 100644 --- a/components/viz/service/frame_sinks/surface_references_unittest.cc +++ b/components/viz/service/frame_sinks/surface_references_unittest.cc
@@ -212,6 +212,7 @@ EXPECT_THAT(GetReferencesFor(id3), UnorderedElementsAre(id2, id2_next)); RemoveSurfaceReference(id1, id2); + GetSurfaceManager().GarbageCollectSurfaces(); EXPECT_THAT(GetReferencesFor(id2), IsEmpty()); EXPECT_THAT(GetReferencesFor(id2_next), UnorderedElementsAre(id1)); EXPECT_THAT(GetReferencesFor(id3), UnorderedElementsAre(id2_next)); @@ -240,6 +241,8 @@ RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); + GetSurfaceManager().GarbageCollectSurfaces(); + // Removing the reference from the root to id1 should allow all three surfaces // to be deleted during GC even with a cycle between 2 and 3. EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1)); @@ -261,19 +264,23 @@ // active reference on all surfaces. DestroySurface(id1); DestroySurface(id2); + GetSurfaceManager().GarbageCollectSurfaces(); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id1)); EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); // Should delete |id2| when the only reference to it is removed. RemoveSurfaceReference(id1, id2); + GetSurfaceManager().GarbageCollectSurfaces(); EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); // Should delete |id1| when the only reference to it is removed. RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); + GetSurfaceManager().GarbageCollectSurfaces(); EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1)); } -TEST_F(SurfaceReferencesTest, GarbageCollectionWorksRecusively) { +TEST_F(SurfaceReferencesTest, GarbageCollectionWorksRecursively) { SurfaceId id1 = CreateSurface(kFrameSink1, 1); SurfaceId id2 = CreateSurface(kFrameSink2, 1); SurfaceId id3 = CreateSurface(kFrameSink3, 1); @@ -286,6 +293,8 @@ DestroySurface(id2); DestroySurface(id1); + GetSurfaceManager().GarbageCollectSurfaces(); + // Destroying the surfaces shouldn't delete them yet, since there is still an // active reference on all surfaces. EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id3)); @@ -294,6 +303,8 @@ RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); + GetSurfaceManager().GarbageCollectSurfaces(); + // Removing the reference from the root to id1 should allow all three surfaces // to be deleted during GC. EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1)); @@ -316,18 +327,21 @@ // Marking |id3| for destruction shouldn't cause it be garbage collected // because |id2| is still reachable from the root. DestroySurface(id3); + GetSurfaceManager().GarbageCollectSurfaces(); EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id3)); // Removing the surface reference to |id2| makes it not reachable from the // root, however it's not marked as destroyed and is still live. Make sure we // also don't delete any dependencies, such as |id3|, as well. RemoveSurfaceReference(id1, id2); + GetSurfaceManager().GarbageCollectSurfaces(); EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id3)); EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); // |id2| is unreachable and destroyed. Garbage collection should delete both // |id2| and |id3| now. DestroySurface(id2); + GetSurfaceManager().GarbageCollectSurfaces(); EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id3)); EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); } @@ -497,6 +511,8 @@ DestroySurface(id2); RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); + GetSurfaceManager().GarbageCollectSurfaces(); + // |id1| is destroyed and has no references, so it's deleted. EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1));
diff --git a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc index 93f4c2d..3727707 100644 --- a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc +++ b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -238,6 +238,8 @@ frame_sink_manager().surface_manager()->GetRootSurfaceId()), UnorderedElementsAre(display_id_second)); + frame_sink_manager().surface_manager()->GarbageCollectSurfaces(); + // Surface |display_id_first| is unreachable and should get deleted. EXPECT_EQ(nullptr, GetSurfaceForId(display_id_first)); } @@ -1028,6 +1030,8 @@ // Destroy the surface. child_support1().EvictCurrentSurface(); + frame_sink_manager().surface_manager()->GarbageCollectSurfaces(); + EXPECT_EQ(nullptr, GetSurfaceForId(child_id)); // Submit another frame with the same local surface id. This should work fine @@ -1631,6 +1635,8 @@ display_support().SubmitCompositorFrame(display_id.local_surface_id(), MakeCompositorFrame()); + frame_sink_manager().surface_manager()->GarbageCollectSurfaces(); + parent_surface = GetSurfaceForId(parent_id); EXPECT_EQ(nullptr, parent_surface); }
diff --git a/components/viz/service/gl/DEPS b/components/viz/service/gl/DEPS index fb1eb953..310c262 100644 --- a/components/viz/service/gl/DEPS +++ b/components/viz/service/gl/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+components/arc/video_accelerator", "+gpu/command_buffer", "+gpu/config", "+gpu/ipc",
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc index a2403248..349b6f5 100644 --- a/components/viz/service/gl/gpu_service_impl.cc +++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -51,6 +51,13 @@ #include "media/gpu/android/content_video_view_overlay_allocator.h" #endif +#if defined(OS_CHROMEOS) +#include "components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h" +#include "components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h" +#include "components/arc/video_accelerator/protected_buffer_manager.h" +#include "components/arc/video_accelerator/protected_buffer_manager_proxy.h" +#endif // defined(OS_CHROMEOS) + #if defined(OS_WIN) #include "gpu/ipc/service/direct_composition_surface_win.h" #endif @@ -111,6 +118,9 @@ bindings_(base::MakeUnique<mojo::BindingSet<mojom::GpuService>>()), weak_ptr_factory_(this) { DCHECK(!io_runner_->BelongsToCurrentThread()); +#if defined(OS_CHROMEOS) + protected_buffer_manager_ = std::make_unique<arc::ProtectedBufferManager>(); +#endif // defined(OS_CHROMEOS) weak_ptr_ = weak_ptr_factory_.GetWeakPtr(); } @@ -231,6 +241,76 @@ (*gpu_host_)->RecordLogMessage(severity, header, message); } +void GpuServiceImpl::CreateArcVideoDecodeAccelerator( + arc::mojom::VideoDecodeAcceleratorRequest vda_request) { +#if defined(OS_CHROMEOS) + DCHECK(io_runner_->BelongsToCurrentThread()); + main_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &GpuServiceImpl::CreateArcVideoDecodeAcceleratorOnMainThread, + weak_ptr_, std::move(vda_request))); +#else + NOTREACHED(); +#endif // defined(OS_CHROMEOS) +} + +void GpuServiceImpl::CreateArcVideoEncodeAccelerator( + arc::mojom::VideoEncodeAcceleratorRequest vea_request) { +#if defined(OS_CHROMEOS) + DCHECK(io_runner_->BelongsToCurrentThread()); + main_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &GpuServiceImpl::CreateArcVideoEncodeAcceleratorOnMainThread, + weak_ptr_, std::move(vea_request))); +#else + NOTREACHED(); +#endif // defined(OS_CHROMEOS) +} + +void GpuServiceImpl::CreateArcProtectedBufferManager( + arc::mojom::ProtectedBufferManagerRequest pbm_request) { +#if defined(OS_CHROMEOS) + DCHECK(io_runner_->BelongsToCurrentThread()); + main_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &GpuServiceImpl::CreateArcProtectedBufferManagerOnMainThread, + weak_ptr_, std::move(pbm_request))); +#else + NOTREACHED(); +#endif // defined(OS)CHROMEOS) +} + +#if defined(OS_CHROMEOS) +void GpuServiceImpl::CreateArcVideoDecodeAcceleratorOnMainThread( + arc::mojom::VideoDecodeAcceleratorRequest vda_request) { + DCHECK(main_runner_->BelongsToCurrentThread()); + mojo::MakeStrongBinding( + std::make_unique<arc::GpuArcVideoDecodeAccelerator>( + gpu_preferences_, protected_buffer_manager_.get()), + std::move(vda_request)); +} + +void GpuServiceImpl::CreateArcVideoEncodeAcceleratorOnMainThread( + arc::mojom::VideoEncodeAcceleratorRequest vea_request) { + DCHECK(main_runner_->BelongsToCurrentThread()); + mojo::MakeStrongBinding( + std::make_unique<arc::GpuArcVideoEncodeAccelerator>(gpu_preferences_), + std::move(vea_request)); +} + +void GpuServiceImpl::CreateArcProtectedBufferManagerOnMainThread( + arc::mojom::ProtectedBufferManagerRequest pbm_request) { + DCHECK(main_runner_->BelongsToCurrentThread()); + mojo::MakeStrongBinding( + std::make_unique<arc::GpuArcProtectedBufferManagerProxy>( + protected_buffer_manager_.get()), + std::move(pbm_request)); +} +#endif // defined(OS_CHROMEOS) + void GpuServiceImpl::CreateJpegDecodeAccelerator( media::mojom::GpuJpegDecodeAcceleratorRequest jda_request) { DCHECK(io_runner_->BelongsToCurrentThread());
diff --git a/components/viz/service/gl/gpu_service_impl.h b/components/viz/service/gl/gpu_service_impl.h index 00fdf20..27d6a08c 100644 --- a/components/viz/service/gl/gpu_service_impl.h +++ b/components/viz/service/gl/gpu_service_impl.h
@@ -28,6 +28,12 @@ #include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h" #include "ui/gfx/native_widget_types.h" +#if defined(OS_CHROMEOS) +namespace arc { +class ProtectedBufferManager; +} +#endif // OS_CHROMEOS + namespace gpu { class GpuMemoryBufferFactory; class GpuWatchdogThread; @@ -133,6 +139,12 @@ bool is_gpu_host, EstablishGpuChannelCallback callback) override; void CloseChannel(int32_t client_id) override; + void CreateArcVideoDecodeAccelerator( + arc::mojom::VideoDecodeAcceleratorRequest vda_request) override; + void CreateArcVideoEncodeAccelerator( + arc::mojom::VideoEncodeAcceleratorRequest vea_request) override; + void CreateArcProtectedBufferManager( + arc::mojom::ProtectedBufferManagerRequest pbm_request) override; void CreateJpegDecodeAccelerator( media::mojom::GpuJpegDecodeAcceleratorRequest jda_request) override; void CreateVideoEncodeAcceleratorProvider( @@ -163,6 +175,15 @@ void ThrowJavaException() override; void Stop(StopCallback callback) override; +#if defined(OS_CHROMEOS) + void CreateArcVideoDecodeAcceleratorOnMainThread( + arc::mojom::VideoDecodeAcceleratorRequest vda_request); + void CreateArcVideoEncodeAcceleratorOnMainThread( + arc::mojom::VideoEncodeAcceleratorRequest vea_request); + void CreateArcProtectedBufferManagerOnMainThread( + arc::mojom::ProtectedBufferManagerRequest pbm_request); +#endif // defined(OS_CHROMEOS) + void RequestHDRStatusOnMainThread(RequestHDRStatusCallback callback); scoped_refptr<base::SingleThreadTaskRunner> main_runner_; @@ -172,7 +193,7 @@ std::unique_ptr<gpu::GpuMemoryBufferFactory> gpu_memory_buffer_factory_; - gpu::GpuPreferences gpu_preferences_; + const gpu::GpuPreferences gpu_preferences_; // Information about the GPU, such as device and vendor ID. gpu::GPUInfo gpu_info_; @@ -202,6 +223,10 @@ base::CancelableTaskTracker bind_task_tracker_; std::unique_ptr<mojo::BindingSet<mojom::GpuService>> bindings_; +#if defined(OS_CHROMEOS) + std::unique_ptr<arc::ProtectedBufferManager> protected_buffer_manager_; +#endif // defined(OS_CHROMEOS) + base::WeakPtr<GpuServiceImpl> weak_ptr_; base::WeakPtrFactory<GpuServiceImpl> weak_ptr_factory_;
diff --git a/components/viz/service/main/BUILD.gn b/components/viz/service/main/BUILD.gn index 0e827e9..79f8996 100644 --- a/components/viz/service/main/BUILD.gn +++ b/components/viz/service/main/BUILD.gn
@@ -35,4 +35,8 @@ if (use_ozone) { deps += [ "//ui/ozone:ozone" ] } + + if (is_chromeos) { + deps += [ "//media/gpu" ] + } }
diff --git a/components/viz/service/main/DEPS b/components/viz/service/main/DEPS index ac38231..db0cb4b0 100644 --- a/components/viz/service/main/DEPS +++ b/components/viz/service/main/DEPS
@@ -5,6 +5,7 @@ "+gpu/ipc", "+gpu/ipc/common", "+gpu/ipc/service", + "+media/gpu", "+mojo/public/cpp", "+services/metrics/public", "+services/service_manager/public/cpp",
diff --git a/components/viz/service/main/viz_main_impl.cc b/components/viz/service/main/viz_main_impl.cc index e944922..486e66c 100644 --- a/components/viz/service/main/viz_main_impl.cc +++ b/components/viz/service/main/viz_main_impl.cc
@@ -21,11 +21,16 @@ #include "gpu/ipc/gpu_in_process_thread_service.h" #include "gpu/ipc/service/gpu_memory_buffer_factory.h" #include "gpu/ipc/service/gpu_watchdog_thread.h" +#include "media/gpu/features.h" #include "services/metrics/public/cpp/delegating_ukm_recorder.h" #include "services/metrics/public/cpp/mojo_ukm_recorder.h" #include "services/metrics/public/interfaces/constants.mojom.h" #include "services/service_manager/public/cpp/connector.h" +#if defined(OS_CHROMEOS) && BUILDFLAG(USE_VAAPI) +#include "media/gpu/vaapi_wrapper.h" +#endif + namespace { std::unique_ptr<base::Thread> CreateAndStartCompositorThread() { @@ -94,6 +99,14 @@ bool success = gpu::SwitchValueToGpuPreferences(value, &gpu_preferences); CHECK(success); } +#if defined(OS_CHROMEOS) && BUILDFLAG(USE_VAAPI) + // Initialize media codec. The UI service is running in a priviliged + // process. We don't need care when to initialize media codec. When we have + // a separate GPU (or VIZ) service process, we should initialize them + // before sandboxing + media::VaapiWrapper::PreSandboxInitialization(); +#endif + // Initialize GpuInit before starting the IO or compositor threads. gpu_init_ = std::make_unique<gpu::GpuInit>(); gpu_init_->set_sandbox_helper(this);
diff --git a/components/viz/service/surfaces/surface_manager.cc b/components/viz/service/surfaces/surface_manager.cc index 06dc61090..eaa2f2e 100644 --- a/components/viz/service/surfaces/surface_manager.cc +++ b/components/viz/service/surfaces/surface_manager.cc
@@ -132,7 +132,6 @@ for (auto& observer : observer_list_) observer.OnSurfaceDestroyed(surface_id); surfaces_to_destroy_.insert(surface_id); - GarbageCollectSurfaces(); } void SurfaceManager::SurfaceSubtreeDamaged(const SurfaceId& surface_id) { @@ -156,7 +155,6 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_EQ(lifetime_type_, LifetimeType::SEQUENCES); satisfied_sequences_.insert(sequence); - GarbageCollectSurfaces(); } void SurfaceManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) { @@ -218,8 +216,6 @@ for (const auto& reference : references) RemoveSurfaceReferenceImpl(reference.parent_id(), reference.child_id()); - - GarbageCollectSurfaces(); } void SurfaceManager::AssignTemporaryReference(const SurfaceId& surface_id, @@ -244,23 +240,8 @@ RemoveTemporaryReference(surface_id, false); } -const base::flat_set<SurfaceId>& SurfaceManager::GetSurfacesReferencedByParent( - const SurfaceId& surface_id) const { - auto iter = references_.find(surface_id); - if (iter == references_.end()) - return empty_surface_id_set_; - return iter->second.children; -} - -const base::flat_set<SurfaceId>& SurfaceManager::GetSurfacesThatReferenceChild( - const SurfaceId& surface_id) const { - auto iter = references_.find(surface_id); - if (iter == references_.end()) - return empty_surface_id_set_; - return iter->second.parents; -} - void SurfaceManager::GarbageCollectSurfaces() { + TRACE_EVENT0("viz", "SurfaceManager::GarbageCollectSurfaces"); if (surfaces_to_destroy_.empty()) return; @@ -286,6 +267,22 @@ DestroySurfaceInternal(surface_id); } +const base::flat_set<SurfaceId>& SurfaceManager::GetSurfacesReferencedByParent( + const SurfaceId& surface_id) const { + auto iter = references_.find(surface_id); + if (iter == references_.end()) + return empty_surface_id_set_; + return iter->second.children; +} + +const base::flat_set<SurfaceId>& SurfaceManager::GetSurfacesThatReferenceChild( + const SurfaceId& surface_id) const { + auto iter = references_.find(surface_id); + if (iter == references_.end()) + return empty_surface_id_set_; + return iter->second.parents; +} + SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForReferences() { DCHECK(using_surface_references());
diff --git a/components/viz/service/surfaces/surface_manager.h b/components/viz/service/surfaces/surface_manager.h index 237c14f..d4970f0 100644 --- a/components/viz/service/surfaces/surface_manager.h +++ b/components/viz/service/surfaces/surface_manager.h
@@ -176,6 +176,9 @@ // nothing. void DropTemporaryReference(const SurfaceId& surface_id); + // Garbage collects all destroyed surfaces that aren't live. + void GarbageCollectSurfaces(); + // Returns all surfaces referenced by parent |surface_id|. Will return an // empty set if |surface_id| is unknown or has no references. const base::flat_set<SurfaceId>& GetSurfacesReferencedByParent( @@ -228,9 +231,6 @@ bool marked_as_old = false; }; - // Garbage collects all destroyed surfaces that aren't live. - void GarbageCollectSurfaces(); - // Returns set of live surfaces for |lifetime_manager_| is REFERENCES. SurfaceIdSet GetLiveSurfacesForReferences();
diff --git a/components/viz/service/surfaces/surface_unittest.cc b/components/viz/service/surfaces/surface_unittest.cc index d1710fe..76cddb3 100644 --- a/components/viz/service/surfaces/surface_unittest.cc +++ b/components/viz/service/surfaces/surface_unittest.cc
@@ -27,7 +27,6 @@ TEST(SurfaceTest, PresentationCallback) { const gfx::Size kSurfaceSize(300, 300); const LocalSurfaceId local_surface_id(6, base::UnguessableToken::Create()); - const SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id); FrameSinkManagerImpl frame_sink_manager; MockCompositorFrameSinkClient client; @@ -73,6 +72,7 @@ // The frame with token 2 will be discarded when the surface is destroyed. EXPECT_CALL(client, DidDiscardCompositorFrame(2)).Times(1); support->EvictCurrentSurface(); + frame_sink_manager.surface_manager()->GarbageCollectSurfaces(); } TEST(SurfaceTest, SurfaceLifetime) { @@ -88,6 +88,7 @@ support->SubmitCompositorFrame(local_surface_id, test::MakeCompositorFrame()); EXPECT_TRUE(surface_manager->GetSurfaceForId(surface_id)); support->EvictCurrentSurface(); + frame_sink_manager.surface_manager()->GarbageCollectSurfaces(); EXPECT_EQ(nullptr, surface_manager->GetSurfaceForId(surface_id)); }
diff --git a/components/web_cache/README.md b/components/web_cache/README.md new file mode 100644 index 0000000..ac7a349 --- /dev/null +++ b/components/web_cache/README.md
@@ -0,0 +1,3 @@ +The WebCache component aims to coordinate the in-memory cache resource +usage of all renderers to not exceed a certain threshold while ensuring +that the active renderer has the most memory available for caching.
diff --git a/components/zoom/zoom_controller.cc b/components/zoom/zoom_controller.cc index c9ce9904..eb5732cd 100644 --- a/components/zoom/zoom_controller.cc +++ b/components/zoom/zoom_controller.cc
@@ -6,6 +6,7 @@ #include "components/zoom/zoom_event_manager.h" #include "components/zoom/zoom_observer.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/host_zoom_map.h" #include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_entry.h" @@ -20,6 +21,8 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(zoom::ZoomController); +using content::BrowserThread; + namespace zoom { double ZoomController::GetZoomLevelForWebContents( @@ -40,6 +43,7 @@ zoom_mode_(ZOOM_MODE_DEFAULT), zoom_level_(1.0), browser_context_(web_contents->GetBrowserContext()) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); host_zoom_map_ = content::HostZoomMap::GetForWebContents(web_contents); zoom_level_ = host_zoom_map_->GetDefaultZoomLevel(); @@ -49,43 +53,52 @@ UpdateState(std::string()); } -ZoomController::~ZoomController() {} +ZoomController::~ZoomController() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); +} bool ZoomController::IsAtDefaultZoom() const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); return content::ZoomValuesEqual(GetZoomLevel(), GetDefaultZoomLevel()); } ZoomController::RelativeZoom ZoomController::GetZoomRelativeToDefault() const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); double current_level = GetZoomLevel(); double default_level = GetDefaultZoomLevel(); if (content::ZoomValuesEqual(current_level, default_level)) return ZOOM_AT_DEFAULT_ZOOM; - else if (current_level > default_level) + if (current_level > default_level) return ZOOM_ABOVE_DEFAULT_ZOOM; return ZOOM_BELOW_DEFAULT_ZOOM; } void ZoomController::AddObserver(ZoomObserver* observer) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); observers_.AddObserver(observer); } void ZoomController::RemoveObserver(ZoomObserver* observer) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); observers_.RemoveObserver(observer); } double ZoomController::GetZoomLevel() const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); return zoom_mode_ == ZOOM_MODE_MANUAL ? zoom_level_ : content::HostZoomMap::GetZoomLevel(web_contents()); } int ZoomController::GetZoomPercent() const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); double zoom_factor = content::ZoomLevelToZoomFactor(GetZoomLevel()); // Round double for return. return static_cast<int>(zoom_factor * 100 + 0.5); } bool ZoomController::SetZoomLevel(double zoom_level) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); // A client did not initiate this zoom change. return SetZoomLevelByClient(zoom_level, nullptr); } @@ -93,6 +106,7 @@ bool ZoomController::SetZoomLevelByClient( double zoom_level, const scoped_refptr<const ZoomRequestClient>& client) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); content::NavigationEntry* entry = web_contents()->GetController().GetLastCommittedEntry(); // Cannot zoom in disabled mode. Also, don't allow changing zoom level on @@ -167,6 +181,7 @@ } void ZoomController::SetZoomMode(ZoomMode new_mode) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (new_mode == zoom_mode_) return; @@ -260,6 +275,7 @@ } void ZoomController::ResetZoomModeOnNavigationIfNeeded(const GURL& url) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (zoom_mode_ != ZOOM_MODE_ISOLATED && zoom_mode_ != ZOOM_MODE_MANUAL) return; @@ -286,6 +302,7 @@ void ZoomController::DidFinishNavigation( content::NavigationHandle* navigation_handle) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!navigation_handle->IsInMainFrame() || !navigation_handle->HasCommitted()) return; @@ -302,6 +319,7 @@ } void ZoomController::WebContentsDestroyed() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); // At this point we should no longer be sending any zoom events with this // WebContents. observers_.Clear(); @@ -310,6 +328,7 @@ void ZoomController::RenderFrameHostChanged( content::RenderFrameHost* old_host, content::RenderFrameHost* new_host) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); // If our associated HostZoomMap changes, update our event subscription. content::HostZoomMap* new_host_zoom_map = content::HostZoomMap::GetForWebContents(web_contents()); @@ -323,10 +342,12 @@ void ZoomController::OnZoomLevelChanged( const content::HostZoomMap::ZoomLevelChange& change) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); UpdateState(change.host); } void ZoomController::UpdateState(const std::string& host) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); // If |host| is empty, all observers should be updated. if (!host.empty()) { // Use the navigation entry's URL instead of the WebContents' so virtual @@ -374,6 +395,7 @@ } bool ZoomController::PageScaleFactorIsOne() const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); return content::HostZoomMap::PageScaleFactorIsOne(web_contents()); }
diff --git a/components/zoom/zoom_controller.h b/components/zoom/zoom_controller.h index b0ecd4cf..a29adb84 100644 --- a/components/zoom/zoom_controller.h +++ b/components/zoom/zoom_controller.h
@@ -39,7 +39,8 @@ DISALLOW_COPY_AND_ASSIGN(ZoomRequestClient); }; -// Per-tab class to manage zoom changes and the Omnibox zoom icon. +// Per-tab class to manage zoom changes and the Omnibox zoom icon. Lives on the +// UI thread. class ZoomController : public content::WebContentsObserver, public content::WebContentsUserData<ZoomController> { public:
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index f7a1fea..d64f9b7 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -662,6 +662,8 @@ "dom_storage/local_storage_context_mojo.h", "dom_storage/local_storage_database_adapter.cc", "dom_storage/local_storage_database_adapter.h", + "dom_storage/session_storage_context_mojo.cc", + "dom_storage/session_storage_context_mojo.h", "dom_storage/session_storage_database.cc", "dom_storage/session_storage_database.h", "dom_storage/session_storage_database_adapter.cc", @@ -1394,6 +1396,8 @@ "renderer_host/render_widget_helper.h", "renderer_host/render_widget_host_delegate.cc", "renderer_host/render_widget_host_delegate.h", + "renderer_host/render_widget_host_factory.cc", + "renderer_host/render_widget_host_factory.h", "renderer_host/render_widget_host_impl.cc", "renderer_host/render_widget_host_impl.h", "renderer_host/render_widget_host_input_event_router.cc",
diff --git a/content/browser/DEPS b/content/browser/DEPS index ff51b2f..1ffdd3a 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -51,6 +51,7 @@ "+third_party/iaccessible2", "+third_party/isimpledom", "+third_party/khronos", # For enum definitions only + "+third_party/libaom/av1_features.h", "+third_party/re2", "+third_party/zlib",
diff --git a/content/browser/accessibility/accessibility_ui.cc b/content/browser/accessibility/accessibility_ui.cc index 5aba2ef..e745f631 100644 --- a/content/browser/accessibility/accessibility_ui.cc +++ b/content/browser/accessibility/accessibility_ui.cc
@@ -22,6 +22,7 @@ #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" +#include "content/browser/web_contents/web_contents_view.h" #include "content/browser/webui/web_ui_data_source_impl.h" #include "content/common/view_message_enums.h" #include "content/grit/content_resources.h" @@ -36,6 +37,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "net/base/escape.h" +#include "ui/accessibility/platform/ax_platform_node.h" static const char kTargetsDataFile[] = "targets-data.json"; @@ -176,6 +178,20 @@ return true; } +std::string RecursiveDumpAXPlatformNodeAsString(ui::AXPlatformNode* node, + int indent) { + std::string str(2 * indent, '+'); + str += node->GetDelegate()->GetData().ToString() + "\n"; + for (int i = 0; i < node->GetDelegate()->GetChildCount(); i++) { + gfx::NativeViewAccessible child = node->GetDelegate()->ChildAtIndex(i); + ui::AXPlatformNode* child_node = + ui::AXPlatformNode::FromNativeViewAccessible(child); + if (child_node) + str += RecursiveDumpAXPlatformNodeAsString(child_node, indent + 1); + } + return str; +} + } // namespace AccessibilityUI::AccessibilityUI(WebUI* web_ui) : WebUIController(web_ui) { @@ -183,19 +199,6 @@ WebUIDataSourceImpl* html_source = static_cast<WebUIDataSourceImpl*>( WebUIDataSource::Create(kChromeUIAccessibilityHost)); - web_ui->RegisterMessageCallback( - "toggleAccessibility", - base::Bind(&AccessibilityUI::ToggleAccessibility, - base::Unretained(this))); - web_ui->RegisterMessageCallback( - "setGlobalFlag", - base::Bind(&AccessibilityUI::SetGlobalFlag, - base::Unretained(this))); - web_ui->RegisterMessageCallback( - "requestAccessibilityTree", - base::Bind(&AccessibilityUI::RequestAccessibilityTree, - base::Unretained(this))); - // Add required resources. html_source->SetJsonPath("strings.js"); html_source->AddResourcePath("accessibility.css", IDR_ACCESSIBILITY_CSS); @@ -210,11 +213,38 @@ BrowserContext* browser_context = web_ui->GetWebContents()->GetBrowserContext(); WebUIDataSource::Add(browser_context, html_source); + + web_ui->AddMessageHandler(base::MakeUnique<AccessibilityUIMessageHandler>()); } AccessibilityUI::~AccessibilityUI() {} -void AccessibilityUI::ToggleAccessibility(const base::ListValue* args) { +AccessibilityUIMessageHandler::AccessibilityUIMessageHandler() {} + +AccessibilityUIMessageHandler::~AccessibilityUIMessageHandler() {} + +void AccessibilityUIMessageHandler::RegisterMessages() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + web_ui()->RegisterMessageCallback( + "toggleAccessibility", + base::Bind(&AccessibilityUIMessageHandler::ToggleAccessibility, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "setGlobalFlag", base::Bind(&AccessibilityUIMessageHandler::SetGlobalFlag, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "requestWebContentsTree", + base::Bind(&AccessibilityUIMessageHandler::RequestWebContentsTree, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "requestNativeUITree", + base::Bind(&AccessibilityUIMessageHandler::RequestNativeUITree, + base::Unretained(this))); +} + +void AccessibilityUIMessageHandler::ToggleAccessibility( + const base::ListValue* args) { std::string process_id_str; std::string route_id_str; int process_id; @@ -228,6 +258,7 @@ CHECK(base::StringToInt(process_id_str, &process_id)); CHECK(base::StringToInt(route_id_str, &route_id)); + AllowJavascript(); RenderViewHost* rvh = RenderViewHost::FromID(process_id, route_id); if (!rvh) return; @@ -253,13 +284,14 @@ web_contents->SetAccessibilityMode(current_mode); } -void AccessibilityUI::SetGlobalFlag(const base::ListValue* args) { +void AccessibilityUIMessageHandler::SetGlobalFlag(const base::ListValue* args) { std::string flag_name_str; bool enabled; CHECK_EQ(2U, args->GetSize()); CHECK(args->GetString(0, &flag_name_str)); CHECK(args->GetBoolean(1, &enabled)); + AllowJavascript(); if (flag_name_str == kInternal) { g_show_internal_accessibility_tree = enabled; LOG(ERROR) << "INTERNAL: " << g_show_internal_accessibility_tree; @@ -306,7 +338,8 @@ state->RemoveAccessibilityModeFlags(new_mode); } -void AccessibilityUI::RequestAccessibilityTree(const base::ListValue* args) { +void AccessibilityUIMessageHandler::RequestWebContentsTree( + const base::ListValue* args) { std::string process_id_str; std::string route_id_str; int process_id; @@ -317,14 +350,14 @@ CHECK(base::StringToInt(process_id_str, &process_id)); CHECK(base::StringToInt(route_id_str, &route_id)); + AllowJavascript(); RenderViewHost* rvh = RenderViewHost::FromID(process_id, route_id); if (!rvh) { std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); result->SetInteger(kProcessIdField, process_id); result->SetInteger(kRouteIdField, route_id); result->SetString("error", "Renderer no longer exists."); - web_ui()->CallJavascriptFunctionUnsafe("accessibility.showTree", - *(result.get())); + CallJavascriptFunction("accessibility.showTree", *(result.get())); return; } @@ -352,8 +385,23 @@ formatter->FormatAccessibilityTree(ax_mgr->GetRoot(), &accessibility_contents_utf16); result->SetString("tree", base::UTF16ToUTF8(accessibility_contents_utf16)); - web_ui()->CallJavascriptFunctionUnsafe("accessibility.showTree", - *(result.get())); + CallJavascriptFunction("accessibility.showTree", *(result.get())); +} + +void AccessibilityUIMessageHandler::RequestNativeUITree( + const base::ListValue* args) { + AllowJavascript(); + WebContentsImpl* web_contents = + static_cast<WebContentsImpl*>(web_ui()->GetWebContents()); + gfx::NativeWindow native_window = + web_contents->GetView()->GetTopLevelNativeWindow(); + ui::AXPlatformNode* node = + ui::AXPlatformNode::FromNativeWindow(native_window); + std::string str = RecursiveDumpAXPlatformNodeAsString(node, 0); + + std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); + result->SetString("tree", str); + CallJavascriptFunction("accessibility.showNativeUITree", *(result.get())); } } // namespace content
diff --git a/content/browser/accessibility/accessibility_ui.h b/content/browser/accessibility/accessibility_ui.h index 2167b292..a54f23d3 100644 --- a/content/browser/accessibility/accessibility_ui.h +++ b/content/browser/accessibility/accessibility_ui.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_data_source.h" +#include "content/public/browser/web_ui_message_handler.h" namespace base { class ListValue; @@ -19,13 +20,22 @@ public: explicit AccessibilityUI(WebUI* web_ui); ~AccessibilityUI() override; +}; + +class AccessibilityUIMessageHandler : public content::WebUIMessageHandler { + public: + AccessibilityUIMessageHandler(); + ~AccessibilityUIMessageHandler() override; + + void RegisterMessages() override; private: void ToggleAccessibility(const base::ListValue* args); void SetGlobalFlag(const base::ListValue* args); - void RequestAccessibilityTree(const base::ListValue* args); + void RequestWebContentsTree(const base::ListValue* args); + void RequestNativeUITree(const base::ListValue* args); - DISALLOW_COPY_AND_ASSIGN(AccessibilityUI); + DISALLOW_COPY_AND_ASSIGN(AccessibilityUIMessageHandler); }; } // namespace content
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc index 3fb9c98..5c24a18 100644 --- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -302,8 +302,9 @@ RunEventTest(FILE_PATH_LITERAL("live-region-ignores-click.html")); } +// http:/crbug.com/786848 IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - AccessibilityEventsLiveRegionRemove) { + DISABLED_AccessibilityEventsLiveRegionRemove) { RunEventTest(FILE_PATH_LITERAL("live-region-remove.html")); }
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc index 5128c89..d5ec2e9 100644 --- a/content/browser/background_sync/background_sync_manager_unittest.cc +++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -469,17 +469,9 @@ ServiceWorkerProviderHost* provider_host = sw_registration_1_->active_version()->provider_host(); ASSERT_TRUE(provider_host); - int process_id = provider_host->process_id(); - int provider_id = provider_host->provider_id(); // Remove the registration object host. - ServiceWorkerDispatcherHost* dispatcher_host = - helper_->context()->GetDispatcherHost(process_id); - ServiceWorkerRegistrationObjectHost* registration_object_host = - dispatcher_host->FindServiceWorkerRegistrationObjectHost( - provider_id, sw_registration_1_->id()); - dispatcher_host->UnregisterServiceWorkerRegistrationObjectHost( - registration_object_host->handle_id()); + provider_host->registration_object_hosts_.clear(); // Ensure |sw_registration_1_| is the last reference to the registration. ASSERT_TRUE(sw_registration_1_->HasOneRef());
diff --git a/content/browser/compositor/reflector_impl_unittest.cc b/content/browser/compositor/reflector_impl_unittest.cc index 2e96dab..bcf802a 100644 --- a/content/browser/compositor/reflector_impl_unittest.cc +++ b/content/browser/compositor/reflector_impl_unittest.cc
@@ -175,9 +175,9 @@ void TearDown() override { if (reflector_) reflector_->RemoveMirroringLayer(mirroring_layer_.get()); - viz::TextureMailbox mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release; - if (mirroring_layer_->PrepareTextureMailbox(&mailbox, &release)) { + if (mirroring_layer_->PrepareTransferableResource(&resource, &release)) { release->Run(gpu::SyncToken(), false); } compositor_.reset();
diff --git a/content/browser/device_sensors/device_sensor_browsertest.cc b/content/browser/device_sensors/device_sensor_browsertest.cc index a1cfa33..54171a1 100644 --- a/content/browser/device_sensors/device_sensor_browsertest.cc +++ b/content/browser/device_sensors/device_sensor_browsertest.cc
@@ -14,9 +14,12 @@ #include "base/synchronization/waitable_event.h" #include "base/threading/platform_thread.h" #include "build/build_config.h" +#include "components/network_session_configurator/common/network_switches.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" +#include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" @@ -26,6 +29,7 @@ #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/system/buffer.h" +#include "net/dns/mock_host_resolver.h" #include "services/device/public/cpp/generic_sensor/platform_sensor_configuration.h" #include "services/device/public/cpp/generic_sensor/sensor_reading.h" #include "services/device/public/interfaces/constants.mojom.h" @@ -263,6 +267,16 @@ base::WaitableEvent::InitialState::NOT_SIGNALED) {} void SetUpOnMainThread() override { + https_embedded_test_server_.reset( + new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); + // Serve both a.com and b.com (and any other domain). + host_resolver()->AddRule("*", "127.0.0.1"); + ASSERT_TRUE(https_embedded_test_server_->InitializeAndListen()); + content::SetupCrossSiteRedirector(https_embedded_test_server_.get()); + https_embedded_test_server_->ServeFilesFromSourceDirectory( + "content/test/data/device_sensors"); + https_embedded_test_server_->StartAcceptingConnections(); + sensor_provider_ = std::make_unique<FakeSensorProvider>(); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, @@ -271,6 +285,12 @@ io_loop_finished_event_.Wait(); } + void SetUpCommandLine(base::CommandLine* command_line) override { + // HTTPS server only serves a valid cert for localhost, so this is needed + // to load pages from other hosts without an error. + command_line->AppendSwitch(switches::kIgnoreCertificateErrors); + } + void SetUpOnIOThread() { // Because Device Service also runs in this process(browser process), here // we can directly set our binder to intercept interface requests against @@ -301,6 +321,7 @@ } std::unique_ptr<FakeSensorProvider> sensor_provider_; + std::unique_ptr<net::EmbeddedTestServer> https_embedded_test_server_; private: base::WaitableEvent io_loop_finished_event_; @@ -437,6 +458,52 @@ EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref()); } +IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, + DeviceMotionCrossOriginIframeTest) { + // Main frame is on a.com, iframe is on b.com. + GURL main_frame_url = + https_embedded_test_server_->GetURL("a.com", "/cross_origin_iframe.html"); + GURL iframe_url = + https_embedded_test_server_->GetURL("b.com", "/device_motion_test.html"); + + // Wait for the main frame, subframe, and the #pass/#fail commits. + TestNavigationObserver navigation_observer(shell()->web_contents(), 3); + + EXPECT_TRUE(NavigateToURL(shell(), main_frame_url)); + EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), + "cross_origin_iframe", iframe_url)); + + navigation_observer.Wait(); + + content::RenderFrameHost* iframe = + ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0); + ASSERT_TRUE(iframe); + EXPECT_EQ("pass", iframe->GetLastCommittedURL().ref()); +} + +IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, + DeviceOrientationCrossOriginIframeTest) { + // Main frame is on a.com, iframe is on b.com. + GURL main_frame_url = + https_embedded_test_server_->GetURL("a.com", "/cross_origin_iframe.html"); + GURL iframe_url = https_embedded_test_server_->GetURL( + "b.com", "/device_orientation_test.html"); + + // Wait for the main frame, subframe, and the #pass/#fail commits. + TestNavigationObserver navigation_observer(shell()->web_contents(), 3); + + EXPECT_TRUE(NavigateToURL(shell(), main_frame_url)); + EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), + "cross_origin_iframe", iframe_url)); + + navigation_observer.Wait(); + + content::RenderFrameHost* iframe = + ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0); + ASSERT_TRUE(iframe); + EXPECT_EQ("pass", iframe->GetLastCommittedURL().ref()); +} + } // namespace } // namespace content
diff --git a/content/browser/devtools/devtools_agent_host_impl.cc b/content/browser/devtools/devtools_agent_host_impl.cc index 497472b..0dfe264 100644 --- a/content/browser/devtools/devtools_agent_host_impl.cc +++ b/content/browser/devtools/devtools_agent_host_impl.cc
@@ -86,21 +86,6 @@ return result; } -// Called on the UI thread. -// static -scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForWorker( - int worker_process_id, - int worker_route_id) { - if (scoped_refptr<DevToolsAgentHost> host = - SharedWorkerDevToolsManager::GetInstance() - ->GetDevToolsAgentHostForWorker(worker_process_id, - worker_route_id)) { - return host; - } - return ServiceWorkerDevToolsManager::GetInstance() - ->GetDevToolsAgentHostForWorker(worker_process_id, worker_route_id); -} - DevToolsAgentHostImpl::DevToolsAgentHostImpl(const std::string& id) : id_(id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); }
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index 9fd868b9..bab5656 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -359,7 +359,7 @@ std::string frame_id = web_contents->GetMainFrame()->GetDevToolsFrameToken().ToString(); std::string error_string = net::ErrorToString(net::ERR_ABORTED); - navigate_callback_->sendSuccess(frame_id, + navigate_callback_->sendSuccess(frame_id, Maybe<std::string>(), Maybe<std::string>(error_string)); } navigate_callback_ = std::move(callback); @@ -384,6 +384,8 @@ net::ErrorToString(navigation_request->net_error()); navigate_callback_->sendSuccess( frame_id, + Maybe<std::string>( + navigation_request->devtools_navigation_token().ToString()), success ? Maybe<std::string>(error_string) : Maybe<std::string>()); navigate_callback_.reset(); }
diff --git a/content/browser/devtools/protocol/service_worker_handler.cc b/content/browser/devtools/protocol/service_worker_handler.cc index 619d763..54e667e 100644 --- a/content/browser/devtools/protocol/service_worker_handler.cc +++ b/content/browser/devtools/protocol/service_worker_handler.cc
@@ -12,6 +12,7 @@ #include "content/browser/background_sync/background_sync_manager.h" #include "content/browser/devtools/service_worker_devtools_agent_host.h" #include "content/browser/devtools/service_worker_devtools_manager.h" +#include "content/browser/devtools/shared_worker_devtools_manager.h" #include "content/browser/frame_host/frame_tree.h" #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/service_worker/embedded_worker_status.h" @@ -396,13 +397,6 @@ continue; client_set.insert( DevToolsAgentHost::GetOrCreateFor(web_contents)->GetId()); - } else if (client.second.type == - SERVICE_WORKER_PROVIDER_FOR_SHARED_WORKER) { - scoped_refptr<DevToolsAgentHost> agent_host( - DevToolsAgentHost::GetForWorker(client.second.process_id, - client.second.route_id)); - if (agent_host) - client_set.insert(agent_host->GetId()); } } std::unique_ptr<protocol::Array<std::string>> clients =
diff --git a/content/browser/devtools/shared_worker_devtools_agent_host.cc b/content/browser/devtools/shared_worker_devtools_agent_host.cc index afcec9c8..96689aad 100644 --- a/content/browser/devtools/shared_worker_devtools_agent_host.cc +++ b/content/browser/devtools/shared_worker_devtools_agent_host.cc
@@ -11,16 +11,6 @@ namespace content { -namespace { - -void TerminateSharedWorkerOnIO( - WorkerDevToolsAgentHost::WorkerId worker_id) { - SharedWorkerServiceImpl::GetInstance()->TerminateWorker( - worker_id.first, worker_id.second); -} - -} // namespace - SharedWorkerDevToolsAgentHost::SharedWorkerDevToolsAgentHost( WorkerId worker_id, const SharedWorkerInstance& shared_worker) @@ -49,9 +39,8 @@ } bool SharedWorkerDevToolsAgentHost::Close() { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&TerminateSharedWorkerOnIO, worker_id())); + SharedWorkerServiceImpl::GetInstance()->TerminateWorker(worker_id().first, + worker_id().second); return true; }
diff --git a/content/browser/devtools/shared_worker_devtools_manager.cc b/content/browser/devtools/shared_worker_devtools_manager.cc index 4d38241..9903398 100644 --- a/content/browser/devtools/shared_worker_devtools_manager.cc +++ b/content/browser/devtools/shared_worker_devtools_manager.cc
@@ -16,15 +16,6 @@ return base::Singleton<SharedWorkerDevToolsManager>::get(); } -DevToolsAgentHostImpl* -SharedWorkerDevToolsManager::GetDevToolsAgentHostForWorker( - int worker_process_id, - int worker_route_id) { - AgentHostMap::iterator it = workers_.find( - WorkerId(worker_process_id, worker_route_id)); - return it == workers_.end() ? NULL : it->second; -} - void SharedWorkerDevToolsManager::AddAllAgentHosts( SharedWorkerDevToolsAgentHost::List* result) { for (auto& worker : workers_) {
diff --git a/content/browser/devtools/shared_worker_devtools_manager.h b/content/browser/devtools/shared_worker_devtools_manager.h index 40d1ffc..c7f4f7c 100644 --- a/content/browser/devtools/shared_worker_devtools_manager.h +++ b/content/browser/devtools/shared_worker_devtools_manager.h
@@ -14,7 +14,6 @@ namespace content { -class DevToolsAgentHostImpl; class SharedWorkerDevToolsAgentHost; class SharedWorkerInstance; @@ -27,8 +26,6 @@ // Returns the SharedWorkerDevToolsManager singleton. static SharedWorkerDevToolsManager* GetInstance(); - DevToolsAgentHostImpl* GetDevToolsAgentHostForWorker(int worker_process_id, - int worker_route_id); void AddAllAgentHosts( std::vector<scoped_refptr<SharedWorkerDevToolsAgentHost>>* result);
diff --git a/content/browser/devtools/shared_worker_devtools_manager_unittest.cc b/content/browser/devtools/shared_worker_devtools_manager_unittest.cc index eab045f..1ff57d25 100644 --- a/content/browser/devtools/shared_worker_devtools_manager_unittest.cc +++ b/content/browser/devtools/shared_worker_devtools_manager_unittest.cc
@@ -76,24 +76,30 @@ void CheckWorkerState(int worker_process_id, int worker_route_id, WorkerState state) { - const SharedWorkerDevToolsManager::WorkerId id(worker_process_id, - worker_route_id); - SharedWorkerDevToolsManager::AgentHostMap::iterator it = - manager_->workers_.find(id); - EXPECT_TRUE(manager_->workers_.end() != it); - EXPECT_EQ(state, it->second->state_); + SharedWorkerDevToolsAgentHost* host = + GetDevToolsAgentHostForWorker(worker_process_id, worker_route_id); + EXPECT_TRUE(!!host); + EXPECT_EQ(state, host->state_); } void CheckWorkerNotExist(int worker_process_id, int worker_route_id) { - const SharedWorkerDevToolsManager::WorkerId id(worker_process_id, - worker_route_id); - EXPECT_TRUE(manager_->workers_.end() == manager_->workers_.find(id)); + EXPECT_TRUE( + !GetDevToolsAgentHostForWorker(worker_process_id, worker_route_id)); } void CheckWorkerCount(size_t size) { EXPECT_EQ(size, manager_->workers_.size()); } + SharedWorkerDevToolsAgentHost* GetDevToolsAgentHostForWorker( + int worker_process_id, + int worker_route_id) { + const SharedWorkerDevToolsManager::WorkerId id(worker_process_id, + worker_route_id); + auto it = manager_->workers_.find(id); + return it == manager_->workers_.end() ? nullptr : it->second; + } + TestBrowserThreadBundle browser_thread_bundle_; std::unique_ptr<TestBrowserContext> browser_context_; std::unique_ptr<WorkerStoragePartition> partition_; @@ -111,7 +117,7 @@ blink::mojom::SharedWorkerCreationContextType::kNonsecure, base::UnguessableToken::Create()); - agent_host = manager_->GetDevToolsAgentHostForWorker(1, 1); + agent_host = GetDevToolsAgentHostForWorker(1, 1); EXPECT_FALSE(agent_host.get()); // Created -> Started -> Destroyed @@ -127,10 +133,10 @@ CheckWorkerNotExist(1, 2); manager_->WorkerCreated(1, 2, instance1); CheckWorkerState(1, 2, WorkerState::WORKER_UNINSPECTED); - agent_host = manager_->GetDevToolsAgentHostForWorker(1, 2); + agent_host = GetDevToolsAgentHostForWorker(1, 2); EXPECT_TRUE(agent_host.get()); CheckWorkerState(1, 2, WorkerState::WORKER_UNINSPECTED); - EXPECT_EQ(agent_host.get(), manager_->GetDevToolsAgentHostForWorker(1, 2)); + EXPECT_EQ(agent_host.get(), GetDevToolsAgentHostForWorker(1, 2)); manager_->WorkerReadyForInspection(1, 2); CheckWorkerState(1, 2, WorkerState::WORKER_UNINSPECTED); manager_->WorkerDestroyed(1, 2); @@ -144,7 +150,7 @@ CheckWorkerState(1, 3, WorkerState::WORKER_UNINSPECTED); manager_->WorkerReadyForInspection(1, 3); CheckWorkerState(1, 3, WorkerState::WORKER_UNINSPECTED); - agent_host = manager_->GetDevToolsAgentHostForWorker(1, 3); + agent_host = GetDevToolsAgentHostForWorker(1, 3); EXPECT_TRUE(agent_host.get()); CheckWorkerState(1, 3, WorkerState::WORKER_UNINSPECTED); manager_->WorkerDestroyed(1, 3); @@ -163,7 +169,7 @@ CheckWorkerNotExist(1, 5); manager_->WorkerCreated(1, 5, instance1); CheckWorkerState(1, 5, WorkerState::WORKER_UNINSPECTED); - agent_host = manager_->GetDevToolsAgentHostForWorker(1, 5); + agent_host = GetDevToolsAgentHostForWorker(1, 5); EXPECT_TRUE(agent_host.get()); CheckWorkerState(1, 5, WorkerState::WORKER_UNINSPECTED); manager_->WorkerDestroyed(1, 5); @@ -175,7 +181,7 @@ CheckWorkerNotExist(1, 6); manager_->WorkerCreated(1, 6, instance1); CheckWorkerState(1, 6, WorkerState::WORKER_UNINSPECTED); - agent_host = manager_->GetDevToolsAgentHostForWorker(1, 6); + agent_host = GetDevToolsAgentHostForWorker(1, 6); EXPECT_TRUE(agent_host.get()); CheckWorkerState(1, 6, WorkerState::WORKER_UNINSPECTED); agent_host = nullptr; @@ -206,17 +212,17 @@ CheckWorkerNotExist(2, 1); manager_->WorkerCreated(2, 1, instance1); CheckWorkerState(2, 1, WorkerState::WORKER_UNINSPECTED); - agent_host1 = manager_->GetDevToolsAgentHostForWorker(2, 1); + agent_host1 = GetDevToolsAgentHostForWorker(2, 1); EXPECT_TRUE(agent_host1.get()); CheckWorkerState(2, 1, WorkerState::WORKER_UNINSPECTED); - EXPECT_EQ(agent_host1.get(), manager_->GetDevToolsAgentHostForWorker(2, 1)); + EXPECT_EQ(agent_host1.get(), GetDevToolsAgentHostForWorker(2, 1)); client_host1->InspectAgentHost(agent_host1.get()); CheckWorkerState(2, 1, WorkerState::WORKER_INSPECTED); manager_->WorkerReadyForInspection(2, 1); CheckWorkerState(2, 1, WorkerState::WORKER_INSPECTED); manager_->WorkerDestroyed(2, 1); CheckWorkerState(2, 1, WorkerState::WORKER_TERMINATED); - EXPECT_EQ(agent_host1.get(), manager_->GetDevToolsAgentHostForWorker(2, 1)); + EXPECT_EQ(agent_host1.get(), GetDevToolsAgentHostForWorker(2, 1)); // Created -> Started -> GetDevToolsAgentHost -> Register -> Destroyed std::unique_ptr<TestDevToolsClientHost> client_host2( @@ -225,23 +231,23 @@ CheckWorkerState(2, 2, WorkerState::WORKER_UNINSPECTED); manager_->WorkerReadyForInspection(2, 2); CheckWorkerState(2, 2, WorkerState::WORKER_UNINSPECTED); - agent_host2 = manager_->GetDevToolsAgentHostForWorker(2, 2); + agent_host2 = GetDevToolsAgentHostForWorker(2, 2); EXPECT_TRUE(agent_host2.get()); EXPECT_NE(agent_host1.get(), agent_host2.get()); - EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 2)); + EXPECT_EQ(agent_host2.get(), GetDevToolsAgentHostForWorker(2, 2)); CheckWorkerState(2, 2, WorkerState::WORKER_UNINSPECTED); client_host2->InspectAgentHost(agent_host2.get()); CheckWorkerState(2, 2, WorkerState::WORKER_INSPECTED); manager_->WorkerDestroyed(2, 2); CheckWorkerState(2, 2, WorkerState::WORKER_TERMINATED); - EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 2)); + EXPECT_EQ(agent_host2.get(), GetDevToolsAgentHostForWorker(2, 2)); // Re-created -> Started -> ClientHostClosing -> Destroyed CheckWorkerState(2, 1, WorkerState::WORKER_TERMINATED); manager_->WorkerCreated(2, 3, instance1); CheckWorkerNotExist(2, 1); CheckWorkerState(2, 3, WorkerState::WORKER_PAUSED_FOR_REATTACH); - EXPECT_EQ(agent_host1.get(), manager_->GetDevToolsAgentHostForWorker(2, 3)); + EXPECT_EQ(agent_host1.get(), GetDevToolsAgentHostForWorker(2, 3)); manager_->WorkerReadyForInspection(2, 3); CheckWorkerState(2, 3, WorkerState::WORKER_INSPECTED); client_host1->InspectAgentHost(nullptr); @@ -255,7 +261,7 @@ manager_->WorkerCreated(2, 4, instance2); CheckWorkerNotExist(2, 2); CheckWorkerState(2, 4, WorkerState::WORKER_PAUSED_FOR_REATTACH); - EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 4)); + EXPECT_EQ(agent_host2.get(), GetDevToolsAgentHostForWorker(2, 4)); manager_->WorkerDestroyed(2, 4); CheckWorkerNotExist(2, 2); CheckWorkerState(2, 4, WorkerState::WORKER_TERMINATED); @@ -264,7 +270,7 @@ manager_->WorkerCreated(2, 5, instance2); CheckWorkerNotExist(2, 2); CheckWorkerState(2, 5, WorkerState::WORKER_PAUSED_FOR_REATTACH); - EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 5)); + EXPECT_EQ(agent_host2.get(), GetDevToolsAgentHostForWorker(2, 5)); client_host2->InspectAgentHost(nullptr); CheckWorkerCount(1); agent_host2 = nullptr; @@ -286,7 +292,7 @@ manager_->WorkerCreated(3, 1, instance); CheckWorkerState(3, 1, WorkerState::WORKER_UNINSPECTED); scoped_refptr<DevToolsAgentHost> agent_host( - manager_->GetDevToolsAgentHostForWorker(3, 1)); + GetDevToolsAgentHostForWorker(3, 1)); EXPECT_TRUE(agent_host.get()); CheckWorkerState(3, 1, WorkerState::WORKER_UNINSPECTED); client_host->InspectAgentHost(agent_host.get()); @@ -316,9 +322,8 @@ new TestDevToolsClientHost()); manager_->WorkerCreated(3, 1, instance); CheckWorkerState(3, 1, WorkerState::WORKER_UNINSPECTED); - scoped_refptr<WorkerDevToolsAgentHost> agent_host( - static_cast<WorkerDevToolsAgentHost*>( - manager_->GetDevToolsAgentHostForWorker(3, 1))); + scoped_refptr<SharedWorkerDevToolsAgentHost> agent_host( + GetDevToolsAgentHostForWorker(3, 1)); EXPECT_TRUE(agent_host.get()); CheckWorkerState(3, 1, WorkerState::WORKER_UNINSPECTED); agent_host->PauseForDebugOnStart();
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper.cc b/content/browser/dom_storage/dom_storage_context_wrapper.cc index bb57d32..382ccddd 100644 --- a/content/browser/dom_storage/dom_storage_context_wrapper.cc +++ b/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -25,6 +25,7 @@ #include "content/browser/dom_storage/dom_storage_context_impl.h" #include "content/browser/dom_storage/dom_storage_task_runner.h" #include "content/browser/dom_storage/local_storage_context_mojo.h" +#include "content/browser/dom_storage/session_storage_context_mojo.h" #include "content/browser/dom_storage/session_storage_namespace_impl.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/local_storage_usage_info.h" @@ -135,6 +136,15 @@ storage_dir, special_storage_policy); } + if (base::FeatureList::IsEnabled(features::kMojoSessionStorage)) { + base::FilePath session_storage_dir; + if (!profile_path.empty()) + session_storage_dir = + local_partition_path.AppendASCII(kSessionStorageDirectory); + mojo_session_state_ = std::make_unique<SessionStorageContextMojo>( + connector, session_storage_dir); + } + if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) { base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this); } else { @@ -332,6 +342,16 @@ std::move(request))); } +void DOMStorageContextWrapper::OpenSessionStorage( + int64_t namespace_id, + const url::Origin& origin, + mojom::LevelDBWrapperRequest request) { + if (!mojo_session_state_) + return; + mojo_session_state_->OpenSessionStorage(namespace_id, origin, + std::move(request)); +} + void DOMStorageContextWrapper::SetLocalStorageDatabaseForTesting( leveldb::mojom::LevelDBDatabaseAssociatedPtr database) { if (!mojo_state_) @@ -346,6 +366,12 @@ base::Unretained(mojo_state_), std::move(database))); } +base::WeakPtr<SessionStorageContextMojo> +DOMStorageContextWrapper::GetMojoSessionStateWeakPtr() { + return mojo_session_state_ ? mojo_session_state_->AsWeakPtr() + : base::WeakPtr<SessionStorageContextMojo>(); +} + void DOMStorageContextWrapper::OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { DOMStorageContextImpl::PurgeOption purge_option =
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper.h b/content/browser/dom_storage/dom_storage_context_wrapper.h index ef74dc30..ccc7d2f 100644 --- a/content/browser/dom_storage/dom_storage_context_wrapper.h +++ b/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -12,6 +12,7 @@ #include "base/memory/memory_coordinator_client.h" #include "base/memory/memory_pressure_listener.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "content/browser/dom_storage/dom_storage_context_impl.h" #include "content/common/content_export.h" #include "content/common/storage_partition_service.mojom.h" @@ -34,6 +35,7 @@ class DOMStorageContextImpl; class LocalStorageContextMojo; +class SessionStorageContextMojo; // This is owned by Storage Partition and encapsulates all its dom storage // state. @@ -76,6 +78,9 @@ // See mojom::StoragePartitionService interface. void OpenLocalStorage(const url::Origin& origin, mojom::LevelDBWrapperRequest request); + void OpenSessionStorage(int64_t namespace_id, + const url::Origin& origin, + mojom::LevelDBWrapperRequest request); void SetLocalStorageDatabaseForTesting( leveldb::mojom::LevelDBDatabaseAssociatedPtr database); @@ -88,6 +93,10 @@ ~DOMStorageContextWrapper() override; DOMStorageContextImpl* context() const { return context_.get(); } + SessionStorageContextMojo* mojo_session_state() { + return mojo_session_state_.get(); + } + base::WeakPtr<SessionStorageContextMojo> GetMojoSessionStateWeakPtr(); // Called on UI thread when the system is under memory pressure. void OnMemoryPressure( @@ -103,6 +112,7 @@ // asynchronously on the |mojo_task_runner_|. LocalStorageContextMojo* mojo_state_ = nullptr; scoped_refptr<base::SingleThreadTaskRunner> mojo_task_runner_; + std::unique_ptr<SessionStorageContextMojo> mojo_session_state_; // To receive memory pressure signals. std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
diff --git a/content/browser/dom_storage/dom_storage_session.cc b/content/browser/dom_storage/dom_storage_session.cc index 3cdaded..a8a4595 100644 --- a/content/browser/dom_storage/dom_storage_session.cc +++ b/content/browser/dom_storage/dom_storage_session.cc
@@ -9,11 +9,15 @@ #include "base/logging.h" #include "content/browser/dom_storage/dom_storage_context_impl.h" #include "content/browser/dom_storage/dom_storage_task_runner.h" +#include "content/browser/dom_storage/session_storage_context_mojo.h" namespace content { -DOMStorageSession::DOMStorageSession(DOMStorageContextImpl* context) +DOMStorageSession::DOMStorageSession( + DOMStorageContextImpl* context, + base::WeakPtr<SessionStorageContextMojo> mojo_context) : context_(context), + mojo_context_(mojo_context), namespace_id_(context->AllocateSessionId()), persistent_namespace_id_(context->AllocatePersistentSessionId()), should_persist_(false) { @@ -21,11 +25,17 @@ FROM_HERE, base::BindOnce(&DOMStorageContextImpl::CreateSessionNamespace, context_, namespace_id_, persistent_namespace_id_)); + if (mojo_context_) + mojo_context_->CreateSessionNamespace(namespace_id_, + persistent_namespace_id_); } -DOMStorageSession::DOMStorageSession(DOMStorageContextImpl* context, - const std::string& persistent_namespace_id) +DOMStorageSession::DOMStorageSession( + DOMStorageContextImpl* context, + base::WeakPtr<SessionStorageContextMojo> mojo_context, + const std::string& persistent_namespace_id) : context_(context), + mojo_context_(mojo_context), namespace_id_(context->AllocateSessionId()), persistent_namespace_id_(persistent_namespace_id), should_persist_(false) { @@ -33,6 +43,9 @@ FROM_HERE, base::BindOnce(&DOMStorageContextImpl::CreateSessionNamespace, context_, namespace_id_, persistent_namespace_id_)); + if (mojo_context_) + mojo_context_->CreateSessionNamespace(namespace_id_, + persistent_namespace_id_); } void DOMStorageSession::SetShouldPersist(bool should_persist) { @@ -48,25 +61,34 @@ } DOMStorageSession* DOMStorageSession::Clone() { - return CloneFrom(context_.get(), namespace_id_); + return CloneFrom(context_.get(), mojo_context_, namespace_id_); } // static -DOMStorageSession* DOMStorageSession::CloneFrom(DOMStorageContextImpl* context, - int64_t namepace_id_to_clone) { +DOMStorageSession* DOMStorageSession::CloneFrom( + DOMStorageContextImpl* context, + base::WeakPtr<SessionStorageContextMojo> mojo_context, + int64_t namespace_id_to_clone) { int64_t clone_id = context->AllocateSessionId(); std::string persistent_clone_id = context->AllocatePersistentSessionId(); context->task_runner()->PostTask( FROM_HERE, base::BindOnce(&DOMStorageContextImpl::CloneSessionNamespace, context, - namepace_id_to_clone, clone_id, persistent_clone_id)); - return new DOMStorageSession(context, clone_id, persistent_clone_id); + namespace_id_to_clone, clone_id, persistent_clone_id)); + if (mojo_context) + mojo_context->CloneSessionNamespace(namespace_id_to_clone, clone_id, + persistent_clone_id); + return new DOMStorageSession(context, std::move(mojo_context), clone_id, + persistent_clone_id); } -DOMStorageSession::DOMStorageSession(DOMStorageContextImpl* context, - int64_t namespace_id, - const std::string& persistent_namespace_id) +DOMStorageSession::DOMStorageSession( + DOMStorageContextImpl* context, + base::WeakPtr<SessionStorageContextMojo> mojo_context, + int64_t namespace_id, + const std::string& persistent_namespace_id) : context_(context), + mojo_context_(mojo_context), namespace_id_(namespace_id), persistent_namespace_id_(persistent_namespace_id), should_persist_(false) { @@ -77,6 +99,8 @@ context_->task_runner()->PostTask( FROM_HERE, base::BindOnce(&DOMStorageContextImpl::DeleteSessionNamespace, context_, namespace_id_, should_persist_)); + if (mojo_context_) + mojo_context_->DeleteSessionNamespace(namespace_id_, should_persist_); } } // namespace content
diff --git a/content/browser/dom_storage/dom_storage_session.h b/content/browser/dom_storage/dom_storage_session.h index 08e54f3..352a41e 100644 --- a/content/browser/dom_storage/dom_storage_session.h +++ b/content/browser/dom_storage/dom_storage_session.h
@@ -11,11 +11,13 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "content/common/content_export.h" namespace content { class DOMStorageContextImpl; +class SessionStorageContextMojo; // This refcounted class determines the lifetime of a session // storage namespace and provides an interface to Clone() an @@ -25,11 +27,14 @@ : public base::RefCountedThreadSafe<DOMStorageSession> { public: // Constructs a |DOMStorageSession| and allocates new IDs for it. - explicit DOMStorageSession(DOMStorageContextImpl* context); + explicit DOMStorageSession( + DOMStorageContextImpl* context, + base::WeakPtr<SessionStorageContextMojo> mojo_context); // Constructs a |DOMStorageSession| and assigns |persistent_namespace_id| // to it. Allocates a new non-persistent ID. DOMStorageSession(DOMStorageContextImpl* context, + base::WeakPtr<SessionStorageContextMojo> mojo_context, const std::string& persistent_namespace_id); int64_t namespace_id() const { return namespace_id_; } @@ -43,18 +48,22 @@ // Constructs a |DOMStorageSession| by cloning // |namespace_id_to_clone|. Allocates new IDs for it. - static DOMStorageSession* CloneFrom(DOMStorageContextImpl* context, - int64_t namepace_id_to_clone); + static DOMStorageSession* CloneFrom( + DOMStorageContextImpl* context, + base::WeakPtr<SessionStorageContextMojo> mojo_context, + int64_t namepace_id_to_clone); private: friend class base::RefCountedThreadSafe<DOMStorageSession>; DOMStorageSession(DOMStorageContextImpl* context, + base::WeakPtr<SessionStorageContextMojo> mojo_context, int64_t namespace_id, const std::string& persistent_namespace_id); ~DOMStorageSession(); scoped_refptr<DOMStorageContextImpl> context_; + base::WeakPtr<SessionStorageContextMojo> mojo_context_; int64_t namespace_id_; std::string persistent_namespace_id_; bool should_persist_;
diff --git a/content/browser/dom_storage/local_storage_context_mojo.cc b/content/browser/dom_storage/local_storage_context_mojo.cc index db1696c..ba83170 100644 --- a/content/browser/dom_storage/local_storage_context_mojo.cc +++ b/content/browser/dom_storage/local_storage_context_mojo.cc
@@ -457,8 +457,16 @@ connection_state_ = CONNECTION_SHUTDOWN; // Flush any uncommitted data. - for (const auto& it : level_db_wrappers_) - it.second->level_db_wrapper()->ScheduleImmediateCommit(); + for (const auto& it : level_db_wrappers_) { + auto* wrapper = it.second->level_db_wrapper(); + LOCAL_HISTOGRAM_BOOLEAN( + "LocalStorageContext.ShutdownAndDelete.MaybeDroppedChanges", + wrapper->has_pending_load_tasks()); + wrapper->ScheduleImmediateCommit(); + // TODO(dmurph): Monitor the above histogram, and if dropping changes is + // common then handle that here. + wrapper->CancelAllPendingRequests(); + } // Respect the content policy settings about what to // keep and what to discard. @@ -796,8 +804,10 @@ void LocalStorageContextMojo::DeleteAndRecreateDatabase( const char* histogram_name) { - // We're about to set database_ to null, so delete and LevelDBWrappers + // We're about to set database_ to null, so delete the LevelDBWrappers // that might still be using the old database. + for (const auto& it : level_db_wrappers_) + it.second->level_db_wrapper()->CancelAllPendingRequests(); level_db_wrappers_.clear(); // Reset state to be in process of connecting. This will cause requests for
diff --git a/content/browser/dom_storage/local_storage_context_mojo.h b/content/browser/dom_storage/local_storage_context_mojo.h index 0dda7b2..e100572 100644 --- a/content/browser/dom_storage/local_storage_context_mojo.h +++ b/content/browser/dom_storage/local_storage_context_mojo.h
@@ -5,9 +5,15 @@ #ifndef CONTENT_BROWSER_DOM_STORAGE_LOCAL_STORAGE_CONTEXT_MOJO_H_ #define CONTENT_BROWSER_DOM_STORAGE_LOCAL_STORAGE_CONTEXT_MOJO_H_ +#include <stdint.h> +#include <map> #include <memory> +#include <string> +#include <vector> +#include "base/callback_forward.h" #include "base/files/file_path.h" +#include "base/memory/ref_counted.h" #include "base/trace_event/memory_dump_provider.h" #include "content/common/content_export.h" #include "content/common/leveldb_wrapper.mojom.h"
diff --git a/content/browser/dom_storage/session_storage_context_mojo.cc b/content/browser/dom_storage/session_storage_context_mojo.cc new file mode 100644 index 0000000..7ed27d6 --- /dev/null +++ b/content/browser/dom_storage/session_storage_context_mojo.cc
@@ -0,0 +1,58 @@ +// 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/dom_storage/session_storage_context_mojo.h" + +#include "content/browser/leveldb_wrapper_impl.h" +#include "content/common/dom_storage/dom_storage_types.h" +#include "content/public/common/content_features.h" +#include "services/service_manager/public/cpp/connector.h" + +namespace content { + +SessionStorageContextMojo::SessionStorageContextMojo( + service_manager::Connector* connector, + base::FilePath subdirectory) + : connector_(connector ? connector->Clone() : nullptr), + subdirectory_(std::move(subdirectory)), + weak_ptr_factory_(this) { + DCHECK(base::FeatureList::IsEnabled(features::kMojoSessionStorage)); +} + +SessionStorageContextMojo::~SessionStorageContextMojo() {} + +void SessionStorageContextMojo::OpenSessionStorage( + int64_t namespace_id, + const url::Origin& origin, + mojom::LevelDBWrapperRequest request) { + NOTREACHED(); +} + +void SessionStorageContextMojo::CreateSessionNamespace( + int64_t namespace_id, + const std::string& persistent_namespace_id) { + NOTREACHED(); +} + +void SessionStorageContextMojo::CloneSessionNamespace( + int64_t namespace_id_to_clone, + int64_t clone_namespace_id, + const std::string& clone_persistent_namespace_id) { + NOTREACHED(); +} + +void SessionStorageContextMojo::DeleteSessionNamespace(int64_t namespace_id, + bool should_persist) { + NOTREACHED(); +} + +void SessionStorageContextMojo::PurgeMemory() { + NOTREACHED(); +} + +void SessionStorageContextMojo::PurgeUnusedWrappersIfNeeded() { + NOTREACHED(); +} + +} // namespace content
diff --git a/content/browser/dom_storage/session_storage_context_mojo.h b/content/browser/dom_storage/session_storage_context_mojo.h new file mode 100644 index 0000000..49465ccf7 --- /dev/null +++ b/content/browser/dom_storage/session_storage_context_mojo.h
@@ -0,0 +1,62 @@ +// 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_BROWSER_DOM_STORAGE_SESSION_STORAGE_CONTEXT_MOJO_H_ +#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_CONTEXT_MOJO_H_ + +#include <stdint.h> +#include <memory> +#include <string> + +#include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" +#include "content/common/content_export.h" +#include "content/common/leveldb_wrapper.mojom.h" +#include "url/origin.h" + +namespace service_manager { +class Connector; +} // namespace service_manager + +namespace content { + +// Used for mojo-based SessionStorage implementation. +class CONTENT_EXPORT SessionStorageContextMojo { + public: + SessionStorageContextMojo(service_manager::Connector* connector, + base::FilePath subdirectory); + ~SessionStorageContextMojo(); + + void OpenSessionStorage(int64_t namespace_id, + const url::Origin& origin, + mojom::LevelDBWrapperRequest request); + + void CreateSessionNamespace(int64_t namespace_id, + const std::string& persistent_namespace_id); + void CloneSessionNamespace(int64_t namespace_id_to_clone, + int64_t clone_namespace_id, + const std::string& clone_persistent_namespace_id); + void DeleteSessionNamespace(int64_t namespace_id, bool should_persist); + + // Clears any caches, to free up as much memory as possible. Next access to + // storage for a particular origin will reload the data from the database. + void PurgeMemory(); + + // Clears unused leveldb wrappers, when thresholds are reached. + void PurgeUnusedWrappersIfNeeded(); + + base::WeakPtr<SessionStorageContextMojo> AsWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + + private: + std::unique_ptr<service_manager::Connector> connector_; + const base::FilePath subdirectory_; + + base::WeakPtrFactory<SessionStorageContextMojo> weak_ptr_factory_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_CONTEXT_MOJO_H_
diff --git a/content/browser/dom_storage/session_storage_namespace_impl.cc b/content/browser/dom_storage/session_storage_namespace_impl.cc index 0811fab4..b241ef791 100644 --- a/content/browser/dom_storage/session_storage_namespace_impl.cc +++ b/content/browser/dom_storage/session_storage_namespace_impl.cc
@@ -6,24 +6,29 @@ #include "content/browser/dom_storage/dom_storage_context_wrapper.h" #include "content/browser/dom_storage/dom_storage_session.h" +#include "content/browser/dom_storage/session_storage_context_mojo.h" namespace content { SessionStorageNamespaceImpl::SessionStorageNamespaceImpl( DOMStorageContextWrapper* context) - : session_(new DOMStorageSession(context->context())) { -} + : session_(new DOMStorageSession(context->context(), + context->GetMojoSessionStateWeakPtr())) {} SessionStorageNamespaceImpl::SessionStorageNamespaceImpl( DOMStorageContextWrapper* context, int64_t namepace_id_to_clone) - : session_(DOMStorageSession::CloneFrom(context->context(), - namepace_id_to_clone)) {} + : session_( + DOMStorageSession::CloneFrom(context->context(), + context->GetMojoSessionStateWeakPtr(), + namepace_id_to_clone)) {} SessionStorageNamespaceImpl::SessionStorageNamespaceImpl( - DOMStorageContextWrapper* context, const std::string& persistent_id) - : session_(new DOMStorageSession(context->context(), persistent_id)) { -} + DOMStorageContextWrapper* context, + const std::string& persistent_id) + : session_(new DOMStorageSession(context->context(), + context->GetMojoSessionStateWeakPtr(), + persistent_id)) {} int64_t SessionStorageNamespaceImpl::id() const { return session_->namespace_id();
diff --git a/content/browser/download/drag_download_file_browsertest.cc b/content/browser/download/drag_download_file_browsertest.cc index a023cdf..8fb11555 100644 --- a/content/browser/download/drag_download_file_browsertest.cc +++ b/content/browser/download/drag_download_file_browsertest.cc
@@ -7,6 +7,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" +#include "base/path_service.h" #include "content/browser/download/download_file_factory.h" #include "content/browser/download/download_file_impl.h" #include "content/browser/download/download_item_impl.h" @@ -16,6 +17,7 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/content_browser_client.h" #include "content/public/common/content_client.h" +#include "content/public/common/content_paths.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/public/test/download_test_observer.h" @@ -69,13 +71,10 @@ shell()->web_contents()->GetBrowserContext() ->GetDownloadManagerDelegate()); delegate->SetDownloadBehaviorForTesting(downloads_directory()); - } - - void SetUpServer() { - base::FilePath mock_base(GetTestFilePath("download", "")); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&net::URLRequestMockHTTPJob::AddUrlHandlers, mock_base)); + base::FilePath test_data_dir; + ASSERT_TRUE(PathService::Get(content::DIR_TEST_DATA, &test_data_dir)); + embedded_test_server()->ServeFilesFromDirectory(test_data_dir); + ASSERT_TRUE(embedded_test_server()->Start()); } const base::FilePath& downloads_directory() const { @@ -91,7 +90,8 @@ IN_PROC_BROWSER_TEST_F(DragDownloadFileTest, DragDownloadFileTest_NetError) { base::FilePath name(downloads_directory().AppendASCII( "DragDownloadFileTest_NetError.txt")); - GURL url(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")); + GURL url = embedded_test_server()->GetURL("/download/download-test.lib"); + ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); Referrer referrer; std::string referrer_encoding; scoped_refptr<DragDownloadFile> file( @@ -110,10 +110,9 @@ IN_PROC_BROWSER_TEST_F(DragDownloadFileTest, DragDownloadFileTest_Complete) { base::FilePath name(downloads_directory().AppendASCII( "DragDownloadFileTest_Complete.txt")); - GURL url(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")); + GURL url = embedded_test_server()->GetURL("/download/download-test.lib"); Referrer referrer; std::string referrer_encoding; - SetUpServer(); scoped_refptr<DragDownloadFile> file(new DragDownloadFile( name, base::File(), url, referrer, referrer_encoding, shell()->web_contents()));
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index e2a1d7c..6083fad 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -613,8 +613,13 @@ // destination could change. dest_site_instance_ = nullptr; + // For now, DevTools needs the POST data sent to the renderer process even if + // it is no longer a POST after the redirect. + // TODO(caseq): Send the requestWillBeSent from browser and remove the + // IsNetworkHandlerEnabled check here. // If the navigation is no longer a POST, the POST data should be reset. - if (redirect_info.new_method != "POST") + if (redirect_info.new_method != "POST" && + !RenderFrameDevToolsAgentHost::IsNetworkHandlerEnabled(frame_tree_node_)) common_params_.post_data = nullptr; // Mark time for the Navigation Timing API.
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index bc458a99..44c3e21 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -68,6 +68,7 @@ #include "content/browser/renderer_host/render_view_host_delegate_view.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" +#include "content/browser/renderer_host/render_widget_host_factory.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/renderer_host/render_widget_host_view_child_frame.h" @@ -541,10 +542,9 @@ } if (!render_widget_host_) { DCHECK(frame_tree_node->parent()); - - render_widget_host_ = new RenderWidgetHostImpl(rwh_delegate, GetProcess(), - widget_routing_id, - std::move(widget), hidden); + render_widget_host_ = RenderWidgetHostFactory::Create( + rwh_delegate, GetProcess(), widget_routing_id, std::move(widget), + hidden); render_widget_host_->set_owned_by_render_frame_host(true); } else { DCHECK(!render_widget_host_->owned_by_render_frame_host());
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 610c48a1..32f8d05 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -350,7 +350,7 @@ // This method crashes if this RenderFrameHostImpl does not own a // a RenderWidgetHost and nor does any of its ancestors. That would // typically mean that the frame has been detached from the frame tree. - RenderWidgetHostImpl* GetRenderWidgetHost(); + virtual RenderWidgetHostImpl* GetRenderWidgetHost(); GlobalFrameRoutingId GetGlobalFrameRoutingId();
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc index 038a046..326f62e 100644 --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -15,6 +15,7 @@ #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "build/build_config.h" #include "content/browser/frame_host/navigation_controller_impl.h" @@ -40,6 +41,7 @@ #include "content/public/browser/web_ui_controller.h" #include "content/public/common/bindings_policy.h" #include "content/public/common/browser_side_navigation_policy.h" +#include "content/public/common/content_features.h" #include "content/public/common/javascript_dialog_type.h" #include "content/public/common/previews_state.h" #include "content/public/common/url_constants.h" @@ -49,10 +51,12 @@ #include "content/public/test/navigation_simulator.h" #include "content/public/test/test_notification_tracker.h" #include "content/public/test/test_utils.h" +#include "content/test/mock_widget_input_handler.h" #include "content/test/test_content_browser_client.h" #include "content/test/test_content_client.h" #include "content/test/test_render_frame_host.h" #include "content/test/test_render_view_host.h" +#include "content/test/test_render_widget_host.h" #include "content/test/test_web_contents.h" #include "net/base/load_flags.h" #include "testing/gtest/include/gtest/gtest.h" @@ -77,6 +81,17 @@ EXPECT_EQ(expected_focus, std::get<0>(params)); } +// VerifyPageFocusMessage from the mojo input handler. +void VerifyPageFocusMessage(TestRenderWidgetHost* twh, bool expected_focus) { + MockWidgetInputHandler::MessageVector events = + twh->GetMockWidgetInputHandler()->GetAndResetDispatchedMessages(); + EXPECT_EQ(1u, events.size()); + MockWidgetInputHandler::DispatchedFocusMessage* focus_message = + events.at(0)->ToFocus(); + EXPECT_TRUE(focus_message); + EXPECT_EQ(expected_focus, focus_message->focused()); +} + // Helper function for strict mixed content checking tests. void CheckInsecureRequestPolicyIPC( TestRenderFrameHost* rfh, @@ -304,6 +319,7 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness { public: void SetUp() override { + mojo_feature_list_.InitAndEnableFeature(features::kMojoInputMessages); RenderViewHostImplTestHarness::SetUp(); WebUIControllerFactory::RegisterFactory(&factory_); } @@ -492,6 +508,7 @@ RenderFrameHostManager*)>& commit_lambda); private: + base::test::ScopedFeatureList mojo_feature_list_; RenderFrameHostManagerTestWebUIControllerFactory factory_; }; @@ -2446,6 +2463,7 @@ RenderFrameProxyHost* proxyC = root->render_manager()->GetRenderFrameProxyHost(host3->GetSiteInstance()); EXPECT_TRUE(proxyC); + base::RunLoop().RunUntilIdle(); // Focus the main page, and verify that the focus message was sent to all // processes. The message to A should be sent through the main frame's @@ -2455,8 +2473,8 @@ host1->GetProcess()->sink().ClearMessages(); host3->GetProcess()->sink().ClearMessages(); main_test_rfh()->GetRenderWidgetHost()->Focus(); - VerifyPageFocusMessage(main_test_rfh()->GetProcess(), true, - main_test_rfh()->GetRenderViewHost()->GetRoutingID()); + base::RunLoop().RunUntilIdle(); + VerifyPageFocusMessage(main_test_rfh()->GetRenderWidgetHost(), true); VerifyPageFocusMessage(host1->GetProcess(), true, proxyB->GetRoutingID()); VerifyPageFocusMessage(host3->GetProcess(), true, proxyC->GetRoutingID()); @@ -2466,8 +2484,8 @@ host1->GetProcess()->sink().ClearMessages(); host3->GetProcess()->sink().ClearMessages(); main_test_rfh()->GetRenderWidgetHost()->Blur(); - VerifyPageFocusMessage(main_test_rfh()->GetProcess(), false, - main_test_rfh()->GetRenderViewHost()->GetRoutingID()); + base::RunLoop().RunUntilIdle(); + VerifyPageFocusMessage(main_test_rfh()->GetRenderWidgetHost(), false); VerifyPageFocusMessage(host1->GetProcess(), false, proxyB->GetRoutingID()); VerifyPageFocusMessage(host3->GetProcess(), false, proxyC->GetRoutingID()); }
diff --git a/content/browser/generic_sensor_browsertest.cc b/content/browser/generic_sensor_browsertest.cc index 6138d730b..cf0c4dc 100644 --- a/content/browser/generic_sensor_browsertest.cc +++ b/content/browser/generic_sensor_browsertest.cc
@@ -8,8 +8,11 @@ #include "base/test/scoped_feature_list.h" #include "base/threading/platform_thread.h" #include "build/build_config.h" +#include "components/network_session_configurator/common/network_switches.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" @@ -20,6 +23,7 @@ #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/system/buffer.h" +#include "net/dns/mock_host_resolver.h" #include "services/device/public/cpp/device_features.h" #include "services/device/public/cpp/generic_sensor/platform_sensor_configuration.h" #include "services/device/public/cpp/generic_sensor/sensor_reading.h" @@ -181,6 +185,16 @@ ~GenericSensorBrowserTest() override {} void SetUpOnMainThread() override { + https_embedded_test_server_.reset( + new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); + // Serve both a.com and b.com (and any other domain). + host_resolver()->AddRule("*", "127.0.0.1"); + ASSERT_TRUE(https_embedded_test_server_->InitializeAndListen()); + content::SetupCrossSiteRedirector(https_embedded_test_server_.get()); + https_embedded_test_server_->ServeFilesFromSourceDirectory( + "content/test/data/generic_sensor"); + https_embedded_test_server_->StartAcceptingConnections(); + fake_sensor_provider_ = std::make_unique<FakeSensorProvider>(); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, @@ -190,6 +204,12 @@ io_loop_finished_event_.Wait(); } + void SetUpCommandLine(base::CommandLine* command_line) override { + // HTTPS server only serves a valid cert for localhost, so this is needed + // to load pages from other hosts without an error. + command_line->AppendSwitch(switches::kIgnoreCertificateErrors); + } + void SetBinderOnIOThread() { // Because Device Service also runs in this process(browser process), here // we can directly set our binder to intercept interface requests against @@ -202,6 +222,9 @@ io_loop_finished_event_.Signal(); } + protected: + std::unique_ptr<net::EmbeddedTestServer> https_embedded_test_server_; + private: base::test::ScopedFeatureList scoped_feature_list_; base::WaitableEvent io_loop_finished_event_; @@ -219,6 +242,29 @@ EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref()); } +IN_PROC_BROWSER_TEST_F(GenericSensorBrowserTest, + AmbientLightSensorCrossOriginIframeTest) { + // Main frame is on a.com, iframe is on b.com. + GURL main_frame_url = + https_embedded_test_server_->GetURL("a.com", "/cross_origin_iframe.html"); + GURL iframe_url = https_embedded_test_server_->GetURL( + "b.com", "/ambient_light_sensor_cross_origin_iframe_test.html"); + + // Wait for the main frame, subframe, and the #pass/#fail commits. + TestNavigationObserver navigation_observer(shell()->web_contents(), 3); + + EXPECT_TRUE(NavigateToURL(shell(), main_frame_url)); + EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), + "cross_origin_iframe", iframe_url)); + + navigation_observer.Wait(); + + content::RenderFrameHost* iframe = + ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0); + ASSERT_TRUE(iframe); + EXPECT_EQ("pass", iframe->GetLastCommittedURL().ref()); +} + } // namespace } // namespace content
diff --git a/content/browser/host_zoom_map_impl.cc b/content/browser/host_zoom_map_impl.cc index 788ed10..f4518184 100644 --- a/content/browser/host_zoom_map_impl.cc +++ b/content/browser/host_zoom_map_impl.cc
@@ -52,6 +52,7 @@ } // namespace GURL HostZoomMap::GetURLFromEntry(const NavigationEntry* entry) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); switch (entry->GetPageType()) { case PAGE_TYPE_ERROR: return GURL(kUnreachableWebDataURL); @@ -63,6 +64,7 @@ } HostZoomMap* HostZoomMap::GetDefaultForBrowserContext(BrowserContext* context) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(context); DCHECK(partition); @@ -70,6 +72,7 @@ } HostZoomMap* HostZoomMap::Get(SiteInstance* instance) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); StoragePartition* partition = BrowserContext::GetStoragePartition( instance->GetBrowserContext(), instance); DCHECK(partition); @@ -77,6 +80,7 @@ } HostZoomMap* HostZoomMap::GetForWebContents(const WebContents* contents) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); // TODO(wjmaclean): Update this behaviour to work with OOPIF. // See crbug.com/528407. StoragePartition* partition = @@ -89,6 +93,7 @@ // Helper function for setting/getting zoom levels for WebContents without // having to import HostZoomMapImpl everywhere. double HostZoomMap::GetZoomLevel(const WebContents* web_contents) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>( HostZoomMap::GetForWebContents(web_contents)); return host_zoom_map->GetZoomLevelForWebContents( @@ -96,6 +101,7 @@ } bool HostZoomMap::PageScaleFactorIsOne(const WebContents* web_contents) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>( HostZoomMap::GetForWebContents(web_contents)); return host_zoom_map->PageScaleFactorIsOneForWebContents( @@ -103,6 +109,7 @@ } void HostZoomMap::SetZoomLevel(const WebContents* web_contents, double level) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>( HostZoomMap::GetForWebContents(web_contents)); host_zoom_map->SetZoomLevelForWebContents( @@ -111,6 +118,7 @@ void HostZoomMap::SendErrorPageZoomLevelRefresh( const WebContents* web_contents) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext( web_contents->GetBrowserContext())); @@ -120,44 +128,32 @@ HostZoomMapImpl::HostZoomMapImpl() : default_zoom_level_(0.0), store_last_modified_(false), - clock_(new base::DefaultClock) {} + clock_(std::make_unique<base::DefaultClock>()) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); +} void HostZoomMapImpl::CopyFrom(HostZoomMap* copy_interface) { - // This can only be called on the UI thread to avoid deadlocks, otherwise - // UI: a.CopyFrom(b); - // IO: b.CopyFrom(a); - // can deadlock. DCHECK_CURRENTLY_ON(BrowserThread::UI); HostZoomMapImpl* copy = static_cast<HostZoomMapImpl*>(copy_interface); - base::AutoLock auto_lock(lock_); - base::AutoLock copy_auto_lock(copy->lock_); - host_zoom_levels_. - insert(copy->host_zoom_levels_.begin(), copy->host_zoom_levels_.end()); - for (SchemeHostZoomLevels::const_iterator i(copy-> - scheme_host_zoom_levels_.begin()); - i != copy->scheme_host_zoom_levels_.end(); ++i) { - scheme_host_zoom_levels_[i->first] = HostZoomLevels(); - scheme_host_zoom_levels_[i->first]. - insert(i->second.begin(), i->second.end()); + host_zoom_levels_.insert(copy->host_zoom_levels_.begin(), + copy->host_zoom_levels_.end()); + for (const auto& it : copy->scheme_host_zoom_levels_) { + const std::string& host = it.first; + scheme_host_zoom_levels_[host] = HostZoomLevels(); + scheme_host_zoom_levels_[host].insert(it.second.begin(), it.second.end()); } default_zoom_level_ = copy->default_zoom_level_; } double HostZoomMapImpl::GetZoomLevelForHost(const std::string& host) const { - base::AutoLock auto_lock(lock_); - return GetZoomLevelForHostInternal(host); -} - -double HostZoomMapImpl::GetZoomLevelForHostInternal( - const std::string& host) const { - HostZoomLevels::const_iterator i(host_zoom_levels_.find(host)); - return (i == host_zoom_levels_.end()) ? default_zoom_level_ : i->second.level; + DCHECK_CURRENTLY_ON(BrowserThread::UI); + const auto it = host_zoom_levels_.find(host); + return it != host_zoom_levels_.end() ? it->second.level : default_zoom_level_; } bool HostZoomMapImpl::HasZoomLevel(const std::string& scheme, const std::string& host) const { - base::AutoLock auto_lock(lock_); - + DCHECK_CURRENTLY_ON(BrowserThread::UI); SchemeHostZoomLevels::const_iterator scheme_iterator( scheme_host_zoom_levels_.find(scheme)); @@ -166,13 +162,13 @@ ? scheme_iterator->second : host_zoom_levels_; - HostZoomLevels::const_iterator i(zoom_levels.find(host)); - return i != zoom_levels.end(); + return base::ContainsKey(zoom_levels, host); } -double HostZoomMapImpl::GetZoomLevelForHostAndSchemeInternal( +double HostZoomMapImpl::GetZoomLevelForHostAndScheme( const std::string& scheme, const std::string& host) const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); SchemeHostZoomLevels::const_iterator scheme_iterator( scheme_host_zoom_levels_.find(scheme)); if (scheme_iterator != scheme_host_zoom_levels_.end()) { @@ -181,51 +177,43 @@ return i->second.level; } - return GetZoomLevelForHostInternal(host); -} - -double HostZoomMapImpl::GetZoomLevelForHostAndScheme( - const std::string& scheme, - const std::string& host) const { - base::AutoLock auto_lock(lock_); - return GetZoomLevelForHostAndSchemeInternal(scheme, host); + return GetZoomLevelForHost(host); } HostZoomMap::ZoomLevelVector HostZoomMapImpl::GetAllZoomLevels() const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); HostZoomMap::ZoomLevelVector result; - { - base::AutoLock auto_lock(lock_); - result.reserve(host_zoom_levels_.size() + scheme_host_zoom_levels_.size()); - for (const auto& entry : host_zoom_levels_) { + result.reserve(host_zoom_levels_.size() + scheme_host_zoom_levels_.size()); + for (const auto& entry : host_zoom_levels_) { + ZoomLevelChange change = { + HostZoomMap::ZOOM_CHANGED_FOR_HOST, + entry.first, // host + std::string(), // scheme + entry.second.level, // zoom level + entry.second.last_modified // last modified + }; + result.push_back(change); + } + for (const auto& scheme_entry : scheme_host_zoom_levels_) { + const std::string& scheme = scheme_entry.first; + const HostZoomLevels& host_zoom_levels = scheme_entry.second; + for (const auto& entry : host_zoom_levels) { ZoomLevelChange change = { - HostZoomMap::ZOOM_CHANGED_FOR_HOST, + HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST, entry.first, // host - std::string(), // scheme + scheme, // scheme entry.second.level, // zoom level entry.second.last_modified // last modified }; result.push_back(change); } - for (const auto& scheme_entry : scheme_host_zoom_levels_) { - const std::string& scheme = scheme_entry.first; - const HostZoomLevels& host_zoom_levels = scheme_entry.second; - for (const auto& entry : host_zoom_levels) { - ZoomLevelChange change = { - HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST, - entry.first, // host - scheme, // scheme - entry.second.level, // zoom level - entry.second.last_modified // last modified - }; - result.push_back(change); - } - } } return result; } void HostZoomMapImpl::SetZoomLevelForHost(const std::string& host, double level) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); base::Time last_modified = store_last_modified_ ? clock_->Now() : base::Time(); SetZoomLevelForHostInternal(host, level, last_modified); @@ -234,6 +222,7 @@ void HostZoomMapImpl::InitializeZoomLevelForHost(const std::string& host, double level, base::Time last_modified) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); SetZoomLevelForHostInternal(host, level, last_modified); } @@ -242,16 +231,12 @@ base::Time last_modified) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - { - base::AutoLock auto_lock(lock_); - - if (ZoomValuesEqual(level, default_zoom_level_)) { - host_zoom_levels_.erase(host); - } else { - ZoomLevel& zoomLevel = host_zoom_levels_[host]; - zoomLevel.level = level; - zoomLevel.last_modified = last_modified; - } + if (ZoomValuesEqual(level, default_zoom_level_)) { + host_zoom_levels_.erase(host); + } else { + ZoomLevel& zoomLevel = host_zoom_levels_[host]; + zoomLevel.level = level; + zoomLevel.last_modified = last_modified; } // TODO(wjmaclean) Should we use a GURL here? crbug.com/384486 @@ -270,12 +255,9 @@ const std::string& host, double level) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - { - base::AutoLock auto_lock(lock_); - // No last_modified timestamp for scheme and host because they are - // not persistet and are used for special cases only. - scheme_host_zoom_levels_[scheme][host].level = level; - } + // No last_modified timestamp for scheme and host because they are + // not persistet and are used for special cases only. + scheme_host_zoom_levels_[scheme][host].level = level; SendZoomLevelChange(scheme, host, level); @@ -303,14 +285,11 @@ default_zoom_level_ = level; // First, remove all entries that match the new default zoom level. - { - base::AutoLock auto_lock(lock_); - for (auto it = host_zoom_levels_.begin(); it != host_zoom_levels_.end(); ) { - if (ZoomValuesEqual(it->second.level, default_zoom_level_)) - it = host_zoom_levels_.erase(it); - else - it++; - } + for (auto it = host_zoom_levels_.begin(); it != host_zoom_levels_.end();) { + if (ZoomValuesEqual(it->second.level, default_zoom_level_)) + it = host_zoom_levels_.erase(it); + else + it++; } // Second, update zoom levels for all pages that do not have an overriding @@ -362,11 +341,13 @@ std::unique_ptr<HostZoomMap::Subscription> HostZoomMapImpl::AddZoomLevelChangedCallback( const ZoomLevelChangedCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); return zoom_level_changed_callbacks_.Add(callback); } double HostZoomMapImpl::GetZoomLevelForWebContents( const WebContentsImpl& web_contents_impl) const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); int render_process_id = web_contents_impl.GetRenderViewHost()->GetProcess()->GetID(); int routing_id = web_contents_impl.GetRenderViewHost()->GetRoutingID(); @@ -391,6 +372,7 @@ void HostZoomMapImpl::SetZoomLevelForWebContents( const WebContentsImpl& web_contents_impl, double level) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); int render_process_id = web_contents_impl.GetRenderViewHost()->GetProcess()->GetID(); int render_view_id = web_contents_impl.GetRenderViewHost()->GetRoutingID(); @@ -417,6 +399,7 @@ int render_view_id, double level, const std::string& host) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (UsesTemporaryZoomLevel(render_process_id, render_view_id)) SetTemporaryZoomLevel(render_process_id, render_view_id, level); else @@ -426,11 +409,9 @@ void HostZoomMapImpl::SetPageScaleFactorIsOneForView(int render_process_id, int render_view_id, bool is_one) { - { - base::AutoLock auto_lock(lock_); - view_page_scale_factors_are_one_[RenderViewKey(render_process_id, - render_view_id)] = is_one; - } + DCHECK_CURRENTLY_ON(BrowserThread::UI); + view_page_scale_factors_are_one_[RenderViewKey(render_process_id, + render_view_id)] = is_one; HostZoomMap::ZoomLevelChange change; change.mode = HostZoomMap::PAGE_SCALE_IS_ONE_CHANGED; zoom_level_changed_callbacks_.Notify(change); @@ -438,40 +419,36 @@ bool HostZoomMapImpl::PageScaleFactorIsOneForWebContents( const WebContentsImpl& web_contents_impl) const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!web_contents_impl.GetRenderViewHost()->GetProcess()) return true; - base::AutoLock auto_lock(lock_); - auto found = view_page_scale_factors_are_one_.find(RenderViewKey( + + const auto it = view_page_scale_factors_are_one_.find(RenderViewKey( web_contents_impl.GetRenderViewHost()->GetProcess()->GetID(), web_contents_impl.GetRenderViewHost()->GetRoutingID())); - if (found == view_page_scale_factors_are_one_.end()) - return true; - return found->second; + return it != view_page_scale_factors_are_one_.end() ? it->second : true; } void HostZoomMapImpl::ClearPageScaleFactorIsOneForView(int render_process_id, int render_view_id) { - base::AutoLock auto_lock(lock_); + DCHECK_CURRENTLY_ON(BrowserThread::UI); view_page_scale_factors_are_one_.erase( RenderViewKey(render_process_id, render_view_id)); } bool HostZoomMapImpl::UsesTemporaryZoomLevel(int render_process_id, int render_view_id) const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); RenderViewKey key(render_process_id, render_view_id); - - base::AutoLock auto_lock(lock_); return base::ContainsKey(temporary_zoom_levels_, key); } double HostZoomMapImpl::GetTemporaryZoomLevel(int render_process_id, int render_view_id) const { - base::AutoLock auto_lock(lock_); + DCHECK_CURRENTLY_ON(BrowserThread::UI); RenderViewKey key(render_process_id, render_view_id); - if (!base::ContainsKey(temporary_zoom_levels_, key)) - return 0; - - return temporary_zoom_levels_.find(key)->second; + const auto it = temporary_zoom_levels_.find(key); + return it != temporary_zoom_levels_.end() ? it->second : 0; } void HostZoomMapImpl::SetTemporaryZoomLevel(int render_process_id, @@ -479,11 +456,8 @@ double level) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - { - RenderViewKey key(render_process_id, render_view_id); - base::AutoLock auto_lock(lock_); - temporary_zoom_levels_[key] = level; - } + RenderViewKey key(render_process_id, render_view_id); + temporary_zoom_levels_[key] = level; WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost( @@ -501,20 +475,21 @@ double HostZoomMapImpl::GetZoomLevelForView(const GURL& url, int render_process_id, int render_view_id) const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); RenderViewKey key(render_process_id, render_view_id); - base::AutoLock auto_lock(lock_); if (base::ContainsKey(temporary_zoom_levels_, key)) return temporary_zoom_levels_.find(key)->second; - return GetZoomLevelForHostAndSchemeInternal(url.scheme(), - net::GetHostOrSpecFromURL(url)); + return GetZoomLevelForHostAndScheme(url.scheme(), + net::GetHostOrSpecFromURL(url)); } void HostZoomMapImpl::ClearZoomLevels(base::Time delete_begin, base::Time delete_end) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); double default_zoom_level = GetDefaultZoomLevel(); - for (auto& zoom_level : GetAllZoomLevels()) { + for (const auto& zoom_level : GetAllZoomLevels()) { if (zoom_level.scheme.empty() && delete_begin <= zoom_level.last_modified && (delete_end.is_null() || zoom_level.last_modified < delete_end)) { SetZoomLevelForHost(zoom_level.host, default_zoom_level); @@ -523,19 +498,19 @@ } void HostZoomMapImpl::SetStoreLastModified(bool store_last_modified) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); store_last_modified_ = store_last_modified; } void HostZoomMapImpl::ClearTemporaryZoomLevel(int render_process_id, int render_view_id) { - { - base::AutoLock auto_lock(lock_); - RenderViewKey key(render_process_id, render_view_id); - TemporaryZoomLevels::iterator it = temporary_zoom_levels_.find(key); - if (it == temporary_zoom_levels_.end()) - return; - temporary_zoom_levels_.erase(it); - } + DCHECK_CURRENTLY_ON(BrowserThread::UI); + RenderViewKey key(render_process_id, render_view_id); + TemporaryZoomLevels::iterator it = temporary_zoom_levels_.find(key); + if (it == temporary_zoom_levels_.end()) + return; + + temporary_zoom_levels_.erase(it); WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost( RenderViewHost::FromID(render_process_id, render_view_id))); @@ -546,6 +521,7 @@ void HostZoomMapImpl::SendZoomLevelChange(const std::string& scheme, const std::string& host, double level) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); // We'll only send to WebContents not using temporary zoom levels. The one // other case of interest is where the renderer is hosting a plugin document; // that should be reflected in our temporary zoom level map, but we will @@ -566,6 +542,7 @@ } void HostZoomMapImpl::SendErrorPageZoomLevelRefresh() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); GURL error_url(kUnreachableWebDataURL); std::string host = net::GetHostOrSpecFromURL(error_url); double error_page_zoom_level = GetZoomLevelForHost(host); @@ -575,6 +552,7 @@ void HostZoomMapImpl::WillCloseRenderView(int render_process_id, int render_view_id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); ClearTemporaryZoomLevel(render_process_id, render_view_id); ClearPageScaleFactorIsOneForView(render_process_id, render_view_id); }
diff --git a/content/browser/host_zoom_map_impl.h b/content/browser/host_zoom_map_impl.h index 418acedf..e35249b 100644 --- a/content/browser/host_zoom_map_impl.h +++ b/content/browser/host_zoom_map_impl.h
@@ -13,15 +13,13 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/sequenced_task_runner_helpers.h" -#include "base/synchronization/lock.h" #include "content/public/browser/host_zoom_map.h" namespace content { class WebContentsImpl; -// HostZoomMap needs to be deleted on the UI thread because it listens -// to notifications on there. +// HostZoomMap lives on the UI thread. class CONTENT_EXPORT HostZoomMapImpl : public HostZoomMap { public: HostZoomMapImpl(); @@ -84,15 +82,11 @@ // Returns the temporary zoom level that's only valid for the lifetime of // the given WebContents (i.e. isn't saved and doesn't affect other // WebContentses) if it exists, the default zoom level otherwise. - // - // This may be called on any thread. double GetTemporaryZoomLevel(int render_process_id, int render_view_id) const; // Returns the zoom level regardless of whether it's temporary, host-keyed or // scheme+host-keyed. - // - // This may be called on any thread. double GetZoomLevelForView(const GURL& url, int render_process_id, int render_view_id) const; @@ -128,12 +122,6 @@ double GetZoomLevelForHost(const std::string& host) const; - // Non-locked versions for internal use. These should only be called within - // a scope where a lock has been acquired. - double GetZoomLevelForHostInternal(const std::string& host) const; - double GetZoomLevelForHostAndSchemeInternal(const std::string& scheme, - const std::string& host) const; - // Set a zoom level for |host| and store the |last_modified| timestamp. // Use only to explicitly set a timestamp. void SetZoomLevelForHostInternal(const std::string& host, @@ -151,7 +139,7 @@ base::CallbackList<void(const ZoomLevelChange&)> zoom_level_changed_callbacks_; - // Copy of the pref data, so that we can read it on the IO thread. + // Copy of the pref data. HostZoomLevels host_zoom_levels_; SchemeHostZoomLevels scheme_host_zoom_levels_; double default_zoom_level_; @@ -161,11 +149,6 @@ TemporaryZoomLevels temporary_zoom_levels_; - // Used around accesses to |host_zoom_levels_|, |default_zoom_level_|, - // |temporary_zoom_levels_|, and |view_page_scale_factors_are_one_| to - // guarantee thread safety. - mutable base::Lock lock_; - bool store_last_modified_; std::unique_ptr<base::Clock> clock_;
diff --git a/content/browser/leveldb_wrapper_impl.cc b/content/browser/leveldb_wrapper_impl.cc index b3c5d91..7708bda 100644 --- a/content/browser/leveldb_wrapper_impl.cc +++ b/content/browser/leveldb_wrapper_impl.cc
@@ -5,6 +5,8 @@ #include "content/browser/leveldb_wrapper_impl.h" #include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" @@ -13,6 +15,13 @@ #include "content/public/browser/browser_thread.h" namespace content { +namespace { +using leveldb::mojom::BatchedOperation; +using leveldb::mojom::BatchedOperationPtr; +using leveldb::mojom::DatabaseError; +} // namespace + +LevelDBWrapperImpl::Delegate::~Delegate() {} void LevelDBWrapperImpl::Delegate::MigrateData( base::OnceCallback<void(std::unique_ptr<ValueMap>)> callback) { @@ -24,7 +33,7 @@ return std::vector<Change>(); } -void LevelDBWrapperImpl::Delegate::OnMapLoaded(leveldb::mojom::DatabaseError) {} +void LevelDBWrapperImpl::Delegate::OnMapLoaded(DatabaseError) {} bool LevelDBWrapperImpl::s_aggressive_flushing_enabled_ = false; @@ -57,10 +66,7 @@ : prefix_(leveldb::StdStringToUint8Vector(prefix)), delegate_(delegate), database_(database), - desired_load_state_( - (options.cache_mode == CacheMode::KEYS_ONLY_WHEN_POSSIBLE && database) - ? LoadState::KEYS_ONLY - : LoadState::KEYS_AND_VALUES), + cache_mode_(database ? options.cache_mode : CacheMode::KEYS_AND_VALUES), storage_used_(0), max_size_(options.max_size), memory_used_(0), @@ -76,6 +82,7 @@ } LevelDBWrapperImpl::~LevelDBWrapperImpl() { + DCHECK(!has_pending_load_tasks()); if (commit_batch_) CommitChanges(); } @@ -88,8 +95,33 @@ // only keys when the number of bindings goes back to 1 could cause // inconsistency due to the async notifications of mutations to the client // reaching late. - if (desired_load_state_ == LoadState::KEYS_ONLY && bindings_.size() > 1) + if (cache_mode_ == CacheMode::KEYS_ONLY_WHEN_POSSIBLE && + bindings_.size() > 1) { SetCacheMode(LevelDBWrapperImpl::CacheMode::KEYS_AND_VALUES); + } +} + +std::unique_ptr<LevelDBWrapperImpl> LevelDBWrapperImpl::ForkToNewPrefix( + const std::string& new_prefix, + Delegate* delegate, + const Options& options) { + auto forked_wrapper = std::make_unique<LevelDBWrapperImpl>( + database_, new_prefix, delegate, options); + + forked_wrapper->map_state_ = MapState::LOADING_FROM_FORK; + + if (IsMapLoaded()) { + DoForkOperation(forked_wrapper->weak_ptr_factory_.GetWeakPtr()); + } else { + LoadMap(base::BindOnce(&LevelDBWrapperImpl::DoForkOperation, + weak_ptr_factory_.GetWeakPtr(), + forked_wrapper->weak_ptr_factory_.GetWeakPtr())); + } + return forked_wrapper; +} + +void LevelDBWrapperImpl::CancelAllPendingRequests() { + on_load_complete_tasks_.clear(); } void LevelDBWrapperImpl::EnableAggressiveCommitDelay() { @@ -98,8 +130,8 @@ void LevelDBWrapperImpl::ScheduleImmediateCommit() { if (!on_load_complete_tasks_.empty()) { - LoadMap(base::Bind(&LevelDBWrapperImpl::ScheduleImmediateCommit, - base::Unretained(this))); + LoadMap(base::BindOnce(&LevelDBWrapperImpl::ScheduleImmediateCommit, + base::Unretained(this))); return; } @@ -111,7 +143,7 @@ void LevelDBWrapperImpl::OnMemoryDump( const std::string& name, base::trace_event::ProcessMemoryDump* pmd) { - if (CurrentLoadState() == LoadState::UNLOADED) + if (!IsMapLoaded()) return; const char* system_allocator_name = @@ -119,10 +151,11 @@ ->system_allocator_pool_name(); if (commit_batch_) { size_t data_size = 0; - for (const auto& iter : commit_batch_->changed_values) { - data_size += - iter.first.size() + (iter.second ? iter.second.value().size() : 0); - } + for (const auto& iter : commit_batch_->changed_values) + data_size += iter.first.size() + iter.second.size(); + for (const auto& key : commit_batch_->changed_keys) + data_size += key.size(); + auto* commit_batch_mad = pmd->CreateAllocatorDump(name + "/commit_batch"); commit_batch_mad->AddScalar( base::trace_event::MemoryAllocatorDump::kNameSize, @@ -140,21 +173,23 @@ base::trace_event::MemoryAllocatorDump::kUnitsBytes, memory_used_); map_mad->AddString("load_state", "", - keys_only_map_ ? "keys_only" : "keys_and_values"); + map_state_ == MapState::LOADED_KEYS_ONLY + ? "keys_only" + : "keys_and_values"); if (system_allocator_name) pmd->AddSuballocation(map_mad->guid(), system_allocator_name); } void LevelDBWrapperImpl::PurgeMemory() { - if (CurrentLoadState() == - LoadState::UNLOADED || // We're not using any memory. - commit_batch_ || // We leave things alone with changes pending. + if (!IsMapLoaded() || // We're not using any memory. + commit_batch_ || // We leave things alone with changes pending. !database_) { // Don't purge anything if we're not backed by a database. return; } - keys_values_map_.reset(); - keys_only_map_.reset(); + map_state_ = MapState::UNLOADED; + keys_only_map_.clear(); + keys_values_map_.clear(); } void LevelDBWrapperImpl::SetCacheModeForTesting(CacheMode cache_mode) { @@ -165,7 +200,7 @@ mojom::LevelDBObserverAssociatedPtrInfo observer) { mojom::LevelDBObserverAssociatedPtr observer_ptr; observer_ptr.Bind(std::move(observer)); - if (desired_load_state_ == LoadState::KEYS_AND_VALUES) + if (cache_mode_ == CacheMode::KEYS_AND_VALUES) observer_ptr->ShouldSendOldValueOnMutations(false); observers_.AddPtr(std::move(observer_ptr)); } @@ -176,10 +211,10 @@ const base::Optional<std::vector<uint8_t>>& client_old_value, const std::string& source, PutCallback callback) { - if (IsMapReloadNeeded()) { - LoadMap(base::Bind(&LevelDBWrapperImpl::Put, base::Unretained(this), key, - value, client_old_value, source, - base::Passed(&callback))); + if (!IsMapLoaded() || IsMapUpgradeNeeded()) { + LoadMap(base::BindOnce(&LevelDBWrapperImpl::Put, base::Unretained(this), + key, value, client_old_value, source, + std::move(callback))); return; } @@ -187,9 +222,9 @@ size_t old_item_memory = 0; size_t new_item_memory = 0; base::Optional<std::vector<uint8_t>> old_value; - if (keys_only_map_) { - KeysOnlyMap::const_iterator found = keys_only_map_->find(key); - if (found != keys_only_map_->end()) { + if (map_state_ == MapState::LOADED_KEYS_ONLY) { + KeysOnlyMap::const_iterator found = keys_only_map_.find(key); + if (found != keys_only_map_.end()) { if (client_old_value && client_old_value.value().size() == found->second) { if (client_old_value == value) { @@ -197,18 +232,32 @@ return; } old_value = client_old_value.value(); + } else { +#if DCHECK_IS_ON() + // If |client_old_value| was not provided or if it's size does not + // match, then we still let the change go through. But the notification + // sent to clients will not contain old value. This is okay since + // currently the only observer to these notification is the client + // itself. + DVLOG(1) << "Wrapper with prefix " + << leveldb::Uint8VectorToStdString(prefix_) + << ": past value has length of " << found->second << ", but:"; + if (client_old_value) { + DVLOG(1) << "Given past value has incorrect length of " + << client_old_value.value().size(); + } else { + DVLOG(1) << "No given past value was provided."; + } +#endif } - // If |client_old_value| was not provided or if it's size does not match, - // then we still let the change go through. But the notification sent to - // clients will not contain old value. This is okay since currently the - // only observer to these notification is the client itself. old_item_size = key.size() + found->second; old_item_memory = key.size() + sizeof(size_t); } new_item_memory = key.size() + sizeof(size_t); } else { - ValueMap::iterator found = keys_values_map_->find(key); - if (found != keys_values_map_->end()) { + DCHECK_EQ(map_state_, MapState::LOADED_KEYS_AND_VALUES); + ValueMap::iterator found = keys_values_map_.find(key); + if (found != keys_values_map_.end()) { if (found->second == value) { std::move(callback).Run(true); // Key already has this value. return; @@ -226,7 +275,7 @@ // Only check quota if the size is increasing, this allows // shrinking changes to pre-existing maps that are over budget. if (new_item_size > old_item_size && new_storage_used > max_size_) { - if (desired_load_state_ == LoadState::KEYS_ONLY) { + if (map_state_ == MapState::LOADED_KEYS_ONLY) { bindings_.ReportBadMessage( "The quota in browser cannot exceed when there is only one " "renderer."); @@ -241,16 +290,16 @@ // No need to store values in |commit_batch_| if values are already // available in |keys_values_map_|, since CommitChanges() will take values // from there. - if (keys_only_map_) + if (map_state_ == MapState::LOADED_KEYS_ONLY) commit_batch_->changed_values[key] = value; else - commit_batch_->changed_values[key] = base::nullopt; + commit_batch_->changed_keys.insert(key); } - if (keys_only_map_) - (*keys_only_map_)[key] = value.size(); + if (map_state_ == MapState::LOADED_KEYS_ONLY) + keys_only_map_[key] = value.size(); else - (*keys_values_map_)[key] = value; + keys_values_map_[key] = value; storage_used_ = new_storage_used; memory_used_ += new_item_memory - old_item_memory; @@ -275,43 +324,61 @@ const base::Optional<std::vector<uint8_t>>& client_old_value, const std::string& source, DeleteCallback callback) { - if (IsMapReloadNeeded()) { - LoadMap(base::Bind(&LevelDBWrapperImpl::Delete, base::Unretained(this), key, - client_old_value, source, base::Passed(&callback))); + // Map upgrade check is required because the cache state could be changed + // due to multiple bindings, and when multiple bindings are involved the + // |client_old_value| can race. Thus any changes require checking for an + // upgrade. + if (!IsMapLoaded() || IsMapUpgradeNeeded()) { + LoadMap(base::BindOnce(&LevelDBWrapperImpl::Delete, base::Unretained(this), + key, client_old_value, source, std::move(callback))); return; } + if (database_) + CreateCommitBatchIfNeeded(); + std::vector<uint8_t> old_value; - if (keys_only_map_) { - KeysOnlyMap::const_iterator found = keys_only_map_->find(key); - if (found == keys_only_map_->end()) { + if (map_state_ == MapState::LOADED_KEYS_ONLY) { + KeysOnlyMap::const_iterator found = keys_only_map_.find(key); + if (found == keys_only_map_.end()) { std::move(callback).Run(true); return; } - if (client_old_value && client_old_value.value().size() == found->second) + if (client_old_value && client_old_value.value().size() == found->second) { old_value = client_old_value.value(); - // If |client_old_value| was not provided or if it's size does not match, - // then we still let the change go through. But the notification sent to - // clients will not contain old value. This is okay since currently the - // only observer to these notification is the client itself. + } else { +#if DCHECK_IS_ON() + // If |client_old_value| was not provided or if it's size does not match, + // then we still let the change go through. But the notification sent to + // clients will not contain old value. This is okay since currently the + // only observer to these notification is the client itself. + DVLOG(1) << "Wrapper with prefix " + << leveldb::Uint8VectorToStdString(prefix_) + << ": past value has length of " << found->second << ", but:"; + if (client_old_value) { + DVLOG(1) << "Given past value has incorrect length of " + << client_old_value.value().size(); + } else { + DVLOG(1) << "No given past value was provided."; + } +#endif + } storage_used_ -= key.size() + found->second; - keys_only_map_->erase(found); + keys_only_map_.erase(found); memory_used_ -= key.size() + sizeof(size_t); + commit_batch_->changed_values[key] = std::vector<uint8_t>(); } else { - ValueMap::iterator found = keys_values_map_->find(key); - if (found == keys_values_map_->end()) { + DCHECK_EQ(map_state_, MapState::LOADED_KEYS_AND_VALUES); + ValueMap::iterator found = keys_values_map_.find(key); + if (found == keys_values_map_.end()) { std::move(callback).Run(true); return; } old_value.swap(found->second); - keys_values_map_->erase(found); + keys_values_map_.erase(found); memory_used_ -= key.size() + old_value.size(); storage_used_ -= key.size() + old_value.size(); - } - - if (database_) { - CreateCommitBatchIfNeeded(); - commit_batch_->changed_values[key] = base::nullopt; + commit_batch_->changed_keys.insert(key); } observers_.ForAllPtrs( @@ -323,14 +390,24 @@ void LevelDBWrapperImpl::DeleteAll(const std::string& source, DeleteAllCallback callback) { - if (IsMapReloadNeeded()) { - LoadMap(base::Bind(&LevelDBWrapperImpl::DeleteAll, base::Unretained(this), - source, base::Passed(&callback))); + // Don't check if a map upgrade is needed here and instead just create an + // empty map ourself. + if (!IsMapLoaded()) { + LoadMap(base::BindOnce(&LevelDBWrapperImpl::DeleteAll, + base::Unretained(this), source, + std::move(callback))); return; } - if ((keys_only_map_ && keys_only_map_->empty()) || - (keys_values_map_ && keys_values_map_->empty())) { + bool already_empty = IsMapLoadedAndEmpty(); + + // Upgrade map state if needed. + if (IsMapUpgradeNeeded()) { + DCHECK(keys_values_map_.empty()); + map_state_ = MapState::LOADED_KEYS_AND_VALUES; + } + + if (already_empty) { std::move(callback).Run(true); return; } @@ -339,12 +416,12 @@ CreateCommitBatchIfNeeded(); commit_batch_->clear_all_first = true; commit_batch_->changed_values.clear(); + commit_batch_->changed_keys.clear(); } - if (keys_only_map_) - keys_only_map_->clear(); - else - keys_values_map_->clear(); + keys_only_map_.clear(); + keys_values_map_.clear(); + storage_used_ = 0; memory_used_ = 0; observers_.ForAllPtrs( @@ -358,18 +435,18 @@ GetCallback callback) { // TODO(ssid): Remove this method since it is not supported in only keys mode, // crbug.com/764127. - if (desired_load_state_ != LoadState::KEYS_AND_VALUES) { + if (cache_mode_ == CacheMode::KEYS_ONLY_WHEN_POSSIBLE) { NOTREACHED(); return; } - if (IsMapReloadNeeded()) { - LoadMap(base::Bind(&LevelDBWrapperImpl::Get, base::Unretained(this), key, - base::Passed(&callback))); + if (!IsMapLoaded() || IsMapUpgradeNeeded()) { + LoadMap(base::BindOnce(&LevelDBWrapperImpl::Get, base::Unretained(this), + key, std::move(callback))); return; } - auto found = keys_values_map_->find(key); - if (found == keys_values_map_->end()) { + auto found = keys_values_map_.find(key); + if (found == keys_values_map_.end()) { std::move(callback).Run(false, std::vector<uint8_t>()); return; } @@ -379,21 +456,21 @@ void LevelDBWrapperImpl::GetAll( mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo complete_callback, GetAllCallback callback) { - if (!keys_values_map_) { - LoadMap(base::Bind(&LevelDBWrapperImpl::GetAll, base::Unretained(this), - base::Passed(&complete_callback), - base::Passed(&callback))); + // The map must always be loaded for the KEYS_ONLY_WHEN_POSSIBLE mode. + if (map_state_ != MapState::LOADED_KEYS_AND_VALUES) { + LoadMap(base::BindOnce(&LevelDBWrapperImpl::GetAll, base::Unretained(this), + std::move(complete_callback), std::move(callback))); return; } std::vector<mojom::KeyValuePtr> all; - for (const auto& it : (*keys_values_map_)) { + for (const auto& it : keys_values_map_) { mojom::KeyValuePtr kv = mojom::KeyValue::New(); kv->key = it.first; kv->value = it.second; all.push_back(std::move(kv)); } - std::move(callback).Run(leveldb::mojom::DatabaseError::OK, std::move(all)); + std::move(callback).Run(DatabaseError::OK, std::move(all)); if (complete_callback.is_valid()) { mojom::LevelDBWrapperGetAllCallbackAssociatedPtr complete_ptr; complete_ptr.Bind(std::move(complete_callback)); @@ -402,14 +479,11 @@ } void LevelDBWrapperImpl::SetCacheMode(CacheMode cache_mode) { - LoadState new_desired_state = cache_mode == CacheMode::KEYS_ONLY_WHEN_POSSIBLE - ? LoadState::KEYS_ONLY - : LoadState::KEYS_AND_VALUES; - if ((!database_ && new_desired_state == LoadState::KEYS_ONLY) || - new_desired_state == desired_load_state_) { + if (cache_mode_ == cache_mode || + (!database_ && cache_mode == CacheMode::KEYS_ONLY_WHEN_POSSIBLE)) { return; } - desired_load_state_ = new_desired_state; + cache_mode_ = cache_mode; bool should_send_values = cache_mode == CacheMode::KEYS_ONLY_WHEN_POSSIBLE; observers_.ForAllPtrs([should_send_values](mojom::LevelDBObserver* observer) { observer->ShouldSendOldValueOnMutations(should_send_values); @@ -432,29 +506,35 @@ delegate_->OnNoBindings(); } -void LevelDBWrapperImpl::LoadMap(const base::Closure& completion_callback) { - DCHECK(!keys_values_map_); +void LevelDBWrapperImpl::LoadMap(base::OnceClosure completion_callback) { + DCHECK_NE(map_state_, MapState::LOADED_KEYS_AND_VALUES); + DCHECK(keys_values_map_.empty()); + // Current commit batch needs to be applied before re-loading the map. The // re-load of map occurs only when GetAll() is called or CacheMode is set to // keys and values, and the |keys_only_map_| is already loaded. In this case // commit batch needs to be committed before reading the database. - if (keys_only_map_) { + if (map_state_ == MapState::LOADED_KEYS_ONLY) { DCHECK(on_load_complete_tasks_.empty()); DCHECK(database_); if (commit_batch_) CommitChanges(); // Make sure the keys only map is not used when on load tasks are in queue. // The changes to the wrapper will be queued to on load tasks. - keys_only_map_ = nullptr; + keys_only_map_.clear(); + map_state_ = MapState::UNLOADED; } - DCHECK_EQ(LoadState::UNLOADED, CurrentLoadState()); - on_load_complete_tasks_.push_back(completion_callback); - if (on_load_complete_tasks_.size() > 1) + on_load_complete_tasks_.push_back(std::move(completion_callback)); + if (map_state_ == MapState::LOADING_FROM_DATABASE || + map_state_ == MapState::LOADING_FROM_FORK) { return; + } + + map_state_ = MapState::LOADING_FROM_DATABASE; if (!database_) { - OnMapLoaded(leveldb::mojom::DatabaseError::IO_ERROR, + OnMapLoaded(DatabaseError::IO_ERROR, std::vector<leveldb::mojom::KeyValuePtr>()); return; } @@ -465,60 +545,58 @@ } void LevelDBWrapperImpl::OnMapLoaded( - leveldb::mojom::DatabaseError status, + DatabaseError status, std::vector<leveldb::mojom::KeyValuePtr> data) { - DCHECK(!keys_values_map_); + DCHECK(keys_values_map_.empty()); + DCHECK_EQ(map_state_, MapState::LOADING_FROM_DATABASE); - if (data.empty() && status == leveldb::mojom::DatabaseError::OK) { + if (data.empty() && status == DatabaseError::OK) { delegate_->MigrateData( base::BindOnce(&LevelDBWrapperImpl::OnGotMigrationData, weak_ptr_factory_.GetWeakPtr())); return; } + keys_only_map_.clear(); + map_state_ = MapState::LOADED_KEYS_AND_VALUES; - keys_values_map_ = std::make_unique<ValueMap>(); - storage_used_ = 0; + keys_values_map_.clear(); for (auto& it : data) { DCHECK_GE(it->key.size(), prefix_.size()); - storage_used_ += it->key.size() - prefix_.size() + it->value.size(); - (*keys_values_map_)[std::vector<uint8_t>(it->key.begin() + prefix_.size(), - it->key.end())] = + keys_values_map_[std::vector<uint8_t>(it->key.begin() + prefix_.size(), + it->key.end())] = std::move(it->value); } + CalculateStorageAndMemoryUsed(); - std::vector<Change> changes = delegate_->FixUpData(*keys_values_map_); + std::vector<Change> changes = delegate_->FixUpData(keys_values_map_); if (!changes.empty()) { DCHECK(database_); CreateCommitBatchIfNeeded(); for (auto& change : changes) { - auto it = keys_values_map_->find(change.first); + auto it = keys_values_map_.find(change.first); if (!change.second) { - DCHECK(it != keys_values_map_->end()); - storage_used_ -= it->first.size() + it->second.size(); - keys_values_map_->erase(it); + DCHECK(it != keys_values_map_.end()); + keys_values_map_.erase(it); } else { - if (it != keys_values_map_->end()) { - storage_used_ -= it->second.size(); + if (it != keys_values_map_.end()) { it->second = std::move(*change.second); - storage_used_ += it->second.size(); } else { - storage_used_ += change.first.size() + change.second->size(); - (*keys_values_map_)[change.first] = std::move(*change.second); + keys_values_map_[change.first] = std::move(*change.second); } } // No need to store values in |commit_batch_| if values are already // available in |keys_values_map_|, since CommitChanges() will take values // from there. - commit_batch_->changed_values[std::move(change.first)] = base::nullopt; + commit_batch_->changed_keys.insert(std::move(change.first)); } + CalculateStorageAndMemoryUsed(); CommitChanges(); } - memory_used_ = storage_used_; // We proceed without using a backing store, nothing will be persisted but the // class is functional for the lifetime of the object. delegate_->OnMapLoaded(status); - if (status != leveldb::mojom::DatabaseError::OK) { + if (status != DatabaseError::OK) { database_ = nullptr; SetCacheMode(CacheMode::KEYS_AND_VALUES); } @@ -527,32 +605,58 @@ } void LevelDBWrapperImpl::OnGotMigrationData(std::unique_ptr<ValueMap> data) { - keys_values_map_ = data ? std::move(data) : std::make_unique<ValueMap>(); - storage_used_ = 0; - for (const auto& it : *keys_values_map_) - storage_used_ += it.first.size() + it.second.size(); - memory_used_ = storage_used_; + keys_only_map_.clear(); + keys_values_map_ = data ? std::move(*data) : ValueMap(); + map_state_ = MapState::LOADED_KEYS_AND_VALUES; + CalculateStorageAndMemoryUsed(); if (database_ && !empty()) { CreateCommitBatchIfNeeded(); // CommitChanges() will take values from |keys_values_map_|. - for (const auto& it : *keys_values_map_) - commit_batch_->changed_values[it.first] = base::nullopt; + for (const auto& it : keys_values_map_) + commit_batch_->changed_keys.insert(it.first); CommitChanges(); } OnLoadComplete(); } -void LevelDBWrapperImpl::OnLoadComplete() { - std::vector<base::Closure> tasks; - on_load_complete_tasks_.swap(tasks); - for (auto& task : tasks) - task.Run(); +void LevelDBWrapperImpl::CalculateStorageAndMemoryUsed() { + memory_used_ = 0; + storage_used_ = 0; - // Unload the map if only keys are desired. + for (auto& it : keys_values_map_) + memory_used_ += it.first.size() + it.second.size(); + storage_used_ = memory_used_; + + for (auto& it : keys_only_map_) { + memory_used_ += it.first.size() + sizeof(size_t); + storage_used_ += it.first.size() + it.second; + } +} + +void LevelDBWrapperImpl::OnLoadComplete() { + DCHECK(IsMapLoaded()); + + std::vector<base::OnceClosure> tasks; + on_load_complete_tasks_.swap(tasks); + for (auto it = tasks.begin(); it != tasks.end(); ++it) { + // Some tasks (like GetAll) can require a reload if they need a different + // map type. If this happens, stop our task execution. Appending tasks is + // required (instead of replacing) because the task that required the + // reload-requesting-task put itself on the task queue and it still needs + // to be executed before the rest of the tasks. + if (!IsMapLoaded()) { + on_load_complete_tasks_.reserve(on_load_complete_tasks_.size() + + (tasks.end() - it)); + std::move(it, tasks.end(), std::back_inserter(on_load_complete_tasks_)); + return; + } + std::move(*it).Run(); + } + + // Call before |OnNoBindings| as delegate can destroy this object. UnloadMapIfPossible(); - DCHECK(!IsMapReloadNeeded()); // We might need to call the no_bindings_callback_ here if bindings became // empty while waiting for load to complete. @@ -609,47 +713,73 @@ return; DCHECK(database_); - DCHECK_NE(LoadState::UNLOADED, CurrentLoadState()); + DCHECK(IsMapLoaded()) << static_cast<int>(map_state_); commit_rate_limiter_.add_samples(1); // Commit all our changes in a single batch. - std::vector<leveldb::mojom::BatchedOperationPtr> operations = - delegate_->PrepareToCommit(); + std::vector<BatchedOperationPtr> operations = delegate_->PrepareToCommit(); + bool has_changes = !operations.empty() || + !commit_batch_->changed_values.empty() || + !commit_batch_->changed_keys.empty(); + if (commit_batch_->clear_all_first) { - leveldb::mojom::BatchedOperationPtr item = - leveldb::mojom::BatchedOperation::New(); + BatchedOperationPtr item = BatchedOperation::New(); item->type = leveldb::mojom::BatchOperationType::DELETE_PREFIXED_KEY; item->key = prefix_; operations.push_back(std::move(item)); } size_t data_size = 0; - for (auto& it : commit_batch_->changed_values) { - const auto& key = it.first; - data_size += key.size(); - leveldb::mojom::BatchedOperationPtr item = - leveldb::mojom::BatchedOperation::New(); - item->key.reserve(prefix_.size() + key.size()); - item->key.insert(item->key.end(), prefix_.begin(), prefix_.end()); - item->key.insert(item->key.end(), key.begin(), key.end()); - if (keys_values_map_) { - auto kv_it = keys_values_map_->find(key); - if (kv_it != keys_values_map_->end()) { + if (map_state_ == MapState::LOADED_KEYS_AND_VALUES) { + DCHECK(commit_batch_->changed_values.empty()) + << "Map state and commit state out of sync."; + for (const auto& key : commit_batch_->changed_keys) { + data_size += key.size(); + BatchedOperationPtr item = BatchedOperation::New(); + item->key.reserve(prefix_.size() + key.size()); + item->key.insert(item->key.end(), prefix_.begin(), prefix_.end()); + item->key.insert(item->key.end(), key.begin(), key.end()); + auto kv_it = keys_values_map_.find(key); + if (kv_it != keys_values_map_.end()) { item->type = leveldb::mojom::BatchOperationType::PUT_KEY; data_size += kv_it->second.size(); item->value = kv_it->second; } else { item->type = leveldb::mojom::BatchOperationType::DELETE_KEY; } - } else { - if (it.second) { + operations.push_back(std::move(item)); + } + } else { + DCHECK(commit_batch_->changed_keys.empty()) + << "Map state and commit state out of sync."; + DCHECK_EQ(map_state_, MapState::LOADED_KEYS_ONLY); + for (auto& it : commit_batch_->changed_values) { + const auto& key = it.first; + data_size += key.size(); + BatchedOperationPtr item = BatchedOperation::New(); + item->key.reserve(prefix_.size() + key.size()); + item->key.insert(item->key.end(), prefix_.begin(), prefix_.end()); + item->key.insert(item->key.end(), key.begin(), key.end()); + auto kv_it = keys_only_map_.find(key); + if (kv_it != keys_only_map_.end()) { item->type = leveldb::mojom::BatchOperationType::PUT_KEY; - data_size += it.second.value().size(); - item->value = std::move(it.second.value()); + data_size += it.second.size(); + item->value = std::move(it.second); } else { item->type = leveldb::mojom::BatchOperationType::DELETE_KEY; } + operations.push_back(std::move(item)); } + } + // Schedule the copy, and ignore if |clear_all_first| is specified and there + // are no changing keys. + if (commit_batch_->copy_to_prefix) { + DCHECK(!has_changes); + DCHECK(!commit_batch_->clear_all_first); + BatchedOperationPtr item = BatchedOperation::New(); + item->type = leveldb::mojom::BatchOperationType::COPY_PREFIXED_KEY; + item->key = prefix_; + item->value = std::move(commit_batch_->copy_to_prefix.value()); operations.push_back(std::move(item)); } commit_batch_.reset(); @@ -658,78 +788,102 @@ ++commit_batches_in_flight_; - // TODO(michaeln): Currently there is no guarantee LevelDBDatabaseImp::Write + // TODO(michaeln): Currently there is no guarantee LevelDBDatabaseImpl::Write // will run during a clean shutdown. We need that to avoid dataloss. database_->Write(std::move(operations), base::BindOnce(&LevelDBWrapperImpl::OnCommitComplete, weak_ptr_factory_.GetWeakPtr())); } -void LevelDBWrapperImpl::OnCommitComplete(leveldb::mojom::DatabaseError error) { +void LevelDBWrapperImpl::OnCommitComplete(DatabaseError error) { --commit_batches_in_flight_; StartCommitTimer(); - if (error == leveldb::mojom::DatabaseError::OK) { - // When the desired load state is changed, the unload of map is deferred - // when there are uncommitted changes. So, try again after Starting a - // commit. - UnloadMapIfPossible(); - } else { - // If commit fails store the values in memory. - SetCacheMode(LevelDBWrapperImpl::CacheMode::KEYS_AND_VALUES); - } + if (error != DatabaseError::OK) + SetCacheMode(CacheMode::KEYS_AND_VALUES); + + // Call before |DidCommit| as delegate can destroy this object. + UnloadMapIfPossible(); + delegate_->DidCommit(error); } void LevelDBWrapperImpl::UnloadMapIfPossible() { - if (CurrentLoadState() == LoadState::UNLOADED || - CurrentLoadState() == desired_load_state_) { + // Do not unload the map if: + // * The desired cache mode isn't key-only, + // * The map isn't a loaded key-value map, + // * There are pending tasks waiting on the key-value map being loaded, or + // * There is no database connection. + // * We have commit batches in-flight. + if (cache_mode_ != CacheMode::KEYS_ONLY_WHEN_POSSIBLE || + map_state_ != MapState::LOADED_KEYS_AND_VALUES || + has_pending_load_tasks() || !database_ || commit_batches_in_flight_ > 0) { return; } - // Do not clear the map if there are uncommitted changes since the commit - // batch might not have the values populated. - if (!database_ || commit_batch_ || commit_batches_in_flight_) - return; - if (desired_load_state_ == LoadState::KEYS_ONLY) { - keys_only_map_ = std::make_unique<KeysOnlyMap>(); - memory_used_ = 0; - for (auto& it : *keys_values_map_) { - keys_only_map_->insert( - std::make_pair(std::move(it.first), it.second.size())); - memory_used_ += it.first.size() + sizeof(size_t); + keys_only_map_.clear(); + memory_used_ = 0; + for (auto& it : keys_values_map_) { + keys_only_map_.insert(std::make_pair(it.first, it.second.size())); + } + if (commit_batch_) { + for (const auto& key : commit_batch_->changed_keys) { + auto value_it = keys_values_map_.find(key); + commit_batch_->changed_values[key] = value_it == keys_values_map_.end() + ? std::vector<uint8_t>() + : std::move(value_it->second); } - keys_values_map_ = nullptr; - } else { - // Since |keys_only_map_| is loaded and desired state is keys and values, - // the |keys_values_map_| can be re-created only if |keys_only_map_| was - // empty. Else this function returns in an unloaded state and a load is - // triggered when needed. - if (keys_only_map_->empty()) - keys_values_map_ = std::make_unique<ValueMap>(); - keys_only_map_ = nullptr; + commit_batch_->changed_keys.clear(); } + + keys_values_map_.clear(); + map_state_ = MapState::LOADED_KEYS_ONLY; + + CalculateStorageAndMemoryUsed(); } -bool LevelDBWrapperImpl::IsMapReloadNeeded() const { - // If current load state is not equal to desired state, reload is needed - // unless |keys_values_map_| is loaded. If |on_load_complete_tasks_| is not - // empty and desired state is achieved, it means that there was a task that - // required reload to load values (eg: GetAll()). If we continue other tasks - // without reload, the result returned by the task in queue will be - // inconsistent since the reply callback for the other task reached earlier. - // So, we must queue all tasks from that point till reload finishes. - return (CurrentLoadState() != desired_load_state_ && !keys_values_map_) || - !on_load_complete_tasks_.empty(); +void LevelDBWrapperImpl::DoForkOperation( + const base::WeakPtr<LevelDBWrapperImpl>& forked_wrapper) { + if (!forked_wrapper) + return; + + DCHECK(IsMapLoaded()); + // TODO(dmurph): If these commits fails, then the disk could be in an + // inconsistant state. Ideally all further operations will fail and the code + // will correctly delete the database? + if (database_) { + // All changes must be stored in the database before the copy operation. + if (has_changes_to_commit()) + CommitChanges(); + CreateCommitBatchIfNeeded(); + commit_batch_->copy_to_prefix = forked_wrapper->prefix_; + CommitChanges(); + } + + forked_wrapper->OnForkStateLoaded(database_ != nullptr, keys_values_map_, + keys_only_map_); } -LevelDBWrapperImpl::LoadState LevelDBWrapperImpl::CurrentLoadState() const { - if (keys_only_map_) - return LoadState::KEYS_ONLY; - else if (keys_values_map_) - return LoadState::KEYS_AND_VALUES; - else - return LoadState::UNLOADED; +void LevelDBWrapperImpl::OnForkStateLoaded(bool database_enabled, + const ValueMap& value_map, + const KeysOnlyMap& keys_only_map) { + // This callback can get either the value map or the key only map depending + // on parent operations and other things. So handle both. + if (!value_map.empty() || keys_only_map.empty()) { + keys_values_map_ = value_map; + map_state_ = MapState::LOADED_KEYS_AND_VALUES; + } else { + keys_only_map_ = keys_only_map; + map_state_ = MapState::LOADED_KEYS_ONLY; + } + + if (!database_enabled) { + database_ = nullptr; + cache_mode_ = CacheMode::KEYS_AND_VALUES; + } + + CalculateStorageAndMemoryUsed(); + OnLoadComplete(); } } // namespace content
diff --git a/content/browser/leveldb_wrapper_impl.h b/content/browser/leveldb_wrapper_impl.h index 9ed919da..bf6855d2 100644 --- a/content/browser/leveldb_wrapper_impl.h +++ b/content/browser/leveldb_wrapper_impl.h
@@ -15,6 +15,7 @@ #include "base/macros.h" #include "base/optional.h" #include "base/time/time.h" +#include "content/common/content_export.h" #include "content/common/leveldb_wrapper.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/interface_ptr_set.h" @@ -37,6 +38,8 @@ // 2) Enforces a max_size constraint. // 3) Informs observers when values scoped by prefix are modified. // 4) Throttles requests to avoid overwhelming the disk. +// +// The wrapper supports two different caching modes. class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper { public: using ValueMap = std::map<std::vector<uint8_t>, std::vector<uint8_t>>; @@ -47,6 +50,7 @@ class CONTENT_EXPORT Delegate { public: + virtual ~Delegate(); virtual void OnNoBindings() = 0; virtual std::vector<leveldb::mojom::BatchedOperationPtr> PrepareToCommit() = 0; @@ -93,16 +97,41 @@ void Bind(mojom::LevelDBWrapperRequest request); + // Forks, or copies, all data in this prefix to another prefix. + // Note: this object (the parent) must stay alive until the forked wrapper + // has been loaded (see initialized()). + std::unique_ptr<LevelDBWrapperImpl> ForkToNewPrefix( + const std::string& new_prefix, + Delegate* delegate, + const Options& options); + + // Cancels all pending load tasks. Useful for emergency destructions. If the + // wrapper is unloaded (initialized() returns false), this will DROP all + // pending changes to the database, and any uninitialized wrappers created + // through |ForkToNewPrefix| will stay BROKEN and unresponsive. + void CancelAllPendingRequests(); + // The total bytes used by items which counts towards the quota. size_t storage_used() const { return storage_used_; } // The physical memory used by the cache. size_t memory_used() const { return memory_used_; } + bool empty() const { return storage_used_ == 0; } + // If this wrapper is loaded and sending changes to the database. + bool initialized() const { return IsMapLoaded(); } + + CacheMode cache_mode() const { return cache_mode_; } + + // Tasks that are waiting for the map to be loaded. bool has_pending_load_tasks() const { return !on_load_complete_tasks_.empty(); } + bool has_changes_to_commit() const { return commit_batch_.get(); } + + const std::vector<uint8_t>& prefix() { return prefix_; } + // Commence aggressive flushing. This should be called early during startup, // before any localStorage writing. Currently scheduled writes will not be // rescheduled and will be flushed at the scheduled time after which @@ -146,11 +175,12 @@ GetAllCallback callback) override; private: - FRIEND_TEST_ALL_PREFIXES(LevelDBWrapperImplTest, SetOnlyKeysWithoutDatabase); - FRIEND_TEST_ALL_PREFIXES(LevelDBWrapperImplTest, CommitOnDifferentCacheModes); - FRIEND_TEST_ALL_PREFIXES(LevelDBWrapperImplTest, GetAllWhenCacheOnlyKeys); FRIEND_TEST_ALL_PREFIXES(LevelDBWrapperImplTest, GetAllAfterSetCacheMode); + FRIEND_TEST_ALL_PREFIXES(LevelDBWrapperImplTest, + PutLoadsValuesAfterCacheModeUpgrade); FRIEND_TEST_ALL_PREFIXES(LevelDBWrapperImplTest, SetCacheModeConsistent); + FRIEND_TEST_ALL_PREFIXES(LevelDBWrapperImplParamTest, + CommitOnDifferentCacheModes); // Used to rate limit commits. class RateLimiter { @@ -169,57 +199,112 @@ base::TimeDelta ComputeDelayNeeded( const base::TimeDelta elapsed_time) const; + float rate() const { return rate_; } + private: float rate_; float samples_; base::TimeDelta time_quantum_; }; - enum class LoadState { UNLOADED = 0, KEYS_ONLY, KEYS_AND_VALUES }; - + // There can be only one fork operation per commit batch. struct CommitBatch { bool clear_all_first; - // Values in this map are only used if |keys_only_map_| is loaded. - std::map<std::vector<uint8_t>, base::Optional<std::vector<uint8_t>>> - changed_values; + // Prefix copying is performed before applying changes. + base::Optional<std::vector<uint8_t>> copy_to_prefix; + // Used if the map_type_ is LOADED_KEYS_ONLY. + std::map<std::vector<uint8_t>, std::vector<uint8_t>> changed_values; + // Used if the map_type_ is LOADED_KEYS_AND_VALUES. + std::set<std::vector<uint8_t>> changed_keys; CommitBatch(); ~CommitBatch(); }; - // Changes the cache (a copy of map stored in memory) to contain only keys - // instead of keys and values. The only keys mode can be set only when there - // is one client binding and it automatically changes to keys and values mode - // when more than one binding exists. The max size constraints are still - // valid. Notification to the observers when an item is mutated depends on the - // |client_old_value| when cache contains only keys. Changing the mode and - // using GetAll() when only keys are stored would cause extra disk access. + enum class MapState { + UNLOADED, + // Loading from the database connection. + LOADING_FROM_DATABASE, + // Loading from another LevelDBWrapperImpl that we have forked from. + LOADING_FROM_FORK, + LOADED_KEYS_ONLY, + LOADED_KEYS_AND_VALUES + }; + + using LoadStateForForkCallback = base::OnceCallback< + void(bool database_enabled, const ValueMap&, const KeysOnlyMap&)>; + using ForkSourceEarlyDeathCallback = + base::OnceCallback<void(std::vector<uint8_t> source_prefix)>; + + // Changes the cache mode of the wrapper. If applicable, this will change the + // internal storage type after the next commit. The keys-only mode can only + // be set only when there is one client binding. It automatically changes to + // keys-and-values mode when more than one binding exists. + // Notifications to observers when an item is mutated depends on the + // |client_old_value| when in keys-only mode. Using GetAll during + // keys-only mode will cause extra disk access. void SetCacheMode(CacheMode cache_mode); void OnConnectionError(); - void LoadMap(const base::Closure& completion_callback); + + // Always loads the |keys_values_map_|, sets the |map_state_| to + // LOADED_KEYS_AND_VALUES, and calls through all the completion callbacks. + // + // Then if the |cache_mode_| is keys-only, it unloads the map to the + // |keys_only_map_| and sets the |map_state_| to LOADED_KEYS_ONLY + void LoadMap(base::OnceClosure completion_callback); void OnMapLoaded(leveldb::mojom::DatabaseError status, std::vector<leveldb::mojom::KeyValuePtr> data); void OnGotMigrationData(std::unique_ptr<ValueMap> data); + void CalculateStorageAndMemoryUsed(); void OnLoadComplete(); + void CreateCommitBatchIfNeeded(); void StartCommitTimer(); base::TimeDelta ComputeCommitDelay() const; + void CommitChanges(); void OnCommitComplete(leveldb::mojom::DatabaseError error); + void UnloadMapIfPossible(); - bool IsMapReloadNeeded() const; - LoadState CurrentLoadState() const; + + bool IsMapUpgradeNeeded() const { + return map_state_ == MapState::LOADED_KEYS_ONLY && + cache_mode_ == CacheMode::KEYS_AND_VALUES; + } + + bool IsMapLoaded() const { + return map_state_ == MapState::LOADED_KEYS_ONLY || + map_state_ == MapState::LOADED_KEYS_AND_VALUES; + } + + bool IsMapLoadedAndEmpty() const { + return (map_state_ == MapState::LOADED_KEYS_ONLY && + keys_only_map_.empty()) || + (map_state_ == MapState::LOADED_KEYS_AND_VALUES && + keys_values_map_.empty()); + } + + void DoForkOperation(const base::WeakPtr<LevelDBWrapperImpl>& forked_wrapper); + void OnForkStateLoaded(bool database_enabled, + const ValueMap& map, + const KeysOnlyMap& key_only_map); std::vector<uint8_t> prefix_; mojo::BindingSet<mojom::LevelDBWrapper> bindings_; mojo::AssociatedInterfacePtrSet<mojom::LevelDBObserver> observers_; Delegate* delegate_; leveldb::mojom::LevelDBDatabase* database_; - std::unique_ptr<ValueMap> keys_values_map_; - std::unique_ptr<KeysOnlyMap> keys_only_map_; - LoadState desired_load_state_; - std::vector<base::Closure> on_load_complete_tasks_; + + // For commits to work correctly the map loaded state (keys vs keys & values) + // must stay consistent for a given commit batch. + MapState map_state_ = MapState::UNLOADED; + CacheMode cache_mode_; + ValueMap keys_values_map_; + KeysOnlyMap keys_only_map_; + // These are always consumed & cleared when the map is loaded. + std::vector<base::OnceClosure> on_load_complete_tasks_; + size_t storage_used_; size_t max_size_; size_t memory_used_; @@ -229,6 +314,7 @@ RateLimiter commit_rate_limiter_; int commit_batches_in_flight_ = 0; std::unique_ptr<CommitBatch> commit_batch_; + base::WeakPtrFactory<LevelDBWrapperImpl> weak_ptr_factory_; static bool s_aggressive_flushing_enabled_;
diff --git a/content/browser/leveldb_wrapper_impl_unittest.cc b/content/browser/leveldb_wrapper_impl_unittest.cc index 12f7d95..ac7b59e 100644 --- a/content/browser/leveldb_wrapper_impl_unittest.cc +++ b/content/browser/leveldb_wrapper_impl_unittest.cc
@@ -4,13 +4,23 @@ #include "content/browser/leveldb_wrapper_impl.h" +#include "base/atomic_ref_count.h" +#include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" +#include "base/task_runner_util.h" +#include "base/task_scheduler/post_task.h" +#include "base/test/test_simple_task_runner.h" +#include "base/threading/thread.h" #include "components/leveldb/public/cpp/util.h" +#include "components/leveldb/public/interfaces/leveldb.mojom.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/test/fake_leveldb_database.h" #include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/bindings/strong_associated_binding.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { @@ -30,39 +40,94 @@ return leveldb::StdStringToUint8Vector(input); } +class InternalIncrementalBarrier { + public: + InternalIncrementalBarrier(base::OnceClosure done_closure) + : num_callbacks_left_(1), done_closure_(std::move(done_closure)) {} + + void Dec() { + // This is the same as in BarrierClosure. + DCHECK(!num_callbacks_left_.IsZero()); + if (!num_callbacks_left_.Decrement()) { + base::OnceClosure done = std::move(done_closure_); + delete this; + std::move(done).Run(); + } + } + + base::OnceClosure Inc() { + num_callbacks_left_.Increment(); + return base::BindOnce(&InternalIncrementalBarrier::Dec, + base::Unretained(this)); + } + + private: + base::AtomicRefCount num_callbacks_left_; + base::OnceClosure done_closure_; + + DISALLOW_COPY_AND_ASSIGN(InternalIncrementalBarrier); +}; + +// The callbacks returned by Get might get called after destruction of this +// class (and thus the done_closure), so there needs to be an internal class +// to hold the final callback & manage the refcount. +class IncrementalBarrier { + public: + explicit IncrementalBarrier(base::OnceClosure done_closure) + : internal_barrier_( + new InternalIncrementalBarrier(std::move(done_closure))) {} + + ~IncrementalBarrier() { internal_barrier_->Dec(); } + + base::OnceClosure Get() { return internal_barrier_->Inc(); } + + private: + InternalIncrementalBarrier* internal_barrier_; // self-deleting + + DISALLOW_COPY_AND_ASSIGN(IncrementalBarrier); +}; + class GetAllCallback : public mojom::LevelDBWrapperGetAllCallback { public: static mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo CreateAndBind( bool* result, base::OnceClosure callback) { - mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo ptr_info; - auto request = mojo::MakeRequest(&ptr_info); + mojom::LevelDBWrapperGetAllCallbackAssociatedPtr ptr; + auto request = mojo::MakeRequestAssociatedWithDedicatedPipe(&ptr); mojo::MakeStrongAssociatedBinding( base::WrapUnique(new GetAllCallback(result, std::move(callback))), std::move(request)); - return ptr_info; + return ptr.PassInterface(); } private: GetAllCallback(bool* result, base::OnceClosure callback) - : m_result(result), m_callback(std::move(callback)) {} + : result_(result), callback_(std::move(callback)) {} void Complete(bool success) override { - *m_result = success; - if (!m_callback.is_null()) - std::move(m_callback).Run(); + *result_ = success; + if (callback_) + std::move(callback_).Run(); } - bool* m_result; - base::OnceClosure m_callback; + bool* result_; + base::OnceClosure callback_; }; class MockDelegate : public LevelDBWrapperImpl::Delegate { public: + MockDelegate() {} + ~MockDelegate() override {} + void OnNoBindings() override {} std::vector<leveldb::mojom::BatchedOperationPtr> PrepareToCommit() override { return std::vector<leveldb::mojom::BatchedOperationPtr>(); } - void DidCommit(DatabaseError error) override {} + void DidCommit(DatabaseError error) override { + if (error != DatabaseError::OK) + LOG(ERROR) << "error committing!"; + if (committed_) + std::move(committed_).Run(); + } void OnMapLoaded(DatabaseError error) override { map_load_count_++; } std::vector<LevelDBWrapperImpl::Change> FixUpData( const LevelDBWrapperImpl::ValueMap& data) override { @@ -74,9 +139,14 @@ mock_changes_ = std::move(changes); } + void SetDidCommitCallback(base::OnceClosure committed) { + committed_ = std::move(committed); + } + private: int map_load_count_ = 0; std::vector<LevelDBWrapperImpl::Change> mock_changes_; + base::OnceClosure committed_; }; void GetCallback(base::OnceClosure callback, @@ -89,6 +159,29 @@ std::move(callback).Run(); } +base::OnceCallback<void(bool, const std::vector<uint8_t>&)> MakeGetCallback( + base::OnceClosure callback, + bool* success_out, + std::vector<uint8_t>* value_out) { + return base::BindOnce(&GetCallback, std::move(callback), success_out, + value_out); +} + +void GetAllDataCallback(leveldb::mojom::DatabaseError* status_out, + std::vector<mojom::KeyValuePtr>* data_out, + leveldb::mojom::DatabaseError status, + std::vector<mojom::KeyValuePtr> data) { + *status_out = status; + *data_out = std::move(data); +} + +base::OnceCallback<void(leveldb::mojom::DatabaseError status, + std::vector<mojom::KeyValuePtr> data)> +MakeGetAllCallback(leveldb::mojom::DatabaseError* status_out, + std::vector<mojom::KeyValuePtr>* data_out) { + return base::BindOnce(&GetAllDataCallback, status_out, data_out); +} + void SuccessCallback(base::OnceClosure callback, bool* success_out, bool success) { @@ -96,8 +189,23 @@ std::move(callback).Run(); } +base::OnceCallback<void(bool)> MakeSuccessCallback(base::OnceClosure callback, + bool* success_out) { + return base::BindOnce(&SuccessCallback, std::move(callback), success_out); +} + void NoOpSuccessCallback(bool success) {} +LevelDBWrapperImpl::Options GetDefaultTestingOptions(CacheMode cache_mode) { + LevelDBWrapperImpl::Options options; + options.max_size = kTestSizeLimit; + options.default_commit_delay = base::TimeDelta::FromSeconds(5); + options.max_bytes_per_hour = 10 * 1024 * 1024; + options.max_commits_per_hour = 60; + options.cache_mode = cache_mode; + return options; +} + } // namespace class LevelDBWrapperImplTest : public testing::Test, @@ -112,21 +220,18 @@ bool should_send_old_value; }; - LevelDBWrapperImplTest() - : db_(&mock_data_), - observer_binding_(this) { - LevelDBWrapperImpl::Options options; - options.max_size = kTestSizeLimit; - options.default_commit_delay = base::TimeDelta::FromSeconds(5); - options.max_bytes_per_hour = 10 * 1024 * 1024; - options.max_commits_per_hour = 60; - options.cache_mode = CacheMode::KEYS_ONLY_WHEN_POSSIBLE; + LevelDBWrapperImplTest() : db_(&mock_data_), observer_binding_(this) { + auto request = mojo::MakeRequest(&level_db_database_ptr_); + db_.Bind(std::move(request)); + + LevelDBWrapperImpl::Options options = + GetDefaultTestingOptions(CacheMode::KEYS_ONLY_WHEN_POSSIBLE); level_db_wrapper_ = std::make_unique<LevelDBWrapperImpl>( - &db_, test_prefix_, &delegate_, options); + level_db_database_ptr_.get(), test_prefix_, &delegate_, options); set_mock_data(test_prefix_ + test_key1_, test_value1_); set_mock_data(test_prefix_ + test_key2_, test_value2_); - set_mock_data(test_key2_, "baddata"); + set_mock_data("123", "baddata"); level_db_wrapper_->Bind(mojo::MakeRequest(&level_db_wrapper_ptr_)); mojom::LevelDBObserverAssociatedPtrInfo ptr_info; @@ -134,6 +239,8 @@ level_db_wrapper_ptr_->AddObserver(std::move(ptr_info)); } + ~LevelDBWrapperImplTest() override {} + void set_mock_data(const std::string& key, const std::string& value) { mock_data_[ToBytes(key)] = ToBytes(value); } @@ -156,51 +263,108 @@ mojom::LevelDBWrapper* wrapper() { return level_db_wrapper_ptr_.get(); } LevelDBWrapperImpl* wrapper_impl() { return level_db_wrapper_.get(); } - bool GetSync(const std::vector<uint8_t>& key, std::vector<uint8_t>* result) { - base::RunLoop run_loop; + bool GetSync(mojom::LevelDBWrapper* wrapper, + const std::vector<uint8_t>& key, + std::vector<uint8_t>* result) { bool success = false; - wrapper()->Get(key, base::BindOnce(&GetCallback, run_loop.QuitClosure(), - &success, result)); - run_loop.Run(); + base::RunLoop loop; + wrapper->Get(key, MakeGetCallback(loop.QuitClosure(), &success, result)); + loop.Run(); return success; } + bool PutSync(mojom::LevelDBWrapper* wrapper, + const std::vector<uint8_t>& key, + const std::vector<uint8_t>& value, + const base::Optional<std::vector<uint8_t>>& client_old_value, + std::string source = kTestSource) { + bool success = false; + base::RunLoop loop; + wrapper->Put(key, value, client_old_value, source, + MakeSuccessCallback(loop.QuitClosure(), &success)); + loop.Run(); + return success; + } + + bool DeleteSync( + mojom::LevelDBWrapper* wrapper, + const std::vector<uint8_t>& key, + const base::Optional<std::vector<uint8_t>>& client_old_value) { + bool success = false; + base::RunLoop loop; + wrapper->Delete(key, client_old_value, test_source_, + MakeSuccessCallback(loop.QuitClosure(), &success)); + loop.Run(); + return success; + } + + bool DeleteAllSync(mojom::LevelDBWrapper* wrapper) { + bool success = false; + base::RunLoop loop; + wrapper->DeleteAll(test_source_, + MakeSuccessCallback(loop.QuitClosure(), &success)); + loop.Run(); + return success; + } + + bool GetSync(const std::vector<uint8_t>& key, std::vector<uint8_t>* result) { + return GetSync(wrapper(), key, result); + } + bool PutSync(const std::vector<uint8_t>& key, const std::vector<uint8_t>& value, const base::Optional<std::vector<uint8_t>>& client_old_value, std::string source = kTestSource) { - base::RunLoop run_loop; - bool success = false; - wrapper()->Put( - key, value, client_old_value, source, - base::BindOnce(&SuccessCallback, run_loop.QuitClosure(), &success)); - run_loop.Run(); - return success; + return PutSync(wrapper(), key, value, client_old_value, source); } bool DeleteSync( const std::vector<uint8_t>& key, const base::Optional<std::vector<uint8_t>>& client_old_value) { - base::RunLoop run_loop; - bool success = false; - wrapper()->Delete( - key, client_old_value, kTestSource, - base::BindOnce(&SuccessCallback, run_loop.QuitClosure(), &success)); - run_loop.Run(); - return success; + return DeleteSync(wrapper(), key, client_old_value); } - bool DeleteAllSync() { - base::RunLoop run_loop; - bool success = false; - wrapper()->DeleteAll( - kTestSource, - base::BindOnce(&SuccessCallback, run_loop.QuitClosure(), &success)); - run_loop.Run(); - return success; + bool DeleteAllSync() { return DeleteAllSync(wrapper()); } + + std::string GetSyncStrUsingGetAll(LevelDBWrapperImpl* wrapper_impl, + const std::string& key) { + leveldb::mojom::DatabaseError status; + std::vector<mojom::KeyValuePtr> data; + bool done = false; + + base::RunLoop loop; + // Testing the 'Sync' mojo version is a big headache involving 3 threads, so + // just test the async version. + wrapper_impl->GetAll( + GetAllCallback::CreateAndBind(&done, loop.QuitClosure()), + MakeGetAllCallback(&status, &data)); + loop.Run(); + + if (!done) + return ""; + + if (status != leveldb::mojom::DatabaseError::OK) + return ""; + + for (const auto& key_value : data) { + if (key_value->key == ToBytes(key)) { + return ToString(key_value->value); + } + } + return ""; } - void CommitChanges() { level_db_wrapper_->ScheduleImmediateCommit(); } + void BlockingCommit() { BlockingCommit(&delegate_, level_db_wrapper_.get()); } + + void BlockingCommit(MockDelegate* delegate, LevelDBWrapperImpl* wrapper) { + while (wrapper->has_pending_load_tasks() || + wrapper->has_changes_to_commit()) { + base::RunLoop loop; + delegate->SetDidCommitCallback(loop.QuitClosure()); + wrapper->ScheduleImmediateCommit(); + loop.Run(); + } + } const std::vector<Observation>& observations() { return observations_; } @@ -216,10 +380,15 @@ const std::string test_key2_ = "123"; const std::string test_value1_ = "defdata"; const std::string test_value2_ = "123data"; + const std::string test_copy_prefix1_ = "www"; + const std::string test_copy_prefix2_ = "xxx"; + const std::string test_copy_prefix3_ = "yyy"; + const std::string test_source_ = kTestSource; const std::vector<uint8_t> test_prefix_bytes_ = ToBytes(test_prefix_); const std::vector<uint8_t> test_key1_bytes_ = ToBytes(test_key1_); const std::vector<uint8_t> test_key2_bytes_ = ToBytes(test_key2_); + const std::vector<uint8_t> test_value1_bytes_ = ToBytes(test_value1_); const std::vector<uint8_t> test_value2_bytes_ = ToBytes(test_value2_); private: @@ -257,6 +426,7 @@ TestBrowserThreadBundle thread_bundle_; std::map<std::vector<uint8_t>, std::vector<uint8_t>> mock_data_; FakeLevelDBDatabase db_; + leveldb::mojom::LevelDBDatabasePtr level_db_database_ptr_; MockDelegate delegate_; std::unique_ptr<LevelDBWrapperImpl> level_db_wrapper_; mojom::LevelDBWrapperPtr level_db_wrapper_ptr_; @@ -292,10 +462,21 @@ std::vector<uint8_t> key = test_key2_bytes_; std::vector<uint8_t> value = ToBytes("foo"); - EXPECT_TRUE(PutSync(key, value, test_value2_bytes_)); - + base::RunLoop loop; + bool put_success = false; std::vector<uint8_t> result; - EXPECT_TRUE(GetSync(key, &result)); + bool get_success = false; + { + IncrementalBarrier barrier(loop.QuitClosure()); + wrapper()->Put(key, value, test_value2_bytes_, test_source_, + MakeSuccessCallback(barrier.Get(), &put_success)); + wrapper()->Get(key, MakeGetCallback(barrier.Get(), &get_success, &result)); + } + + loop.Run(); + EXPECT_TRUE(put_success); + EXPECT_TRUE(get_success); + EXPECT_EQ(value, result); } @@ -311,19 +492,45 @@ EXPECT_EQ(value, result); } +TEST_F(LevelDBWrapperImplTest, PutLoadsValuesAfterCacheModeUpgrade) { + std::vector<uint8_t> key = ToBytes("newkey"); + std::vector<uint8_t> value1 = ToBytes("foo"); + std::vector<uint8_t> value2 = ToBytes("bar"); + + ASSERT_EQ(CacheMode::KEYS_ONLY_WHEN_POSSIBLE, wrapper_impl()->cache_mode()); + + // Do a put to load the key-only cache. + EXPECT_TRUE(PutSync(key, value1, base::nullopt)); + EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY, + wrapper_impl()->map_state_); + + // Change cache mode. + wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES); + // Loading new map isn't necessary yet. + EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY, + wrapper_impl()->map_state_); + + // Do another put and check that the map has been upgraded + EXPECT_TRUE(PutSync(key, value2, value1)); + EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_AND_VALUES, + wrapper_impl()->map_state_); +} + TEST_P(LevelDBWrapperImplParamTest, GetAll) { wrapper_impl()->SetCacheModeForTesting(GetParam()); DatabaseError status; std::vector<mojom::KeyValuePtr> data; - base::RunLoop run_loop; bool result = false; - EXPECT_TRUE(wrapper()->GetAll( - GetAllCallback::CreateAndBind(&result, run_loop.QuitClosure()), &status, - &data)); - EXPECT_EQ(DatabaseError::OK, status); + + base::RunLoop loop; + // Testing the 'Sync' mojo version is a big headache involving 3 threads, so + // just test the async version. + wrapper_impl()->GetAll( + GetAllCallback::CreateAndBind(&result, loop.QuitClosure()), + MakeGetAllCallback(&status, &data)); + loop.Run(); + EXPECT_EQ(leveldb::mojom::DatabaseError::OK, status); EXPECT_EQ(2u, data.size()); - EXPECT_FALSE(result); - run_loop.Run(); EXPECT_TRUE(result); } @@ -334,13 +541,32 @@ std::string key2 = test_prefix_; std::string value2 = "data abc"; - EXPECT_TRUE(PutSync(ToBytes(key1), ToBytes(value1), test_value2_bytes_)); - EXPECT_TRUE(PutSync(ToBytes(key2), ToBytes("old value"), base::nullopt)); - EXPECT_TRUE(PutSync(ToBytes(key2), ToBytes(value2), ToBytes("old value"))); + base::RunLoop loop; + bool put_success1 = false; + bool put_success2 = false; + bool put_success3 = false; + { + IncrementalBarrier barrier(loop.QuitClosure()); + + wrapper()->Put(ToBytes(key1), ToBytes(value1), test_value2_bytes_, + test_source_, + MakeSuccessCallback(barrier.Get(), &put_success1)); + wrapper()->Put(ToBytes(key2), ToBytes("old value"), base::nullopt, + test_source_, + MakeSuccessCallback(barrier.Get(), &put_success2)); + wrapper()->Put(ToBytes(key2), ToBytes(value2), ToBytes("old value"), + test_source_, + MakeSuccessCallback(barrier.Get(), &put_success3)); + } + + loop.Run(); + EXPECT_TRUE(put_success1); + EXPECT_TRUE(put_success2); + EXPECT_TRUE(put_success3); EXPECT_FALSE(has_mock_data(test_prefix_ + key2)); - CommitChanges(); + BlockingCommit(); EXPECT_TRUE(has_mock_data(test_prefix_ + key1)); EXPECT_EQ(value1, get_mock_data(test_prefix_ + key1)); EXPECT_TRUE(has_mock_data(test_prefix_ + key2)); @@ -371,7 +597,7 @@ EXPECT_EQ(source2, observations()[1].source); // Same put should not cause another observation. - EXPECT_TRUE(PutSync(ToBytes(key), ToBytes(value2), base::nullopt, source2)); + EXPECT_TRUE(PutSync(ToBytes(key), ToBytes(value2), ToBytes(value2), source2)); ASSERT_EQ(2u, observations().size()); } @@ -392,11 +618,11 @@ EXPECT_EQ(Observation::kDelete, observations()[0].type); EXPECT_EQ(key, observations()[0].key); EXPECT_EQ(value, observations()[0].old_value); - EXPECT_EQ(kTestSource, observations()[0].source); + EXPECT_EQ(test_source_, observations()[0].source); EXPECT_TRUE(has_mock_data(test_prefix_ + key)); - CommitChanges(); + BlockingCommit(); EXPECT_FALSE(has_mock_data(test_prefix_ + key)); } @@ -411,12 +637,12 @@ EXPECT_TRUE(DeleteAllSync()); ASSERT_EQ(1u, observations().size()); EXPECT_EQ(Observation::kDeleteAll, observations()[0].type); - EXPECT_EQ(kTestSource, observations()[0].source); + EXPECT_EQ(test_source_, observations()[0].source); EXPECT_TRUE(has_mock_data(test_prefix_ + key)); EXPECT_TRUE(has_mock_data(dummy_key)); - CommitChanges(); + BlockingCommit(); EXPECT_FALSE(has_mock_data(test_prefix_ + key)); EXPECT_TRUE(has_mock_data(dummy_key)); @@ -441,11 +667,11 @@ EXPECT_TRUE(DeleteAllSync()); ASSERT_EQ(2u, observations().size()); EXPECT_EQ(Observation::kDeleteAll, observations()[1].type); - EXPECT_EQ(kTestSource, observations()[1].source); + EXPECT_EQ(test_source_, observations()[1].source); EXPECT_TRUE(has_mock_data(dummy_key)); - CommitChanges(); + BlockingCommit(); EXPECT_FALSE(has_mock_data(test_prefix_ + key)); EXPECT_TRUE(has_mock_data(dummy_key)); } @@ -463,11 +689,11 @@ EXPECT_TRUE(DeleteAllSync()); ASSERT_EQ(2u, observations().size()); EXPECT_EQ(Observation::kDeleteAll, observations()[1].type); - EXPECT_EQ(kTestSource, observations()[1].source); + EXPECT_EQ(test_source_, observations()[1].source); EXPECT_TRUE(has_mock_data(dummy_key)); - CommitChanges(); + BlockingCommit(); EXPECT_FALSE(has_mock_data(test_prefix_ + key)); EXPECT_TRUE(has_mock_data(dummy_key)); } @@ -605,15 +831,19 @@ changes.push_back(std::make_pair(test_prefix_bytes_, ToBytes("bla"))); delegate()->set_mock_changes(std::move(changes)); + leveldb::mojom::DatabaseError status; std::vector<mojom::KeyValuePtr> data; - DatabaseError status; - bool success = false; - base::RunLoop run_loop; - EXPECT_TRUE(wrapper()->GetAll( - GetAllCallback::CreateAndBind(&success, run_loop.QuitClosure()), &status, - &data)); - run_loop.Run(); - EXPECT_EQ(DatabaseError::OK, status); + bool result = false; + + base::RunLoop loop; + // Testing the 'Sync' mojo version is a big headache involving 3 threads, so + // just test the async version. + wrapper_impl()->GetAll( + GetAllCallback::CreateAndBind(&result, loop.QuitClosure()), + MakeGetAllCallback(&status, &data)); + loop.Run(); + + EXPECT_EQ(leveldb::mojom::DatabaseError::OK, status); ASSERT_EQ(2u, data.size()); EXPECT_EQ(test_prefix_, ToString(data[0]->key)); EXPECT_EQ("bla", ToString(data[0]->value)); @@ -629,20 +859,16 @@ std::vector<uint8_t> key = test_key2_bytes_; std::vector<uint8_t> value = ToBytes("foo"); MockDelegate delegate; - LevelDBWrapperImpl::Options options = { - CacheMode::KEYS_ONLY_WHEN_POSSIBLE, kTestSizeLimit, - base::TimeDelta::FromSeconds(5), - 10 * 1024 * 1024 /* max_bytes_per_hour */, 60 /* max_commits_per_hour */}; - LevelDBWrapperImpl level_db_wrapper(nullptr, test_prefix_, &delegate, - options); + LevelDBWrapperImpl level_db_wrapper( + nullptr, test_prefix_, &delegate, + GetDefaultTestingOptions(CacheMode::KEYS_ONLY_WHEN_POSSIBLE)); mojom::LevelDBWrapperPtr level_db_wrapper_ptr; level_db_wrapper.Bind(mojo::MakeRequest(&level_db_wrapper_ptr)); // Setting only keys mode is noop. level_db_wrapper.SetCacheModeForTesting(CacheMode::KEYS_ONLY_WHEN_POSSIBLE); - EXPECT_EQ(LevelDBWrapperImpl::LoadState::UNLOADED, - level_db_wrapper.CurrentLoadState()); - EXPECT_EQ(LevelDBWrapperImpl::LoadState::KEYS_AND_VALUES, - level_db_wrapper.desired_load_state_); + + EXPECT_FALSE(level_db_wrapper.initialized()); + EXPECT_EQ(CacheMode::KEYS_AND_VALUES, level_db_wrapper.cache_mode()); // Put and Get can work synchronously without reload. bool put_callback_called = false; @@ -667,37 +893,60 @@ EXPECT_EQ(expected_value, value); } -TEST_F(LevelDBWrapperImplTest, CommitOnDifferentCacheModes) { +TEST_P(LevelDBWrapperImplParamTest, CommitOnDifferentCacheModes) { + wrapper_impl()->SetCacheModeForTesting(GetParam()); std::vector<uint8_t> key = test_key2_bytes_; std::vector<uint8_t> value = ToBytes("foo"); std::vector<uint8_t> value2 = ToBytes("foobar"); + // The initial map always has values, so a nullopt is fine for the old value. ASSERT_TRUE(PutSync(key, value, base::nullopt)); ASSERT_TRUE(wrapper_impl()->commit_batch_); - auto* changes = &wrapper_impl()->commit_batch_->changed_values; - EXPECT_EQ(1u, changes->size()); - auto it = changes->find(key); - ASSERT_NE(it, changes->end()); - EXPECT_FALSE(it->second); - wrapper_impl()->CommitChanges(); + if (GetParam() == CacheMode::KEYS_AND_VALUES) { + EXPECT_TRUE(wrapper_impl()->commit_batch_->changed_values.empty()); + auto* changes = &wrapper_impl()->commit_batch_->changed_keys; + ASSERT_EQ(1u, changes->size()); + EXPECT_EQ(key, *changes->begin()); + } else { + EXPECT_TRUE(wrapper_impl()->commit_batch_->changed_keys.empty()); + auto* changes = &wrapper_impl()->commit_batch_->changed_values; + ASSERT_EQ(1u, changes->size()); + auto it = changes->begin(); + EXPECT_EQ(key, it->first); + EXPECT_EQ(value, it->second); + } + + BlockingCommit(); + EXPECT_EQ("foo", get_mock_data(test_prefix_ + test_key2_)); - ASSERT_TRUE(wrapper_impl()->keys_only_map_); - EXPECT_EQ(2u, wrapper_impl()->keys_only_map_->size()); + if (GetParam() == CacheMode::KEYS_AND_VALUES) + EXPECT_EQ(2u, wrapper_impl()->keys_values_map_.size()); + else + EXPECT_EQ(2u, wrapper_impl()->keys_only_map_.size()); ASSERT_TRUE(PutSync(key, value, value)); EXPECT_FALSE(wrapper_impl()->commit_batch_); ASSERT_TRUE(PutSync(key, value2, value)); - EXPECT_TRUE(wrapper_impl()->keys_only_map_); ASSERT_TRUE(wrapper_impl()->commit_batch_); - changes = &wrapper_impl()->commit_batch_->changed_values; - EXPECT_EQ(1u, changes->size()); - it = changes->find(key); - ASSERT_NE(it, changes->end()); - EXPECT_EQ(value2, it->second.value()); + + if (GetParam() == CacheMode::KEYS_AND_VALUES) { + auto* changes = &wrapper_impl()->commit_batch_->changed_keys; + EXPECT_EQ(1u, changes->size()); + auto it = changes->find(key); + ASSERT_NE(it, changes->end()); + } else { + auto* changes = &wrapper_impl()->commit_batch_->changed_values; + EXPECT_EQ(1u, changes->size()); + auto it = changes->find(key); + ASSERT_NE(it, changes->end()); + EXPECT_EQ(value2, it->second); + } clear_mock_data(); - wrapper_impl()->CommitChanges(); + EXPECT_TRUE(wrapper_impl()->has_changes_to_commit()); + BlockingCommit(); EXPECT_EQ("foobar", get_mock_data(test_prefix_ + test_key2_)); + EXPECT_FALSE(wrapper_impl()->has_changes_to_commit()); } TEST_F(LevelDBWrapperImplTest, GetAllWhenCacheOnlyKeys) { @@ -707,31 +956,57 @@ // Go to load state only keys. ASSERT_TRUE(PutSync(key, value, base::nullopt)); - CommitChanges(); - EXPECT_TRUE(wrapper_impl()->keys_only_map_); + BlockingCommit(); ASSERT_TRUE(PutSync(key, value2, value)); - EXPECT_TRUE(wrapper_impl()->commit_batch_); + EXPECT_TRUE(wrapper_impl()->has_changes_to_commit()); - auto get_all_callback = [](const std::vector<uint8_t>& expected_value, - DatabaseError status, - std::vector<mojom::KeyValuePtr> data) { - EXPECT_EQ(1u, data.size()); - EXPECT_EQ(expected_value, data[0]->value); - EXPECT_EQ(DatabaseError::OK, status); - }; - clear_mock_data(); - base::RunLoop run_loop; + leveldb::mojom::DatabaseError status; + std::vector<mojom::KeyValuePtr> data; bool result = false; - // This GetAll() should get |value2| from the previous Put(). - wrapper()->GetAll( - GetAllCallback::CreateAndBind(&result, run_loop.QuitClosure()), - base::BindOnce(get_all_callback, value2)); - // This Put should not affect the value returned by GetAll(). - EXPECT_TRUE(PutSync(key, value, value2)); + + base::RunLoop loop; + + bool put_result1 = false; + bool put_result2 = false; + { + IncrementalBarrier barrier(loop.QuitClosure()); + + wrapper_impl()->Put(key, value, value2, test_source_, + MakeSuccessCallback(barrier.Get(), &put_result1)); + + wrapper_impl()->GetAll( + GetAllCallback::CreateAndBind(&result, barrier.Get()), + MakeGetAllCallback(&status, &data)); + wrapper_impl()->Put(key, value2, value, test_source_, + MakeSuccessCallback(barrier.Get(), &put_result2)); + } + + // GetAll triggers a commit when it's switching map types. + EXPECT_TRUE(put_result1); + EXPECT_EQ("foo", get_mock_data(test_prefix_ + test_key2_)); + + EXPECT_FALSE(put_result2); + EXPECT_FALSE(result); + loop.Run(); + EXPECT_TRUE(result); - run_loop.Run(); - // GetAll should trigger a commit first and database gets the value from the - // last Put() before GetAll(). + EXPECT_TRUE(put_result1); + + EXPECT_EQ(2u, data.size()); + EXPECT_TRUE( + data[1]->Equals(mojom::KeyValue(test_key1_bytes_, test_value1_bytes_))) + << ToString(data[1]->value) << " vs expected " << test_value1_; + EXPECT_TRUE(data[0]->Equals(mojom::KeyValue(key, value))) + << ToString(data[0]->value) << " vs expected " << ToString(value); + + EXPECT_EQ(leveldb::mojom::DatabaseError::OK, status); + + // The last "put" isn't committed yet. + EXPECT_EQ("foo", get_mock_data(test_prefix_ + test_key2_)); + + ASSERT_TRUE(wrapper_impl()->has_changes_to_commit()); + BlockingCommit(); + EXPECT_EQ("foobar", get_mock_data(test_prefix_ + test_key2_)); } @@ -742,46 +1017,67 @@ // Go to load state only keys. ASSERT_TRUE(PutSync(key, value, base::nullopt)); - CommitChanges(); - EXPECT_TRUE(wrapper_impl()->keys_only_map_); + BlockingCommit(); + EXPECT_TRUE(wrapper_impl()->map_state_ == + LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY); ASSERT_TRUE(PutSync(key, value2, value)); - EXPECT_TRUE(wrapper_impl()->commit_batch_); + EXPECT_TRUE(wrapper_impl()->has_changes_to_commit()); wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES); - EXPECT_EQ(LevelDBWrapperImpl::LoadState::KEYS_AND_VALUES, - wrapper_impl()->desired_load_state_); - // Cache isn't cleared when commit batch exists. - EXPECT_TRUE(wrapper_impl()->keys_only_map_); - // Add a put task to on load tasks queue, which should affect the GetAll(). - wrapper()->Put(key, value, value2, "source", - base::BindOnce([](bool success) { EXPECT_TRUE(success); })); - // Commit batch still has old value. New Put() task is queued. - ASSERT_TRUE(wrapper_impl()->commit_batch_); - EXPECT_EQ(value2, - wrapper_impl()->commit_batch_->changed_values.find(key)->second); - auto get_all_callback = [](const std::vector<uint8_t>& expected_value, - DatabaseError status, - std::vector<mojom::KeyValuePtr> data) { - EXPECT_EQ(1u, data.size()); - EXPECT_EQ(expected_value, data[0]->value); - EXPECT_EQ(DatabaseError::OK, status); - }; - clear_mock_data(); - base::RunLoop run_loop; - bool result = false; - wrapper()->GetAll( - GetAllCallback::CreateAndBind(&result, run_loop.QuitClosure()), - base::BindOnce(get_all_callback, value)); - // This Delete() should not affect the value returned by GetAll(). - wrapper()->Delete(key, value, "source", - base::BindOnce([](bool success) { EXPECT_TRUE(success); })); - run_loop.Run(); - EXPECT_TRUE(result); - // GetAll should trigger a commit first and database gets the value from the - // commit batch before GetAll(). The async Put() call is not part of that - // commit. + // Cache isn't cleared when commit batch exists. + EXPECT_TRUE(wrapper_impl()->map_state_ == + LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY); + + base::RunLoop loop; + + bool put_success = false; + leveldb::mojom::DatabaseError status; + std::vector<mojom::KeyValuePtr> data; + bool get_all_success = false; + bool delete_success = false; + { + IncrementalBarrier barrier(loop.QuitClosure()); + + wrapper_impl()->Put(key, value, value2, test_source_, + MakeSuccessCallback(barrier.Get(), &put_success)); + + // Put task triggers database upgrade, so there are no more changes + // to commit. + EXPECT_FALSE(wrapper_impl()->has_changes_to_commit()); + EXPECT_TRUE(wrapper_impl()->has_pending_load_tasks()); + + wrapper_impl()->GetAll( + GetAllCallback::CreateAndBind(&get_all_success, barrier.Get()), + MakeGetAllCallback(&status, &data)); + + // This Delete() should not affect the value returned by GetAll(). + wrapper_impl()->Delete(key, value, test_source_, + MakeSuccessCallback(barrier.Get(), &delete_success)); + } + loop.Run(); + + EXPECT_EQ(2u, data.size()); + EXPECT_TRUE( + data[1]->Equals(mojom::KeyValue(test_key1_bytes_, test_value1_bytes_))) + << ToString(data[1]->value) << " vs expected " << test_value1_; + EXPECT_TRUE(data[0]->Equals(mojom::KeyValue(key, value))) + << ToString(data[0]->value) << " vs expected " << ToString(value2); + + EXPECT_EQ(leveldb::mojom::DatabaseError::OK, status); + + EXPECT_TRUE(put_success); + EXPECT_TRUE(get_all_success); + EXPECT_TRUE(delete_success); + + // GetAll shouldn't trigger a commit before it runs now because the value + // map should be loading. EXPECT_EQ("foobar", get_mock_data(test_prefix_ + test_key2_)); + + ASSERT_TRUE(wrapper_impl()->has_changes_to_commit()); + BlockingCommit(); + + EXPECT_FALSE(has_mock_data(test_prefix_ + test_key2_)); } TEST_F(LevelDBWrapperImplTest, SetCacheModeConsistent) { @@ -789,58 +1085,55 @@ std::vector<uint8_t> value = ToBytes("foo"); std::vector<uint8_t> value2 = ToBytes("foobar"); - EXPECT_EQ(LevelDBWrapperImpl::LoadState::UNLOADED, - wrapper_impl()->CurrentLoadState()); - EXPECT_EQ(LevelDBWrapperImpl::LoadState::KEYS_ONLY, - wrapper_impl()->desired_load_state_); - EXPECT_TRUE(PutSync(key, value, base::nullopt)); - EXPECT_FALSE(wrapper_impl()->keys_only_map_); - ASSERT_TRUE(wrapper_impl()->keys_values_map_); - EXPECT_EQ(2u, wrapper_impl()->keys_values_map_->size()); - EXPECT_EQ(value, wrapper_impl()->keys_values_map_->find(key)->second); - EXPECT_TRUE(wrapper_impl()->commit_batch_); + EXPECT_FALSE(wrapper_impl()->IsMapLoaded()); + EXPECT_TRUE(wrapper_impl()->cache_mode() == + CacheMode::KEYS_ONLY_WHEN_POSSIBLE); - // Clear the default database and include only the new items. + // Clear the database before the wrapper loads data. clear_mock_data(); - wrapper_impl()->CommitChanges(); + + EXPECT_TRUE(PutSync(key, value, base::nullopt)); + EXPECT_TRUE(wrapper_impl()->has_changes_to_commit()); + BlockingCommit(); + EXPECT_TRUE(PutSync(key, value2, value)); - EXPECT_TRUE(wrapper_impl()->commit_batch_); - EXPECT_TRUE(wrapper_impl()->keys_only_map_); - EXPECT_EQ(2u, wrapper_impl()->keys_only_map_->size()); + EXPECT_TRUE(wrapper_impl()->has_changes_to_commit()); // Setting cache mode does not reload the cache till it is required. wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES); - EXPECT_EQ(LevelDBWrapperImpl::LoadState::KEYS_AND_VALUES, - wrapper_impl()->desired_load_state_); - EXPECT_TRUE(wrapper_impl()->keys_only_map_); - EXPECT_FALSE(wrapper_impl()->keys_values_map_); - EXPECT_EQ(LevelDBWrapperImpl::LoadState::KEYS_AND_VALUES, - wrapper_impl()->desired_load_state_); + EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY, + wrapper_impl()->map_state_); - // Reload deletes keys_only_map and reloads keys_values_map from database (has - // only one entry from previous commit). + // Put operation should change the mode. EXPECT_TRUE(PutSync(key, value, value2)); - EXPECT_TRUE(wrapper_impl()->commit_batch_); - ASSERT_TRUE(wrapper_impl()->keys_values_map_); - EXPECT_EQ(1u, wrapper_impl()->keys_values_map_->size()); - EXPECT_EQ(value, wrapper_impl()->keys_values_map_->find(key)->second); - EXPECT_FALSE(wrapper_impl()->keys_only_map_); - wrapper_impl()->CommitChanges(); + EXPECT_TRUE(wrapper_impl()->has_changes_to_commit()); + EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_AND_VALUES, + wrapper_impl()->map_state_); + std::vector<uint8_t> result; + EXPECT_TRUE(GetSync(key, &result)); + EXPECT_EQ(value, result); + EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_AND_VALUES, + wrapper_impl()->map_state_); - // Changing back the cache mode still works. - wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_ONLY_WHEN_POSSIBLE); - EXPECT_EQ(LevelDBWrapperImpl::LoadState::KEYS_ONLY, - wrapper_impl()->desired_load_state_); + BlockingCommit(); + // Test that the map will unload correctly EXPECT_TRUE(PutSync(key, value2, value)); - ASSERT_TRUE(wrapper_impl()->keys_only_map_); - EXPECT_EQ(1u, wrapper_impl()->keys_only_map_->size()); - EXPECT_EQ(value2.size(), wrapper_impl()->keys_only_map_->find(key)->second); - wrapper_impl()->CommitChanges(); - EXPECT_EQ(LevelDBWrapperImpl::LoadState::KEYS_ONLY, - wrapper_impl()->desired_load_state_); - ASSERT_TRUE(wrapper_impl()->keys_only_map_); - EXPECT_EQ(1u, wrapper_impl()->keys_only_map_->size()); + wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_ONLY_WHEN_POSSIBLE); + EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY, + wrapper_impl()->map_state_); + BlockingCommit(); + EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY, + wrapper_impl()->map_state_); + + // Test the map will unload right away when there are no changes. + wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES); + EXPECT_TRUE(GetSync(key, &result)); + EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_AND_VALUES, + wrapper_impl()->map_state_); + wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_ONLY_WHEN_POSSIBLE); + EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY, + wrapper_impl()->map_state_); } TEST_F(LevelDBWrapperImplTest, SendOldValueObservations) { @@ -859,4 +1152,262 @@ EXPECT_TRUE(observations()[1].should_send_old_value); } +TEST_P(LevelDBWrapperImplParamTest, PrefixForking) { + std::string value3 = "value3"; + std::string value4 = "value4"; + std::string value5 = "value5"; + + // In order to test the interaction between forking and mojo calls where + // forking can happen in between a request and reply to the wrapper mojo + // service, all calls are done on the 'impl' object itself. + + // Operations in the same run cycle: + // Fork 1 created from original + // Put on fork 1 + // Fork 2 create from fork 1 + // Put on fork 1 + // Put on original + // Fork 3 created from original + std::unique_ptr<LevelDBWrapperImpl> fork1; + MockDelegate fork1_delegate; + std::unique_ptr<LevelDBWrapperImpl> fork2; + MockDelegate fork2_delegate; + std::unique_ptr<LevelDBWrapperImpl> fork3; + MockDelegate fork3_delegate; + + auto options = GetDefaultTestingOptions(GetParam()); + bool put_success1 = false; + bool put_success2 = false; + bool put_success3 = false; + base::RunLoop loop; + { + IncrementalBarrier barrier(loop.QuitClosure()); + + // Create fork 1. + fork1 = wrapper_impl()->ForkToNewPrefix(test_copy_prefix1_, &fork1_delegate, + options); + + // Do a put on fork 1 and create fork 2. + // Note - these are 'skipping' the mojo layer, which is why the fork isn't + // scheduled. + fork1->Put(test_key2_bytes_, ToBytes(value4), test_value2_bytes_, + test_source_, MakeSuccessCallback(barrier.Get(), &put_success1)); + fork2 = + fork1->ForkToNewPrefix(test_copy_prefix2_, &fork2_delegate, options); + fork1->Put(test_key2_bytes_, ToBytes(value5), ToBytes(value4), test_source_, + MakeSuccessCallback(barrier.Get(), &put_success2)); + + // Do a put on original and create fork 3, which is key-only. + wrapper_impl()->Put(test_key1_bytes_, ToBytes(value3), test_value1_bytes_, + test_source_, + MakeSuccessCallback(barrier.Get(), &put_success3)); + fork3 = wrapper_impl()->ForkToNewPrefix( + test_copy_prefix3_, &fork3_delegate, + GetDefaultTestingOptions(CacheMode::KEYS_ONLY_WHEN_POSSIBLE)); + } + loop.Run(); + EXPECT_TRUE(put_success1); + EXPECT_TRUE(put_success2); + EXPECT_TRUE(fork2.get()); + EXPECT_TRUE(fork3.get()); + + EXPECT_EQ(value3, GetSyncStrUsingGetAll(wrapper_impl(), test_key1_)); + EXPECT_EQ(test_value1_, GetSyncStrUsingGetAll(fork1.get(), test_key1_)); + EXPECT_EQ(test_value1_, GetSyncStrUsingGetAll(fork2.get(), test_key1_)); + EXPECT_EQ(value3, GetSyncStrUsingGetAll(fork3.get(), test_key1_)); + + EXPECT_EQ(test_value2_, GetSyncStrUsingGetAll(wrapper_impl(), test_key2_)); + EXPECT_EQ(value5, GetSyncStrUsingGetAll(fork1.get(), test_key2_)); + EXPECT_EQ(value4, GetSyncStrUsingGetAll(fork2.get(), test_key2_)); + EXPECT_EQ(test_value2_, GetSyncStrUsingGetAll(fork3.get(), test_key2_)); + + BlockingCommit(delegate(), wrapper_impl()); + BlockingCommit(&fork1_delegate, fork1.get()); + + // test_key1_ values. + EXPECT_EQ(value3, get_mock_data(test_prefix_ + test_key1_)); + EXPECT_EQ(test_value1_, get_mock_data(test_copy_prefix1_ + test_key1_)); + EXPECT_EQ(test_value1_, get_mock_data(test_copy_prefix2_ + test_key1_)); + EXPECT_EQ(value3, get_mock_data(test_copy_prefix3_ + test_key1_)); + + // test_key2_ values. + EXPECT_EQ(test_value2_, get_mock_data(test_prefix_ + test_key2_)); + EXPECT_EQ(value5, get_mock_data(test_copy_prefix1_ + test_key2_)); + EXPECT_EQ(value4, get_mock_data(test_copy_prefix2_ + test_key2_)); + EXPECT_EQ(test_value2_, get_mock_data(test_copy_prefix3_ + test_key2_)); +} + +TEST_P(LevelDBWrapperImplParamTest, PrefixForkAfterLoad) { + const std::string kValue = "foo"; + const std::vector<uint8_t> kValueVec = ToBytes(kValue); + + // Do a sync put so the map loads. + EXPECT_TRUE(PutSync(test_key1_bytes_, kValueVec, base::nullopt)); + + // Execute the fork. + MockDelegate fork1_delegate; + std::unique_ptr<LevelDBWrapperImpl> fork1 = + wrapper_impl()->ForkToNewPrefix(test_copy_prefix1_, &fork1_delegate, + GetDefaultTestingOptions(GetParam())); + + // Check our forked state. + EXPECT_EQ(kValue, GetSyncStrUsingGetAll(fork1.get(), test_key1_)); + + BlockingCommit(delegate(), wrapper_impl()); + + EXPECT_EQ(kValue, get_mock_data(test_copy_prefix1_ + test_key1_)); +} + +namespace { +std::string GetNewPrefix(int* i) { + std::string prefix = "prefix-" + base::Int64ToString(*i) + "-"; + (*i)++; + return prefix; +} + +struct FuzzState { + base::Optional<std::vector<uint8_t>> val1; + base::Optional<std::vector<uint8_t>> val2; +}; +} // namespace + +TEST_F(LevelDBWrapperImplTest, PrefixForkingPsuedoFuzzer) { + const std::string kKey1 = "key1"; + const std::vector<uint8_t> kKey1Vec = ToBytes(kKey1); + const std::string kKey2 = "key2"; + const std::vector<uint8_t> kKey2Vec = ToBytes(kKey2); + const int kTotalWrappers = 1000; + + // This tests tries to throw all possible enumartions of operations and + // forking at wrappers. The purpose is to hit all edge cases possible to + // expose any loading bugs. + + std::vector<FuzzState> states(kTotalWrappers); + std::vector<std::unique_ptr<LevelDBWrapperImpl>> wrappers(kTotalWrappers); + std::vector<MockDelegate> delegates(kTotalWrappers); + std::list<bool> successes; + int curr_prefix = 0; + + base::RunLoop loop; + { + IncrementalBarrier barrier(loop.QuitClosure()); + for (int64_t i = 0; i < kTotalWrappers; i++) { + FuzzState& state = states[i]; + if (!wrappers[i]) { + wrappers[i] = wrapper_impl()->ForkToNewPrefix( + GetNewPrefix(&curr_prefix), &delegates[i], + GetDefaultTestingOptions(CacheMode::KEYS_ONLY_WHEN_POSSIBLE)); + } + int64_t forks = i; + if ((i % 5 == 0 || i % 6 == 0) && forks + 1 < kTotalWrappers) { + forks++; + states[forks] = state; + wrappers[forks] = wrappers[i]->ForkToNewPrefix( + GetNewPrefix(&curr_prefix), &delegates[forks], + GetDefaultTestingOptions(CacheMode::KEYS_AND_VALUES)); + } + if (i % 13 == 0) { + FuzzState old_state = state; + state.val1 = base::nullopt; + successes.push_back(false); + wrappers[i]->Delete( + kKey1Vec, old_state.val1, test_source_, + MakeSuccessCallback(barrier.Get(), &successes.back())); + } + if (i % 4 == 0) { + FuzzState old_state = state; + state.val2 = base::make_optional<std::vector<uint8_t>>( + {static_cast<uint8_t>(i)}); + successes.push_back(false); + wrappers[i]->Put(kKey2Vec, state.val2.value(), old_state.val2, + test_source_, + MakeSuccessCallback(barrier.Get(), &successes.back())); + } + if (i % 3 == 0) { + FuzzState old_state = state; + state.val1 = base::make_optional<std::vector<uint8_t>>( + {static_cast<uint8_t>(i + 5)}); + successes.push_back(false); + wrappers[i]->Put(kKey1Vec, state.val1.value(), old_state.val1, + test_source_, + MakeSuccessCallback(barrier.Get(), &successes.back())); + } + if (i % 11 == 0) { + state.val1 = base::nullopt; + state.val2 = base::nullopt; + successes.push_back(false); + wrappers[i]->DeleteAll( + test_source_, + MakeSuccessCallback(barrier.Get(), &successes.back())); + } + if (i % 2 == 0 && forks + 1 < kTotalWrappers) { + CacheMode mode = i % 3 == 0 ? CacheMode::KEYS_AND_VALUES + : CacheMode::KEYS_ONLY_WHEN_POSSIBLE; + forks++; + states[forks] = state; + wrappers[forks] = wrappers[i]->ForkToNewPrefix( + GetNewPrefix(&curr_prefix), &delegates[forks], + GetDefaultTestingOptions(mode)); + } + if (i % 3 == 0) { + FuzzState old_state = state; + state.val1 = base::make_optional<std::vector<uint8_t>>( + {static_cast<uint8_t>(i + 9)}); + successes.push_back(false); + wrappers[i]->Put(kKey1Vec, state.val1.value(), old_state.val1, + test_source_, + MakeSuccessCallback(barrier.Get(), &successes.back())); + } + } + } + loop.Run(); + + // This section checks that we get the correct values when we query the + // wrappers (which may or may not be maintaining their own cache). + for (size_t i = 0; i < kTotalWrappers; i++) { + FuzzState& state = states[i]; + std::vector<uint8_t> result; + + // Note: this will cause all keys-only wrappers to commit. + std::string result1 = GetSyncStrUsingGetAll(wrappers[i].get(), kKey1); + std::string result2 = GetSyncStrUsingGetAll(wrappers[i].get(), kKey2); + EXPECT_EQ(!!state.val1, !result1.empty()) << i; + if (state.val1) + EXPECT_EQ(state.val1.value(), ToBytes(result1)); + EXPECT_EQ(!!state.val2, !result2.empty()) << i; + if (state.val2) + EXPECT_EQ(state.val2.value(), ToBytes(result2)) << i; + } + + // This section verifies that all wrappers have committed their changes to + // the database. + ASSERT_EQ(wrappers.size(), delegates.size()); + size_t half = kTotalWrappers / 2; + for (size_t i = 0; i < half; i++) { + BlockingCommit(&delegates[i], wrappers[i].get()); + } + + for (size_t i = kTotalWrappers - 1; i >= half; i--) { + BlockingCommit(&delegates[i], wrappers[i].get()); + } + + // This section checks the data in the database itself to verify all wrappers + // committed changes correctly. + for (size_t i = 0; i < kTotalWrappers; ++i) { + FuzzState& state = states[i]; + + std::vector<uint8_t> prefix = wrappers[i]->prefix(); + std::string key1 = ToString(prefix) + kKey1; + std::string key2 = ToString(prefix) + kKey2; + EXPECT_EQ(!!state.val1, has_mock_data(key1)); + if (state.val1) + EXPECT_EQ(ToString(state.val1.value()), get_mock_data(key1)); + EXPECT_EQ(!!state.val2, has_mock_data(key2)); + if (state.val2) + EXPECT_EQ(ToString(state.val2.value()), get_mock_data(key2)); + + EXPECT_FALSE(wrappers[i]->has_pending_load_tasks()) << i; + } +} + } // namespace content
diff --git a/content/browser/loader/navigation_url_loader_impl_core.cc b/content/browser/loader/navigation_url_loader_impl_core.cc index 0166832..00a75c64 100644 --- a/content/browser/loader/navigation_url_loader_impl_core.cc +++ b/content/browser/loader/navigation_url_loader_impl_core.cc
@@ -28,7 +28,7 @@ NavigationURLLoaderImplCore::NavigationURLLoaderImplCore( const base::WeakPtr<NavigationURLLoaderImpl>& loader) - : loader_(loader), resource_handler_(nullptr) { + : loader_(loader), resource_handler_(nullptr), weak_factory_(this) { // This object is created on the UI thread but otherwise is accessed and // deleted on the IO thread. DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -46,10 +46,8 @@ std::unique_ptr<NavigationUIData> navigation_ui_data) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestStarted, loader_, - base::TimeTicks::Now())); + base::WeakPtr<NavigationURLLoaderImplCore> weak_this = + weak_factory_.GetWeakPtr(); // The ResourceDispatcherHostImpl can be null in unit tests. if (ResourceDispatcherHostImpl::Get()) { @@ -59,6 +57,15 @@ std::move(navigation_ui_data), this, service_worker_handle_core, appcache_handle_core); } + + // Careful, |this| could be destroyed at this point. Don't notify start if + // that's the case (i.e. the request failed). + if (!weak_this) + return; + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestStarted, loader_, + base::TimeTicks::Now())); } void NavigationURLLoaderImplCore::FollowRedirect() {
diff --git a/content/browser/loader/navigation_url_loader_impl_core.h b/content/browser/loader/navigation_url_loader_impl_core.h index 2d5d5f88..cf9c64f 100644 --- a/content/browser/loader/navigation_url_loader_impl_core.h +++ b/content/browser/loader/navigation_url_loader_impl_core.h
@@ -95,6 +95,8 @@ base::WeakPtr<NavigationURLLoaderImpl> loader_; NavigationResourceHandler* resource_handler_; + base::WeakPtrFactory<NavigationURLLoaderImplCore> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(NavigationURLLoaderImplCore); };
diff --git a/content/browser/loader/navigation_url_loader_unittest.cc b/content/browser/loader/navigation_url_loader_unittest.cc index c5098c8..471b042 100644 --- a/content/browser/loader/navigation_url_loader_unittest.cc +++ b/content/browser/loader/navigation_url_loader_unittest.cc
@@ -394,7 +394,9 @@ // Wait for the request to fail as expected. delegate.WaitForRequestFailed(); EXPECT_EQ(net::ERR_ABORTED, delegate.net_error()); - EXPECT_EQ(1, delegate.on_request_handled_counter()); + + // Failing before start means OnRequestStarted is never called. + EXPECT_EQ(0, delegate.on_request_handled_counter()); host_.SetDelegate(nullptr); }
diff --git a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc index 3f91cb4..35987b59 100644 --- a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc +++ b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
@@ -22,6 +22,7 @@ #include "content/browser/browser_thread_impl.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_view_host_factory.h" +#include "content/browser/renderer_host/render_widget_host_factory.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_frame_subscriber.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -32,6 +33,7 @@ #include "content/public/test/test_utils.h" #include "content/test/test_render_frame_host_factory.h" #include "content/test/test_render_view_host.h" +#include "content/test/test_render_widget_host_factory.h" #include "content/test/test_web_contents.h" #include "media/base/video_frame.h" #include "media/base/video_util.h" @@ -187,11 +189,10 @@ int32_t main_frame_routing_id, bool swapped_out) : TestRenderViewHost(instance, - std::make_unique<RenderWidgetHostImpl>( + TestRenderWidgetHost::Create( widget_delegate, instance->GetProcess(), routing_id, - nullptr, false /* This means: "Is not hidden." */), delegate, main_frame_routing_id, @@ -469,11 +470,15 @@ // CopyFromSurfaceToVideoFrame functionality into TestRenderWidgetHostView // itself. - render_process_host_factory_.reset(new MockRenderProcessHostFactory()); + render_process_host_factory_ = + std::make_unique<MockRenderProcessHostFactory>(); // Create our (self-registering) RVH factory, so that when we create a // WebContents, it in turn creates CaptureTestRenderViewHosts. - render_view_host_factory_.reset(new CaptureTestRenderViewHostFactory()); - render_frame_host_factory_.reset(new TestRenderFrameHostFactory()); + render_view_host_factory_ = + std::make_unique<CaptureTestRenderViewHostFactory>(); + render_frame_host_factory_ = std::make_unique<TestRenderFrameHostFactory>(); + render_widget_host_factory_ = + std::make_unique<TestRenderWidgetHostFactory>(); browser_context_.reset(new TestBrowserContext()); @@ -632,6 +637,9 @@ // Self-registering RenderFrameHostFactory. std::unique_ptr<TestRenderFrameHostFactory> render_frame_host_factory_; + // Self-registering RenderWidgetHostFactory. + std::unique_ptr<TestRenderWidgetHostFactory> render_widget_host_factory_; + // A mocked-out browser and tab. std::unique_ptr<TestBrowserContext> browser_context_; std::unique_ptr<WebContents> web_contents_;
diff --git a/content/browser/media/media_canplaytype_browsertest.cc b/content/browser/media/media_canplaytype_browsertest.cc index 6b197c71..73c1744 100644 --- a/content/browser/media/media_canplaytype_browsertest.cc +++ b/content/browser/media/media_canplaytype_browsertest.cc
@@ -7,6 +7,7 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/strings/string_util.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "content/browser/media/media_browsertest.h" #include "content/public/test/browser_test_utils.h" @@ -14,6 +15,7 @@ #include "content/shell/browser/shell.h" #include "media/base/media_switches.h" #include "media/media_features.h" +#include "third_party/libaom/av1_features.h" #include "ui/display/display_switches.h" #if defined(OS_ANDROID) @@ -70,9 +72,15 @@ class MediaCanPlayTypeTest : public MediaBrowserTest { public: - MediaCanPlayTypeTest() : url_("about:blank") { } + MediaCanPlayTypeTest() : url_("about:blank") {} - void SetUpOnMainThread() override { NavigateToURL(shell(), url_); } + void SetUpOnMainThread() override { +#if BUILDFLAG(ENABLE_AV1_DECODER) + scoped_feature_list_.InitAndEnableFeature(media::kAv1Decoder); +#endif + + NavigateToURL(shell(), url_); + } std::string CanPlay(const std::string& type) { std::string command("document.createElement('video').canPlayType("); @@ -573,6 +581,7 @@ private: GURL url_; + base::test::ScopedFeatureList scoped_feature_list_; DISALLOW_COPY_AND_ASSIGN(MediaCanPlayTypeTest); }; @@ -588,6 +597,19 @@ TestWAVUnacceptableCombinations("audio/x-wav"); } +IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_av1) { +#if BUILDFLAG(ENABLE_AV1_DECODER) + // TODO(dalecurtis): This is not the correct final string. Fix before enabling + // by default. This test needs to be merged into the existing mp4 and webm + // before release as well. http://crbug.com/784607 + EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"av1\"'")); + EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"av1\"'")); +#else + EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"av1\"'")); + EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"av1\"'")); +#endif +} + IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_webm) { EXPECT_EQ(kMaybe, CanPlay("'video/webm'"));
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index b077196..a6ad7bb 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -502,9 +502,14 @@ root_window->AttachCompositor(this); CreateLayerTreeHost(); resource_manager_.Init(host_->GetUIResourceManager()); + + // Listen to display density change events and update painted device scale + // factor accordingly. + display::Screen::GetScreen()->AddObserver(this); } CompositorImpl::~CompositorImpl() { + display::Screen::GetScreen()->RemoveObserver(this); root_window_->DetachCompositor(); root_window_->SetLayer(nullptr); // Clean-up any surface references. @@ -602,7 +607,6 @@ host_->SetFrameSinkId(frame_sink_id_); host_->SetViewportSize(size_); host_->SetDeviceScaleFactor(1); - // TODO(fsamuel): We should listen to display density change events. host_->SetPaintedDeviceScaleFactor(root_window_->GetDipScale()); if (needs_animate_) @@ -648,6 +652,10 @@ root_window_->GetLayer()->SetBounds(size); } +void CompositorImpl::SetDeferCommits(bool defer_commits) { + host_->SetDeferCommits(defer_commits); +} + void CompositorImpl::SetRequiresAlphaChannel(bool flag) { requires_alpha_channel_ = flag; } @@ -820,6 +828,10 @@ auto* gpu_memory_buffer_manager = BrowserMainLoop::GetInstance() ->gpu_channel_establish_factory() ->GetGpuMemoryBufferManager(); + + // Don't re-register BeginFrameSource on context loss. + const bool should_register_begin_frame_source = !display_; + display_ = std::make_unique<viz::Display>( viz::ServerSharedBitmapManager::current(), gpu_memory_buffer_manager, renderer_settings, frame_sink_id_, std::move(display_output_surface), @@ -841,8 +853,10 @@ display_->SetVisible(true); display_->Resize(size_); display_->SetColorSpace(display_color_space_, display_color_space_); - GetFrameSinkManager()->RegisterBeginFrameSource( - root_window_->GetBeginFrameSource(), frame_sink_id_); + if (should_register_begin_frame_source) { + GetFrameSinkManager()->RegisterBeginFrameSource( + root_window_->GetBeginFrameSource(), frame_sink_id_); + } host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink)); } @@ -945,6 +959,17 @@ // surface should be set here. } +void CompositorImpl::OnDisplayMetricsChanged(const display::Display& display, + uint32_t changed_metrics) { + if (changed_metrics & display::DisplayObserver::DisplayMetric:: + DISPLAY_METRIC_DEVICE_SCALE_FACTOR && + display.id() == display::Screen::GetScreen() + ->GetDisplayNearestWindow(root_window_) + .id()) { + host_->SetPaintedDeviceScaleFactor(root_window_->GetDipScale()); + } +} + bool CompositorImpl::HavePendingReadbacks() { return !readback_layer_tree_->children().empty(); }
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h index bf6090c..dc931d14 100644 --- a/content/browser/renderer_host/compositor_impl_android.h +++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -28,6 +28,7 @@ #include "ui/android/resources/resource_manager_impl.h" #include "ui/android/resources/ui_resource_provider.h" #include "ui/android/window_android_compositor.h" +#include "ui/display/display_observer.h" struct ANativeWindow; @@ -58,7 +59,8 @@ public cc::LayerTreeHostSingleThreadClient, public ui::UIResourceProvider, public ui::WindowAndroidCompositor, - public viz::HostFrameSinkClient { + public viz::HostFrameSinkClient, + public display::DisplayObserver { public: CompositorImpl(CompositorClient* client, gfx::NativeWindow root_window); ~CompositorImpl() override; @@ -80,6 +82,7 @@ void SetSurface(jobject surface) override; void SetBackgroundColor(int color) override; void SetWindowBounds(const gfx::Size& size) override; + void SetDeferCommits(bool defer_commits) override; void SetRequiresAlphaChannel(bool flag) override; void SetNeedsComposite() override; ui::UIResourceProvider& GetUIResourceProvider() override; @@ -126,6 +129,10 @@ void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override; void OnFrameTokenChanged(uint32_t frame_token) override {} + // display::DisplayObserver implementation. + void OnDisplayMetricsChanged(const display::Display& display, + uint32_t changed_metrics) override; + void SetVisible(bool visible); void CreateLayerTreeHost();
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index 14f8f04..58cf5bd 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -461,11 +461,6 @@ gfx::Size frame_size_in_dip = gfx::ConvertSizeToDIP(frame_device_scale_factor, frame_size); - gfx::Rect damage_rect = root_pass->damage_rect; - damage_rect.Intersect(gfx::Rect(frame_size)); - gfx::Rect damage_rect_in_dip = - gfx::ConvertRectToDIP(frame_device_scale_factor, damage_rect); - if (ShouldSkipFrame(frame_size_in_dip)) { std::vector<viz::ReturnedResource> resources = viz::TransferableResource::ReturnResources(frame.resource_list); @@ -490,12 +485,10 @@ if (skipped_frames_) { skipped_frames_ = false; - damage_rect = gfx::Rect(frame_size); - damage_rect_in_dip = gfx::Rect(frame_size_in_dip); // Give the same damage rect to the compositor. viz::RenderPass* root_pass = frame.render_pass_list.back().get(); - root_pass->damage_rect = damage_rect; + root_pass->damage_rect = gfx::Rect(frame_size); } background_color_ = frame.metadata.root_background_color; @@ -518,13 +511,7 @@ DCHECK(enable_surface_synchronization_ || has_primary_surface_); } - // TODO(fsamuel): This is used to detect video. We need to develop an - // alternative mechanism to detect video in a frame for Viz. if (!enable_surface_synchronization_) { - if (!damage_rect_in_dip.IsEmpty()) { - client_->DelegatedFrameHostGetLayer()->OnDelegatedFrameDamage( - damage_rect_in_dip); - } if (has_primary_surface_) frame_evictor_->SwappedFrame(client_->DelegatedFrameHostIsVisible()); // Note: the frame may have been evicted immediately.
diff --git a/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc b/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc index 36a3366c..f808ebb 100644 --- a/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc +++ b/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc
@@ -37,11 +37,23 @@ DoGetDeviceInfos(callback); } + void AddVirtualDevice(const media::VideoCaptureDeviceInfo& device_info, + video_capture::mojom::ProducerPtr producer, + video_capture::mojom::VirtualDeviceRequest + virtual_device_request) override { + DoAddVirtualDevice(device_info, producer.get(), &virtual_device_request); + } + MOCK_METHOD1(DoGetDeviceInfos, void(GetDeviceInfosCallback& callback)); MOCK_METHOD3(DoCreateDevice, void(const std::string& device_id, video_capture::mojom::DeviceRequest* device_request, CreateDeviceCallback& callback)); + MOCK_METHOD3( + DoAddVirtualDevice, + void(const media::VideoCaptureDeviceInfo& device_info, + video_capture::mojom::ProducerProxy* producer, + video_capture::mojom::VirtualDeviceRequest* virtual_device_request)); }; class MockVideoCaptureDeviceLauncherCallbacks
diff --git a/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc b/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc index ed85dee..1197fcb2 100644 --- a/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc +++ b/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc
@@ -58,12 +58,23 @@ CreateDeviceCallback callback) override { DoCreateDevice(device_id, &device_request, callback); } + void AddVirtualDevice(const media::VideoCaptureDeviceInfo& device_info, + video_capture::mojom::ProducerPtr producer, + video_capture::mojom::VirtualDeviceRequest + virtual_device_request) override { + DoAddVirtualDevice(device_info, producer.get(), &virtual_device_request); + } MOCK_METHOD1(DoGetDeviceInfos, void(GetDeviceInfosCallback& callback)); MOCK_METHOD3(DoCreateDevice, void(const std::string& device_id, video_capture::mojom::DeviceRequest* device_request, CreateDeviceCallback& callback)); + MOCK_METHOD3( + DoAddVirtualDevice, + void(const media::VideoCaptureDeviceInfo& device_info, + video_capture::mojom::ProducerProxy* producer, + video_capture::mojom::VirtualDeviceRequest* virtual_device_request)); }; class MockVideoCaptureDeviceLauncherCallbacks
diff --git a/content/browser/renderer_host/render_widget_host_factory.cc b/content/browser/renderer_host/render_widget_host_factory.cc new file mode 100644 index 0000000..2a0c4f1 --- /dev/null +++ b/content/browser/renderer_host/render_widget_host_factory.cc
@@ -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. + +#include "content/browser/renderer_host/render_widget_host_factory.h" + +#include "content/browser/renderer_host/render_widget_host_impl.h" + +namespace content { + +// static +RenderWidgetHostFactory* RenderWidgetHostFactory::factory_ = nullptr; + +// static +RenderWidgetHostImpl* RenderWidgetHostFactory::Create( + RenderWidgetHostDelegate* delegate, + RenderProcessHost* process, + int32_t routing_id, + mojom::WidgetPtr widget_interface, + bool hidden) { + if (factory_) { + return factory_->CreateRenderWidgetHost( + delegate, process, routing_id, std::move(widget_interface), hidden); + } + return new RenderWidgetHostImpl(delegate, process, routing_id, + std::move(widget_interface), hidden); +} + +// static +void RenderWidgetHostFactory::RegisterFactory( + RenderWidgetHostFactory* factory) { + DCHECK(!factory_) << "Can't register two factories at once."; + factory_ = factory; +} + +// static +void RenderWidgetHostFactory::UnregisterFactory() { + DCHECK(factory_) << "No factory to unregister."; + factory_ = nullptr; +} + +} // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_factory.h b/content/browser/renderer_host/render_widget_host_factory.h new file mode 100644 index 0000000..c691954 --- /dev/null +++ b/content/browser/renderer_host/render_widget_host_factory.h
@@ -0,0 +1,69 @@ +// 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_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_FACTORY_H_ +#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_FACTORY_H_ + +#include <stdint.h> + +#include "base/macros.h" +#include "content/common/content_export.h" +#include "content/common/widget.mojom.h" + +namespace content { +class RenderProcessHost; +class RenderWidgetHostDelegate; +class RenderWidgetHostImpl; + +// A factory for creating RenderWidgetHostImpls. There is a global factory +// function that can be installed for the purposes of testing to provide a +// specialized RenderWidgetHostImpl class. +class RenderWidgetHostFactory { + public: + // Creates a RenderWidgetHostImpl using the currently registered factory, or + // the default one if no factory is registered. Ownership of the returned + // pointer will be passed to the caller. + static RenderWidgetHostImpl* Create(RenderWidgetHostDelegate* delegate, + RenderProcessHost* process, + int32_t routing_id, + mojom::WidgetPtr widget_interface, + bool hidden); + + // Returns true if there is currently a globally-registered factory. + static bool has_factory() { return !!factory_; } + + protected: + RenderWidgetHostFactory() {} + virtual ~RenderWidgetHostFactory() {} + + // You can derive from this class and specify an implementation for this + // function to create a different kind of RenderWidgetHostImpl for testing. + virtual RenderWidgetHostImpl* CreateRenderWidgetHost( + RenderWidgetHostDelegate* delegate, + RenderProcessHost* process, + int32_t routing_id, + mojom::WidgetPtr widget_interface, + bool hidden) = 0; + + // Registers your factory to be called when new RenderWidgetHostImpls are + // created. We have only one global factory, so there must be no factory + // registered before the call. This class does NOT take ownership of the + // pointer. + CONTENT_EXPORT static void RegisterFactory(RenderWidgetHostFactory* factory); + + // Unregister the previously registered factory. With no factory registered, + // the default RenderWidgetHostImpls will be created. + CONTENT_EXPORT static void UnregisterFactory(); + + private: + // The current globally registered factory. This is NULL when we should + // create the default RenderWidgetHostImpls. + CONTENT_EXPORT static RenderWidgetHostFactory* factory_; + + DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostFactory); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_FACTORY_H_
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 d50fca9..410e176 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
@@ -37,6 +37,7 @@ #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/fake_external_begin_frame_source.h" #include "components/viz/test/fake_surface_observer.h" +#include "content/browser/browser_main_loop.h" #include "content/browser/browser_thread_impl.h" #include "content/browser/compositor/test/no_transport_image_transport_factory.h" #include "content/browser/frame_host/render_widget_host_view_guest.h" @@ -135,6 +136,13 @@ namespace { +constexpr uint64_t kFrameIndexStart = + viz::CompositorFrameSinkSupport::kFrameIndexStart; + +const viz::LocalSurfaceId kArbitraryLocalSurfaceId( + 1, + base::UnguessableToken::Deserialize(2, 3)); + std::string GetMessageNames( const MockWidgetInputHandler::MessageVector& events) { std::vector<std::string> result; @@ -143,9 +151,25 @@ return base::JoinString(result, " "); } -const viz::LocalSurfaceId kArbitraryLocalSurfaceId( - 1, - base::UnguessableToken::Deserialize(2, 3)); +uint64_t FrameIndexForView(RenderWidgetHostViewAura* view) { + return ImageTransportFactory::GetInstance() + ->GetContextFactoryPrivate() + ->GetFrameSinkManager() + ->surface_manager() + ->GetSurfaceForId(view->SurfaceIdForTesting()) + ->GetActiveFrameIndex(); +} + +const gfx::Rect& DamageRectForView(RenderWidgetHostViewAura* view) { + return ImageTransportFactory::GetInstance() + ->GetContextFactoryPrivate() + ->GetFrameSinkManager() + ->surface_manager() + ->GetSurfaceForId(view->SurfaceIdForTesting()) + ->GetActiveFrame() + .render_pass_list.back() + ->damage_rect; +} class TestOverscrollDelegate : public OverscrollControllerDelegate { public: @@ -605,11 +629,6 @@ DISALLOW_COPY_AND_ASSIGN(FullscreenLayoutManager); }; -class MockWindowObserver : public aura::WindowObserver { - public: - MOCK_METHOD2(OnDelegatedFrameDamage, void(aura::Window*, const gfx::Rect&)); -}; - class MockRenderWidgetHostImpl : public RenderWidgetHostImpl { public: ~MockRenderWidgetHostImpl() override {} @@ -2631,39 +2650,6 @@ } } -// Swapping a frame should notify the window. -TEST_F(RenderWidgetHostViewAuraTest, SwapNotifiesWindow) { - gfx::Size view_size(100, 100); - gfx::Rect view_rect(view_size); - - view_->InitAsChild(nullptr); - aura::client::ParentWindowWithContext( - view_->GetNativeView(), - parent_view_->GetNativeView()->GetRootWindow(), - gfx::Rect()); - view_->SetSize(view_size); - view_->Show(); - - MockWindowObserver observer; - view_->window_->AddObserver(&observer); - - // Delegated renderer path - EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect)); - view_->SubmitCompositorFrame(kArbitraryLocalSurfaceId, - MakeDelegatedFrame(1.f, view_size, view_rect), - nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); - - EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, - gfx::Rect(5, 5, 5, 5))); - view_->SubmitCompositorFrame( - kArbitraryLocalSurfaceId, - MakeDelegatedFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); - - view_->window_->RemoveObserver(&observer); -} - // If the view size is larger than the compositor frame then extra layers // should be created to fill the gap. TEST_F(RenderWidgetHostViewAuraTest, DelegatedFrameGutter) { @@ -2838,25 +2824,21 @@ gfx::Rect()); view_->SetSize(view_rect.size()); - MockWindowObserver observer; - view_->window_->AddObserver(&observer); - // A full frame of damage. - EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect)); view_->SubmitCompositorFrame(local_surface_id, MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 1u, FrameIndexForView(view_)); + EXPECT_EQ(view_rect, DamageRectForView(view_)); view_->RunOnCompositingDidCommit(); // A partial damage frame. gfx::Rect partial_view_rect(30, 30, 20, 20); - EXPECT_CALL(observer, - OnDelegatedFrameDamage(view_->window_, partial_view_rect)); view_->SubmitCompositorFrame( local_surface_id, MakeDelegatedFrame(1.f, frame_size, partial_view_rect), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 2u, FrameIndexForView(view_)); + EXPECT_EQ(partial_view_rect, DamageRectForView(view_)); view_->RunOnCompositingDidCommit(); EXPECT_FALSE(view_->resize_locked()); @@ -2870,19 +2852,17 @@ // This frame is dropped. gfx::Rect dropped_damage_rect_1(10, 20, 30, 40); - EXPECT_CALL(observer, OnDelegatedFrameDamage(_, _)).Times(0); view_->SubmitCompositorFrame( local_surface_id, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_1), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 2u, FrameIndexForView(view_)); view_->RunOnCompositingDidCommit(); gfx::Rect dropped_damage_rect_2(40, 50, 10, 20); - EXPECT_CALL(observer, OnDelegatedFrameDamage(_, _)).Times(0); view_->SubmitCompositorFrame( local_surface_id, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_2), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 2u, FrameIndexForView(view_)); view_->RunOnCompositingDidCommit(); EXPECT_TRUE(view_->resize_locked()); @@ -2893,27 +2873,25 @@ local_surface_id = local_surface_id_allocator_.GenerateId(); gfx::Rect new_damage_rect(5, 6, 10, 10); - EXPECT_CALL(observer, - OnDelegatedFrameDamage(view_->window_, view_rect)); view_->SubmitCompositorFrame( local_surface_id, MakeDelegatedFrame(1.f, frame_size, new_damage_rect), nullptr); // The swap unlocks the compositor. EXPECT_TRUE(view_->resize_locked()); EXPECT_FALSE(view_->compositor_locked()); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 3u, FrameIndexForView(view_)); + EXPECT_EQ(view_rect, DamageRectForView(view_)); // The UI commit unlocks for further resize. view_->RunOnCompositingDidCommit(); EXPECT_FALSE(view_->resize_locked()); EXPECT_FALSE(view_->compositor_locked()); // A partial damage frame, this should not be dropped. - EXPECT_CALL(observer, - OnDelegatedFrameDamage(view_->window_, partial_view_rect)); view_->SubmitCompositorFrame( local_surface_id, MakeDelegatedFrame(1.f, frame_size, partial_view_rect), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 4u, FrameIndexForView(view_)); + EXPECT_EQ(partial_view_rect, DamageRectForView(view_)); view_->RunOnCompositingDidCommit(); EXPECT_FALSE(view_->resize_locked()); EXPECT_FALSE(view_->compositor_locked()); @@ -2934,18 +2912,16 @@ EXPECT_TRUE(view_->compositor_locked()); // This frame should not be dropped. - EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect)); view_->SubmitCompositorFrame(local_surface_id, MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 5u, FrameIndexForView(view_)); + EXPECT_EQ(view_rect, DamageRectForView(view_)); EXPECT_TRUE(view_->resize_locked()); EXPECT_FALSE(view_->compositor_locked()); view_->RunOnCompositingDidCommit(); EXPECT_FALSE(view_->resize_locked()); EXPECT_FALSE(view_->compositor_locked()); - - view_->window_->RemoveObserver(&observer); } // If resize races with a renderer frame, we should lock for the right size. @@ -2960,23 +2936,19 @@ gfx::Rect()); view_->SetSize(view_rect.size()); - MockWindowObserver observer; - view_->window_->AddObserver(&observer); - // A frame of initial size. - EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect)); view_->SubmitCompositorFrame( local_surface_id, MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 1, FrameIndexForView(view_)); + EXPECT_EQ(view_rect, DamageRectForView(view_)); view_->RunOnCompositingDidCommit(); // A frame of initial size arrives, but we don't commit in the UI yet. - EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, _)); view_->SubmitCompositorFrame( local_surface_id, MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 2, FrameIndexForView(view_)); EXPECT_FALSE(view_->resize_locked()); EXPECT_FALSE(view_->compositor_locked()); @@ -2987,11 +2959,10 @@ EXPECT_TRUE(view_->resize_locked()); EXPECT_TRUE(view_->compositor_locked()); - EXPECT_CALL(observer, OnDelegatedFrameDamage(_, _)).Times(0); view_->SubmitCompositorFrame( local_surface_id, MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 2, FrameIndexForView(view_)); // If the CompositorLock times out in the meantime, a commit would happen. // Verify that if a commit occurs, the lock remains and we reject frames @@ -3002,31 +2973,27 @@ // In this case we lied about it and the CompositorLock is still active. EXPECT_TRUE(view_->compositor_locked()); - EXPECT_CALL(observer, OnDelegatedFrameDamage(_, _)).Times(0); view_->SubmitCompositorFrame( local_surface_id, MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 2, FrameIndexForView(view_)); // A frame arrives of the new size, which will be accepted. frame_size = view_rect.size(); local_surface_id = local_surface_id_allocator_.GenerateId(); - EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, _)); view_->SubmitCompositorFrame( local_surface_id, MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)), nullptr); // Receiving the frame unlocks the compositor so it can commit. EXPECT_TRUE(view_->resize_locked()); EXPECT_FALSE(view_->compositor_locked()); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 3, FrameIndexForView(view_)); // When the frame of the correct size is committed, the CompositorResizeLock // is released. view_->RunOnCompositingDidCommit(); EXPECT_FALSE(view_->resize_locked()); EXPECT_FALSE(view_->compositor_locked()); - - view_->window_->RemoveObserver(&observer); } // When the DelegatedFrameHost does not have a frame from the renderer, it has @@ -3089,26 +3056,23 @@ gfx::Rect()); view_->SetSize(view_rect.size()); - MockWindowObserver observer; - view_->window_->AddObserver(&observer); - // Swap a frame. - EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect)); view_->SubmitCompositorFrame(kArbitraryLocalSurfaceId, MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 1, FrameIndexForView(view_)); + EXPECT_EQ(view_rect, DamageRectForView(view_)); view_->RunOnCompositingDidCommit(); // Signal that a new RendererCompositorFrameSink was created. view_->CreateNewRendererCompositorFrameSink(); // Submit a frame from the new RendererCompositorFrameSink. - EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect)); view_->SubmitCompositorFrame(local_surface_id_allocator_.GenerateId(), MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 1, FrameIndexForView(view_)); + EXPECT_EQ(view_rect, DamageRectForView(view_)); view_->RunOnCompositingDidCommit(); // Signal that a new RendererCompositorFrameSink was created. @@ -3118,21 +3082,20 @@ view_->SubmitCompositorFrame( local_surface_id_allocator_.GenerateId(), MakeDelegatedFrame(1.f, gfx::Size(), gfx::Rect()), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 1, FrameIndexForView(view_)); + EXPECT_EQ(view_rect, DamageRectForView(view_)); view_->RunOnCompositingDidCommit(); // Signal that a new RendererCompositorFrameSink was created. view_->CreateNewRendererCompositorFrameSink(); // Swap another frame, with a different surface id. - EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect)); view_->SubmitCompositorFrame(local_surface_id_allocator_.GenerateId(), MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr); - testing::Mock::VerifyAndClearExpectations(&observer); + EXPECT_EQ(kFrameIndexStart + 1, FrameIndexForView(view_)); + EXPECT_EQ(view_rect, DamageRectForView(view_)); view_->RunOnCompositingDidCommit(); - - view_->window_->RemoveObserver(&observer); } // This test verifies that the primary SurfaceInfo is populated on resize and
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index 10a73e47..2a4d50f 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -402,6 +402,7 @@ RenderWidgetHostImpl::From(rvh()->GetWidget())->SetView(rwhv_mac_); rwhv_cocoa_.reset([rwhv_mac_->cocoa_view() retain]); + base::RunLoop().RunUntilIdle(); } void TearDown() override {
diff --git a/content/browser/resources/accessibility/accessibility.html b/content/browser/resources/accessibility/accessibility.html index 8e30acb7..80e7b7a 100644 --- a/content/browser/resources/accessibility/accessibility.html +++ b/content/browser/resources/accessibility/accessibility.html
@@ -135,6 +135,11 @@ <a is="action-link" role="button" id="toggle_internal" aria-labelledby="internal"></a> </div> --> + <h2>Chrome Native UI:</h2> + <div id="native_ui"> + <a is="action-link" tabindex="0" role="button" id="showNativeUI">show accessibility tree</a> + </div> + <h2>Pages:</h2> <div id="pages" class="list"></div> <script src="chrome://resources/js/i18n_template.js"></script>
diff --git a/content/browser/resources/accessibility/accessibility.js b/content/browser/resources/accessibility/accessibility.js index 47503648..979aa311 100644 --- a/content/browser/resources/accessibility/accessibility.js +++ b/content/browser/resources/accessibility/accessibility.js
@@ -44,8 +44,8 @@ document.location.reload(); } - function requestAccessibilityTree(data, element) { - chrome.send('requestAccessibilityTree', + function requestWebContentsTree(data, element) { + chrome.send('requestWebContentsTree', [String(data.processId), String(data.routeId)]); } @@ -66,6 +66,11 @@ for (var i = 0; i < list.length; i++) { addToPagesList(list[i]); } + + var showNativeUI = $('showNativeUI'); + showNativeUI.addEventListener('click', function() { + chrome.send('requestNativeUITree', []); + }); } function bindCheckbox(name, value) { @@ -190,7 +195,7 @@ link.textContent = 'show accessibility tree'; link.id = row.id + ':showTree'; link.addEventListener('click', - requestAccessibilityTree.bind(this, data, link)); + requestWebContentsTree.bind(this, data, link)); return link; } @@ -228,6 +233,7 @@ return errorMessageElement; } + // Called from C++ function showTree(data) { var id = data.processId + '.' + data.routeId; var row = $(id); @@ -238,6 +244,16 @@ formatRow(row, data); } + // Called from C++ + function showNativeUITree(data) { + var treeElement = document.querySelector('#native_ui pre'); + if (!treeElement) { + var treeElement = document.createElement('pre'); + $('native_ui').appendChild(treeElement); + } + treeElement.textContent = data.tree; + } + function createAccessibilityTreeElement(data) { var treeElement = document.createElement('pre'); var tree = data.tree; @@ -245,9 +261,11 @@ return treeElement; } + // These are the functions we export so they can be called from C++. return { initialize: initialize, - showTree: showTree + showTree: showTree, + showNativeUITree: showNativeUITree }; });
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc index 562af31..91d4d2a 100644 --- a/content/browser/service_worker/service_worker_context_core.cc +++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -249,7 +249,6 @@ loader_factory_getter_(url_loader_factory_getter), force_update_on_page_load_(false), next_handle_id_(0), - next_registration_handle_id_(0), was_service_worker_registered_(false), observer_list_(observer_list), weak_factory_(this) { @@ -270,7 +269,6 @@ providers_(old_context->providers_.release()), provider_by_uuid_(old_context->provider_by_uuid_.release()), next_handle_id_(old_context->next_handle_id_), - next_registration_handle_id_(old_context->next_registration_handle_id_), was_service_worker_registered_( old_context->was_service_worker_registered_), observer_list_(old_context->observer_list_), @@ -679,10 +677,6 @@ return next_handle_id_++; } -int ServiceWorkerContextCore::GetNewRegistrationHandleId() { - return next_registration_handle_id_++; -} - void ServiceWorkerContextCore::ScheduleDeleteAndStartOver() const { storage_->Disable(); base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h index 194f7c4..afe5905 100644 --- a/content/browser/service_worker/service_worker_context_core.h +++ b/content/browser/service_worker/service_worker_context_core.h
@@ -265,7 +265,6 @@ // Returns new context-local unique ID. int GetNewServiceWorkerHandleId(); - int GetNewRegistrationHandleId(); void ScheduleDeleteAndStartOver() const; @@ -378,7 +377,6 @@ bool force_update_on_page_load_; int next_handle_id_; - int next_registration_handle_id_; // Set in RegisterServiceWorker(), cleared in ClearAllServiceWorkersForTest(). // This is used to avoid unnecessary disk read operation in tests. This value // is false if Chrome was relaunched after service workers were registered.
diff --git a/content/browser/service_worker/service_worker_context_unittest.cc b/content/browser/service_worker/service_worker_context_unittest.cc index c558f2a..ba1896a 100644 --- a/content/browser/service_worker/service_worker_context_unittest.cc +++ b/content/browser/service_worker/service_worker_context_unittest.cc
@@ -742,10 +742,9 @@ true /* expect_active */)); content::RunAllTasksUntilIdle(); - // Next handle ids should be 1 (the next call should return 2) because + // Next handle id should be 1 (the next call should return 2) because // registered worker should have taken ID 0. EXPECT_EQ(1, context()->GetNewServiceWorkerHandleId()); - EXPECT_EQ(1, context()->GetNewRegistrationHandleId()); context()->ScheduleDeleteAndStartOver(); @@ -786,10 +785,9 @@ true /* expect_active */)); content::RunAllTasksUntilIdle(); - // The new context should take over next handle ids. ID 2 should have been + // The new context should take over next handle id. ID 2 should have been // taken by the running registration, so the following method calls return 3. EXPECT_EQ(3, context()->GetNewServiceWorkerHandleId()); - EXPECT_EQ(3, context()->GetNewRegistrationHandleId()); ASSERT_EQ(3u, notifications_.size()); EXPECT_EQ(REGISTRATION_STORED, notifications_[0].type);
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index 18ce0cd..d53ced3 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -22,7 +22,6 @@ #include "content/browser/service_worker/service_worker_handle.h" #include "content/browser/service_worker/service_worker_navigation_handle_core.h" #include "content/browser/service_worker/service_worker_registration.h" -#include "content/browser/service_worker/service_worker_registration_object_host.h" #include "content/common/service_worker/embedded_worker_messages.h" #include "content/common/service_worker/service_worker_event_dispatcher.mojom.h" #include "content/common/service_worker/service_worker_messages.h" @@ -170,17 +169,6 @@ handles_.AddWithID(std::move(handle), handle_id); } -void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationObjectHost( - ServiceWorkerRegistrationObjectHost* host) { - int handle_id = host->handle_id(); - registration_object_hosts_.AddWithID(base::WrapUnique(host), handle_id); -} - -void ServiceWorkerDispatcherHost::UnregisterServiceWorkerRegistrationObjectHost( - int handle_id) { - registration_object_hosts_.Remove(handle_id); -} - ServiceWorkerHandle* ServiceWorkerDispatcherHost::FindServiceWorkerHandle( int provider_id, int64_t version_id) { @@ -448,22 +436,6 @@ handles_.Remove(source_info.handle_id); } -ServiceWorkerRegistrationObjectHost* -ServiceWorkerDispatcherHost::FindServiceWorkerRegistrationObjectHost( - int provider_id, - int64_t registration_id) { - for (base::IDMap<std::unique_ptr<ServiceWorkerRegistrationObjectHost>>:: - iterator iter(®istration_object_hosts_); - !iter.IsAtEnd(); iter.Advance()) { - ServiceWorkerRegistrationObjectHost* host = iter.GetCurrentValue(); - if (host->provider_id() == provider_id && - host->registration()->id() == registration_id) { - return host; - } - } - return nullptr; -} - void ServiceWorkerDispatcherHost::OnCountFeature(int64_t version_id, uint32_t feature) { if (!GetContext())
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h index dce485c..ce3d794 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.h +++ b/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -38,7 +38,6 @@ class ServiceWorkerContextWrapper; class ServiceWorkerHandle; class ServiceWorkerProviderHost; -class ServiceWorkerRegistrationObjectHost; class ServiceWorkerVersion; // ServiceWorkerDispatcherHost is the browser-side endpoint for several IPC @@ -88,18 +87,12 @@ // be destroyed. bool Send(IPC::Message* message) override; - // Following methods are virtual only for testing. + // This method is virtual only for testing. virtual void RegisterServiceWorkerHandle( std::unique_ptr<ServiceWorkerHandle> handle); - virtual void RegisterServiceWorkerRegistrationObjectHost( - ServiceWorkerRegistrationObjectHost* host); - virtual void UnregisterServiceWorkerRegistrationObjectHost(int handle_id); ServiceWorkerHandle* FindServiceWorkerHandle(int provider_id, int64_t version_id); - ServiceWorkerRegistrationObjectHost* FindServiceWorkerRegistrationObjectHost( - int provider_id, - int64_t registration_id); ResourceContext* resource_context() { return resource_context_; } @@ -189,9 +182,6 @@ base::IDMap<std::unique_ptr<ServiceWorkerHandle>> handles_; - base::IDMap<std::unique_ptr<ServiceWorkerRegistrationObjectHost>> - registration_object_hosts_; - bool channel_ready_; // True after BrowserMessageFilter::sender_ != NULL. std::vector<std::unique_ptr<IPC::Message>> pending_messages_;
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc index 17e9a5f..1d321564 100644 --- a/content/browser/service_worker/service_worker_job_unittest.cc +++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -52,8 +52,7 @@ namespace { -// A dispatcher host that holds on to all registered ServiceWorkerHandles and -// ServiceWorkerRegistrationObjectHosts. +// A dispatcher host that holds on to all registered ServiceWorkerHandles. class KeepHandlesDispatcherHost : public ServiceWorkerDispatcherHost { public: KeepHandlesDispatcherHost(int render_process_id, @@ -63,41 +62,19 @@ std::unique_ptr<ServiceWorkerHandle> handle) override { handles_.push_back(std::move(handle)); } - void RegisterServiceWorkerRegistrationObjectHost( - ServiceWorkerRegistrationObjectHost* registration_object_host) override { - registration_object_hosts_.push_back( - base::WrapUnique(registration_object_host)); - } - void UnregisterServiceWorkerRegistrationObjectHost(int handle_id) override { - auto iter = registration_object_hosts_.begin(); - for (; iter != registration_object_hosts_.end(); ++iter) { - if ((*iter)->handle_id() == handle_id) - break; - } - ASSERT_NE(registration_object_hosts_.end(), iter); - registration_object_hosts_.erase(iter); - } void Clear() { handles_.clear(); - registration_object_hosts_.clear(); } const std::vector<std::unique_ptr<ServiceWorkerHandle>>& handles() { return handles_; } - const std::vector<std::unique_ptr<ServiceWorkerRegistrationObjectHost>>& - registration_object_hosts() { - return registration_object_hosts_; - } - private: ~KeepHandlesDispatcherHost() override {} std::vector<std::unique_ptr<ServiceWorkerHandle>> handles_; - std::vector<std::unique_ptr<ServiceWorkerRegistrationObjectHost>> - registration_object_hosts_; DISALLOW_COPY_AND_ASSIGN(KeepHandlesDispatcherHost); }; @@ -404,8 +381,10 @@ TEST_F(ServiceWorkerJobTest, Unregister) { GURL pattern("http://www.example.com/"); - // During registration, handles will be created for hosting the worker's - // context. KeepHandlesDispatcherHost will store the handles. + // During registration, service worker handles will be created to host the + // {installing,waiting,active} service worker objects for + // ServiceWorkerGlobalScope#registration. KeepHandlesDispatcherHost will store + // the handles. scoped_refptr<KeepHandlesDispatcherHost> dispatcher_host = base::MakeRefCounted<KeepHandlesDispatcherHost>( helper_->mock_render_process_id(), @@ -417,22 +396,29 @@ scoped_refptr<ServiceWorkerRegistration> registration = RunRegisterJob(pattern, GURL("http://www.example.com/service_worker.js")); - EXPECT_EQ(1UL, dispatcher_host->registration_object_hosts().size()); + // During the above registration, a service worker registration object host + // for ServiceWorkerGlobalScope#registration has been created/added into + // |provider_host|. + ServiceWorkerProviderHost* provider_host = + registration->active_version()->provider_host(); + ASSERT_NE(nullptr, provider_host); + EXPECT_EQ(1UL, provider_host->registration_object_hosts_.size()); EXPECT_EQ(3UL, dispatcher_host->handles().size()); RunUnregisterJob(pattern); - // Clear all the references. The only reference to the registration object - // should be |registration|. + // Clear all service worker handles. dispatcher_host->Clear(); - EXPECT_EQ(0UL, dispatcher_host->registration_object_hosts().size()); EXPECT_EQ(0UL, dispatcher_host->handles().size()); - ASSERT_TRUE(registration->HasOneRef()); + // The service worker registration object host has been destroyed together + // with |provider_host| by the above unregistration. Then the only reference + // to the registration should be |registration|. + EXPECT_TRUE(registration->HasOneRef()); registration = FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND); - ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(nullptr), registration); + EXPECT_FALSE(registration); } TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) { @@ -486,10 +472,19 @@ scoped_refptr<ServiceWorkerRegistration> old_registration = RunRegisterJob(pattern, script_url); - // Ensure that the registration's object host doesn't have the reference. - EXPECT_EQ(1UL, dispatcher_host->registration_object_hosts().size()); + // During the above registration, a service worker registration object host + // for ServiceWorkerGlobalScope#registration has been created/added into + // |provider_host|. + ServiceWorkerProviderHost* provider_host = + old_registration->active_version()->provider_host(); + ASSERT_NE(nullptr, provider_host); + + // Clear all service worker handles. dispatcher_host->Clear(); - EXPECT_EQ(0UL, dispatcher_host->registration_object_hosts().size()); + // Ensure that the registration's object host doesn't have the reference. + EXPECT_EQ(1UL, provider_host->registration_object_hosts_.size()); + provider_host->registration_object_hosts_.clear(); + EXPECT_EQ(0UL, provider_host->registration_object_hosts_.size()); ASSERT_TRUE(old_registration->HasOneRef()); scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern =
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc index 2e42c21..b303a1a 100644 --- a/content/browser/service_worker/service_worker_provider_host.cc +++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -433,6 +433,19 @@ return nullptr; } +void ServiceWorkerProviderHost::RemoveServiceWorkerRegistrationObjectHost( + int64_t registration_id) { + DCHECK(base::ContainsKey(registration_object_hosts_, registration_id)); + registration_object_hosts_.erase(registration_id); +} + +bool ServiceWorkerProviderHost::AllowServiceWorker(const GURL& scope) { + return GetContentClient()->browser()->AllowServiceWorker( + scope, topmost_frame_url(), dispatcher_host_->resource_context(), + base::Bind(&WebContentsImpl::FromRenderFrameHostID, render_process_id_, + frame_id())); +} + void ServiceWorkerProviderHost::NotifyControllerLost() { SetControllerVersionAttribute(nullptr, true /* notify_controllerchange */); } @@ -483,23 +496,6 @@ return std::unique_ptr<ServiceWorkerRequestHandler>(); } -blink::mojom::ServiceWorkerRegistrationObjectInfoPtr -ServiceWorkerProviderHost::CreateServiceWorkerRegistrationObjectInfo( - ServiceWorkerRegistration* registration) { - DCHECK(dispatcher_host_); - ServiceWorkerRegistrationObjectHost* existing_host = - dispatcher_host_->FindServiceWorkerRegistrationObjectHost( - provider_id(), registration->id()); - if (existing_host) { - return existing_host->CreateObjectInfo(); - } - // ServiceWorkerRegistrationObjectHost ctor will register itself into - // |dispatcher_host_->registration_object_hosts_|. - auto* new_host = new ServiceWorkerRegistrationObjectHost( - context_, dispatcher_host_.get(), AsWeakPtr(), registration); - return new_host->CreateObjectInfo(); -} - blink::mojom::ServiceWorkerObjectInfoPtr ServiceWorkerProviderHost::GetOrCreateServiceWorkerHandle( ServiceWorkerVersion* version) { @@ -713,8 +709,8 @@ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info = mojom::ServiceWorkerProviderInfoForStartWorker::New(); provider_info->provider_id = provider_id(); - provider_info->registration = - CreateServiceWorkerRegistrationObjectInfo(registration); + provider_info->registration = CreateServiceWorkerRegistrationObjectInfo( + scoped_refptr<ServiceWorkerRegistration>(registration)); provider_info->client_request = mojo::MakeRequest(&container_); mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory_ptr_info; @@ -823,7 +819,8 @@ } std::move(*get_ready_callback_) - .Run(CreateServiceWorkerRegistrationObjectInfo(registration)); + .Run(CreateServiceWorkerRegistrationObjectInfo( + scoped_refptr<ServiceWorkerRegistration>(registration))); } bool ServiceWorkerProviderHost::IsReadyToSendMessages() const { @@ -935,7 +932,8 @@ std::move(callback).Run( blink::mojom::ServiceWorkerErrorType::kNone, base::nullopt, - CreateServiceWorkerRegistrationObjectInfo(registration)); + CreateServiceWorkerRegistrationObjectInfo( + scoped_refptr<ServiceWorkerRegistration>(registration))); } void ServiceWorkerProviderHost::GetRegistration( @@ -1028,7 +1026,7 @@ DCHECK(status != SERVICE_WORKER_OK || registration); blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info; if (status == SERVICE_WORKER_OK && !registration->is_uninstalling()) - info = CreateServiceWorkerRegistrationObjectInfo(registration.get()); + info = CreateServiceWorkerRegistrationObjectInfo(std::move(registration)); std::move(callback).Run(blink::mojom::ServiceWorkerErrorType::kNone, base::nullopt, std::move(info)); @@ -1070,7 +1068,7 @@ DCHECK(registration.get()); if (!registration->is_uninstalling()) { object_infos.push_back( - CreateServiceWorkerRegistrationObjectInfo(registration.get())); + CreateServiceWorkerRegistrationObjectInfo(std::move(registration))); } } @@ -1207,6 +1205,20 @@ running_hosted_version_->script_origin(), render_process_id_)); } +blink::mojom::ServiceWorkerRegistrationObjectInfoPtr +ServiceWorkerProviderHost::CreateServiceWorkerRegistrationObjectInfo( + scoped_refptr<ServiceWorkerRegistration> registration) { + int64_t registration_id = registration->id(); + auto existing_host = registration_object_hosts_.find(registration_id); + if (existing_host != registration_object_hosts_.end()) { + return existing_host->second->CreateObjectInfo(); + } + registration_object_hosts_[registration_id] = + std::make_unique<ServiceWorkerRegistrationObjectHost>( + context_, this, std::move(registration)); + return registration_object_hosts_[registration_id]->CreateObjectInfo(); +} + template <typename CallbackType, typename... Args> bool ServiceWorkerProviderHost::CanServeContainerHostMethods( CallbackType* callback, @@ -1233,10 +1245,7 @@ return false; } - if (!GetContentClient()->browser()->AllowServiceWorker( - scope, topmost_frame_url(), dispatcher_host_->resource_context(), - base::Bind(&WebContentsImpl::FromRenderFrameHostID, - render_process_id_, frame_id()))) { + if (!AllowServiceWorker(scope)) { std::move(*callback).Run( blink::mojom::ServiceWorkerErrorType::kDisabled, std::string(error_prefix) +
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h index 23244bc..c851fb0 100644 --- a/content/browser/service_worker/service_worker_provider_host.h +++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -47,6 +47,7 @@ class ResourceRequestBody; class ServiceWorkerContextCore; class ServiceWorkerDispatcherHost; +class ServiceWorkerRegistrationObjectHost; class ServiceWorkerRequestHandler; class ServiceWorkerVersion; class WebContents; @@ -234,15 +235,6 @@ scoped_refptr<ResourceRequestBody> body, bool skip_service_worker); - // Returns an object info representing |registration|. The object info holds a - // Mojo connection to the ServiceWorkerRegistrationObjectHost for the - // |registration| to ensure the host stays alive while the object info is - // alive. A new ServiceWorkerRegistrationObjectHost instance is created if one - // does not already exist. - blink::mojom::ServiceWorkerRegistrationObjectInfoPtr - CreateServiceWorkerRegistrationObjectInfo( - ServiceWorkerRegistration* registration); - // Used to get a ServiceWorkerObjectInfo to send to the renderer. Finds an // existing ServiceWorkerHandle, and increments its reference count, or else // creates a new one (initialized to ref count 1). Returns the @@ -320,6 +312,16 @@ // for current document. ServiceWorkerRegistration* MatchRegistration() const; + // Removes the ServiceWorkerRegistrationObjectHost corresponding to + // |registration_id|. + void RemoveServiceWorkerRegistrationObjectHost(int64_t registration_id); + + // Calls ContentBrowserClient::AllowServiceWorker(). Returns true if content + // settings allows service workers to run at |scope|. If this provider is for + // a window client, the check involves the topmost frame url as well as + // |scope|, and may display tab-level UI. + bool AllowServiceWorker(const GURL& scope); + // Called when our controller has been terminated and doomed due to an // exceptional condition like it could no longer be read from the script // cache. @@ -345,6 +347,10 @@ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent_Fail); FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProviderHostTest, ContextSecurity); + FRIEND_TEST_ALL_PREFIXES(ServiceWorkerJobTest, Unregister); + FRIEND_TEST_ALL_PREFIXES(ServiceWorkerJobTest, RegisterDuplicateScript); + FRIEND_TEST_ALL_PREFIXES(BackgroundSyncManagerTest, + RegisterWithoutLiveSWRegistration); ServiceWorkerProviderHost( int process_id, @@ -443,6 +449,15 @@ void GetInterface(const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) override; + // Returns an object info representing |registration|. The object info holds a + // Mojo connection to the ServiceWorkerRegistrationObjectHost for the + // |registration| to ensure the host stays alive while the object info is + // alive. A new ServiceWorkerRegistrationObjectHost instance is created if one + // can not be found in |registration_object_hosts_|. + blink::mojom::ServiceWorkerRegistrationObjectInfoPtr + CreateServiceWorkerRegistrationObjectInfo( + scoped_refptr<ServiceWorkerRegistration> registration); + // Perform common checks that need to run before ContainerHost methods that // come from a child process are handled. // |scope| is checked if it is allowed to run a service worker. @@ -487,6 +502,14 @@ // false. ServiceWorkerRegistrationMap matching_registrations_; + // Contains all ServiceWorkerRegistrationObjectHost instances corresponding to + // the service worker registration JavaScript objects for the hosted execution + // context (service worker global scope or service worker client) in the + // renderer process. + std::map<int64_t /* registration_id */, + std::unique_ptr<ServiceWorkerRegistrationObjectHost>> + registration_object_hosts_; + // The ready() promise is only allowed to be created once. // |get_ready_callback_| has three states: // 1. |get_ready_callback_| is null when ready() has not yet been called.
diff --git a/content/browser/service_worker/service_worker_registration_object_host.cc b/content/browser/service_worker/service_worker_registration_object_host.cc index a425566..5f2606a 100644 --- a/content/browser/service_worker/service_worker_registration_object_host.cc +++ b/content/browser/service_worker/service_worker_registration_object_host.cc
@@ -4,19 +4,12 @@ #include "content/browser/service_worker/service_worker_registration_object_host.h" +#include "base/memory/ptr_util.h" #include "content/browser/service_worker/service_worker_consts.h" #include "content/browser/service_worker/service_worker_context_core.h" -#include "content/browser/service_worker/service_worker_dispatcher_host.h" #include "content/browser/service_worker/service_worker_handle.h" #include "content/browser/service_worker/service_worker_provider_host.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/common/service_worker/service_worker_messages.h" -#include "content/common/service_worker/service_worker_types.h" #include "content/common/service_worker/service_worker_utils.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/web_contents.h" -#include "content/public/common/content_client.h" #include "content/public/common/service_worker_modes.h" #include "net/http/http_util.h" #include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h" @@ -25,26 +18,18 @@ ServiceWorkerRegistrationObjectHost::ServiceWorkerRegistrationObjectHost( base::WeakPtr<ServiceWorkerContextCore> context, - ServiceWorkerDispatcherHost* dispatcher_host, - base::WeakPtr<ServiceWorkerProviderHost> provider_host, - ServiceWorkerRegistration* registration) - : dispatcher_host_(dispatcher_host), - provider_host_(provider_host), + ServiceWorkerProviderHost* provider_host, + scoped_refptr<ServiceWorkerRegistration> registration) + : provider_host_(provider_host), context_(context), - provider_id_(provider_host ? provider_host->provider_id() - : kInvalidServiceWorkerProviderId), - handle_id_(context - ? context->GetNewRegistrationHandleId() - : blink::mojom::kInvalidServiceWorkerRegistrationHandleId), registration_(registration), weak_ptr_factory_(this) { DCHECK(registration_.get()); + DCHECK(provider_host_); registration_->AddListener(this); bindings_.set_connection_error_handler( base::Bind(&ServiceWorkerRegistrationObjectHost::OnConnectionError, base::Unretained(this))); - - dispatcher_host_->RegisterServiceWorkerRegistrationObjectHost(this); } ServiceWorkerRegistrationObjectHost::~ServiceWorkerRegistrationObjectHost() { @@ -54,7 +39,6 @@ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr ServiceWorkerRegistrationObjectHost::CreateObjectInfo() { - DCHECK(provider_host_); auto info = blink::mojom::ServiceWorkerRegistrationObjectInfo::New(); info->options = blink::mojom::ServiceWorkerRegistrationOptions::New( registration_->pattern()); @@ -116,7 +100,7 @@ context_->UpdateServiceWorker( registration_.get(), false /* force_bypass_cache */, - false /* skip_script_comparison */, provider_host_.get(), + false /* skip_script_comparison */, provider_host_, base::AdaptCallbackForRepeating( base::BindOnce(&ServiceWorkerRegistrationObjectHost::UpdateComplete, weak_ptr_factory_.GetWeakPtr(), std::move(callback)))); @@ -286,8 +270,6 @@ ServiceWorkerVersion* installing_version, ServiceWorkerVersion* waiting_version, ServiceWorkerVersion* active_version) { - if (!provider_host_) - return; // Could be nullptr in some tests. if (!changed_mask.changed()) return; @@ -313,7 +295,8 @@ if (!bindings_.empty()) return; // Will destroy |this|. - dispatcher_host_->UnregisterServiceWorkerRegistrationObjectHost(handle_id_); + provider_host_->RemoveServiceWorkerRegistrationObjectHost( + registration()->id()); } template <typename CallbackType, typename... Args> @@ -321,7 +304,7 @@ CallbackType* callback, const char* error_prefix, Args... args) { - if (!provider_host_ || !context_) { + if (!context_) { std::move(*callback).Run( blink::mojom::ServiceWorkerErrorType::kAbort, std::string(error_prefix) + @@ -348,12 +331,7 @@ return false; } - if (!GetContentClient()->browser()->AllowServiceWorker( - registration_->pattern(), provider_host_->topmost_frame_url(), - dispatcher_host_->resource_context(), - base::Bind(&WebContentsImpl::FromRenderFrameHostID, - provider_host_->process_id(), - provider_host_->frame_id()))) { + if (!provider_host_->AllowServiceWorker(registration_->pattern())) { std::move(*callback).Run( blink::mojom::ServiceWorkerErrorType::kDisabled, std::string(error_prefix) +
diff --git a/content/browser/service_worker/service_worker_registration_object_host.h b/content/browser/service_worker/service_worker_registration_object_host.h index 9b0e8e3..be87d38c 100644 --- a/content/browser/service_worker/service_worker_registration_object_host.h +++ b/content/browser/service_worker/service_worker_registration_object_host.h
@@ -11,7 +11,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "content/browser/service_worker/service_worker_registration.h" -#include "content/browser/service_worker/service_worker_version.h" #include "content/common/content_export.h" #include "content/common/service_worker/service_worker_types.h" #include "mojo/public/cpp/bindings/associated_binding_set.h" @@ -20,12 +19,8 @@ namespace content { class ServiceWorkerContextCore; -class ServiceWorkerDispatcherHost; class ServiceWorkerVersion; -// TODO(leonhsl): Manage instances of this class per ServiceWorkerProviderHost -// rather than per ServiceWorkerDispatcherHost (per renderer process). - // ServiceWorkerRegistrationObjectHost has a 1:1 correspondence to // WebServiceWorkerRegistration in the renderer process. // The host stays alive while the WebServiceWorkerRegistration is alive, and @@ -41,17 +36,13 @@ public: ServiceWorkerRegistrationObjectHost( base::WeakPtr<ServiceWorkerContextCore> context, - ServiceWorkerDispatcherHost* dispatcher_host, - base::WeakPtr<ServiceWorkerProviderHost> provider_host, - ServiceWorkerRegistration* registration); + ServiceWorkerProviderHost* provider_host, + scoped_refptr<ServiceWorkerRegistration> registration); ~ServiceWorkerRegistrationObjectHost() override; // Establishes a new mojo connection into |bindings_|. blink::mojom::ServiceWorkerRegistrationObjectInfoPtr CreateObjectInfo(); - int provider_id() const { return provider_id_; } - int handle_id() const { return handle_id_; } - ServiceWorkerRegistration* registration() { return registration_.get(); } private: @@ -115,13 +106,10 @@ const char* error_prefix, Args... args); - // |dispatcher_host_| is valid throughout lifetime of |this| because it owns + // |provider_host_| is valid throughout lifetime of |this| because it owns // |this|. - ServiceWorkerDispatcherHost* dispatcher_host_; - base::WeakPtr<ServiceWorkerProviderHost> provider_host_; + ServiceWorkerProviderHost* provider_host_; base::WeakPtr<ServiceWorkerContextCore> context_; - const int provider_id_; - const int handle_id_; mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerRegistrationObjectHost> bindings_; // Mojo connection to the content::WebServiceWorkerRegistrationImpl in the
diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc index d3779ca3..5c4e7460 100644 --- a/content/browser/service_worker/service_worker_registration_unittest.cc +++ b/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -262,12 +262,23 @@ auto dispatcher_host = base::MakeRefCounted<ServiceWorkerDispatcherHost>( helper_->mock_render_process_id(), helper_->browser_context()->GetResourceContext()); - // ServiceWorkerRegistrationObjectHost ctor will make - // |registration_object_host| be owned by |dispatcher_host|. - auto* registration_object_host = new ServiceWorkerRegistrationObjectHost( - context()->AsWeakPtr(), dispatcher_host.get(), - base::WeakPtr<ServiceWorkerProviderHost>(), registration.get()); - ALLOW_UNUSED_LOCAL(registration_object_host); + // Prepare a ServiceWorkerProviderHost. + ServiceWorkerRemoteProviderEndpoint remote_endpoint; + std::unique_ptr<ServiceWorkerProviderHost> provider_host = + CreateProviderHostWithDispatcherHost( + helper_->mock_render_process_id(), 1 /* dummy provider_id */, + context()->AsWeakPtr(), 1 /* route_id */, dispatcher_host.get(), + &remote_endpoint); + auto registration_object_host = + std::make_unique<ServiceWorkerRegistrationObjectHost>( + context()->AsWeakPtr(), provider_host.get(), registration); + // To enable the caller end point + // |registration_object_host->remote_registration_| to make calls safely with + // no need to pass |object_info_->request| through a message pipe endpoint. + blink::mojom::ServiceWorkerRegistrationObjectInfoPtr object_info = + registration_object_host->CreateObjectInfo(); + mojo::AssociateWithDisconnectedPipe(object_info->request.PassHandle()); + registration->NotifyRegistrationFailed(); // Don't crash when |registration_object_host| gets destructed. }
diff --git a/content/browser/shared_worker/shared_worker_service_impl.cc b/content/browser/shared_worker/shared_worker_service_impl.cc index c43eeb0..8191afb 100644 --- a/content/browser/shared_worker/shared_worker_service_impl.cc +++ b/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -19,7 +19,6 @@ #include "content/common/shared_worker/shared_worker_client.mojom.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" -#include "content/public/browser/worker_service_observer.h" #include "content/public/common/bind_interface_helpers.h" #include "third_party/WebKit/common/message_port/message_port_channel.h" @@ -53,7 +52,6 @@ void SharedWorkerServiceImpl::ResetForTesting() { worker_hosts_.clear(); - observers_.Clear(); } bool SharedWorkerServiceImpl::TerminateWorker(int process_id, int route_id) { @@ -80,34 +78,6 @@ } } -std::vector<WorkerService::WorkerInfo> SharedWorkerServiceImpl::GetWorkers() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - std::vector<WorkerService::WorkerInfo> results; - for (const auto& iter : worker_hosts_) { - SharedWorkerHost* host = iter.second.get(); - const SharedWorkerInstance* instance = host->instance(); - if (instance) { - WorkerService::WorkerInfo info; - info.url = instance->url(); - info.name = instance->name(); - info.route_id = host->route_id(); - info.process_id = host->process_id(); - results.push_back(info); - } - } - return results; -} - -void SharedWorkerServiceImpl::AddObserver(WorkerServiceObserver* observer) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - observers_.AddObserver(observer); -} - -void SharedWorkerServiceImpl::RemoveObserver(WorkerServiceObserver* observer) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - observers_.RemoveObserver(observer); -} - void SharedWorkerServiceImpl::ConnectToWorker( int process_id, int frame_id, @@ -154,9 +124,6 @@ void SharedWorkerServiceImpl::DestroyHost(int process_id, int route_id) { worker_hosts_.erase(WorkerID(process_id, route_id)); - for (auto& observer : observers_) - observer.WorkerDestroyed(process_id, route_id); - // Complete the call to TerminateAllWorkersForTesting if no more workers. if (worker_hosts_.empty() && terminate_all_workers_callback_) std::move(terminate_all_workers_callback_).Run(); @@ -207,9 +174,6 @@ const std::string name = host->instance()->name(); worker_hosts_[WorkerID(worker_process_id, worker_route_id)] = std::move(host); - - for (auto& observer : observers_) - observer.WorkerCreated(url, name, worker_process_id, worker_route_id); } SharedWorkerHost* SharedWorkerServiceImpl::FindSharedWorkerHost(int process_id,
diff --git a/content/browser/shared_worker/shared_worker_service_impl.h b/content/browser/shared_worker/shared_worker_service_impl.h index 756fab6..c8c29ca 100644 --- a/content/browser/shared_worker/shared_worker_service_impl.h +++ b/content/browser/shared_worker/shared_worker_service_impl.h
@@ -14,12 +14,9 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/singleton.h" -#include "base/observer_list.h" #include "content/browser/shared_worker/shared_worker_host.h" #include "content/common/shared_worker/shared_worker_connector.mojom.h" #include "content/common/shared_worker/shared_worker_factory.mojom.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" #include "content/public/browser/worker_service.h" namespace blink { @@ -31,7 +28,6 @@ class SharedWorkerInstance; class SharedWorkerHost; class ResourceContext; -class WorkerServiceObserver; class WorkerStoragePartitionId; // The implementation of WorkerService. We try to place workers in an existing @@ -41,12 +37,11 @@ // Returns the SharedWorkerServiceImpl singleton. static SharedWorkerServiceImpl* GetInstance(); + // Terminates the given worker. Returns true if the process was found. + bool TerminateWorker(int process_id, int route_id); + // WorkerService implementation: - bool TerminateWorker(int process_id, int route_id) override; void TerminateAllWorkersForTesting(base::OnceClosure callback) override; - std::vector<WorkerInfo> GetWorkers() override; - void AddObserver(WorkerServiceObserver* observer) override; - void RemoveObserver(WorkerServiceObserver* observer) override; // Creates the worker if necessary or connects to an already existing worker. void ConnectToWorker( @@ -85,7 +80,6 @@ const SharedWorkerInstance& instance); WorkerHostMap worker_hosts_; - base::ObserverList<WorkerServiceObserver> observers_; base::OnceClosure terminate_all_workers_callback_; DISALLOW_COPY_AND_ASSIGN(SharedWorkerServiceImpl);
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 8bb3eaa..534b806 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -706,6 +706,20 @@ dom_storage_context_->OpenLocalStorage(origin, std::move(request)); } +void StoragePartitionImpl::OpenSessionStorage( + int64_t namespace_id, + const url::Origin& origin, + mojo::InterfaceRequest<mojom::LevelDBWrapper> request) { + int process_id = bindings_.dispatch_context(); + if (!ChildProcessSecurityPolicy::GetInstance()->CanAccessDataForOrigin( + process_id, origin.GetURL())) { + bindings_.ReportBadMessage("Access denied for sessionStorage request"); + return; + } + dom_storage_context_->OpenSessionStorage(namespace_id, origin, + std::move(request)); +} + void StoragePartitionImpl::ClearDataImpl( uint32_t remove_mask, uint32_t quota_storage_remove_mask,
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index 6e62286..7fe4531 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -130,6 +130,10 @@ void OpenLocalStorage( const url::Origin& origin, mojo::InterfaceRequest<mojom::LevelDBWrapper> request) override; + void OpenSessionStorage( + int64_t namespace_id, + const url::Origin& origin, + mojo::InterfaceRequest<mojom::LevelDBWrapper> request) override; scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter() { return url_loader_factory_getter_;
diff --git a/content/browser/web_contents/aura/gesture_nav_simple.cc b/content/browser/web_contents/aura/gesture_nav_simple.cc index 416eb31..c655db0 100644 --- a/content/browser/web_contents/aura/gesture_nav_simple.cc +++ b/content/browser/web_contents/aura/gesture_nav_simple.cc
@@ -138,7 +138,6 @@ private: // ui::LayerDelegate: void OnPaintLayer(const ui::PaintContext& context) override; - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override; @@ -185,8 +184,6 @@ canvas->DrawImageInt(image, 0, 0); } -void Arrow::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {} - void Arrow::OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) {} @@ -242,7 +239,6 @@ // ui::LayerDelegate: void OnPaintLayer(const ui::PaintContext& context) override; - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override; @@ -504,8 +500,6 @@ canvas->DrawCircle(center_point, kBackgroundRadius, bg_flags); } -void Affordance::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {} - void Affordance::OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) {}
diff --git a/content/browser/web_contents/aura/shadow_layer_delegate.cc b/content/browser/web_contents/aura/shadow_layer_delegate.cc index e6c92a30..9e6119eb 100644 --- a/content/browser/web_contents/aura/shadow_layer_delegate.cc +++ b/content/browser/web_contents/aura/shadow_layer_delegate.cc
@@ -52,10 +52,6 @@ recorder.canvas()->DrawRect(paint_rect, flags); } -void ShadowLayerDelegate::OnDelegatedFrameDamage( - const gfx::Rect& damage_rect_in_dip) { -} - void ShadowLayerDelegate::OnDeviceScaleFactorChanged( float old_device_scale_factor, float new_device_scale_factor) {}
diff --git a/content/browser/web_contents/aura/shadow_layer_delegate.h b/content/browser/web_contents/aura/shadow_layer_delegate.h index 6a84d2b..c93e990 100644 --- a/content/browser/web_contents/aura/shadow_layer_delegate.h +++ b/content/browser/web_contents/aura/shadow_layer_delegate.h
@@ -31,7 +31,6 @@ private: // Overridden from ui::LayerDelegate: void OnPaintLayer(const ui::PaintContext& context) override; - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override;
diff --git a/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc b/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc index 5cd612de..bca86eb 100644 --- a/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc +++ b/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
@@ -147,27 +147,14 @@ kVideoAudioHtmlFile); } -// Enable these tests once https://crbug.com/785558 is fixed. -#if defined(OS_ANDROID) || defined(OS_CHROMEOS) -#define MAYBE_CaptureFromCanvas2DHandlesContextLoss \ - DISABLED_CaptureFromCanvas2DHandlesContextLoss -#define MAYBE_CaptureFromOpaqueCanvas2DHandlesContextLoss \ - DISABLED_CaptureFromOpaqueCanvas2DHandlesContextLoss -#else -#define MAYBE_CaptureFromCanvas2DHandlesContextLoss \ - CaptureFromCanvas2DHandlesContextLoss -#define MAYBE_CaptureFromOpaqueCanvas2DHandlesContextLoss \ - CaptureFromOpaqueCanvas2DHandlesContextLoss -#endif - IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest, - MAYBE_CaptureFromCanvas2DHandlesContextLoss) { + CaptureFromCanvas2DHandlesContextLoss) { MakeTypicalCall("testCanvas2DContextLoss(true);", kCanvasCaptureColorTestHtmlFile); } IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest, - MAYBE_CaptureFromOpaqueCanvas2DHandlesContextLoss) { + CaptureFromOpaqueCanvas2DHandlesContextLoss) { MakeTypicalCall("testCanvas2DContextLoss(false);", kCanvasCaptureColorTestHtmlFile); }
diff --git a/content/common/storage_partition_service.mojom b/content/common/storage_partition_service.mojom index 5aca10a..9e1816e 100644 --- a/content/common/storage_partition_service.mojom +++ b/content/common/storage_partition_service.mojom
@@ -11,4 +11,7 @@ interface StoragePartitionService { OpenLocalStorage(url.mojom.Origin origin, LevelDBWrapper& database); + OpenSessionStorage(int64 namespace_id, + url.mojom.Origin origin, + LevelDBWrapper& database); };
diff --git a/content/gpu/gpu_sandbox_hook_linux.cc b/content/gpu/gpu_sandbox_hook_linux.cc index 767dd76..27096a62 100644 --- a/content/gpu/gpu_sandbox_hook_linux.cc +++ b/content/gpu/gpu_sandbox_hook_linux.cc
@@ -28,6 +28,10 @@ #include "services/service_manager/sandbox/linux/bpf_gpu_policy_linux.h" #include "services/service_manager/sandbox/linux/sandbox_linux.h" +#if BUILDFLAG(USE_VAAPI) +#include <va/va_version.h> +#endif + using sandbox::bpf_dsl::Policy; using sandbox::syscall_broker::BrokerFilePermission; using sandbox::syscall_broker::BrokerProcess; @@ -83,6 +87,14 @@ #endif } +inline bool IsLibVAVersion2() { +#if BUILDFLAG(USE_VAAPI) && VA_MAJOR_VERSION == 1 + return true; +#else + return false; +#endif +} + constexpr int dlopen_flag = RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE; void AddV4L2GpuWhitelist( @@ -249,23 +261,31 @@ // inside the sandbox, so preload them now. if (options.vaapi_accelerated_video_encode_enabled || options.accelerated_video_decode_enabled) { - const char* I965DrvVideoPath = nullptr; - const char* I965HybridDrvVideoPath = nullptr; - if (IsArchitectureX86_64()) { - I965DrvVideoPath = "/usr/lib64/va/drivers/i965_drv_video.so"; - I965HybridDrvVideoPath = "/usr/lib64/va/drivers/hybrid_drv_video.so"; - } else if (IsArchitectureI386()) { - I965DrvVideoPath = "/usr/lib/va/drivers/i965_drv_video.so"; - } - dlopen(I965DrvVideoPath, dlopen_flag); - if (I965HybridDrvVideoPath) - dlopen(I965HybridDrvVideoPath, dlopen_flag); - dlopen("libva.so.1", dlopen_flag); + if (IsLibVAVersion2()) { + if (IsArchitectureX86_64()) { + dlopen("/usr/lib64/va/drivers/i965_drv_video.so", dlopen_flag); + dlopen("/usr/lib64/va/drivers/hybrid_drv_video.so", dlopen_flag); + } else if (IsArchitectureI386()) { + dlopen("/usr/lib/va/drivers/i965_drv_video.so", dlopen_flag); + } + dlopen("libva.so.2", dlopen_flag); #if defined(USE_OZONE) - dlopen("libva-drm.so.1", dlopen_flag); -#elif defined(USE_X11) - dlopen("libva-x11.so.1", dlopen_flag); + dlopen("libva-drm.so.2", dlopen_flag); #endif + } else { + if (IsArchitectureX86_64()) { + dlopen("/usr/lib64/va1/drivers/i965_drv_video.so", dlopen_flag); + dlopen("/usr/lib64/va1/drivers/hybrid_drv_video.so", dlopen_flag); + } else if (IsArchitectureI386()) { + dlopen("/usr/lib/va1/drivers/i965_drv_video.so", dlopen_flag); + } + dlopen("libva.so.1", dlopen_flag); +#if defined(USE_OZONE) + dlopen("libva-drm.so.1", dlopen_flag); +#elif defined(USE_X11) + dlopen("libva-x11.so.1", dlopen_flag); +#endif + } } } } @@ -300,13 +320,16 @@ bool GpuProcessPreSandboxHook(service_manager::BPFBasePolicy* policy, service_manager::SandboxLinux::Options options) { - service_manager::SandboxLinux::GetInstance()->StartBrokerProcess( - policy, FilePermissionsForGpu(options), - base::BindOnce(BrokerProcessPreSandboxHook), options); + auto* instance = service_manager::SandboxLinux::GetInstance(); + instance->StartBrokerProcess(policy, FilePermissionsForGpu(options), + base::BindOnce(BrokerProcessPreSandboxHook), + options); if (!LoadLibrariesForGpu(options)) return false; + instance->EngageNamespaceSandbox(false /* from_zygote */); + errno = 0; return true; }
diff --git a/content/network/url_loader.cc b/content/network/url_loader.cc index c7a470c..929949e 100644 --- a/content/network/url_loader.cc +++ b/content/network/url_loader.cc
@@ -332,6 +332,8 @@ } } + url_request_->set_initiator(request.request_initiator); + int load_flags = BuildLoadFlagsForRequest(request, false); url_request_->SetLoadFlags(load_flags); if (report_raw_headers_) {
diff --git a/content/public/android/java/src/org/chromium/content/browser/SelectionIndicesConverter.java b/content/public/android/java/src/org/chromium/content/browser/SelectionIndicesConverter.java index 21d6cf9..2951cacb 100644 --- a/content/public/android/java/src/org/chromium/content/browser/SelectionIndicesConverter.java +++ b/content/public/android/java/src/org/chromium/content/browser/SelectionIndicesConverter.java
@@ -108,10 +108,12 @@ } if (end <= initialStartOffset) { - wordIndices[1] = -countWordsForward(end, initialStartOffset, breakIterator); + wordIndices[1] = + -countWordsForward(/* start = */ end, initialStartOffset, breakIterator); } else { // end > initialStartOffset - wordIndices[1] = countWordsBackward(end, initialStartOffset, breakIterator); + wordIndices[1] = + countWordsBackward(/* start = */ end, initialStartOffset, breakIterator); } return true;
diff --git a/content/public/android/junit/src/org/chromium/content/browser/SelectionPopupControllerTest.java b/content/public/android/junit/src/org/chromium/content/browser/SelectionPopupControllerTest.java index 5efa917..cb5073e 100644 --- a/content/public/android/junit/src/org/chromium/content/browser/SelectionPopupControllerTest.java +++ b/content/public/android/junit/src/org/chromium/content/browser/SelectionPopupControllerTest.java
@@ -55,7 +55,7 @@ private static final String AMPHITHEATRE_FULL = "1600 Amphitheatre Parkway"; private static final String AMPHITHEATRE = "Amphitheatre"; - private class TestSelectionClient implements SelectionClient { + private static class TestSelectionClient implements SelectionClient { private SelectionClient.Result mResult; private SelectionClient.ResultCallback mResultCallback; @@ -94,7 +94,7 @@ } } - class SelectionClientOnlyReturnTrue extends TestSelectionClient { + private static class SelectionClientOnlyReturnTrue extends TestSelectionClient { @Override public boolean requestSelectionPopupUpdates(boolean shouldSuggest) { return true;
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json index 61effa58..71d777b 100644 --- a/content/public/app/mojo/content_browser_manifest.json +++ b/content/public/app/mojo/content_browser_manifest.json
@@ -90,7 +90,7 @@ "url_loader" ], "patch_service": [ "patch_file" ], - "ui": [ "display_output_protection", "video_detector" ], + "ui": [ "arc_manager", "display_output_protection", "video_detector" ], "service_manager": [ "service_manager:client_process", "service_manager:instance_name",
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 9ad74820..f7c856f 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -303,7 +303,6 @@ "webvr_service_provider.cc", "webvr_service_provider.h", "worker_service.h", - "worker_service_observer.h", "zygote_handle_linux.h", "zygote_host_linux.h", ]
diff --git a/content/public/browser/android/compositor.h b/content/public/browser/android/compositor.h index 3b1597fe..9b8eb49 100644 --- a/content/public/browser/android/compositor.h +++ b/content/public/browser/android/compositor.h
@@ -68,6 +68,9 @@ // Set the output surface bounds. virtual void SetWindowBounds(const gfx::Size& size) = 0; + // Defer commits on the layer tree host. + virtual void SetDeferCommits(bool defer_commits) = 0; + // Set the output surface which the compositor renders into. virtual void SetSurface(jobject surface) = 0;
diff --git a/content/public/browser/devtools_agent_host.h b/content/public/browser/devtools_agent_host.h index 3930444e..6fa1c93 100644 --- a/content/public/browser/devtools_agent_host.h +++ b/content/public/browser/devtools_agent_host.h
@@ -63,11 +63,6 @@ // does exist. static bool HasFor(WebContents* web_contents); - // Returns DevToolsAgentHost that can be used for inspecting shared worker - // with given worker process host id and routing id. - static scoped_refptr<DevToolsAgentHost> GetForWorker(int worker_process_id, - int worker_route_id); - // Creates DevToolsAgentHost that communicates to the target by means of // provided |delegate|. |delegate| ownership is passed to the created agent // host.
diff --git a/content/public/browser/worker_service.h b/content/public/browser/worker_service.h index 9615fcdd..38876829 100644 --- a/content/public/browser/worker_service.h +++ b/content/public/browser/worker_service.h
@@ -13,8 +13,6 @@ namespace content { -class WorkerServiceObserver; - // A singleton for managing HTML5 shared web workers. These may be run in a // separate process, since multiple renderer processes can be talking to a // single shared worker. All the methods below can only be called on the UI @@ -26,26 +24,10 @@ // Returns the WorkerService singleton. static WorkerService* GetInstance(); - // Terminates the given worker. Returns true if the process was found. - virtual bool TerminateWorker(int process_id, int route_id) = 0; - // Terminates all workers and notifies when complete. This is used for // testing when it is important to make sure that all shared worker activity // has stopped. virtual void TerminateAllWorkersForTesting(base::OnceClosure callback) = 0; - - struct WorkerInfo { - GURL url; - std::string name; - int process_id; - int route_id; - }; - - // Return information about all the currently running workers. - virtual std::vector<WorkerInfo> GetWorkers() = 0; - - virtual void AddObserver(WorkerServiceObserver* observer) = 0; - virtual void RemoveObserver(WorkerServiceObserver* observer) = 0; }; } // namespace content
diff --git a/content/public/browser/worker_service_observer.h b/content/public/browser/worker_service_observer.h deleted file mode 100644 index 8392fb79..0000000 --- a/content/public/browser/worker_service_observer.h +++ /dev/null
@@ -1,29 +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 CONTENT_PUBLIC_BROWSER_WORKER_SERVICE_OBSERVER_H_ -#define CONTENT_PUBLIC_BROWSER_WORKER_SERVICE_OBSERVER_H_ - -#include <string> - -class GURL; - -namespace content { - -// All the methods below are called on the UI thread. -class WorkerServiceObserver { - public: - virtual void WorkerCreated(const GURL& url, - const std::string& name, - int process_id, - int route_id) {} - virtual void WorkerDestroyed(int process_id, int route_id) {} - - protected: - virtual ~WorkerServiceObserver() {} -}; - -} // namespace content - -#endif // CONTENT_PUBLIC_BROWSER_WORKER_SERVICE_OBSERVER_H_
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 56e583b1..e8cd7523 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -168,6 +168,10 @@ const base::Feature kMojoInputMessages{"MojoInputMessages", base::FEATURE_DISABLED_BY_DEFAULT}; +// Mojo-based Session Storage. +const base::Feature kMojoSessionStorage{"MojoSessionStorage", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables/disables hardware video encode acceleration using Mojo (falls back). const base::Feature kMojoVideoEncodeAccelerator{ "MojoVideoEncodeAccelerator", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 93f8abc..55bab48 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -53,6 +53,7 @@ CONTENT_EXPORT extern const base::Feature kMainThreadBusyScrollIntervention; CONTENT_EXPORT extern const base::Feature kMojoBlobs; CONTENT_EXPORT extern const base::Feature kMojoInputMessages; +CONTENT_EXPORT extern const base::Feature kMojoSessionStorage; CONTENT_EXPORT extern const base::Feature kMojoVideoEncodeAccelerator; CONTENT_EXPORT extern const base::Feature kModuleScriptsDynamicImport; CONTENT_EXPORT extern const base::Feature kModuleScriptsImportMetaUrl;
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc index 7afdfe9..3e3d132 100644 --- a/content/public/renderer/content_renderer_client.cc +++ b/content/public/renderer/content_renderer_client.cc
@@ -47,6 +47,10 @@ return false; } +bool ContentRendererClient::ShouldTrackUseCounter(const GURL& url) { + return true; +} + void ContentRendererClient::DeferMediaLoad( RenderFrame* render_frame, bool has_played_media_before,
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index 3d28a01..3d34633 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h
@@ -117,6 +117,10 @@ virtual bool ShouldSuppressErrorPage(RenderFrame* render_frame, const GURL& url); + // Returns false for new tab page activities, which should be filtered out in + // UseCounter; returns true otherwise. + virtual bool ShouldTrackUseCounter(const GURL& url); + // Returns the information to display when a navigation error occurs. // If |error_html| is not null then it may be set to a HTML page containing // the details of the error and maybe links to more info.
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc index 4bea424..ffd8148 100644 --- a/content/public/test/test_renderer_host.cc +++ b/content/public/test/test_renderer_host.cc
@@ -26,6 +26,7 @@ #include "content/test/test_render_frame_host_factory.h" #include "content/test/test_render_view_host.h" #include "content/test/test_render_view_host_factory.h" +#include "content/test/test_render_widget_host_factory.h" #include "content/test/test_web_contents.h" #include "ui/base/material_design/material_design_controller.h" #include "ui/base/test/material_design_controller_test_api.h" @@ -134,7 +135,8 @@ RenderViewHostTestEnabler::RenderViewHostTestEnabler() : rph_factory_(new MockRenderProcessHostFactory()), rvh_factory_(new TestRenderViewHostFactory(rph_factory_.get())), - rfh_factory_(new TestRenderFrameHostFactory()) { + rfh_factory_(new TestRenderFrameHostFactory()), + rwhi_factory_(new TestRenderWidgetHostFactory()) { // A MessageLoop is needed for Mojo bindings to graphics services. Some // tests have their own, so this only creates one when none exists. This // means tests must ensure any MessageLoop they make is created before
diff --git a/content/public/test/test_renderer_host.h b/content/public/test/test_renderer_host.h index 2f742d3..6478b1b 100644 --- a/content/public/test/test_renderer_host.h +++ b/content/public/test/test_renderer_host.h
@@ -48,6 +48,7 @@ class RenderProcessHostFactory; class TestRenderFrameHostFactory; class TestRenderViewHostFactory; +class TestRenderWidgetHostFactory; class WebContents; struct WebPreferences; @@ -182,6 +183,7 @@ std::unique_ptr<MockRenderProcessHostFactory> rph_factory_; std::unique_ptr<TestRenderViewHostFactory> rvh_factory_; std::unique_ptr<TestRenderFrameHostFactory> rfh_factory_; + std::unique_ptr<TestRenderWidgetHostFactory> rwhi_factory_; }; // RenderViewHostTestHarness ---------------------------------------------------
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index aab7b160..a7d64a88 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -119,6 +119,8 @@ "dom_storage/local_storage_cached_areas.h", "dom_storage/local_storage_namespace.cc", "dom_storage/local_storage_namespace.h", + "dom_storage/session_web_storage_namespace_impl.cc", + "dom_storage/session_web_storage_namespace_impl.h", "dom_storage/webstoragearea_impl.cc", "dom_storage/webstoragearea_impl.h", "dom_storage/webstoragenamespace_impl.cc", @@ -915,6 +917,7 @@ "//third_party/webrtc/api:optional", "//third_party/webrtc/api:rtc_stats_api", "//third_party/webrtc/api:video_frame_api", + "//third_party/webrtc/api:video_frame_api_i420", "//third_party/webrtc/api/audio_codecs:audio_codecs_api", "//third_party/webrtc/api/audio_codecs/L16:audio_decoder_L16", "//third_party/webrtc/api/audio_codecs/L16:audio_encoder_L16",
diff --git a/content/renderer/appcache/web_application_cache_host_impl.cc b/content/renderer/appcache/web_application_cache_host_impl.cc index d8593940..4353aec 100644 --- a/content/renderer/appcache/web_application_cache_host_impl.cc +++ b/content/renderer/appcache/web_application_cache_host_impl.cc
@@ -171,13 +171,12 @@ } void WebApplicationCacheHostImpl::WillStartMainResourceRequest( - WebURLRequest& request, + const WebURL& url, + const WebString& method_webstring, const WebApplicationCacheHost* spawning_host) { - request.SetAppCacheHostID(host_id_); + original_main_resource_url_ = ClearUrlRef(url); - original_main_resource_url_ = ClearUrlRef(request.Url()); - - std::string method = request.HttpMethod().Utf8(); + std::string method = method_webstring.Utf8(); is_get_method_ = (method == kHttpGETMethod); DCHECK(method == base::ToUpperASCII(method)); @@ -189,11 +188,6 @@ } } -void WebApplicationCacheHostImpl::WillStartSubResourceRequest( - WebURLRequest& request) { - request.SetAppCacheHostID(host_id_); -} - void WebApplicationCacheHostImpl::SelectCacheWithoutManifest() { if (was_select_cache_called_) return;
diff --git a/content/renderer/appcache/web_application_cache_host_impl.h b/content/renderer/appcache/web_application_cache_host_impl.h index 8771690a..7af412a 100644 --- a/content/renderer/appcache/web_application_cache_host_impl.h +++ b/content/renderer/appcache/web_application_cache_host_impl.h
@@ -42,9 +42,9 @@ // blink::WebApplicationCacheHost: void WillStartMainResourceRequest( - blink::WebURLRequest&, - const blink::WebApplicationCacheHost*) override; - void WillStartSubResourceRequest(blink::WebURLRequest&) override; + const blink::WebURL& url, + const blink::WebString& method, + const WebApplicationCacheHost* spawning_host) override; void SelectCacheWithoutManifest() override; bool SelectCacheWithManifest(const blink::WebURL& manifestURL) override; void DidReceiveResponseForMainResource(const blink::WebURLResponse&) override;
diff --git a/content/renderer/dom_storage/DEPS b/content/renderer/dom_storage/DEPS index b1b5473d..b1259df 100644 --- a/content/renderer/dom_storage/DEPS +++ b/content/renderer/dom_storage/DEPS
@@ -8,5 +8,6 @@ "+content/renderer/dom_storage/local_storage_area.h", "+content/renderer/dom_storage/local_storage_namespace.h", "+content/renderer/dom_storage/mock_leveldb_wrapper.h", + "+content/renderer/render_thread_impl.h", ], }
diff --git a/content/renderer/dom_storage/dom_storage_cached_area.cc b/content/renderer/dom_storage/dom_storage_cached_area.cc index 881556c..dc3f333 100644 --- a/content/renderer/dom_storage/dom_storage_cached_area.cc +++ b/content/renderer/dom_storage/dom_storage_cached_area.cc
@@ -11,16 +11,20 @@ #include "build/build_config.h" #include "content/common/dom_storage/dom_storage_map.h" #include "content/renderer/dom_storage/dom_storage_proxy.h" +#include "third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h" namespace content { -DOMStorageCachedArea::DOMStorageCachedArea(int64_t namespace_id, - const GURL& origin, - DOMStorageProxy* proxy) +DOMStorageCachedArea::DOMStorageCachedArea( + int64_t namespace_id, + const GURL& origin, + DOMStorageProxy* proxy, + blink::scheduler::RendererScheduler* renderer_scheduler) : ignore_all_mutations_(false), namespace_id_(namespace_id), origin_(origin), proxy_(proxy), + renderer_scheduler_(renderer_scheduler), weak_factory_(this) {} DOMStorageCachedArea::~DOMStorageCachedArea() {} @@ -68,10 +72,14 @@ #endif // !defined(OS_ANDROID) // Ignore mutations to 'key' until OnSetItemComplete. + blink::WebScopedVirtualTimePauser virtual_time_pauser = + renderer_scheduler_->CreateWebScopedVirtualTimePauser(); + virtual_time_pauser.PauseVirtualTime(true); ignore_key_mutations_[key]++; proxy_->SetItem(connection_id, key, value, old_value, page_url, base::Bind(&DOMStorageCachedArea::OnSetItemComplete, - weak_factory_.GetWeakPtr(), key)); + weak_factory_.GetWeakPtr(), key, + base::Passed(std::move(virtual_time_pauser)))); return true; } @@ -91,11 +99,15 @@ #endif // Ignore mutations to 'key' until OnRemoveItemComplete. + blink::WebScopedVirtualTimePauser virtual_time_pauser = + renderer_scheduler_->CreateWebScopedVirtualTimePauser(); + virtual_time_pauser.PauseVirtualTime(true); ignore_key_mutations_[key]++; proxy_->RemoveItem(connection_id, key, base::NullableString16(old_value, false), page_url, base::Bind(&DOMStorageCachedArea::OnRemoveItemComplete, - weak_factory_.GetWeakPtr(), key)); + weak_factory_.GetWeakPtr(), key, + base::Passed(std::move(virtual_time_pauser)))); } void DOMStorageCachedArea::Clear(int connection_id, const GURL& page_url) { @@ -104,11 +116,14 @@ map_ = new DOMStorageMap(kPerStorageAreaQuota); // Ignore all mutations until OnClearComplete time. + blink::WebScopedVirtualTimePauser virtual_time_pauser = + renderer_scheduler_->CreateWebScopedVirtualTimePauser(); + virtual_time_pauser.PauseVirtualTime(true); ignore_all_mutations_ = true; - proxy_->ClearArea(connection_id, - page_url, + proxy_->ClearArea(connection_id, page_url, base::Bind(&DOMStorageCachedArea::OnClearComplete, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), + base::Passed(std::move(virtual_time_pauser)))); } void DOMStorageCachedArea::ApplyMutation( @@ -215,6 +230,7 @@ } void DOMStorageCachedArea::OnSetItemComplete(const base::string16& key, + blink::WebScopedVirtualTimePauser, bool success) { if (!success) { Reset(); @@ -227,8 +243,10 @@ ignore_key_mutations_.erase(found); } -void DOMStorageCachedArea::OnRemoveItemComplete(const base::string16& key, - bool success) { +void DOMStorageCachedArea::OnRemoveItemComplete( + const base::string16& key, + blink::WebScopedVirtualTimePauser, + bool success) { DCHECK(success); std::map<base::string16, int>::iterator found = ignore_key_mutations_.find(key); @@ -237,7 +255,8 @@ ignore_key_mutations_.erase(found); } -void DOMStorageCachedArea::OnClearComplete(bool success) { +void DOMStorageCachedArea::OnClearComplete(blink::WebScopedVirtualTimePauser, + bool success) { DCHECK(success); DCHECK(ignore_all_mutations_); ignore_all_mutations_ = false;
diff --git a/content/renderer/dom_storage/dom_storage_cached_area.h b/content/renderer/dom_storage/dom_storage_cached_area.h index be365c08..21a94968 100644 --- a/content/renderer/dom_storage/dom_storage_cached_area.h +++ b/content/renderer/dom_storage/dom_storage_cached_area.h
@@ -14,8 +14,15 @@ #include "base/memory/weak_ptr.h" #include "base/strings/nullable_string16.h" #include "content/common/content_export.h" +#include "third_party/WebKit/public/platform/WebScopedVirtualTimePauser.h" #include "url/gurl.h" +namespace blink { +namespace scheduler { +class RendererScheduler; +} +} // namespace blink + namespace content { class DOMStorageMap; @@ -32,7 +39,8 @@ public: DOMStorageCachedArea(int64_t namespace_id, const GURL& origin, - DOMStorageProxy* proxy); + DOMStorageProxy* proxy, + blink::scheduler::RendererScheduler* renderer_scheduler); int64_t namespace_id() const { return namespace_id_; } const GURL& origin() const { return origin_; } @@ -72,9 +80,15 @@ // mutation events from other processes from overwriting local // changes made after the mutation. void OnLoadComplete(bool success); - void OnSetItemComplete(const base::string16& key, bool success); - void OnClearComplete(bool success); - void OnRemoveItemComplete(const base::string16& key, bool success); + void OnSetItemComplete(const base::string16& key, + blink::WebScopedVirtualTimePauser virtual_time_pauser, + bool success); + void OnClearComplete(blink::WebScopedVirtualTimePauser virtual_time_pauser, + bool success); + void OnRemoveItemComplete( + const base::string16& key, + blink::WebScopedVirtualTimePauser virtual_time_pauser, + bool success); bool should_ignore_key_mutation(const base::string16& key) const { return ignore_key_mutations_.find(key) != ignore_key_mutations_.end(); @@ -87,6 +101,7 @@ GURL origin_; scoped_refptr<DOMStorageMap> map_; scoped_refptr<DOMStorageProxy> proxy_; + blink::scheduler::RendererScheduler* renderer_scheduler_; // NOT OWNED base::WeakPtrFactory<DOMStorageCachedArea> weak_factory_; };
diff --git a/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc b/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc index 46b3815e..8fd3746 100644 --- a/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc +++ b/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc
@@ -9,9 +9,11 @@ #include <list> #include "base/bind.h" +#include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "content/renderer/dom_storage/dom_storage_proxy.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h" namespace content { @@ -128,7 +130,11 @@ const base::string16 kValue; const GURL kPageUrl; - void SetUp() override { mock_proxy_ = new MockProxy(); } + void SetUp() override { + renderer_scheduler_ = + base::MakeUnique<blink::scheduler::FakeRendererScheduler>(); + mock_proxy_ = new MockProxy(); + } bool IsPrimed(DOMStorageCachedArea* cached_area) { return cached_area->map_.get(); @@ -154,13 +160,15 @@ } protected: + base::MessageLoop message_loop_; // Needed to construct a RendererScheduler. + std::unique_ptr<blink::scheduler::RendererScheduler> renderer_scheduler_; scoped_refptr<MockProxy> mock_proxy_; }; TEST_F(DOMStorageCachedAreaTest, Basics) { EXPECT_TRUE(mock_proxy_->HasOneRef()); - scoped_refptr<DOMStorageCachedArea> cached_area = - new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get()); + scoped_refptr<DOMStorageCachedArea> cached_area = new DOMStorageCachedArea( + kNamespaceId, kOrigin, mock_proxy_.get(), renderer_scheduler_.get()); EXPECT_EQ(kNamespaceId, cached_area->namespace_id()); EXPECT_EQ(kOrigin, cached_area->origin()); EXPECT_FALSE(mock_proxy_->HasOneRef()); @@ -184,8 +192,8 @@ TEST_F(DOMStorageCachedAreaTest, Getters) { const int kConnectionId = 7; - scoped_refptr<DOMStorageCachedArea> cached_area = - new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get()); + scoped_refptr<DOMStorageCachedArea> cached_area = new DOMStorageCachedArea( + kNamespaceId, kOrigin, mock_proxy_.get(), renderer_scheduler_.get()); // GetLength, we expect to see one call to load in the proxy. EXPECT_FALSE(IsPrimed(cached_area.get())); @@ -219,8 +227,8 @@ TEST_F(DOMStorageCachedAreaTest, Setters) { const int kConnectionId = 7; - scoped_refptr<DOMStorageCachedArea> cached_area = - new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get()); + scoped_refptr<DOMStorageCachedArea> cached_area = new DOMStorageCachedArea( + kNamespaceId, kOrigin, mock_proxy_.get(), renderer_scheduler_.get()); // SetItem, we expect a call to load followed by a call to set item // in the proxy. @@ -274,8 +282,8 @@ TEST_F(DOMStorageCachedAreaTest, MutationsAreIgnoredUntilLoadCompletion) { const int kConnectionId = 7; - scoped_refptr<DOMStorageCachedArea> cached_area = - new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get()); + scoped_refptr<DOMStorageCachedArea> cached_area = new DOMStorageCachedArea( + kNamespaceId, kOrigin, mock_proxy_.get(), renderer_scheduler_.get()); EXPECT_TRUE(cached_area->GetItem(kConnectionId, kKey).is_null()); EXPECT_TRUE(IsPrimed(cached_area.get())); EXPECT_TRUE(IsIgnoringAllMutations(cached_area.get())); @@ -297,8 +305,8 @@ TEST_F(DOMStorageCachedAreaTest, MutationsAreIgnoredUntilClearCompletion) { const int kConnectionId = 4; - scoped_refptr<DOMStorageCachedArea> cached_area = - new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get()); + scoped_refptr<DOMStorageCachedArea> cached_area = new DOMStorageCachedArea( + kNamespaceId, kOrigin, mock_proxy_.get(), renderer_scheduler_.get()); cached_area->Clear(kConnectionId, kPageUrl); EXPECT_TRUE(IsIgnoringAllMutations(cached_area.get())); mock_proxy_->CompleteOnePendingCallback(true); @@ -319,8 +327,8 @@ TEST_F(DOMStorageCachedAreaTest, KeyMutationsAreIgnoredUntilCompletion) { const int kConnectionId = 8; - scoped_refptr<DOMStorageCachedArea> cached_area = - new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get()); + scoped_refptr<DOMStorageCachedArea> cached_area = new DOMStorageCachedArea( + kNamespaceId, kOrigin, mock_proxy_.get(), renderer_scheduler_.get()); // SetItem EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
diff --git a/content/renderer/dom_storage/dom_storage_dispatcher.cc b/content/renderer/dom_storage/dom_storage_dispatcher.cc index 102f8416..797e8a6 100644 --- a/content/renderer/dom_storage/dom_storage_dispatcher.cc +++ b/content/renderer/dom_storage/dom_storage_dispatcher.cc
@@ -196,8 +196,9 @@ ++(holder->open_count_); return holder->area_.get(); } - scoped_refptr<DOMStorageCachedArea> area = - new DOMStorageCachedArea(namespace_id, origin, this); + scoped_refptr<DOMStorageCachedArea> area = new DOMStorageCachedArea( + namespace_id, origin, this, + content::RenderThreadImpl::current()->GetRendererScheduler()); cached_areas_[key] = CachedAreaHolder(area.get(), 1); return area.get(); }
diff --git a/content/renderer/dom_storage/local_storage_cached_area.cc b/content/renderer/dom_storage/local_storage_cached_area.cc index ee84f52..9fee073 100644 --- a/content/renderer/dom_storage/local_storage_cached_area.cc +++ b/content/renderer/dom_storage/local_storage_cached_area.cc
@@ -16,6 +16,7 @@ #include "content/common/storage_partition_service.mojom.h" #include "content/renderer/dom_storage/local_storage_area.h" #include "content/renderer/dom_storage/local_storage_cached_areas.h" +#include "content/renderer/render_thread_impl.h" #include "mojo/public/cpp/bindings/strong_associated_binding.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/web/WebStorageEventDispatcher.h" @@ -67,11 +68,36 @@ } LocalStorageCachedArea::LocalStorageCachedArea( + int64_t namespace_id, const url::Origin& origin, mojom::StoragePartitionService* storage_partition_service, - LocalStorageCachedAreas* cached_areas) - : origin_(origin), binding_(this), - cached_areas_(cached_areas), weak_factory_(this) { + LocalStorageCachedAreas* cached_areas, + blink::scheduler::RendererScheduler* renderer_scheduler) + : namespace_id_(namespace_id), + origin_(origin), + binding_(this), + cached_areas_(cached_areas), + renderer_scheduler_(renderer_scheduler), + weak_factory_(this) { + DCHECK_NE(namespace_id, kInvalidSessionStorageNamespaceId); + storage_partition_service->OpenSessionStorage(namespace_id, origin_, + mojo::MakeRequest(&leveldb_)); + mojom::LevelDBObserverAssociatedPtrInfo ptr_info; + binding_.Bind(mojo::MakeRequest(&ptr_info)); + leveldb_->AddObserver(std::move(ptr_info)); +} + +LocalStorageCachedArea::LocalStorageCachedArea( + const url::Origin& origin, + mojom::StoragePartitionService* storage_partition_service, + LocalStorageCachedAreas* cached_areas, + blink::scheduler::RendererScheduler* renderer_scheduler) + : namespace_id_(kLocalStorageNamespaceId), + origin_(origin), + binding_(this), + cached_areas_(cached_areas), + renderer_scheduler_(renderer_scheduler), + weak_factory_(this) { storage_partition_service->OpenLocalStorage(origin_, mojo::MakeRequest(&leveldb_)); mojom::LevelDBObserverAssociatedPtrInfo ptr_info; @@ -122,10 +148,15 @@ base::Optional<std::vector<uint8_t>> optional_old_value; if (!old_nullable_value.is_null()) optional_old_value = String16ToUint8Vector(old_nullable_value.string()); + + blink::WebScopedVirtualTimePauser virtual_time_pauser = + renderer_scheduler_->CreateWebScopedVirtualTimePauser(); + virtual_time_pauser.PauseVirtualTime(true); leveldb_->Put(String16ToUint8Vector(key), String16ToUint8Vector(value), optional_old_value, PackSource(page_url, storage_area_id), base::BindOnce(&LocalStorageCachedArea::OnSetItemComplete, - weak_factory_.GetWeakPtr(), key)); + weak_factory_.GetWeakPtr(), key, + std::move(virtual_time_pauser))); return true; } @@ -147,10 +178,15 @@ base::Optional<std::vector<uint8_t>> optional_old_value; if (should_send_old_value_on_mutations_) optional_old_value = String16ToUint8Vector(old_value); + + blink::WebScopedVirtualTimePauser virtual_time_pauser = + renderer_scheduler_->CreateWebScopedVirtualTimePauser(); + virtual_time_pauser.PauseVirtualTime(true); leveldb_->Delete(String16ToUint8Vector(key), optional_old_value, PackSource(page_url, storage_area_id), base::BindOnce(&LocalStorageCachedArea::OnRemoveItemComplete, - weak_factory_.GetWeakPtr(), key)); + weak_factory_.GetWeakPtr(), key, + std::move(virtual_time_pauser))); } void LocalStorageCachedArea::Clear(const GURL& page_url, @@ -159,9 +195,14 @@ Reset(); map_ = new DOMStorageMap(kPerStorageAreaQuota); ignore_all_mutations_ = true; + + blink::WebScopedVirtualTimePauser virtual_time_pauser = + renderer_scheduler_->CreateWebScopedVirtualTimePauser(); + virtual_time_pauser.PauseVirtualTime(true); leveldb_->DeleteAll(PackSource(page_url, storage_area_id), base::BindOnce(&LocalStorageCachedArea::OnClearComplete, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), + std::move(virtual_time_pauser))); } void LocalStorageCachedArea::AreaCreated(LocalStorageArea* area) { @@ -387,8 +428,10 @@ } } -void LocalStorageCachedArea::OnSetItemComplete(const base::string16& key, - bool success) { +void LocalStorageCachedArea::OnSetItemComplete( + const base::string16& key, + blink::WebScopedVirtualTimePauser, + bool success) { if (!success) { Reset(); return; @@ -401,7 +444,9 @@ } void LocalStorageCachedArea::OnRemoveItemComplete( - const base::string16& key, bool success) { + const base::string16& key, + blink::WebScopedVirtualTimePauser, + bool success) { DCHECK(success); auto found = ignore_key_mutations_.find(key); DCHECK(found != ignore_key_mutations_.end()); @@ -409,7 +454,8 @@ ignore_key_mutations_.erase(found); } -void LocalStorageCachedArea::OnClearComplete(bool success) { +void LocalStorageCachedArea::OnClearComplete(blink::WebScopedVirtualTimePauser, + bool success) { DCHECK(success); DCHECK(ignore_all_mutations_); ignore_all_mutations_ = false;
diff --git a/content/renderer/dom_storage/local_storage_cached_area.h b/content/renderer/dom_storage/local_storage_cached_area.h index 0289e4a1..dc19eff 100644 --- a/content/renderer/dom_storage/local_storage_cached_area.h +++ b/content/renderer/dom_storage/local_storage_cached_area.h
@@ -14,9 +14,16 @@ #include "content/common/dom_storage/dom_storage_map.h" #include "content/common/leveldb_wrapper.mojom.h" #include "mojo/public/cpp/bindings/associated_binding.h" +#include "third_party/WebKit/public/platform/WebScopedVirtualTimePauser.h" #include "url/gurl.h" #include "url/origin.h" +namespace blink { +namespace scheduler { +class RendererScheduler; +} +} // namespace blink + namespace content { class LocalStorageArea; class LocalStorageCachedAreas; @@ -33,14 +40,22 @@ // callbacks. // There is one LocalStorageCachedArea for potentially many LocalStorageArea // objects. +// TODO(dmurph): Rename to remove LocalStorage. class CONTENT_EXPORT LocalStorageCachedArea : public mojom::LevelDBObserver, public base::RefCounted<LocalStorageCachedArea> { public: LocalStorageCachedArea( + int64_t namespace_id, const url::Origin& origin, mojom::StoragePartitionService* storage_partition_service, - LocalStorageCachedAreas* cached_areas); + LocalStorageCachedAreas* cached_areas, + blink::scheduler::RendererScheduler* renderer_schedule); + LocalStorageCachedArea( + const url::Origin& origin, + mojom::StoragePartitionService* storage_partition_service, + LocalStorageCachedAreas* cached_areas, + blink::scheduler::RendererScheduler* renderer_schedule); // These correspond to blink::WebStorageArea. unsigned GetLength(); @@ -60,6 +75,7 @@ void AreaCreated(LocalStorageArea* area); void AreaDestroyed(LocalStorageArea* area); + int64_t namespace_id() { return namespace_id_; } const url::Origin& origin() { return origin_; } size_t memory_used() const { return map_ ? map_->memory_used() : 0; } @@ -99,14 +115,21 @@ // fetched already. void EnsureLoaded(); - void OnSetItemComplete(const base::string16& key, bool success); - void OnRemoveItemComplete(const base::string16& key, bool success); - void OnClearComplete(bool success); + void OnSetItemComplete(const base::string16& key, + blink::WebScopedVirtualTimePauser virtual_time_pauser, + bool success); + void OnRemoveItemComplete( + const base::string16& key, + blink::WebScopedVirtualTimePauser virtual_time_pauser, + bool success); + void OnClearComplete(blink::WebScopedVirtualTimePauser virtual_time_pauser, + bool success); void OnGetAllComplete(bool success); // Resets the object back to its newly constructed state. void Reset(); + int64_t namespace_id_; url::Origin origin_; scoped_refptr<DOMStorageMap> map_; std::map<base::string16, int> ignore_key_mutations_; @@ -117,6 +140,7 @@ mojo::AssociatedBinding<mojom::LevelDBObserver> binding_; LocalStorageCachedAreas* cached_areas_; std::map<std::string, LocalStorageArea*> areas_; + blink::scheduler::RendererScheduler* renderer_scheduler_; // NOT OWNED base::WeakPtrFactory<LocalStorageCachedArea> weak_factory_; DISALLOW_COPY_AND_ASSIGN(LocalStorageCachedArea);
diff --git a/content/renderer/dom_storage/local_storage_cached_area_unittest.cc b/content/renderer/dom_storage/local_storage_cached_area_unittest.cc index 4ad21a0..072ce064 100644 --- a/content/renderer/dom_storage/local_storage_cached_area_unittest.cc +++ b/content/renderer/dom_storage/local_storage_cached_area_unittest.cc
@@ -15,6 +15,7 @@ #include "content/renderer/dom_storage/local_storage_cached_areas.h" #include "content/renderer/dom_storage/mock_leveldb_wrapper.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h" namespace content { @@ -27,7 +28,8 @@ kPageUrl("http://dom_storage/page"), kStorageAreaId("7"), kSource(kPageUrl.spec() + "\n" + kStorageAreaId), - cached_areas_(&mock_leveldb_wrapper_) {} + renderer_scheduler_(new blink::scheduler::FakeRendererScheduler()), + cached_areas_(&mock_leveldb_wrapper_, renderer_scheduler_.get()) {} const url::Origin kOrigin; const base::string16 kKey; @@ -73,6 +75,7 @@ protected: TestBrowserThreadBundle test_browser_thread_bundle_; MockLevelDBWrapper mock_leveldb_wrapper_; + std::unique_ptr<blink::scheduler::RendererScheduler> renderer_scheduler_; LocalStorageCachedAreas cached_areas_; };
diff --git a/content/renderer/dom_storage/local_storage_cached_areas.cc b/content/renderer/dom_storage/local_storage_cached_areas.cc index 8f0ef74..a9e4728 100644 --- a/content/renderer/dom_storage/local_storage_cached_areas.cc +++ b/content/renderer/dom_storage/local_storage_cached_areas.cc
@@ -6,7 +6,9 @@ #include "base/metrics/histogram_macros.h" #include "base/sys_info.h" +#include "content/common/dom_storage/dom_storage_types.h" #include "content/renderer/dom_storage/local_storage_cached_area.h" +#include "content/renderer/render_thread_impl.h" namespace content { namespace { @@ -15,47 +17,26 @@ } // namespace LocalStorageCachedAreas::LocalStorageCachedAreas( - mojom::StoragePartitionService* storage_partition_service) + mojom::StoragePartitionService* storage_partition_service, + blink::scheduler::RendererScheduler* renderer_scheduler) : storage_partition_service_(storage_partition_service), total_cache_limit_(base::SysInfo::IsLowEndDevice() ? kTotalCacheLimitInBytesLowEnd - : kTotalCacheLimitInBytes) {} + : kTotalCacheLimitInBytes), + renderer_scheduler_(renderer_scheduler) {} LocalStorageCachedAreas::~LocalStorageCachedAreas() {} scoped_refptr<LocalStorageCachedArea> LocalStorageCachedAreas::GetCachedArea( const url::Origin& origin) { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - enum class CacheMetrics { - kMiss = 0, // Area not in cache. - kHit = 1, // Area with refcount = 0 loaded from cache. - kUnused = 2, // Cache was not used. Area had refcount > 0. - kMaxValue - }; + return GetCachedArea(kLocalStorageNamespaceId, origin, renderer_scheduler_); +} - auto it = cached_areas_.find(origin); - if (it != cached_areas_.end()) { - if (it->second->HasOneRef()) { - UMA_HISTOGRAM_ENUMERATION("LocalStorage.RendererAreaCacheHit", - CacheMetrics::kHit, CacheMetrics::kMaxValue); - } else { - UMA_HISTOGRAM_ENUMERATION("LocalStorage.RendererAreaCacheHit", - CacheMetrics::kUnused, CacheMetrics::kMaxValue); - } - } else { - UMA_HISTOGRAM_ENUMERATION("LocalStorage.RendererAreaCacheHit", - CacheMetrics::kMiss, CacheMetrics::kMaxValue); - } - - if (it == cached_areas_.end()) { - ClearAreasIfNeeded(); - it = cached_areas_ - .emplace(origin, new LocalStorageCachedArea( - origin, storage_partition_service_, this)) - .first; - } - return it->second; +scoped_refptr<LocalStorageCachedArea> +LocalStorageCachedAreas::GetSessionStorageArea(int64_t namespace_id, + const url::Origin& origin) { + DCHECK_NE(kLocalStorageNamespaceId, kInvalidSessionStorageNamespaceId); + return GetCachedArea(namespace_id, origin, renderer_scheduler_); } size_t LocalStorageCachedAreas::TotalCacheSize() const { @@ -77,4 +58,53 @@ } } +scoped_refptr<LocalStorageCachedArea> LocalStorageCachedAreas::GetCachedArea( + int64_t namespace_id, + const url::Origin& origin, + blink::scheduler::RendererScheduler* scheduler) { + AreaKey key(namespace_id, origin); + + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class CacheMetrics { + kMiss = 0, // Area not in cache. + kHit = 1, // Area with refcount = 0 loaded from cache. + kUnused = 2, // Cache was not used. Area had refcount > 0. + kMaxValue + }; + + auto it = cached_areas_.find(key); + CacheMetrics metric; + if (it != cached_areas_.end()) { + if (it->second->HasOneRef()) { + metric = CacheMetrics::kHit; + } else { + metric = CacheMetrics::kUnused; + } + } else { + metric = CacheMetrics::kMiss; + } + if (namespace_id == kLocalStorageNamespaceId) { + UMA_HISTOGRAM_ENUMERATION("LocalStorage.RendererAreaCacheHit", metric, + CacheMetrics::kMaxValue); + } else { + LOCAL_HISTOGRAM_ENUMERATION("SessionStorage.RendererAreaCacheHit", metric, + CacheMetrics::kMaxValue); + } + + if (it == cached_areas_.end()) { + ClearAreasIfNeeded(); + scoped_refptr<LocalStorageCachedArea> area; + if (namespace_id == kLocalStorageNamespaceId) { + area = base::MakeRefCounted<LocalStorageCachedArea>( + origin, storage_partition_service_, this, scheduler); + } else { + area = base::MakeRefCounted<LocalStorageCachedArea>( + namespace_id, origin, storage_partition_service_, this, scheduler); + } + it = cached_areas_.emplace(key, std::move(area)).first; + } + return it->second; +} + } // namespace content
diff --git a/content/renderer/dom_storage/local_storage_cached_areas.h b/content/renderer/dom_storage/local_storage_cached_areas.h index 9bce97c6..37e7ef8 100644 --- a/content/renderer/dom_storage/local_storage_cached_areas.h +++ b/content/renderer/dom_storage/local_storage_cached_areas.h
@@ -12,6 +12,12 @@ #include "content/common/content_export.h" #include "url/origin.h" +namespace blink { +namespace scheduler { +class RendererScheduler; +} +} // namespace blink + namespace content { class LocalStorageCachedArea; @@ -23,16 +29,22 @@ // needed because we can have n LocalStorageArea objects for the same origin but // we want just one LocalStorageCachedArea to service them (no point in having // multiple caches of the same data in the same process). +// TODO(dmurph): Rename to remove LocalStorage. class CONTENT_EXPORT LocalStorageCachedAreas { public: - explicit LocalStorageCachedAreas( - mojom::StoragePartitionService* storage_partition_service); + LocalStorageCachedAreas( + mojom::StoragePartitionService* storage_partition_service, + blink::scheduler::RendererScheduler* renderer_schedule); ~LocalStorageCachedAreas(); // Returns, creating if necessary, a cached storage area for the given origin. scoped_refptr<LocalStorageCachedArea> GetCachedArea(const url::Origin& origin); + scoped_refptr<LocalStorageCachedArea> GetSessionStorageArea( + int64_t namespace_id, + const url::Origin& origin); + size_t TotalCacheSize() const; void set_cache_limit_for_testing(size_t limit) { total_cache_limit_ = limit; } @@ -40,13 +52,22 @@ private: void ClearAreasIfNeeded(); + scoped_refptr<LocalStorageCachedArea> GetCachedArea( + int64_t namespace_id, + const url::Origin& origin, + blink::scheduler::RendererScheduler* scheduler); + mojom::StoragePartitionService* const storage_partition_service_; - // Maps from an origin to its LocalStorageCachedArea object. When this map is - // the only reference to the object, it can be deleted by the cache. - std::map<url::Origin, scoped_refptr<LocalStorageCachedArea>> cached_areas_; + // Maps from a namespace + origin to its LocalStorageCachedArea object. When + // this map is the only reference to the object, it can be deleted by the + // cache. + using AreaKey = std::pair<int64_t, url::Origin>; + std::map<AreaKey, scoped_refptr<LocalStorageCachedArea>> cached_areas_; size_t total_cache_limit_; + blink::scheduler::RendererScheduler* renderer_scheduler_; // NOT OWNED + DISALLOW_COPY_AND_ASSIGN(LocalStorageCachedAreas); };
diff --git a/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc b/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc index 92e4d28b..05c5866 100644 --- a/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc +++ b/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc
@@ -8,6 +8,7 @@ #include "base/test/scoped_task_environment.h" #include "content/renderer/dom_storage/local_storage_cached_area.h" #include "content/renderer/dom_storage/mock_leveldb_wrapper.h" +#include "third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h" namespace content { @@ -24,8 +25,11 @@ const std::string kStorageAreaId("7"); const size_t kCacheLimit = 100; + blink::scheduler::FakeRendererScheduler renderer_scheduler; + MockLevelDBWrapper mock_leveldb_wrapper; - LocalStorageCachedAreas cached_areas(&mock_leveldb_wrapper); + LocalStorageCachedAreas cached_areas(&mock_leveldb_wrapper, + &renderer_scheduler); cached_areas.set_cache_limit_for_testing(kCacheLimit); scoped_refptr<LocalStorageCachedArea> cached_area1 =
diff --git a/content/renderer/dom_storage/mock_leveldb_wrapper.cc b/content/renderer/dom_storage/mock_leveldb_wrapper.cc index 3e6b1a7c..8addc773 100644 --- a/content/renderer/dom_storage/mock_leveldb_wrapper.cc +++ b/content/renderer/dom_storage/mock_leveldb_wrapper.cc
@@ -15,6 +15,13 @@ bindings_.AddBinding(this, std::move(database)); } +void MockLevelDBWrapper::OpenSessionStorage( + int64_t namespace_id, + const url::Origin& origin, + mojom::LevelDBWrapperRequest database) { + bindings_.AddBinding(this, std::move(database)); +} + void MockLevelDBWrapper::AddObserver( mojom::LevelDBObserverAssociatedPtrInfo observer) {}
diff --git a/content/renderer/dom_storage/mock_leveldb_wrapper.h b/content/renderer/dom_storage/mock_leveldb_wrapper.h index 25b28d92..268da9a 100644 --- a/content/renderer/dom_storage/mock_leveldb_wrapper.h +++ b/content/renderer/dom_storage/mock_leveldb_wrapper.h
@@ -22,6 +22,9 @@ // StoragePartitionService implementation: void OpenLocalStorage(const url::Origin& origin, mojom::LevelDBWrapperRequest database) override; + void OpenSessionStorage(int64_t namespace_id, + const url::Origin& origin, + mojom::LevelDBWrapperRequest database) override; // LevelDBWrapper implementation: void AddObserver(mojom::LevelDBObserverAssociatedPtrInfo observer) override;
diff --git a/content/renderer/dom_storage/session_web_storage_namespace_impl.cc b/content/renderer/dom_storage/session_web_storage_namespace_impl.cc new file mode 100644 index 0000000..12843e3 --- /dev/null +++ b/content/renderer/dom_storage/session_web_storage_namespace_impl.cc
@@ -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. + +#include "content/renderer/dom_storage/session_web_storage_namespace_impl.h" + +#include "content/renderer/dom_storage/local_storage_area.h" +#include "content/renderer/dom_storage/local_storage_cached_areas.h" +#include "third_party/WebKit/public/platform/URLConversion.h" +#include "third_party/WebKit/public/platform/WebURL.h" +#include "url/gurl.h" +#include "url/origin.h" + +using blink::WebStorageArea; +using blink::WebStorageNamespace; + +namespace content { + +SessionWebStorageNamespaceImpl::SessionWebStorageNamespaceImpl( + int64_t namespace_id, + LocalStorageCachedAreas* local_storage_cached_areas) + : namespace_id_(namespace_id), + local_storage_cached_areas_(local_storage_cached_areas) {} + +SessionWebStorageNamespaceImpl::~SessionWebStorageNamespaceImpl() {} + +WebStorageArea* SessionWebStorageNamespaceImpl::CreateStorageArea( + const blink::WebSecurityOrigin& origin) { + return new LocalStorageArea( + local_storage_cached_areas_->GetSessionStorageArea(namespace_id_, + origin)); +} + +bool SessionWebStorageNamespaceImpl::IsSameNamespace( + const WebStorageNamespace& other) const { + const SessionWebStorageNamespaceImpl* other_impl = + static_cast<const SessionWebStorageNamespaceImpl*>(&other); + return namespace_id_ == other_impl->namespace_id_; +} + +} // namespace content
diff --git a/content/renderer/dom_storage/session_web_storage_namespace_impl.h b/content/renderer/dom_storage/session_web_storage_namespace_impl.h new file mode 100644 index 0000000..9c3df88 --- /dev/null +++ b/content/renderer/dom_storage/session_web_storage_namespace_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_DOM_STORAGE_SESSION_WEB_STORAGE_NAMESPACE_IMPL_H_ +#define CONTENT_RENDERER_DOM_STORAGE_SESSION_WEB_STORAGE_NAMESPACE_IMPL_H_ + +#include "base/macros.h" +#include "third_party/WebKit/public/platform/WebSecurityOrigin.h" +#include "third_party/WebKit/public/platform/WebStorageNamespace.h" + +namespace content { +class LocalStorageCachedAreas; + +class SessionWebStorageNamespaceImpl : public blink::WebStorageNamespace { + public: + // |local_storage_cached_areas| is guaranteed to outlive this object. + SessionWebStorageNamespaceImpl( + int64_t namespace_id, + LocalStorageCachedAreas* local_storage_cached_areas); + ~SessionWebStorageNamespaceImpl() override; + + // blink::WebStorageNamespace: + blink::WebStorageArea* CreateStorageArea( + const blink::WebSecurityOrigin& origin) override; + bool IsSameNamespace(const WebStorageNamespace&) const override; + + private: + int64_t namespace_id_; + LocalStorageCachedAreas* const local_storage_cached_areas_; + + DISALLOW_COPY_AND_ASSIGN(SessionWebStorageNamespaceImpl); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_DOM_STORAGE_SESSION_WEB_STORAGE_NAMESPACE_IMPL_H_
diff --git a/content/renderer/pepper/pepper_compositor_host.cc b/content/renderer/pepper/pepper_compositor_host.cc index 950a90ed..4149dd7 100644 --- a/content/renderer/pepper/pepper_compositor_host.cc +++ b/content/renderer/pepper/pepper_compositor_host.cc
@@ -280,11 +280,11 @@ static_cast<cc::TextureLayer*>(layer.get())); if (!old_layer || new_layer->common.resource_id != old_layer->common.resource_id) { - viz::TextureMailbox mailbox(new_layer->texture->mailbox, - new_layer->texture->sync_token, - new_layer->texture->target); - texture_layer->SetTextureMailbox( - mailbox, + auto resource = viz::TransferableResource::MakeGL( + new_layer->texture->mailbox, GL_LINEAR, new_layer->texture->target, + new_layer->texture->sync_token); + texture_layer->SetTransferableResource( + resource, viz::SingleReleaseCallback::Create(base::Bind( &PepperCompositorHost::ResourceReleased, weak_factory_.GetWeakPtr(), new_layer->common.resource_id))); @@ -318,9 +318,10 @@ ->shared_bitmap_manager() ->GetBitmapForSharedMemory(image_shm.get()); - viz::TextureMailbox mailbox(bitmap.get(), PP_ToGfxSize(desc.size)); - image_layer->SetTextureMailbox( - mailbox, + auto resource = viz::TransferableResource::MakeSoftware( + bitmap->id(), bitmap->sequence_number(), PP_ToGfxSize(desc.size)); + image_layer->SetTransferableResource( + resource, viz::SingleReleaseCallback::Create(base::Bind( &PepperCompositorHost::ImageReleased, weak_factory_.GetWeakPtr(), new_layer->common.resource_id, base::Passed(&image_shm),
diff --git a/content/renderer/pepper/pepper_graphics_2d_host.cc b/content/renderer/pepper/pepper_graphics_2d_host.cc index 8e8bd9a..adb3424 100644 --- a/content/renderer/pepper/pepper_graphics_2d_host.cc +++ b/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -20,7 +20,6 @@ #include "components/viz/client/client_shared_bitmap_manager.h" #include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/quads/shared_bitmap.h" -#include "components/viz/common/quads/texture_mailbox.h" #include "content/public/renderer/render_thread.h" #include "content/public/renderer/renderer_ppapi_host.h" #include "content/renderer/pepper/gfx_conversion.h" @@ -193,8 +192,7 @@ offscreen_flush_pending_(false), is_always_opaque_(false), scale_(1.0f), - is_running_in_process_(host->IsRunningInProcess()), - texture_mailbox_modified_(true) {} + is_running_in_process_(host->IsRunningInProcess()) {} PepperGraphics2DHost::~PepperGraphics2DHost() { // Delete textures owned by PepperGraphics2DHost, but not those sent to the @@ -324,7 +322,7 @@ } cached_bitmap_.reset(); - texture_mailbox_modified_ = true; + composited_output_modified_ = true; bound_instance_ = new_instance; return true; @@ -603,8 +601,8 @@ context->ContextGL()->DeleteTextures(1, &id); } -bool PepperGraphics2DHost::PrepareTextureMailbox( - viz::TextureMailbox* mailbox, +bool PepperGraphics2DHost::PrepareTransferableResource( + viz::TransferableResource* transferable_resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback) { // Reuse the |main_thread_context_| if it is not lost. If it is lost, we // can't reuse the texture ids, they are invalid. If the compositing mode @@ -625,12 +623,12 @@ } else { // Just switched to software compositing. Force us to send the // frame to the compositor again even if not changed. - texture_mailbox_modified_ = true; + composited_output_modified_ = true; } } } - if (!texture_mailbox_modified_) + if (!composited_output_modified_) return false; // Context creation failed, so we're unable to give this frame to the @@ -694,7 +692,9 @@ gl->BindTexture(GL_TEXTURE_2D, 0); - *mailbox = viz::TextureMailbox(gpu_mailbox, sync_token, GL_TEXTURE_2D); + *transferable_resource = + viz::TransferableResource::MakeGL(std::move(gpu_mailbox), GL_LINEAR, + GL_TEXTURE_2D, std::move(sync_token)); *release_callback = viz::SingleReleaseCallback::Create( base::Bind(&ReleaseTextureCallback, this->AsWeakPtr(), main_thread_context_, texture_id)); @@ -721,16 +721,17 @@ viz::SharedBitmap::CheckedSizeInBytes(pixel_image_size)); image_data_->Unmap(); - *mailbox = viz::TextureMailbox(shared_bitmap.get(), pixel_image_size); + *transferable_resource = viz::TransferableResource::MakeSoftware( + shared_bitmap->id(), shared_bitmap->sequence_number(), pixel_image_size); *release_callback = viz::SingleReleaseCallback::Create(base::Bind( &PepperGraphics2DHost::ReleaseSoftwareCallback, this->AsWeakPtr(), base::Passed(&shared_bitmap), pixel_image_size)); - texture_mailbox_modified_ = false; + composited_output_modified_ = false; return true; } void PepperGraphics2DHost::AttachedToNewLayer() { - texture_mailbox_modified_ = true; + composited_output_modified_ = true; } int32_t PepperGraphics2DHost::Flush(PP_Resource* old_image_data) { @@ -809,7 +810,7 @@ if (!op_rect_in_viewport.IsEmpty()) bound_instance_->InvalidateRect(op_rect_in_viewport); } - texture_mailbox_modified_ = true; + composited_output_modified_ = true; } } queued_operations_.clear();
diff --git a/content/renderer/pepper/pepper_graphics_2d_host.h b/content/renderer/pepper/pepper_graphics_2d_host.h index 0edb0f27..0184f5f1 100644 --- a/content/renderer/pepper/pepper_graphics_2d_host.h +++ b/content/renderer/pepper/pepper_graphics_2d_host.h
@@ -34,7 +34,7 @@ class ContextProvider; class SharedBitmap; class SingleReleaseCallback; -class TextureMailbox; +struct TransferableResource; } namespace content { @@ -74,8 +74,8 @@ const gfx::Rect& plugin_rect, const gfx::Rect& paint_rect); - bool PrepareTextureMailbox( - viz::TextureMailbox* mailbox, + bool PrepareTransferableResource( + viz::TransferableResource* transferable_resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback); void AttachedToNewLayer(); @@ -223,7 +223,7 @@ bool is_running_in_process_; - bool texture_mailbox_modified_; + bool composited_output_modified_ = true; // Local cache of the compositing mode. This is sticky, once true it stays // that way.
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index 05efb06..033cd42 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -774,15 +774,16 @@ } } -void PepperPluginInstanceImpl::CommitTextureMailbox( - const viz::TextureMailbox& texture_mailbox) { - if (committed_texture_.IsValid() && !IsTextureInUse(committed_texture_)) { +void PepperPluginInstanceImpl::CommitTransferableResource( + const viz::TransferableResource& resource) { + if (!committed_texture_.mailbox_holder.mailbox.IsZero() && + !IsTextureInUse(committed_texture_)) { committed_texture_graphics_3d_->ReturnFrontBuffer( - committed_texture_.mailbox(), committed_texture_consumed_sync_token_, - false); + committed_texture_.mailbox_holder.mailbox, + committed_texture_consumed_sync_token_, false); } - committed_texture_ = texture_mailbox; + committed_texture_ = resource; committed_texture_graphics_3d_ = bound_graphics_3d_; committed_texture_consumed_sync_token_ = gpu::SyncToken(); @@ -798,7 +799,7 @@ void PepperPluginInstanceImpl::PassCommittedTextureToTextureLayer() { DCHECK(bound_graphics_3d_); - if (!committed_texture_.IsValid()) + if (committed_texture_.mailbox_holder.mailbox.IsZero()) return; std::unique_ptr<viz::SingleReleaseCallback> callback( @@ -808,17 +809,18 @@ committed_texture_graphics_3d_))); IncrementTextureReferenceCount(committed_texture_); - texture_layer_->SetTextureMailbox(committed_texture_, std::move(callback)); + texture_layer_->SetTransferableResource(committed_texture_, + std::move(callback)); } void PepperPluginInstanceImpl::FinishedConsumingCommittedTexture( - const viz::TextureMailbox& texture_mailbox, + const viz::TransferableResource& resource, scoped_refptr<PPB_Graphics3D_Impl> graphics_3d, const gpu::SyncToken& sync_token, bool is_lost) { - bool removed = DecrementTextureReferenceCount(texture_mailbox); - bool is_committed_texture = - committed_texture_.mailbox() == texture_mailbox.mailbox(); + bool removed = DecrementTextureReferenceCount(resource); + bool is_committed_texture = committed_texture_.mailbox_holder.mailbox == + resource.mailbox_holder.mailbox; if (is_committed_texture && !is_lost) { committed_texture_consumed_sync_token_ = sync_token; @@ -826,7 +828,7 @@ } if (removed && !is_committed_texture) { - graphics_3d->ReturnFrontBuffer(texture_mailbox.mailbox(), sync_token, + graphics_3d->ReturnFrontBuffer(resource.mailbox_holder.mailbox, sync_token, is_lost); } } @@ -1918,59 +1920,50 @@ blink::WebCanvas* canvas) { #if BUILDFLAG(ENABLE_PRINTING) DCHECK(plugin_print_interface_); - PP_PrintPageNumberRange_Dev page_range; - page_range.first_page_number = page_range.last_page_number = page_number; - // The canvas only has a metafile on it for print preview. + + // |canvas| should always have an associated metafile. printing::PdfMetafileSkia* metafile = printing::MetafileSkiaWrapper::GetMetafileFromCanvas(canvas); - bool save_for_later = (metafile != nullptr); -#if defined(OS_MACOSX) - save_for_later = save_for_later && cc::IsPreviewMetafile(canvas); -#endif // defined(OS_MACOSX) - if (save_for_later) { - ranges_.push_back(page_range); - metafile_ = metafile; + DCHECK(metafile); + + // |ranges_| should be empty IFF |metafile_| is not set. + DCHECK_EQ(ranges_.empty(), !metafile_); + if (metafile_) { + // The metafile should be the same across all calls for a given print job. + DCHECK_EQ(metafile_, metafile); } else { - PrintPageHelper(&page_range, 1, metafile); + // Store |metafile| on the first call. + metafile_ = metafile; } + + PP_PrintPageNumberRange_Dev page_range = {page_number, page_number}; + ranges_.push_back(page_range); #endif } -void PepperPluginInstanceImpl::PrintPageHelper( - PP_PrintPageNumberRange_Dev* page_ranges, - int num_ranges, - printing::PdfMetafileSkia* metafile) { - // Keep a reference on the stack. See NOTE above. - scoped_refptr<PepperPluginInstanceImpl> ref(this); - DCHECK(plugin_print_interface_); - if (!plugin_print_interface_) - return; - PP_Resource print_output = plugin_print_interface_->PrintPages( - pp_instance(), page_ranges, num_ranges); - if (!print_output) - return; - - if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_PDF || - current_print_settings_.format == PP_PRINTOUTPUTFORMAT_RASTER) - PrintPDFOutput(print_output, metafile); - - // Now we need to release the print output resource. - PluginModule::GetCore()->ReleaseResource(print_output); -} - void PepperPluginInstanceImpl::PrintEnd() { // Keep a reference on the stack. See NOTE above. scoped_refptr<PepperPluginInstanceImpl> ref(this); DCHECK(plugin_print_interface_); if (!ranges_.empty()) { - PrintPageHelper(&(ranges_.front()), ranges_.size(), metafile_); + PP_Resource print_output = plugin_print_interface_->PrintPages( + pp_instance(), ranges_.data(), ranges_.size()); + if (print_output) { + if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_PDF || + current_print_settings_.format == PP_PRINTOUTPUTFORMAT_RASTER) { + PrintPDFOutput(print_output, metafile_); + } + + // Now release the print output resource. + PluginModule::GetCore()->ReleaseResource(print_output); + } + ranges_.clear(); metafile_ = nullptr; } plugin_print_interface_->End(pp_instance()); - memset(¤t_print_settings_, 0, sizeof(current_print_settings_)); } @@ -2201,13 +2194,13 @@ UpdateLayerTransform(); } -bool PepperPluginInstanceImpl::PrepareTextureMailbox( - viz::TextureMailbox* mailbox, +bool PepperPluginInstanceImpl::PrepareTransferableResource( + viz::TransferableResource* transferable_resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback) { if (!bound_graphics_2d_platform_) return false; - return bound_graphics_2d_platform_->PrepareTextureMailbox(mailbox, - release_callback); + return bound_graphics_2d_platform_->PrepareTransferableResource( + transferable_resource, release_callback); } void PepperPluginInstanceImpl::AccessibilityModeChanged() { @@ -3503,14 +3496,14 @@ } void PepperPluginInstanceImpl::IncrementTextureReferenceCount( - const viz::TextureMailbox& mailbox) { + const viz::TransferableResource& resource) { auto it = std::find_if(texture_ref_counts_.begin(), texture_ref_counts_.end(), - [&mailbox](const TextureMailboxRefCount& ref_count) { - return ref_count.first.mailbox() == mailbox.mailbox(); + [&resource](const TextureMailboxRefCount& ref_count) { + return ref_count.first == resource.mailbox_holder.mailbox; }); if (it == texture_ref_counts_.end()) { - texture_ref_counts_.push_back(std::make_pair(mailbox, 1)); + texture_ref_counts_.emplace_back(resource.mailbox_holder.mailbox, 1); return; } @@ -3518,11 +3511,11 @@ } bool PepperPluginInstanceImpl::DecrementTextureReferenceCount( - const viz::TextureMailbox& mailbox) { + const viz::TransferableResource& resource) { auto it = std::find_if(texture_ref_counts_.begin(), texture_ref_counts_.end(), - [&mailbox](const TextureMailboxRefCount& ref_count) { - return ref_count.first.mailbox() == mailbox.mailbox(); + [&resource](const TextureMailboxRefCount& ref_count) { + return ref_count.first == resource.mailbox_holder.mailbox; }); DCHECK(it != texture_ref_counts_.end()); @@ -3536,11 +3529,11 @@ } bool PepperPluginInstanceImpl::IsTextureInUse( - const viz::TextureMailbox& mailbox) const { + const viz::TransferableResource& resource) const { auto it = std::find_if(texture_ref_counts_.begin(), texture_ref_counts_.end(), - [&mailbox](const TextureMailboxRefCount& ref_count) { - return ref_count.first.mailbox() == mailbox.mailbox(); + [&resource](const TextureMailboxRefCount& ref_count) { + return ref_count.first == resource.mailbox_holder.mailbox; }); return it != texture_ref_counts_.end(); }
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.h b/content/renderer/pepper/pepper_plugin_instance_impl.h index 8ae3cbf7..66a78c20 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.h +++ b/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -25,7 +25,7 @@ #include "cc/layers/content_layer_client.h" #include "cc/layers/layer.h" #include "cc/layers/texture_layer_client.h" -#include "components/viz/common/quads/texture_mailbox.h" +#include "components/viz/common/resources/transferable_resource.h" #include "content/common/content_export.h" #include "content/public/renderer/pepper_plugin_instance.h" #include "content/public/renderer/plugin_instance_throttler.h" @@ -200,15 +200,15 @@ // slow path can also be triggered if there is an overlapping frame. void ScrollRect(int dx, int dy, const gfx::Rect& rect); - // Commit the texture mailbox to the screen. - void CommitTextureMailbox(const viz::TextureMailbox& texture_mailbox); + // Commit the output to the screen. + void CommitTransferableResource(const viz::TransferableResource& resource); // Passes the committed texture to |texture_layer_| and marks it as in use. void PassCommittedTextureToTextureLayer(); // Callback when the compositor is finished consuming the committed texture. void FinishedConsumingCommittedTexture( - const viz::TextureMailbox& texture_mailbox, + const viz::TransferableResource& resource, scoped_refptr<PPB_Graphics3D_Impl> graphics_3d, const gpu::SyncToken& sync_token, bool is_lost); @@ -558,8 +558,8 @@ bool IsValidInstanceOf(PluginModule* module); // cc::TextureLayerClient implementation. - bool PrepareTextureMailbox( - viz::TextureMailbox* mailbox, + bool PrepareTransferableResource( + viz::TransferableResource* transferable_resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override; // RenderFrameObserver @@ -675,11 +675,6 @@ // to the container. Set to true if the bound device has been changed. void UpdateLayer(bool force_creation); - // Internal helper function for PrintPage(). - void PrintPageHelper(PP_PrintPageNumberRange_Dev* page_ranges, - int num_ranges, - printing::PdfMetafileSkia* metafile); - void DoSetCursor(std::unique_ptr<blink::WebCursorInfo> cursor); // Internal helper functions for HandleCompositionXXX(). @@ -736,17 +731,19 @@ // to ensure that a viz::TextureMailbox isn't returned until all copies of it // have been released by texture_layer_. // - // This method should be called each time a viz::TextureMailbox is passed to - // |texture_layer_|. It increments an internal reference count. - void IncrementTextureReferenceCount(const viz::TextureMailbox& mailbox); + // This method should be called each time a viz::TransferableResource is + // passed to |texture_layer_|. It increments an internal reference count. + void IncrementTextureReferenceCount( + const viz::TransferableResource& resource); // This method should be called each time |texture_layer_| finishes consuming - // a viz::TextureMailbox. It decrements an internal reference count. Returns - // whether the last reference was removed. - bool DecrementTextureReferenceCount(const viz::TextureMailbox& mailbox); + // a viz::TransferableResource. It decrements an internal reference count. + // Returns whether the last reference was removed. + bool DecrementTextureReferenceCount( + const viz::TransferableResource& resource); - // Whether a given viz::TextureMailbox is in use by |texture_layer_|. - bool IsTextureInUse(const viz::TextureMailbox& mailbox) const; + // Whether a given viz::TransferableResource is in use by |texture_layer_|. + bool IsTextureInUse(const viz::TransferableResource& resource) const; RenderFrameImpl* render_frame_; scoped_refptr<PluginModule> module_; @@ -841,13 +838,11 @@ // call. PP_PrintSettings_Dev current_print_settings_; - // Always when printing to PDF on Linux and when printing for preview on Mac - // and Win, the entire document goes into one metafile. However, when users - // print only a subset of all the pages, it is impossible to know if a call - // to PrintPage() is the last call. Thus in PrintPage(), just store the page - // number in |ranges_|. The hack is in PrintEnd(), where a valid |metafile_| - // is preserved in PrintWebFrameHelper::PrintPages. This makes it possible - // to generate the entire PDF given the variables below: + // The entire document goes into one metafile. However, it is impossible to + // know if a call to PrintPage() is the last call. Thus in PrintPage(), just + // store the page number in |ranges_|. The hack is in PrintEnd(), where a + // valid |metafile_| is preserved in PrintWebFrameHelper::PrintPages(). This + // makes it possible to generate the entire PDF given the variables below: // // The metafile to save into, which is guaranteed to be valid between a // successful PrintBegin call and a PrintEnd call. @@ -969,7 +964,7 @@ // The most recently committed texture. This is kept around in case the layer // needs to be regenerated. - viz::TextureMailbox committed_texture_; + viz::TransferableResource committed_texture_; // The Graphics3D that produced the most recently committed texture. scoped_refptr<PPB_Graphics3D_Impl> committed_texture_graphics_3d_; @@ -980,7 +975,7 @@ // viz::TextureMailbox. // We expect there to be no more than 10 textures in use at a time. A // std::vector will have better performance than a std::map. - using TextureMailboxRefCount = std::pair<viz::TextureMailbox, int>; + using TextureMailboxRefCount = std::pair<gpu::Mailbox, int>; std::vector<TextureMailboxRefCount> texture_ref_counts_; bool initialized_;
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc index e73ae24ce..f59d980 100644 --- a/content/renderer/pepper/ppb_graphics_3d_impl.cc +++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -185,19 +185,20 @@ // Don't need to check for NULL from GetPluginInstance since when we're // bound, we know our instance is valid. bool is_overlay_candidate = use_image_chromium_; - viz::TextureMailbox texture_mailbox( - taken_front_buffer_, sync_token, -// TODO(reveman): Get texture target from browser process. + // TODO(reveman): Get texture target from browser process. + uint32_t target = GL_TEXTURE_2D; #if defined(OS_MACOSX) - use_image_chromium_ ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, -#else - GL_TEXTURE_2D, + if (use_image_chromium_) + target = GL_TEXTURE_RECTANGLE_ARB; #endif - size, is_overlay_candidate); + viz::TransferableResource resource = + viz::TransferableResource::MakeGLOverlay(taken_front_buffer_, GL_LINEAR, + target, sync_token, size, + is_overlay_candidate); taken_front_buffer_.SetZero(); HostGlobals::Get() ->GetInstance(pp_instance()) - ->CommitTextureMailbox(texture_mailbox); + ->CommitTransferableResource(resource); commit_pending_ = true; } else { // Wait for the command to complete on the GPU to allow for throttling.
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index dd308d9..ff71be2 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -4825,6 +4825,10 @@ observer.DidObserveNewFeatureUsage(feature); } +bool RenderFrameImpl::ShouldTrackUseCounter(const blink::WebURL& url) { + return GetContentClient()->renderer()->ShouldTrackUseCounter(url); +} + void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context, int world_id) { if ((enabled_bindings_ & BINDINGS_POLICY_WEB_UI) && IsMainFrame() &&
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 0dab20e3..89735fb 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -674,6 +674,7 @@ void DidObserveLoadingBehavior( blink::WebLoadingBehaviorFlag behavior) override; void DidObserveNewFeatureUsage(blink::mojom::WebFeature feature) override; + bool ShouldTrackUseCounter(const blink::WebURL& url) override; void DidCreateScriptContext(v8::Local<v8::Context> context, int world_id) override; void WillReleaseScriptContext(v8::Local<v8::Context> context,
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 5540c399..97f031fc 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -467,6 +467,12 @@ base::Unretained(this), "Debugger.resume", "{\"id\":100,\"method\":\"Debugger.resume\"}")); } + + if (notification == "Page.windowOpen") { + window_open_notification_ = + base::WrapUnique(static_cast<base::DictionaryValue*>( + base::JSONReader::Read(message).release())); + } } } @@ -488,6 +494,10 @@ call_frames_count_ = call_frames_count; } + base::DictionaryValue* WindowOpenNotification() { + return window_open_notification_.get(); + } + private: DevToolsAgent* agent() { return frame()->devtools_agent(); @@ -495,6 +505,7 @@ std::vector<std::string> notifications_; std::unique_ptr<base::DictionaryValue> last_message_; + std::unique_ptr<base::DictionaryValue> window_open_notification_; int call_frames_count_; bool expecting_pause_; }; @@ -2696,4 +2707,62 @@ Detach(); } +TEST_F(DevToolsAgentTest, WindowOpenWithEmptyURL) { + Attach(); + DispatchDevToolsMessage("Page.enable", + "{\"id\":1,\"method\":\"Page.enable\"}"); + LoadHTMLWithUrlOverride("<script>window.open()</script>", + "https://www.example.com"); + + base::DictionaryValue* notification = WindowOpenNotification(); + EXPECT_TRUE(notification); + const base::Value* params_value = notification->FindKey("params"); + EXPECT_TRUE(params_value && params_value->is_dict()); + const base::Value* url_value = params_value->FindKey("url"); + EXPECT_TRUE(url_value); + EXPECT_EQ(url::kAboutBlankURL, url_value->GetString()); +} + +TEST_F(DevToolsAgentTest, WindowOpenWithRelativeURL) { + // Enable browser side navigation to avoid actually load url for the new + // window. + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableBrowserSideNavigation); + Attach(); + DispatchDevToolsMessage("Page.enable", + "{\"id\":1,\"method\":\"Page.enable\"}"); + LoadHTMLWithUrlOverride("<script>window.open('path')</script>", + "https://www.example.com"); + + base::DictionaryValue* notification = WindowOpenNotification(); + EXPECT_TRUE(notification); + const base::Value* params_value = notification->FindKey("params"); + EXPECT_TRUE(params_value && params_value->is_dict()); + const base::Value* url_value = params_value->FindKey("url"); + EXPECT_TRUE(url_value); + EXPECT_EQ("https://www.example.com/path", url_value->GetString()); +} + +TEST_F(DevToolsAgentTest, WindowOpenFromClick) { + // Enable browser side navigation to avoid actually load url for the new + // window. + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableBrowserSideNavigation); + Attach(); + DispatchDevToolsMessage("Page.enable", + "{\"id\":1,\"method\":\"Page.enable\"}"); + LoadHTMLWithUrlOverride( + "<a id='my_anchor' href='/anchor' target='_blank'> </a>\n" + "<script>document.getElementById('my_anchor').click();</script>", + "https://www.example.com"); + + base::DictionaryValue* notification = WindowOpenNotification(); + EXPECT_TRUE(notification); + const base::Value* params_value = notification->FindKey("params"); + EXPECT_TRUE(params_value && params_value->is_dict()); + const base::Value* url_value = params_value->FindKey("url"); + EXPECT_TRUE(url_value); + EXPECT_EQ("https://www.example.com/anchor", url_value->GetString()); +} + } // namespace content
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 9f5a7b9..a5db6cdc 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -73,7 +73,6 @@ #include "content/renderer/appcache/web_application_cache_host_impl.h" #include "content/renderer/browser_plugin/browser_plugin.h" #include "content/renderer/browser_plugin/browser_plugin_manager.h" -#include "content/renderer/dom_storage/webstoragenamespace_impl.h" #include "content/renderer/drop_data_builder.h" #include "content/renderer/gpu/render_widget_compositor.h" #include "content/renderer/history_serialization.h" @@ -237,7 +236,6 @@ using blink::WebSecurityPolicy; using blink::WebSettings; using blink::WebSize; -using blink::WebStorageNamespace; using blink::WebStorageQuotaCallbacks; using blink::WebStorageQuotaError; using blink::WebStorageQuotaType; @@ -1449,9 +1447,9 @@ return widget->GetWebWidget(); } -WebStorageNamespace* RenderViewImpl::CreateSessionStorageNamespace() { +int64_t RenderViewImpl::GetSessionStorageNamespaceId() { CHECK(session_storage_namespace_id_ != kInvalidSessionStorageNamespaceId); - return new WebStorageNamespaceImpl(session_storage_namespace_id_); + return session_storage_namespace_id_; } void RenderViewImpl::PrintPage(WebLocalFrame* frame) {
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index d6b96784c..4558d8a 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -72,7 +72,6 @@ class WebGestureEvent; class WebMouseEvent; class WebSpeechRecognizer; -class WebStorageNamespace; class WebTappedInfo; class WebURLRequest; struct WebDateTimeChooserParams; @@ -281,7 +280,7 @@ bool suppress_opener, blink::WebSandboxFlags sandbox_flags) override; blink::WebWidget* CreatePopupMenu(blink::WebPopupType popup_type) override; - blink::WebStorageNamespace* CreateSessionStorageNamespace() override; + int64_t GetSessionStorageNamespaceId() override; void PrintPage(blink::WebLocalFrame* frame) override; bool EnumerateChosenDirectory( const blink::WebString& path,
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 5e1f72da..8375d7e3 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -47,6 +47,7 @@ #include "content/renderer/device_sensors/device_orientation_event_pump.h" #include "content/renderer/dom_storage/local_storage_cached_areas.h" #include "content/renderer/dom_storage/local_storage_namespace.h" +#include "content/renderer/dom_storage/session_web_storage_namespace_impl.h" #include "content/renderer/dom_storage/webstoragenamespace_impl.h" #include "content/renderer/file_info_util.h" #include "content/renderer/fileapi/webfilesystem_impl.h" @@ -562,7 +563,8 @@ switches::kDisableMojoLocalStorage)) { if (!local_storage_cached_areas_) { local_storage_cached_areas_.reset(new LocalStorageCachedAreas( - RenderThreadImpl::current()->GetStoragePartitionService())); + RenderThreadImpl::current()->GetStoragePartitionService(), + renderer_scheduler_)); } return std::make_unique<LocalStorageNamespace>( local_storage_cached_areas_.get()); @@ -571,6 +573,20 @@ return std::make_unique<WebStorageNamespaceImpl>(); } +std::unique_ptr<blink::WebStorageNamespace> +RendererBlinkPlatformImpl::CreateSessionStorageNamespace(int64_t namespace_id) { + if (base::FeatureList::IsEnabled(features::kMojoSessionStorage)) { + if (!local_storage_cached_areas_) { + local_storage_cached_areas_.reset(new LocalStorageCachedAreas( + RenderThreadImpl::current()->GetStoragePartitionService(), + renderer_scheduler_)); + } + return std::make_unique<SessionWebStorageNamespaceImpl>( + namespace_id, local_storage_cached_areas_.get()); + } + + return std::make_unique<WebStorageNamespaceImpl>(namespace_id); +} //------------------------------------------------------------------------------ @@ -1380,7 +1396,7 @@ //------------------------------------------------------------------------------ blink::WebNotificationManager* -RendererBlinkPlatformImpl::GetNotificationManager() { +RendererBlinkPlatformImpl::GetWebNotificationManager() { if (!thread_safe_sender_.get() || !notification_dispatcher_.get()) return nullptr;
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index f8badcc..67115992 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -112,6 +112,8 @@ blink::WebThread* CompositorThread() const override; std::unique_ptr<blink::WebStorageNamespace> CreateLocalStorageNamespace() override; + std::unique_ptr<blink::WebStorageNamespace> CreateSessionStorageNamespace( + int64_t namespace_id) override; blink::Platform::FileHandle DatabaseOpenFile( const blink::WebString& vfs_file_name, int desired_flags) override; @@ -217,7 +219,7 @@ blink::WebPushProvider* PushProvider() override; std::unique_ptr<blink::WebTrialTokenValidator> CreateTrialTokenValidator() override; - blink::WebNotificationManager* GetNotificationManager() override; + blink::WebNotificationManager* GetWebNotificationManager() override; void DidStartWorkerThread() override; void WillStopWorkerThread() override; void WorkerContextCreated(const v8::Local<v8::Context>& worker) override;
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc index 99f407e..2c841d5 100644 --- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc +++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -55,8 +55,9 @@ // loaded by the worker using WorkerScriptLoader. // These overrides are stubbed out. void WillStartMainResourceRequest( - blink::WebURLRequest&, - const blink::WebApplicationCacheHost*) override {} + const blink::WebURL& url, + const blink::WebString& method, + const WebApplicationCacheHost* spawning_host) override {} void DidReceiveResponseForMainResource( const blink::WebURLResponse&) override {} void DidReceiveDataForMainResource(const char* data, unsigned len) override {}
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index 39c20a6..5727bcf 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -231,6 +231,7 @@ "//components/crash/content/app", "//components/crash/content/app:test_support", "//components/crash/content/browser", + "//components/crash/core/common:crash_key", "//components/keyed_service/content", "//components/network_session_configurator/browser", "//components/plugins/renderer",
diff --git a/content/shell/app/shell_main_delegate.cc b/content/shell/app/shell_main_delegate.cc index 9e5347d..796f714 100644 --- a/content/shell/app/shell_main_delegate.cc +++ b/content/shell/app/shell_main_delegate.cc
@@ -15,6 +15,7 @@ #include "base/trace_event/trace_log.h" #include "build/build_config.h" #include "cc/base/switches.h" +#include "components/crash/core/common/crash_key.h" #include "content/common/content_constants_internal.h" #include "content/public/browser/browser_main_runner.h" #include "content/public/common/content_switches.h" @@ -293,6 +294,8 @@ } #endif // !defined(OS_FUCHSIA) + crash_reporter::InitializeCrashKeys(); + InitializeResourceBundle(); }
diff --git a/content/shell/browser/shell_network_delegate.cc b/content/shell/browser/shell_network_delegate.cc index 6f59e83..37ddaab 100644 --- a/content/shell/browser/shell_network_delegate.cc +++ b/content/shell/browser/shell_network_delegate.cc
@@ -97,7 +97,7 @@ } bool ShellNetworkDelegate::OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) { net::StaticCookiePolicy::Type policy_type = g_block_third_party_cookies ? net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
diff --git a/content/shell/browser/shell_network_delegate.h b/content/shell/browser/shell_network_delegate.h index 184bbb9..ddc4e52 100644 --- a/content/shell/browser/shell_network_delegate.h +++ b/content/shell/browser/shell_network_delegate.h
@@ -51,7 +51,7 @@ bool OnCanGetCookies(const net::URLRequest& request, const net::CookieList& cookie_list) override; bool OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) override; bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& original_path,
diff --git a/content/shell/test_runner/test_plugin.cc b/content/shell/test_runner/test_plugin.cc index 4b6f4a5c..d17a484 100644 --- a/content/shell/test_runner/test_plugin.cc +++ b/content/shell/test_runner/test_plugin.cc
@@ -120,7 +120,7 @@ web_local_frame_(frame), gl_(nullptr), color_texture_(0), - mailbox_changed_(false), + content_changed_(false), framebuffer_(0), touch_event_request_( blink::WebPluginContainer::kTouchEventRequestTypeNone), @@ -243,7 +243,9 @@ rect_ = clip_rect; if (rect_.IsEmpty()) { - texture_mailbox_ = viz::TextureMailbox(); + mailbox_ = gpu::Mailbox(); + sync_token_ = gpu::SyncToken(); + shared_bitmap_ = nullptr; } else if (gl_) { gl_->Viewport(0, 0, rect_.width, rect_.height); @@ -260,30 +262,23 @@ DrawSceneGL(); - gpu::Mailbox mailbox; - gl_->GenMailboxCHROMIUM(mailbox.name); - gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); + gl_->GenMailboxCHROMIUM(mailbox_.name); + gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox_.name); const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM(); gl_->Flush(); - gpu::SyncToken sync_token; - gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); - texture_mailbox_ = viz::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D); + gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token_.GetData()); + + shared_bitmap_ = nullptr; } else { - std::unique_ptr<viz::SharedBitmap> bitmap = - delegate_->GetSharedBitmapManager()->AllocateSharedBitmap( - gfx::Rect(rect_).size()); - if (!bitmap) { - texture_mailbox_ = viz::TextureMailbox(); - } else { - DrawSceneSoftware(bitmap->pixels()); - texture_mailbox_ = viz::TextureMailbox( - bitmap.get(), gfx::Size(rect_.width, rect_.height)); - shared_bitmap_ = std::move(bitmap); - } + mailbox_ = gpu::Mailbox(); + sync_token_ = gpu::SyncToken(); + shared_bitmap_ = delegate_->GetSharedBitmapManager()->AllocateSharedBitmap( + gfx::Rect(rect_).size()); + DrawSceneSoftware(shared_bitmap_->pixels()); } - mailbox_changed_ = true; + content_changed_ = true; layer_->SetNeedsDisplay(); } @@ -298,20 +293,24 @@ const gpu::SyncToken& sync_token, bool lost) {} -bool TestPlugin::PrepareTextureMailbox( - viz::TextureMailbox* mailbox, +bool TestPlugin::PrepareTransferableResource( + viz::TransferableResource* resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback) { - if (!mailbox_changed_) + if (!content_changed_) return false; - *mailbox = texture_mailbox_; - if (texture_mailbox_.IsTexture()) { + if (!mailbox_.IsZero()) { + *resource = viz::TransferableResource::MakeGL(mailbox_, GL_LINEAR, + GL_TEXTURE_2D, sync_token_); *release_callback = viz::SingleReleaseCallback::Create(base::Bind(&IgnoreReleaseCallback)); - } else if (texture_mailbox_.IsSharedMemory()) { + } else if (shared_bitmap_) { + *resource = viz::TransferableResource::MakeSoftware( + shared_bitmap_->id(), shared_bitmap_->sequence_number(), + gfx::Size(rect_.width, rect_.height)); *release_callback = viz::SingleReleaseCallback::Create( base::Bind(&ReleaseSharedMemory, base::Passed(&shared_bitmap_))); } - mailbox_changed_ = false; + content_changed_ = false; return true; }
diff --git a/content/shell/test_runner/test_plugin.h b/content/shell/test_runner/test_plugin.h index 7a6b6f9..b33f50c 100644 --- a/content/shell/test_runner/test_plugin.h +++ b/content/shell/test_runner/test_plugin.h
@@ -11,6 +11,8 @@ #include "base/macros.h" #include "cc/layers/texture_layer.h" #include "cc/layers/texture_layer_client.h" +#include "gpu/command_buffer/common/mailbox.h" +#include "gpu/command_buffer/common/sync_token.h" #include "third_party/WebKit/public/platform/WebLayer.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebElement.h" @@ -35,6 +37,10 @@ } } +namespace viz { +struct TransferableResource; +} + namespace test_runner { class WebTestDelegate; @@ -93,8 +99,8 @@ bool IsPlaceholder() override; // cc::TextureLayerClient methods: - bool PrepareTextureMailbox( - viz::TextureMailbox* mailbox, + bool PrepareTransferableResource( + viz::TransferableResource* resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override; private: @@ -156,9 +162,10 @@ std::unique_ptr<blink::WebGraphicsContext3DProvider> context_provider_; gpu::gles2::GLES2Interface* gl_; GLuint color_texture_; - viz::TextureMailbox texture_mailbox_; + gpu::Mailbox mailbox_; + gpu::SyncToken sync_token_; std::unique_ptr<viz::SharedBitmap> shared_bitmap_; - bool mailbox_changed_; + bool content_changed_; GLuint framebuffer_; Scene scene_; scoped_refptr<cc::TextureLayer> layer_;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 19518aab..6a0c703 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -254,6 +254,10 @@ "test_render_view_host.h", "test_render_view_host_factory.cc", "test_render_view_host_factory.h", + "test_render_widget_host.cc", + "test_render_widget_host.h", + "test_render_widget_host_factory.cc", + "test_render_widget_host_factory.h", "test_web_contents.cc", "test_web_contents.h", "test_web_contents_factory.cc", @@ -872,6 +876,7 @@ "//testing/gtest", "//third_party/WebKit/public:blink", "//third_party/leveldatabase", + "//third_party/libaom:av1_features", "//third_party/mesa:osmesa", "//third_party/zlib", "//ui/accessibility", @@ -1829,6 +1834,7 @@ "//third_party/webrtc/api:libjingle_peerconnection", "//third_party/webrtc/api:rtc_stats_api", "//third_party/webrtc/api:video_frame_api", + "//third_party/webrtc/api:video_frame_api_i420", "//third_party/webrtc/api/video_codecs:video_codecs_api", "//third_party/webrtc/media:rtc_media", "//third_party/webrtc/modules/desktop_capture:primitives",
diff --git a/content/test/data/device_sensors/cross_origin_iframe.html b/content/test/data/device_sensors/cross_origin_iframe.html new file mode 100644 index 0000000..286a86d0 --- /dev/null +++ b/content/test/data/device_sensors/cross_origin_iframe.html
@@ -0,0 +1,8 @@ +<html> + <head> + <title>cross-origin iframe</title> + </head> + <body> + <iframe id="cross_origin_iframe" name="cross_origin_iframe_name"></iframe> + </body> +</html>
diff --git a/content/test/data/generic_sensor/ambient_light_sensor_cross_origin_iframe_test.html b/content/test/data/generic_sensor/ambient_light_sensor_cross_origin_iframe_test.html new file mode 100644 index 0000000..685b924 --- /dev/null +++ b/content/test/data/generic_sensor/ambient_light_sensor_cross_origin_iframe_test.html
@@ -0,0 +1,29 @@ +<html> + <head> + <title>AmbientLight Generic Sensor cross-origin iframe test</title> + <script type="text/javascript"> + function start() { + try { + let sensor = new AmbientLightSensor(); + // The Generic Sensor API is expected to throw an exception for + // cross-origin frames. + fail(); + } catch(e) { + pass(); + } + } + + function pass() { + document.getElementById('status').innerHTML = 'PASS'; + document.location = '#pass'; + } + + function fail() { + document.location = '#fail'; + } + </script> + </head> + <body onLoad="setTimeout(start, 200)"> + <div id="status">FAIL</div> + </body> +</html>
diff --git a/content/test/data/generic_sensor/cross_origin_iframe.html b/content/test/data/generic_sensor/cross_origin_iframe.html new file mode 100644 index 0000000..286a86d0 --- /dev/null +++ b/content/test/data/generic_sensor/cross_origin_iframe.html
@@ -0,0 +1,8 @@ +<html> + <head> + <title>cross-origin iframe</title> + </head> + <body> + <iframe id="cross_origin_iframe" name="cross_origin_iframe_name"></iframe> + </body> +</html>
diff --git a/content/test/fake_leveldb_database.cc b/content/test/fake_leveldb_database.cc index f3f47820..d7158a6 100644 --- a/content/test/fake_leveldb_database.cc +++ b/content/test/fake_leveldb_database.cc
@@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <content/test/fake_leveldb_database.h> +#include "content/test/fake_leveldb_database.h" + +#include <iterator> #include <utility> #include "base/strings/string_piece.h" @@ -11,6 +13,8 @@ namespace content { namespace { +using leveldb::mojom::BatchedOperation; +using leveldb::mojom::BatchedOperationPtr; leveldb::mojom::KeyValuePtr CreateKeyValue(std::vector<uint8_t> key, std::vector<uint8_t> value) { @@ -77,17 +81,65 @@ void FakeLevelDBDatabase::Write( std::vector<leveldb::mojom::BatchedOperationPtr> operations, WriteCallback callback) { + // Replace prefix delete and prefix copy with operations first, and then + // execute all operations. This models how the leveldb WriteBatch works. + for (size_t i = 0; i < operations.size(); ++i) { + const auto& op = operations[i]; + switch (op->type) { + case leveldb::mojom::BatchOperationType::PUT_KEY: + break; + case leveldb::mojom::BatchOperationType::DELETE_KEY: + break; + case leveldb::mojom::BatchOperationType::DELETE_PREFIXED_KEY: { + std::vector<leveldb::mojom::BatchedOperationPtr> changes; + for (auto map_it = mock_data_.lower_bound(op->key); + map_it != mock_data_.lower_bound(successor(op->key)); ++map_it) { + BatchedOperationPtr item = BatchedOperation::New(); + item->type = leveldb::mojom::BatchOperationType::DELETE_KEY; + item->key = map_it->first; + changes.push_back(std::move(item)); + } + size_t diff = changes.size(); + operations.insert(operations.begin() + i, + std::make_move_iterator(changes.begin()), + std::make_move_iterator(changes.end())); + i += diff; + continue; + } + case leveldb::mojom::BatchOperationType::COPY_PREFIXED_KEY: { + DCHECK(op->value); + std::vector<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> + copy_changes = CopyPrefixedHelper(op->key, *op->value); + std::vector<leveldb::mojom::BatchedOperationPtr> changes; + for (auto& change : copy_changes) { + BatchedOperationPtr item = BatchedOperation::New(); + item->type = leveldb::mojom::BatchOperationType::PUT_KEY; + item->key = std::move(change.first); + item->value = std::move(change.second); + changes.push_back(std::move(item)); + } + size_t diff = changes.size(); + operations.insert(operations.begin() + i, + std::make_move_iterator(changes.begin()), + std::make_move_iterator(changes.end())); + i += diff; + continue; + } + } + } + for (const auto& op : operations) { switch (op->type) { case leveldb::mojom::BatchOperationType::PUT_KEY: + DCHECK(op->value); mock_data_[op->key] = *op->value; break; case leveldb::mojom::BatchOperationType::DELETE_KEY: mock_data_.erase(op->key); break; case leveldb::mojom::BatchOperationType::DELETE_PREFIXED_KEY: - mock_data_.erase(mock_data_.lower_bound(op->key), - mock_data_.lower_bound(successor(op->key))); + break; + case leveldb::mojom::BatchOperationType::COPY_PREFIXED_KEY: break; } } @@ -115,6 +167,16 @@ std::move(callback).Run(leveldb::mojom::DatabaseError::OK, std::move(data)); } +void FakeLevelDBDatabase::CopyPrefixed( + const std::vector<uint8_t>& source_key_prefix, + const std::vector<uint8_t>& destination_key_prefix, + CopyPrefixedCallback callback) { + std::vector<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> changes = + CopyPrefixedHelper(source_key_prefix, destination_key_prefix); + mock_data_.insert(changes.begin(), changes.end()); + std::move(callback).Run(leveldb::mojom::DatabaseError::OK); +} + void FakeLevelDBDatabase::GetSnapshot(GetSnapshotCallback callback) { NOTREACHED(); } @@ -173,4 +235,29 @@ IteratorPrevCallback callback) { NOTREACHED(); } + +std::vector<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> +FakeLevelDBDatabase::CopyPrefixedHelper( + const std::vector<uint8_t>& source_key_prefix, + const std::vector<uint8_t>& destination_key_prefix) { + size_t source_key_prefix_size = source_key_prefix.size(); + size_t destination_key_prefix_size = destination_key_prefix.size(); + std::vector<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> + write_batch; + for (auto map_it = mock_data_.lower_bound(source_key_prefix); + map_it != mock_data_.lower_bound(successor(source_key_prefix)); + ++map_it) { + size_t excess_key = map_it->first.size() - source_key_prefix_size; + std::vector<uint8_t> new_key(destination_key_prefix_size + excess_key); + std::copy(destination_key_prefix.begin(), destination_key_prefix.end(), + new_key.begin()); + std::copy(map_it->first.begin() + source_key_prefix_size, + map_it->first.end(), + new_key.begin() + destination_key_prefix_size); + write_batch.emplace_back(std::move(new_key), map_it->second); + } + + return write_batch; +} + } // namespace content
diff --git a/content/test/fake_leveldb_database.h b/content/test/fake_leveldb_database.h index 261dea9..913b2b1 100644 --- a/content/test/fake_leveldb_database.h +++ b/content/test/fake_leveldb_database.h
@@ -37,6 +37,9 @@ void Get(const std::vector<uint8_t>& key, GetCallback callback) override; void GetPrefixed(const std::vector<uint8_t>& key_prefix, GetPrefixedCallback callback) override; + void CopyPrefixed(const std::vector<uint8_t>& source_key_prefix, + const std::vector<uint8_t>& destination_key_prefix, + CopyPrefixedCallback callback) override; void GetSnapshot(GetSnapshotCallback callback) override; void ReleaseSnapshot(const base::UnguessableToken& snapshot) override; void GetFromSnapshot(const base::UnguessableToken& snapshot, @@ -60,6 +63,10 @@ IteratorPrevCallback callback) override; private: + std::vector<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> + CopyPrefixedHelper(const std::vector<uint8_t>& source_key_prefix, + const std::vector<uint8_t>& destination_key_prefix); + mojo::BindingSet<leveldb::mojom::LevelDBDatabase> bindings_; std::map<std::vector<uint8_t>, std::vector<uint8_t>>& mock_data_;
diff --git a/content/test/mock_widget_input_handler.cc b/content/test/mock_widget_input_handler.cc index e3e7a97e..3772bce 100644 --- a/content/test/mock_widget_input_handler.cc +++ b/content/test/mock_widget_input_handler.cc
@@ -28,7 +28,7 @@ void MockWidgetInputHandler::SetFocus(bool focused) { dispatched_messages_.emplace_back( - std::make_unique<DispatchedMessage>("SetFocus")); + std::make_unique<DispatchedFocusMessage>(focused)); } void MockWidgetInputHandler::MouseCaptureLost() { @@ -118,6 +118,10 @@ MockWidgetInputHandler::DispatchedMessage::ToEvent() { return nullptr; } +MockWidgetInputHandler::DispatchedFocusMessage* +MockWidgetInputHandler::DispatchedMessage::ToFocus() { + return nullptr; +} MockWidgetInputHandler::DispatchedIMEMessage* MockWidgetInputHandler::DispatchedMessage::ToIME() { return nullptr; @@ -246,4 +250,15 @@ return this; } +MockWidgetInputHandler::DispatchedFocusMessage::DispatchedFocusMessage( + bool focused) + : DispatchedMessage("SetFocus"), focused_(focused) {} + +MockWidgetInputHandler::DispatchedFocusMessage::~DispatchedFocusMessage() {} + +MockWidgetInputHandler::DispatchedFocusMessage* +MockWidgetInputHandler::DispatchedFocusMessage::ToFocus() { + return this; +} + } // namespace content
diff --git a/content/test/mock_widget_input_handler.h b/content/test/mock_widget_input_handler.h index b26d3d9..0001dee 100644 --- a/content/test/mock_widget_input_handler.h +++ b/content/test/mock_widget_input_handler.h
@@ -25,6 +25,7 @@ class DispatchedEditCommandMessage; class DispatchedEventMessage; + class DispatchedFocusMessage; class DispatchedIMEMessage; class DispatchedRequestCompositionUpdatesMessage; @@ -42,7 +43,10 @@ // Cast this to a DispatchedEventMessage if it is one, null otherwise. virtual DispatchedEventMessage* ToEvent(); - // Cast this to a DispatchedIMEMessage if it is one, null otherwise. + // Cast this to an DispatchedFocusMessage if it is one, null otherwise. + virtual DispatchedFocusMessage* ToFocus(); + + // Cast this to an DispatchedIMEMessage if it is one, null otherwise. virtual DispatchedIMEMessage* ToIME(); // Cast this to a DispatchedRequestCompositionUpdateMessage if it is one, @@ -112,6 +116,24 @@ DISALLOW_COPY_AND_ASSIGN(DispatchedEditCommandMessage); }; + // A DispatchedMessage that stores the focus parameters + // that were invoked with. + class DispatchedFocusMessage : public DispatchedMessage { + public: + explicit DispatchedFocusMessage(bool focused); + ~DispatchedFocusMessage() override; + + // Override and return |this|. + DispatchedFocusMessage* ToFocus() override; + + bool focused() const { return focused_; } + + private: + const bool focused_; + + DISALLOW_COPY_AND_ASSIGN(DispatchedFocusMessage); + }; + // A DispatchedMessage that stores the InputEvent and callback // that was passed to the MockWidgetInputHandler interface. class DispatchedEventMessage : public DispatchedMessage {
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index 3df46b2..159b4f4a 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc
@@ -23,6 +23,7 @@ #include "content/public/test/browser_side_navigation_test_utils.h" #include "content/test/test_navigation_url_loader.h" #include "content/test/test_render_view_host.h" +#include "content/test/test_render_widget_host.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "net/base/load_flags.h" #include "net/http/http_response_headers.h" @@ -111,6 +112,11 @@ return static_cast<MockRenderProcessHost*>(RenderFrameHostImpl::GetProcess()); } +TestRenderWidgetHost* TestRenderFrameHost::GetRenderWidgetHost() { + return static_cast<TestRenderWidgetHost*>( + RenderFrameHostImpl::GetRenderWidgetHost()); +} + void TestRenderFrameHost::AddMessageToConsole(ConsoleMessageLevel level, const std::string& message) { console_messages_.push_back(message);
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h index 30ec846d..dd83a54 100644 --- a/content/test/test_render_frame_host.h +++ b/content/test/test_render_frame_host.h
@@ -16,6 +16,7 @@ #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_renderer_host.h" #include "content/test/test_render_view_host.h" +#include "content/test/test_render_widget_host.h" #include "ui/base/page_transition_types.h" struct FrameHostMsg_DidCommitProvisionalLoad_Params; @@ -57,6 +58,7 @@ // RenderFrameHostImpl overrides (same values, but in Test*/Mock* types) TestRenderViewHost* GetRenderViewHost() override; MockRenderProcessHost* GetProcess() override; + TestRenderWidgetHost* GetRenderWidgetHost() override; void AddMessageToConsole(ConsoleMessageLevel level, const std::string& message) override;
diff --git a/content/test/test_render_view_host_factory.cc b/content/test/test_render_view_host_factory.cc index 6c034d5..8fcaeae 100644 --- a/content/test/test_render_view_host_factory.cc +++ b/content/test/test_render_view_host_factory.cc
@@ -9,6 +9,7 @@ #include "content/browser/site_instance_impl.h" #include "content/public/browser/render_process_host_factory.h" #include "content/test/test_render_view_host.h" +#include "content/test/test_render_widget_host.h" namespace content { @@ -35,11 +36,11 @@ int32_t routing_id, int32_t main_frame_routing_id, bool swapped_out) { - return new TestRenderViewHost(instance, - std::make_unique<RenderWidgetHostImpl>( - widget_delegate, instance->GetProcess(), - routing_id, nullptr, false /* hidden */), - delegate, main_frame_routing_id, swapped_out); + return new TestRenderViewHost( + instance, + TestRenderWidgetHost::Create(widget_delegate, instance->GetProcess(), + routing_id, false), + delegate, main_frame_routing_id, swapped_out); } } // namespace content
diff --git a/content/test/test_render_widget_host.cc b/content/test/test_render_widget_host.cc new file mode 100644 index 0000000..9e469f2 --- /dev/null +++ b/content/test/test_render_widget_host.cc
@@ -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. + +#include "content/test/test_render_widget_host.h" + +#include "base/run_loop.h" +#include "content/public/common/content_features.h" + +namespace content { + +std::unique_ptr<RenderWidgetHostImpl> TestRenderWidgetHost::Create( + RenderWidgetHostDelegate* delegate, + RenderProcessHost* process, + int32_t routing_id, + bool hidden) { + mojom::WidgetPtr widget; + std::unique_ptr<MockWidgetImpl> widget_impl = + std::make_unique<MockWidgetImpl>(mojo::MakeRequest(&widget)); + return base::WrapUnique(new TestRenderWidgetHost( + delegate, process, routing_id, std::move(widget_impl), std::move(widget), + hidden)); +} + +TestRenderWidgetHost::TestRenderWidgetHost( + RenderWidgetHostDelegate* delegate, + RenderProcessHost* process, + int32_t routing_id, + std::unique_ptr<MockWidgetImpl> widget_impl, + mojom::WidgetPtr widget, + bool hidden) + : RenderWidgetHostImpl(delegate, + process, + routing_id, + std::move(widget), + hidden), + widget_impl_(std::move(widget_impl)) {} + +TestRenderWidgetHost::~TestRenderWidgetHost() {} +mojom::WidgetInputHandler* TestRenderWidgetHost::GetWidgetInputHandler() { + return widget_impl_->input_handler(); +} + +MockWidgetInputHandler* TestRenderWidgetHost::GetMockWidgetInputHandler() { + return widget_impl_->input_handler(); +} + +} // namespace content
diff --git a/content/test/test_render_widget_host.h b/content/test/test_render_widget_host.h new file mode 100644 index 0000000..9e38af7 --- /dev/null +++ b/content/test/test_render_widget_host.h
@@ -0,0 +1,44 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_TEST_TEST_RENDER_WIDGET_HOST_H_ +#define CONTENT_TEST_TEST_RENDER_WIDGET_HOST_H_ + +#include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/test/mock_widget_impl.h" +#include "content/test/mock_widget_input_handler.h" + +namespace content { +// TestRenderWidgetHostView ---------------------------------------------------- + +// Subclass the RenderWidgetHostImpl so that we can watch the mojo +// input channel. +class TestRenderWidgetHost : public RenderWidgetHostImpl { + public: + static std::unique_ptr<RenderWidgetHostImpl> Create( + RenderWidgetHostDelegate* delegate, + RenderProcessHost* process, + int32_t routing_id, + bool hidden); + ~TestRenderWidgetHost() override; + + // RenderWidgetHostImpl overrides. + mojom::WidgetInputHandler* GetWidgetInputHandler() override; + + MockWidgetInputHandler* GetMockWidgetInputHandler(); + + private: + TestRenderWidgetHost(RenderWidgetHostDelegate* delegate, + RenderProcessHost* process, + int32_t routing_id, + std::unique_ptr<MockWidgetImpl> widget_impl, + mojom::WidgetPtr widget, + bool hidden); + + std::unique_ptr<MockWidgetImpl> widget_impl_; +}; + +} // namespace content + +#endif // CONTENT_TEST_TEST_RENDER_WIDGET_HOST_H_
diff --git a/content/test/test_render_widget_host_factory.cc b/content/test/test_render_widget_host_factory.cc new file mode 100644 index 0000000..29f1b88 --- /dev/null +++ b/content/test/test_render_widget_host_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 "content/test/test_render_widget_host_factory.h" + +#include "content/test/test_render_widget_host.h" + +namespace content { + +TestRenderWidgetHostFactory::TestRenderWidgetHostFactory() { + RenderWidgetHostFactory::RegisterFactory(this); +} + +TestRenderWidgetHostFactory::~TestRenderWidgetHostFactory() { + RenderWidgetHostFactory::UnregisterFactory(); +} + +RenderWidgetHostImpl* TestRenderWidgetHostFactory::CreateRenderWidgetHost( + RenderWidgetHostDelegate* delegate, + RenderProcessHost* process, + int32_t routing_id, + mojom::WidgetPtr widget_interface, + bool hidden) { + return TestRenderWidgetHost::Create(delegate, process, routing_id, hidden) + .release(); +} + +} // namespace content
diff --git a/content/test/test_render_widget_host_factory.h b/content/test/test_render_widget_host_factory.h new file mode 100644 index 0000000..a7c58f42 --- /dev/null +++ b/content/test/test_render_widget_host_factory.h
@@ -0,0 +1,38 @@ +// 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_TEST_TEST_RENDER_WIDGET_HOST_FACTORY_H_ +#define CONTENT_TEST_TEST_RENDER_WIDGET_HOST_FACTORY_H_ + +#include <stdint.h> + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "content/browser/renderer_host/render_widget_host_factory.h" + +namespace content { + +// Manages creation of the RenderWidgetHostImpls using our special subclass. +// This automatically registers itself when it goes in scope, and unregisters +// itself when it goes out of scope. Since you can't have more than one factory +// registered at a time, you can only have one of these objects at a time. +class TestRenderWidgetHostFactory : public RenderWidgetHostFactory { + public: + TestRenderWidgetHostFactory(); + ~TestRenderWidgetHostFactory() override; + + RenderWidgetHostImpl* CreateRenderWidgetHost( + RenderWidgetHostDelegate* delegate, + RenderProcessHost* process, + int32_t routing_id, + mojom::WidgetPtr widget_interface, + bool hidden) override; + + private: + DISALLOW_COPY_AND_ASSIGN(TestRenderWidgetHostFactory); +}; + +} // namespace content + +#endif // CONTENT_TEST_TEST_RENDER_WIDGET_HOST_FACTORY_H_
diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc index 4db8ca6..93fba19 100644 --- a/content/zygote/zygote_main_linux.cc +++ b/content/zygote/zygote_main_linux.cc
@@ -512,8 +512,7 @@ static void EnterNamespaceSandbox(service_manager::SandboxLinux* linux_sandbox, base::Closure* post_fork_parent_callback) { - linux_sandbox->EngageNamespaceSandbox(); - + linux_sandbox->EngageNamespaceSandbox(true /* from_zygote */); if (getpid() == 1) { base::Closure drop_all_caps_callback = base::Bind(&DropAllCapabilities, linux_sandbox->proc_fd());
diff --git a/docs/linux_build_instructions.md b/docs/linux_build_instructions.md index b49a7067c..840e84ff 100644 --- a/docs/linux_build_instructions.md +++ b/docs/linux_build_instructions.md
@@ -176,7 +176,7 @@ #### ccache You can use [ccache](https://ccache.samba.org) to speed up local builds (again, -this is not useful if you're using a Googler using Goma). +this is not useful if you're a Googler using Goma). Increase your ccache hit rate by setting `CCACHE_BASEDIR` to a parent directory that the working directories all have in common (e.g.,
diff --git a/docs/new_port_policy.md b/docs/new_port_policy.md index a1510ef..83aee96 100644 --- a/docs/new_port_policy.md +++ b/docs/new_port_policy.md
@@ -8,5 +8,5 @@ * These will not have bots on Google-run waterfalls (even FYI). * Chromium engineers are not expected to maintain them. * As much as possible, try to use existing branches/ifdefs. -* While changes in src/base are unavoidable, higher level directories shouldnÂ’t have to change. i.e. existing porting APIs should be used. We would not accept new rendering pipelines as an example. -* Send an email to [src/OWNERS](https://chromium.googlesource.com/chromium/src/+/master/ENG_REVIEW_OWNERS) for approval. \ No newline at end of file +* While changes in src/base are unavoidable, higher level directories shouldn't have to change. i.e. existing porting APIs should be used. We would not accept new rendering pipelines as an example. +* Send an email to [src/OWNERS](https://chromium.googlesource.com/chromium/src/+/master/ENG_REVIEW_OWNERS) for approval.
diff --git a/docs/updating_clang.md b/docs/updating_clang.md index 78e4a529..a5498437 100644 --- a/docs/updating_clang.md +++ b/docs/updating_clang.md
@@ -16,6 +16,8 @@ gs://chromium-browser-clang/$x/clang-$rev.tgz ; \ gsutil.py cp -n -a public-read gs://chromium-browser-clang-staging/$x/llvmobjdump-$rev.tgz \ gs://chromium-browser-clang/$x/llvmobjdump-$rev.tgz ; \ + gsutil.py cp -n -a public-read gs://chromium-browser-clang-staging/$x/llvmcfiverify-$rev.tgz \ + gs://chromium-browser-clang/$x/llvmcfiverify-$rev.tgz ; \ gsutil.py cp -n -a public-read gs://chromium-browser-clang-staging/$x/translation_unit-$rev.tgz \ gs://chromium-browser-clang/$x/translation_unit-$rev.tgz ; \ gsutil.py cp -n -a public-read gs://chromium-browser-clang-staging/$x/llvm-code-coverage-$rev.tgz \
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index a46a85f4..5f36fcc 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -39,7 +39,7 @@ ] # TODO(crbug.com/699569): Convert to use the new JS bindings. - use_new_js_bindings = false + js_bindings_mode = "both" } # This must be a static library because extensions common depends on
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn index 863c186..79415fb 100644 --- a/extensions/renderer/BUILD.gn +++ b/extensions/renderer/BUILD.gn
@@ -396,7 +396,6 @@ "module_system_test.cc", "module_system_test.h", "module_system_unittest.cc", - "mojo/keep_alive_client_unittest.cc", "native_extension_bindings_system_unittest.cc", "native_renderer_messaging_service_unittest.cc", "one_time_message_handler_unittest.cc",
diff --git a/extensions/renderer/mojo/keep_alive_client_unittest.cc b/extensions/renderer/mojo/keep_alive_client_unittest.cc deleted file mode 100644 index b6a4166..0000000 --- a/extensions/renderer/mojo/keep_alive_client_unittest.cc +++ /dev/null
@@ -1,143 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <utility> - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/run_loop.h" -#include "extensions/common/extension_builder.h" -#include "extensions/common/mojo/keep_alive.mojom.h" -#include "extensions/common/value_builder.h" -#include "extensions/grit/extensions_renderer_resources.h" -#include "extensions/renderer/api_test_base.h" -#include "extensions/renderer/string_source_map.h" -#include "mojo/public/cpp/bindings/strong_binding.h" - -// A test launcher for tests for the stash client defined in -// extensions/test/data/keep_alive_client_unittest.js. - -namespace extensions { -namespace { - -// A KeepAlive implementation that calls provided callbacks on creation and -// destruction. -class TestKeepAlive : public KeepAlive { - public: - explicit TestKeepAlive(const base::Closure& on_destruction) - : on_destruction_(on_destruction) {} - - ~TestKeepAlive() override { on_destruction_.Run(); } - - static void Create(const base::Closure& on_creation, - const base::Closure& on_destruction, - KeepAliveRequest keep_alive) { - mojo::MakeStrongBinding(std::make_unique<TestKeepAlive>(on_destruction), - std::move(keep_alive)); - on_creation.Run(); - } - - private: - const base::Closure on_destruction_; -}; - -const char kFakeSerialBindings[] = - R"( - var binding = apiBridge || require('binding').Binding.create('serial'); - var utils = require('utils'); - binding.registerCustomHook(function(bindingsAPI) { - utils.handleRequestWithPromiseDoNotUse(bindingsAPI.apiFunctions, - 'serial', 'getDevices', - function() { - if (bindingsAPI.compiledApi.shouldSucceed) { - return Promise.resolve([]); - } else { - return Promise.reject(); - } - }); - }); - - if (!apiBridge) - exports.$set('binding', binding.generate()); - )"; - -} // namespace - -class KeepAliveClientTest : public ApiTestBase { - public: - KeepAliveClientTest() {} - - void SetUp() override { - ApiTestBase::SetUp(); - interface_provider()->AddInterface( - base::Bind(&TestKeepAlive::Create, - base::Bind(&KeepAliveClientTest::KeepAliveCreated, - base::Unretained(this)), - base::Bind(&KeepAliveClientTest::KeepAliveDestroyed, - base::Unretained(this)))); - - // We register fake custom bindings for the serial API to use - // handleRequestWithPromiseDoNotUse(). - env()->source_map()->RegisterModule("serial", kFakeSerialBindings); - } - - scoped_refptr<const Extension> CreateExtension() override { - // Create a platform app with the serial permission. - DictionaryBuilder background; - background.Set("scripts", ListBuilder().Append("test.js").Build()); - - std::unique_ptr<base::DictionaryValue> manifest = - DictionaryBuilder() - .Set("name", "test") - .Set("version", "1.0") - .Set("app", DictionaryBuilder() - .Set("background", background.Build()) - .Build()) - .Set("permissions", ListBuilder().Append("serial").Build()) - .Set("manifest_version", 2) - .Build(); - return ExtensionBuilder().SetManifest(std::move(manifest)).Build(); - } - - void WaitForKeepAlive() { - // Wait for a keep-alive to be created and destroyed. - while (!created_keep_alive_ || !destroyed_keep_alive_) { - base::RunLoop run_loop; - stop_run_loop_ = run_loop.QuitClosure(); - run_loop.Run(); - } - EXPECT_TRUE(created_keep_alive_); - EXPECT_TRUE(destroyed_keep_alive_); - } - - private: - void KeepAliveCreated() { - created_keep_alive_ = true; - if (!stop_run_loop_.is_null()) - stop_run_loop_.Run(); - } - void KeepAliveDestroyed() { - destroyed_keep_alive_ = true; - if (!stop_run_loop_.is_null()) - stop_run_loop_.Run(); - } - - bool created_keep_alive_ = false; - bool destroyed_keep_alive_ = false; - base::Closure stop_run_loop_; - - DISALLOW_COPY_AND_ASSIGN(KeepAliveClientTest); -}; - -TEST_F(KeepAliveClientTest, KeepAliveWithSuccessfulCall) { - RunTest("keep_alive_client_unittest.js", "testKeepAliveWithSuccessfulCall"); - WaitForKeepAlive(); -} - -TEST_F(KeepAliveClientTest, KeepAliveWithError) { - RunTest("keep_alive_client_unittest.js", "testKeepAliveWithError"); - WaitForKeepAlive(); -} - -} // namespace extensions
diff --git a/extensions/renderer/resources/keep_alive.js b/extensions/renderer/resources/keep_alive.js index bbd4ff4..71b4d4c 100644 --- a/extensions/renderer/resources/keep_alive.js +++ b/extensions/renderer/resources/keep_alive.js
@@ -2,40 +2,36 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -define('keep_alive', [ - 'content/public/renderer/frame_interfaces', - 'extensions/common/mojo/keep_alive.mojom', - 'mojo/public/js/core', -], function(frameInterfaces, mojom, core) { +if ((typeof mojo === 'undefined') || !mojo.bindingsLibraryInitialized) { + loadScript('mojo_bindings'); +} +loadScript('extensions/common/mojo/keep_alive.mojom'); +/** + * An object that keeps the background page alive until closed. + * @constructor + * @alias module:keep_alive~KeepAlive + */ +function KeepAlive() { + var pipe = Mojo.createMessagePipe(); /** - * An object that keeps the background page alive until closed. - * @constructor - * @alias module:keep_alive~KeepAlive + * The handle to the keep-alive object in the browser. + * @type {!MojoHandle} + * @private */ - function KeepAlive() { - /** - * The handle to the keep-alive object in the browser. - * @type {!MojoHandle} - * @private - */ - this.handle_ = frameInterfaces.getInterface(mojom.KeepAlive.name); - } + this.handle_ = pipe.handle0; + Mojo.bindInterface(extensions.KeepAlive.name, pipe.handle1); +} - /** - * Removes this keep-alive. - */ - KeepAlive.prototype.close = function() { - core.close(this.handle_); - }; +/** + * Removes this keep-alive. + */ +KeepAlive.prototype.close = function() { + this.handle_.close(); +}; - var exports = {}; - - return { - /** - * Creates a keep-alive. - * @return {!module:keep_alive~KeepAlive} A new keep-alive. - */ - createKeepAlive: function() { return new KeepAlive(); } - }; -}); +/** + * Creates a keep-alive. + * @return {!module:keep_alive~KeepAlive} A new keep-alive. + */ +exports.$set('createKeepAlive', function() { return new KeepAlive(); }); \ No newline at end of file
diff --git a/extensions/renderer/resources/utils.js b/extensions/renderer/resources/utils.js index 0b3d62b4..433fa1c 100644 --- a/extensions/renderer/resources/utils.js +++ b/extensions/renderer/resources/utils.js
@@ -197,9 +197,7 @@ var stack = exceptionHandler.getExtensionStackTrace(); var callback = arguments[arguments.length - 1]; var args = $Array.slice(arguments, 0, arguments.length - 1); - var keepAlivePromise = requireAsync('keep_alive').then(function(module) { - return module.createKeepAlive(); - }); + var keepAlive = require('keep_alive').createKeepAlive(); $Function.apply(customizedFunction, this, args).then(function(result) { if (callback) { exceptionHandler.safeCallbackApply( @@ -211,9 +209,7 @@ runCallbackWithLastError(fullName, message, stack, callback); } }).then(function() { - keepAlivePromise.then(function(keepAlive) { - keepAlive.close(); - }); + keepAlive.close(); }); }); };
diff --git a/extensions/test/data/keep_alive_client_unittest.js b/extensions/test/data/keep_alive_client_unittest.js deleted file mode 100644 index 3a59137..0000000 --- a/extensions/test/data/keep_alive_client_unittest.js +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * Unit tests for the keep-alive client. - * - * They are launched by extensions/renderer/mojo/keep_alive_client_unittest.cc. - */ - -var getApi = requireNative('apiGetter').get; -var test = getApi('test'); -var unittestBindings = require('test_environment_specific_bindings'); -var utils = require('utils'); - -// We need to set custom bindings for a real API and serial.getDevices has a -// simple signature. -var serial = getApi('serial'); -var apiFunction = serial.getDevices; - -function runFunction() { - apiFunction(function() { - if (serial.shouldSucceed) - test.assertNoLastError(); - else - test.assertTrue(!!chrome.runtime.lastError); - test.succeed(); - }); -} - -unittestBindings.exportTests([ - // Test that a keep alive is created and destroyed for a successful API call. - function testKeepAliveWithSuccessfulCall() { - // We cheat and put a property on the API object as a way of passing it to - // the custom hooks. - serial.shouldSucceed = true; - runFunction(); - }, - - // Test that a keep alive is created and destroyed for an unsuccessful API - // call. - function testKeepAliveWithError() { - serial.shouldSucceed = true; - runFunction(); - }, -], test.runTests, exports);
diff --git a/gin/isolate_holder.cc b/gin/isolate_holder.cc index 620e9c8..0018a7f 100644 --- a/gin/isolate_holder.cc +++ b/gin/isolate_holder.cc
@@ -27,6 +27,7 @@ namespace { v8::ArrayBuffer::Allocator* g_array_buffer_allocator = nullptr; +const intptr_t* g_reference_table = nullptr; } // namespace IsolateHolder::IsolateHolder( @@ -39,14 +40,12 @@ : IsolateHolder(std::move(task_runner), access_mode, kAllowAtomicsWait, - nullptr, nullptr) {} IsolateHolder::IsolateHolder( scoped_refptr<base::SingleThreadTaskRunner> task_runner, AccessMode access_mode, AllowAtomicsWaitMode atomics_wait_mode, - const intptr_t* reference, v8::StartupData* startup_data) : access_mode_(access_mode) { v8::ArrayBuffer::Allocator* allocator = g_array_buffer_allocator; @@ -59,10 +58,10 @@ base::SysInfo::AmountOfVirtualMemory()); params.array_buffer_allocator = allocator; params.allow_atomics_wait = atomics_wait_mode == kAllowAtomicsWait; - params.external_references = reference; + params.external_references = g_reference_table; if (startup_data) { - CHECK(reference); + CHECK(g_reference_table); V8Initializer::GetV8ContextSnapshotData(startup_data); if (startup_data->data) { params.snapshot_blob = startup_data; @@ -73,8 +72,7 @@ SetUp(std::move(task_runner)); } -IsolateHolder::IsolateHolder(const intptr_t* reference_table, - v8::StartupData* existing_blob) +IsolateHolder::IsolateHolder(v8::StartupData* existing_blob) : access_mode_(AccessMode::kSingleThread) { CHECK(existing_blob); @@ -85,7 +83,7 @@ } snapshot_creator_.reset( - new v8::SnapshotCreator(reference_table, existing_blob)); + new v8::SnapshotCreator(g_reference_table, existing_blob)); isolate_ = snapshot_creator_->GetIsolate(); SetUp(nullptr); @@ -114,10 +112,12 @@ // static void IsolateHolder::Initialize(ScriptMode mode, V8ExtrasMode v8_extras_mode, - v8::ArrayBuffer::Allocator* allocator) { + v8::ArrayBuffer::Allocator* allocator, + const intptr_t* reference_table) { CHECK(allocator); V8Initializer::Initialize(mode, v8_extras_mode); g_array_buffer_allocator = allocator; + g_reference_table = reference_table; } void IsolateHolder::AddRunMicrotasksObserver() {
diff --git a/gin/public/isolate_holder.h b/gin/public/isolate_holder.h index e2adf65d..f29b2de 100644 --- a/gin/public/isolate_holder.h +++ b/gin/public/isolate_holder.h
@@ -60,13 +60,11 @@ IsolateHolder(scoped_refptr<base::SingleThreadTaskRunner> task_runner, AccessMode access_mode, AllowAtomicsWaitMode atomics_wait_mode, - const intptr_t* reference_table, v8::StartupData* startup_data); // This constructor is to create V8 snapshot for Blink. // Note this constructor calls isolate->Enter() internally. - IsolateHolder(const intptr_t* reference_table, - v8::StartupData* existing_blob); + explicit IsolateHolder(v8::StartupData* existing_blob); ~IsolateHolder(); @@ -78,9 +76,13 @@ // snapshot file is available, it should also be loaded (by calling // V8Initializer::LoadV8SnapshotFromFD or // V8Initializer::LoadV8Snapshot) before calling this method. + // If the snapshot file contains customised contexts which have static + // external references, |reference_table| needs to point an array of those + // reference pointers. Otherwise, it can be nullptr. static void Initialize(ScriptMode mode, V8ExtrasMode v8_extras_mode, - v8::ArrayBuffer::Allocator* allocator); + v8::ArrayBuffer::Allocator* allocator, + const intptr_t* reference_table = nullptr); v8::Isolate* isolate() { return isolate_; }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h index b591103..f2d89c6 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -386,6 +386,8 @@ return feature_info_->feature_flags(); } + void ExitCommandProcessingEarly() { commands_to_process_ = 0; } + GLES2DecoderClient* client_; int commands_to_process_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index aea3e05b..393578a6 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -655,6 +655,11 @@ api()->glCompressedTexImage2DRobustANGLEFn(target, level, internalformat, width, height, border, image_size, data_size, data); + + // Texture data upload can be slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } @@ -672,6 +677,11 @@ api()->glCompressedTexSubImage2DRobustANGLEFn(target, level, xoffset, yoffset, width, height, format, image_size, data_size, data); + + // Texture data upload can be slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } @@ -689,6 +699,11 @@ api()->glCompressedTexImage3DRobustANGLEFn(target, level, internalformat, width, height, depth, border, image_size, data_size, data); + + // Texture data upload can be slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } @@ -708,6 +723,11 @@ api()->glCompressedTexSubImage3DRobustANGLEFn( target, level, xoffset, yoffset, zoffset, width, height, depth, format, image_size, data_size, data); + + // Texture data upload can be slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } @@ -733,6 +753,11 @@ GLint border) { api()->glCopyTexImage2DFn(target, level, internalformat, x, y, width, height, border); + + // Texture data copying can be slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } @@ -746,6 +771,11 @@ GLsizei height) { api()->glCopyTexSubImage2DFn(target, level, xoffset, yoffset, x, y, width, height); + + // Texture data copying can be slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } @@ -760,6 +790,11 @@ GLsizei height) { api()->glCopyTexSubImage3DFn(target, level, xoffset, yoffset, zoffset, x, y, width, height); + + // Texture data copying can be slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } @@ -1997,6 +2032,11 @@ error::Error GLES2DecoderPassthroughImpl::DoLinkProgram(GLuint program) { api()->glLinkProgramFn(GetProgramServiceID(program, resources_)); + + // Program linking can be very slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } @@ -2271,6 +2311,11 @@ api(), image_size != 0 && feature_info_->gl_version_info().is_es3, false); api()->glTexImage2DRobustANGLEFn(target, level, internalformat, width, height, border, format, type, image_size, pixels); + + // Texture data upload can be slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } @@ -2290,6 +2335,11 @@ api()->glTexImage3DRobustANGLEFn(target, level, internalformat, width, height, depth, border, format, type, image_size, pixels); + + // Texture data upload can be slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } @@ -2353,6 +2403,11 @@ api(), image_size != 0 && feature_info_->gl_version_info().is_es3, false); api()->glTexSubImage2DRobustANGLEFn(target, level, xoffset, yoffset, width, height, format, type, image_size, pixels); + + // Texture data upload can be slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } @@ -2373,6 +2428,11 @@ api()->glTexSubImage3DRobustANGLEFn(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, image_size, pixels); + + // Texture data upload can be slow. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; }
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json index e59e7faa..94d39587 100644 --- a/gpu/config/software_rendering_list.json +++ b/gpu/config/software_rendering_list.json
@@ -986,12 +986,13 @@ { "id": 112, "description": "Intel HD 3000 driver crashes frequently on Mac", - "cr_bugs": [592130], + "cr_bugs": [592130, 661596], "os": { "type": "macosx" }, "vendor_id": "0x8086", "device_id": ["0x0116", "0x0126"], + "multi_gpu_category": "any", "features": [ "all" ]
diff --git a/gpu/khronos_glcts_support/BUILD.gn b/gpu/khronos_glcts_support/BUILD.gn index aa7b2c8..ace65c5 100644 --- a/gpu/khronos_glcts_support/BUILD.gn +++ b/gpu/khronos_glcts_support/BUILD.gn
@@ -265,12 +265,10 @@ configs += [ "//build/config/compiler:no_chromium_code" ] configs -= [ "//build/config/compiler:no_rtti" ] configs += [ "//build/config/compiler:rtti" ] + configs -= [ "//build/config/compiler:no_exceptions" ] + configs += [ "//build/config/compiler:exceptions" ] public_configs = [ ":decpp_config" ] - - if (is_linux) { - configs -= [ "//build/config/gcc:no_exceptions" ] - } } group("delibs") { @@ -403,11 +401,12 @@ configs += [ "//build/config/compiler:no_chromium_code" ] configs -= [ "//build/config/compiler:no_rtti" ] configs += [ "//build/config/compiler:rtti" ] + configs -= [ "//build/config/compiler:no_exceptions" ] + configs += [ "//build/config/compiler:exceptions" ] public_configs = [ ":tcutil_config" ] if (is_linux) { - configs -= [ "//build/config/gcc:no_exceptions" ] cflags_cc = [ "-Wno-int-to-pointer-cast" ] } } @@ -442,12 +441,10 @@ configs += [ "//build/config/compiler:no_chromium_code" ] configs -= [ "//build/config/compiler:no_rtti" ] configs += [ "//build/config/compiler:rtti" ] + configs -= [ "//build/config/compiler:no_exceptions" ] + configs += [ "//build/config/compiler:exceptions" ] public_configs = [ ":glwrapper_config" ] - - if (is_linux) { - configs -= [ "//build/config/gcc:no_exceptions" ] - } } config("glutil_config") { @@ -502,12 +499,10 @@ configs += [ "//build/config/compiler:no_chromium_code" ] configs -= [ "//build/config/compiler:no_rtti" ] configs += [ "//build/config/compiler:rtti" ] + configs -= [ "//build/config/compiler:no_exceptions" ] + configs += [ "//build/config/compiler:exceptions" ] public_configs = [ ":glutil_config" ] - - if (is_linux) { - configs -= [ "//build/config/gcc:no_exceptions" ] - } } config("tcutil_egl_config") { @@ -543,6 +538,8 @@ configs += [ "//build/config/compiler:no_chromium_code" ] configs -= [ "//build/config/compiler:no_rtti" ] configs += [ "//build/config/compiler:rtti" ] + configs -= [ "//build/config/compiler:no_exceptions" ] + configs += [ "//build/config/compiler:exceptions" ] public_configs = [ ":tcutil_egl_config", @@ -550,7 +547,6 @@ ] if (is_linux) { - configs -= [ "//build/config/gcc:no_exceptions" ] cflags_cc = [ "-Wno-int-to-void-pointer-cast" ] } } @@ -624,11 +620,12 @@ configs += [ "//build/config/compiler:no_chromium_code" ] configs -= [ "//build/config/compiler:no_rtti" ] configs += [ "//build/config/compiler:rtti" ] + configs -= [ "//build/config/compiler:no_exceptions" ] + configs += [ "//build/config/compiler:exceptions" ] public_configs = [ ":glcts_common_config" ] if (is_linux) { - configs -= [ "//build/config/gcc:no_exceptions" ] cflags_cc = [ "-Wno-string-conversion" ] } } @@ -659,12 +656,10 @@ configs += [ "//build/config/compiler:no_chromium_code" ] configs -= [ "//build/config/compiler:no_rtti" ] configs += [ "//build/config/compiler:rtti" ] + configs -= [ "//build/config/compiler:no_exceptions" ] + configs += [ "//build/config/compiler:exceptions" ] public_configs = [ ":glcts_gtf_wrapper_config" ] - - if (is_linux) { - configs -= [ "//build/config/gcc:no_exceptions" ] - } } config("gtf_es_config") { @@ -874,12 +869,10 @@ configs += [ "//build/config/compiler:no_chromium_code" ] configs -= [ "//build/config/compiler:no_rtti" ] configs += [ "//build/config/compiler:rtti" ] + configs -= [ "//build/config/compiler:no_exceptions" ] + configs += [ "//build/config/compiler:exceptions" ] public_configs = [ ":glcts_gtf_config" ] - - if (is_linux) { - configs -= [ "//build/config/gcc:no_exceptions" ] - } } config("glcts_es2_config") { @@ -907,12 +900,10 @@ configs += [ "//build/config/compiler:no_chromium_code" ] configs -= [ "//build/config/compiler:no_rtti" ] configs += [ "//build/config/compiler:rtti" ] + configs -= [ "//build/config/compiler:no_exceptions" ] + configs += [ "//build/config/compiler:exceptions" ] public_configs = [ ":glcts_es2_config" ] - - if (is_linux) { - configs -= [ "//build/config/gcc:no_exceptions" ] - } } source_set("tcutil_platform_windowless") { @@ -947,10 +938,8 @@ configs += [ ":defaults_config" ] configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] - - if (is_linux) { - configs -= [ "//build/config/gcc:no_exceptions" ] - } + configs -= [ "//build/config/compiler:no_exceptions" ] + configs += [ "//build/config/compiler:exceptions" ] } }
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index d28fbc1..da5186f 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -425,6 +425,7 @@ ] deps += [ + "//components/crash/core/common:crash_key", "//components/security_state/content", "//gin", "//third_party/WebKit/public:blink", @@ -495,6 +496,7 @@ deps = [ ":headless", + "//components/crash/core/common:crash_key", "//third_party/WebKit/public:blink_headers", "//ui/base", "//v8", @@ -804,7 +806,10 @@ "lib/headless_content_main_delegate.h", "lib/headless_content_main_delegate_win.cc", ] - deps += [ "//third_party/WebKit/public:blink_headers" ] + deps += [ + "//components/crash/core/common:crash_key", + "//third_party/WebKit/public:blink_headers", + ] } configs += [ ":headless_implementation" ] @@ -841,7 +846,10 @@ "lib/utility/headless_content_utility_client.cc", "lib/utility/headless_content_utility_client.h", ] - deps += [ "//third_party/WebKit/public:blink_headers" ] + deps += [ + "//components/crash/core/common:crash_key", + "//third_party/WebKit/public:blink_headers", + ] } configs += [ ":headless_implementation" ]
diff --git a/headless/DEPS b/headless/DEPS index 6f55996..5a088fd 100644 --- a/headless/DEPS +++ b/headless/DEPS
@@ -2,6 +2,7 @@ "+components/cookie_config", "+components/crash/content/app", "+components/crash/content/browser", + "+components/crash/core/common/crash_key.h", "+components/os_crypt", "+components/printing/service/public/cpp", "+components/printing/service/public/interfaces",
diff --git a/headless/lib/browser/headless_network_delegate.cc b/headless/lib/browser/headless_network_delegate.cc index 65377c5..51e3960 100644 --- a/headless/lib/browser/headless_network_delegate.cc +++ b/headless/lib/browser/headless_network_delegate.cc
@@ -114,7 +114,7 @@ } bool HeadlessNetworkDelegate::OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) { return true; }
diff --git a/headless/lib/browser/headless_network_delegate.h b/headless/lib/browser/headless_network_delegate.h index ccfb5f6..66ed815 100644 --- a/headless/lib/browser/headless_network_delegate.h +++ b/headless/lib/browser/headless_network_delegate.h
@@ -66,7 +66,7 @@ const net::CookieList& cookie_list) override; bool OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) override; bool OnCanAccessFile(const net::URLRequest& request,
diff --git a/headless/lib/headless_content_main_delegate.cc b/headless/lib/headless_content_main_delegate.cc index 0c81255..30e19fa 100644 --- a/headless/lib/headless_content_main_delegate.cc +++ b/headless/lib/headless_content_main_delegate.cc
@@ -17,6 +17,7 @@ #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "components/crash/content/app/breakpad_linux.h" +#include "components/crash/core/common/crash_key.h" #include "content/public/browser/browser_main_runner.h" #include "content/public/common/content_switches.h" #include "headless/lib/browser/headless_browser_impl.h" @@ -186,6 +187,8 @@ g_headless_crash_client.Pointer()->set_crash_dumps_dir( browser_->options()->crash_dumps_dir); + crash_reporter::InitializeCrashKeys(); + #if defined(HEADLESS_USE_BREAKPAD) if (!browser_->options()->enable_crash_reporter) { DCHECK(!breakpad::IsCrashReporterEnabled());
diff --git a/headless/lib/renderer/headless_print_render_frame_helper_delegate.cc b/headless/lib/renderer/headless_print_render_frame_helper_delegate.cc index b3dc8acf..21dded7 100644 --- a/headless/lib/renderer/headless_print_render_frame_helper_delegate.cc +++ b/headless/lib/renderer/headless_print_render_frame_helper_delegate.cc
@@ -37,10 +37,4 @@ return true; } -#if defined(OS_MACOSX) -bool HeadlessPrintRenderFrameHelperDelegate::UseSingleMetafile() { - return true; -} -#endif - } // namespace headless
diff --git a/headless/lib/renderer/headless_print_render_frame_helper_delegate.h b/headless/lib/renderer/headless_print_render_frame_helper_delegate.h index 7e7b313..c23a7e98 100644 --- a/headless/lib/renderer/headless_print_render_frame_helper_delegate.h +++ b/headless/lib/renderer/headless_print_render_frame_helper_delegate.h
@@ -5,7 +5,7 @@ #ifndef HEADLESS_LIB_RENDERER_HEADLESS_PRINT_RENDER_FRAME_HELPER_DELEGATE_H_ #define HEADLESS_LIB_RENDERER_HEADLESS_PRINT_RENDER_FRAME_HELPER_DELEGATE_H_ -#include "build/build_config.h" +#include "base/macros.h" #include "components/printing/renderer/print_render_frame_helper.h" namespace headless { @@ -23,9 +23,7 @@ bool IsAskPrintSettingsEnabled() override; blink::WebElement GetPdfElement(blink::WebLocalFrame* frame) override; -#if defined(OS_MACOSX) - bool UseSingleMetafile() override; -#endif + DISALLOW_COPY_AND_ASSIGN(HeadlessPrintRenderFrameHelperDelegate); }; } // namespace headless
diff --git a/headless/lib/virtual_time_browsertest.cc b/headless/lib/virtual_time_browsertest.cc index 8637799..35ab20b0 100644 --- a/headless/lib/virtual_time_browsertest.cc +++ b/headless/lib/virtual_time_browsertest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include <memory> +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "content/public/test/browser_test.h" #include "headless/public/devtools/domains/emulation.h" @@ -159,18 +160,20 @@ .spec()); } - void MaybeSetVirtualTimePolicy() override { - if (!page_enabled || !runtime_enabled) + void OnFrameStartedLoading( + const page::FrameStartedLoadingParams& params) override { + if (initial_load_seen_) return; - - // To avoid race conditions start with virtual time paused. + initial_load_seen_ = true; + // The navigation is underway, so allow virtual time to advance while + // network fetches are not pending. devtools_client_->GetEmulation()->GetExperimental()->SetVirtualTimePolicy( emulation::SetVirtualTimePolicyParams::Builder() - .SetPolicy(emulation::VirtualTimePolicy::PAUSE) + .SetPolicy( + emulation::VirtualTimePolicy::PAUSE_IF_NETWORK_FETCHES_PENDING) + .SetBudget(4000) .SetMaxVirtualTimeTaskStarvationCount(100) - .Build(), - base::Bind(&VirtualTimeBrowserTest::SetVirtualTimePolicyDone, - base::Unretained(this))); + .Build()); } // emulation::Observer implementation: @@ -280,6 +283,116 @@ HEADLESS_ASYNC_DEVTOOLED_TEST_F( FrameDetatchWithPendingResourceLoadVirtualTimeTest); +class VirtualTimeLocalStorageTest : public VirtualTimeBrowserTest { + public: + VirtualTimeLocalStorageTest() { + EXPECT_TRUE(embedded_test_server()->Start()); + SetInitialURL(embedded_test_server() + ->GetURL("/virtual_time_local_storage.html") + .spec()); + } + + void OnFrameStartedLoading( + const page::FrameStartedLoadingParams& params) override { + if (initial_load_seen_) + return; + initial_load_seen_ = true; + // The navigation is underway, so allow virtual time to advance while + // network fetches are not pending. + devtools_client_->GetEmulation()->GetExperimental()->SetVirtualTimePolicy( + emulation::SetVirtualTimePolicyParams::Builder() + .SetPolicy( + emulation::VirtualTimePolicy::PAUSE_IF_NETWORK_FETCHES_PENDING) + .SetBudget(4001) + .SetMaxVirtualTimeTaskStarvationCount(100) + .Build()); + } + + void OnConsoleAPICalled( + const runtime::ConsoleAPICalledParams& params) override { + EXPECT_EQ(runtime::ConsoleAPICalledType::LOG, params.GetType()); + ASSERT_EQ(1u, params.GetArgs()->size()); + ASSERT_EQ(runtime::RemoteObjectType::STRING, + (*params.GetArgs())[0]->GetType()); + std::string count_string = (*params.GetArgs())[0]->GetValue()->GetString(); + int count; + ASSERT_TRUE(base::StringToInt(count_string, &count)) << count_string; + // We don't care what exact number |count| has as long as it's not too small + // or too large. + EXPECT_GT(count, 100); + EXPECT_LT(count, 1000); + console_log_seen_ = true; + } + + // emulation::Observer implementation: + void OnVirtualTimeBudgetExpired( + const emulation::VirtualTimeBudgetExpiredParams& params) override { + // If SetMaxVirtualTimeTaskStarvationCount was not set, this callback would + // never fire. + EXPECT_TRUE(console_log_seen_); + FinishAsynchronousTest(); + } + + bool console_log_seen_ = false; +}; + +HEADLESS_ASYNC_DEVTOOLED_TEST_F(VirtualTimeLocalStorageTest); + +class VirtualTimeSessionStorageTest : public VirtualTimeBrowserTest { + public: + VirtualTimeSessionStorageTest() { + EXPECT_TRUE(embedded_test_server()->Start()); + SetInitialURL(embedded_test_server() + ->GetURL("/virtual_time_session_storage.html") + .spec()); + } + + void OnFrameStartedLoading( + const page::FrameStartedLoadingParams& params) override { + if (initial_load_seen_) + return; + initial_load_seen_ = true; + // The navigation is underway, so allow virtual time to advance while + // network fetches are not pending. + devtools_client_->GetEmulation()->GetExperimental()->SetVirtualTimePolicy( + emulation::SetVirtualTimePolicyParams::Builder() + .SetPolicy( + emulation::VirtualTimePolicy::PAUSE_IF_NETWORK_FETCHES_PENDING) + .SetBudget(4001) + .SetMaxVirtualTimeTaskStarvationCount(100) + .Build()); + } + + void OnConsoleAPICalled( + const runtime::ConsoleAPICalledParams& params) override { + EXPECT_EQ(runtime::ConsoleAPICalledType::LOG, params.GetType()); + ASSERT_EQ(1u, params.GetArgs()->size()); + ASSERT_EQ(runtime::RemoteObjectType::STRING, + (*params.GetArgs())[0]->GetType()); + std::string count_string = (*params.GetArgs())[0]->GetValue()->GetString(); + int count; + ASSERT_TRUE(base::StringToInt(count_string, &count)) << count_string; + // We don't care what exact number |count| has as long as it's not too small + // or too large. + EXPECT_GT(count, 100); + EXPECT_LT(count, 1000); + console_log_seen_ = true; + } + + // emulation::Observer implementation: + void OnVirtualTimeBudgetExpired( + const emulation::VirtualTimeBudgetExpiredParams& params) override { + // If SetMaxVirtualTimeTaskStarvationCount was not set, this callback would + // never fire. + EXPECT_TRUE(console_log_seen_); + FinishAsynchronousTest(); + } + + bool console_log_seen_ = false; +}; + +HEADLESS_ASYNC_DEVTOOLED_TEST_F(VirtualTimeSessionStorageTest); + class DeferredLoadDoesntBlockVirtualTimeTest : public VirtualTimeBrowserTest { public: DeferredLoadDoesntBlockVirtualTimeTest() {
diff --git a/headless/test/data/virtual_time_local_storage.html b/headless/test/data/virtual_time_local_storage.html new file mode 100644 index 0000000..1811f14 --- /dev/null +++ b/headless/test/data/virtual_time_local_storage.html
@@ -0,0 +1,24 @@ +<html> +<body> +<script> +// Create an iframe to receive and send storage events with. +var iframe = document.createElement('iframe'); +document.body.appendChild(iframe); +iframe.contentWindow.document.open(); +iframe.contentWindow.document.write('<body></body>'); +iframe.contentWindow.document.close(); + +var listener = function(event) { + var event_count = Number(localStorage.event_count); + localStorage.event_count = event_count + 1; +} +iframe.contentWindow.addEventListener('storage', listener, false); +localStorage.event_count = 0; + +// Print the number of events after 4 seconds. +setTimeout(function() { + console.log(localStorage.event_count); +}, 4000); +</script> +</body> +</html>
diff --git a/headless/test/data/virtual_time_session_storage.html b/headless/test/data/virtual_time_session_storage.html new file mode 100644 index 0000000..455ffac --- /dev/null +++ b/headless/test/data/virtual_time_session_storage.html
@@ -0,0 +1,24 @@ +<html> +<body> +<script> +// Create an iframe to receive and send storage events with. +var iframe = document.createElement('iframe'); +document.body.appendChild(iframe); +iframe.contentWindow.document.open(); +iframe.contentWindow.document.write('<body></body>'); +iframe.contentWindow.document.close(); + +var listener = function(event) { + var event_count = Number(sessionStorage.event_count); + sessionStorage.event_count = event_count + 1; +} +iframe.contentWindow.addEventListener('storage', listener, false); +sessionStorage.event_count = 0; + +// Print the number of events after 4 seconds. +setTimeout(function() { + console.log(sessionStorage.event_count); +}, 4000); +</script> +</body> +</html>
diff --git a/ios/build/bots/scripts/run.py b/ios/build/bots/scripts/run.py index 25b5e78e..ff5e50d 100755 --- a/ios/build/bots/scripts/run.py +++ b/ios/build/bots/scripts/run.py
@@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright 2016 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -10,11 +10,12 @@ -a src/xcodebuild/Release-iphoneos/base_unittests.app \ -o /tmp/out \ -p iPhone 5s \ - -v 9.3 + -v 9.3 \ + -b 9b46 - Installs base_unittests.app in an iPhone 5s simulator running iOS 9.3, - runs it, and captures all test data in /tmp/out. -""" + Installs base_unittests.app in an iPhone 5s simulator running iOS 9.3 under + Xcode build version 9b46, runs it, and captures all test data in /tmp/out. + """ import argparse import json @@ -25,7 +26,9 @@ import test_runner -def main(args, test_args): +def main(): + args, test_args = parse_args() + summary = {} tr = None @@ -40,21 +43,27 @@ args.platform, args.version, args.xcode_version, + args.xcode_build_version, args.out_dir, env_vars=args.env_var, + mac_toolchain=args.mac_toolchain_cmd, retries=args.retries, test_args=test_args, + xcode_path=args.xcode_path, xctest=args.xctest, ) else: tr = test_runner.DeviceTestRunner( args.app, args.xcode_version, + args.xcode_build_version, args.out_dir, env_vars=args.env_var, + mac_toolchain=args.mac_toolchain_cmd, restart=args.restart, retries=args.retries, test_args=test_args, + xcode_path=args.xcode_path, xctest=args.xctest, ) @@ -79,7 +88,7 @@ json.dump(tr.test_results, f) -if __name__ == '__main__': +def parse_args(): parser = argparse.ArgumentParser() parser.add_argument( @@ -141,11 +150,31 @@ metavar='ver', ) parser.add_argument( + '-b', + '--xcode-build-version', + help='Xcode build version to install.', + metavar='build_id', + ) + parser.add_argument( '-x', '--xcode-version', - help='Version of Xcode to use.', + help='Version of Xcode to use. DEPRECATED by --xcode-build-version.', metavar='ver', - required=True, + ) + parser.add_argument( + '--xcode-path', + metavar='PATH', + help=('Path to <Xcode>.app folder where contents of the app will be ' + 'installed. Default: %(default)s. WARNING: this folder will be ' + 'overwritten! This folder is intended to be a cached CIPD ' + 'installation.'), + default='Xcode.app', + ) + parser.add_argument( + '--mac-toolchain-cmd', + help='Command to run mac_toolchain tool. Default: %(default)s.', + default='mac_toolchain', + metavar='mac_toolchain', ) parser.add_argument( '--xctest', @@ -161,6 +190,10 @@ parser.error( 'must specify all or none of -i/--iossim, -p/--platform, -v/--version') + if not (bool(args.xcode_version) ^ bool(args.xcode_build_version)): + parser.error( + 'must specify exactly one of --xcode-build-version or --xcode-version') + args_json = json.loads(args.args_json) args.env_var = args.env_var or [] args.env_var.extend(args_json.get('env_var', [])) @@ -168,4 +201,8 @@ args.xctest = args_json.get('xctest', args.xctest) test_args.extend(args_json.get('test_args', [])) - sys.exit(main(args, test_args)) + return args, test_args + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py index aa1f68a6..99d4fe4 100644 --- a/ios/build/bots/scripts/test_runner.py +++ b/ios/build/bots/scripts/test_runner.py
@@ -90,6 +90,20 @@ 'XCTest not found: %s', xctest_path) +class MacToolchainNotFoundError(TestRunnerError): + """The mac_toolchain is not specified.""" + def __init__(self, mac_toolchain): + super(MacToolchainNotFoundError, self).__init__( + 'mac_toolchain is not specified or not found: "%s"' % mac_toolchain) + + +class XcodePathNotFoundError(TestRunnerError): + """The path to Xcode.app is not specified.""" + def __init__(self, xcode_path): + super(XcodePathNotFoundError, self).__init__( + 'xcode_path is not specified or does not exist: "%s"' % xcode_path) + + def get_kif_test_filter(tests, invert=False): """Returns the KIF test filter to filter the given test cases. @@ -130,6 +144,58 @@ return test_filter +def xcode_select(xcode_app_path): + """Switch the default Xcode system-wide to `xcode_app_path`. + + Raises subprocess.CalledProcessError on failure. + To be mocked in tests. + """ + subprocess.check_call([ + 'sudo', + 'xcode-select', + '-switch', + xcode_app_path, + ]) + + +def install_xcode(xcode_build_version, mac_toolchain_cmd, xcode_app_path): + """Installs the requested Xcode build version. + + Args: + xcode_build_version: (string) Xcode build version to install. + mac_toolchain_cmd: (string) Path to mac_toolchain command to install Xcode. + See https://chromium.googlesource.com/infra/infra/+/master/go/src/infra/cmd/mac_toolchain/ + xcode_app_path: (string) Path to install the contents of Xcode.app. + + Returns: + True if installation was successful. False otherwise. + """ + try: + if not mac_toolchain_cmd: + raise MacToolchainNotFoundError(mac_toolchain_cmd) + # Guard against incorrect install paths. On swarming, this path + # should be a requested named cache, and it must exist. + if not os.path.exists(xcode_app_path): + raise XcodePathNotFoundError(xcode_app_path) + + subprocess.check_call([ + mac_toolchain_cmd, 'install', + '-kind', 'ios', + '-xcode-version', xcode_build_version.lower(), + '-output-dir', xcode_app_path, + ]) + xcode_select(xcode_app_path) + except subprocess.CalledProcessError as e: + # Flush buffers to ensure correct output ordering. + sys.stdout.flush() + sys.stderr.write('Xcode build version %s failed to install: %s\n' % ( + xcode_build_version, e)) + sys.stderr.flush() + return False + + return True + + class TestRunner(object): """Base class containing common functionality.""" @@ -137,22 +203,29 @@ self, app_path, xcode_version, + xcode_build_version, out_dir, env_vars=None, + mac_toolchain='', retries=None, test_args=None, + xcode_path='', xctest=False, ): """Initializes a new instance of this class. Args: app_path: Path to the compiled .app to run. - xcode_version: Version of Xcode to use when running the test. + xcode_version: (deprecated by xcode_build_version) Version of Xcode to use + when running the test. + xcode_build_version: Xcode build version to install before running tests. out_dir: Directory to emit test data into. env_vars: List of environment variables to pass to the test itself. + mac_toolchain: Command to run `mac_toolchain` tool. retries: Number of times to retry failed test cases. test_args: List of strings to pass as arguments to the test when launching. + xcode_path: Path to Xcode.app folder where its contents will be installed. xctest: Whether or not this is an XCTest. Raises: @@ -165,7 +238,10 @@ if not os.path.exists(app_path): raise AppNotFoundError(app_path) - if not find_xcode.find_xcode(xcode_version)['found']: + if xcode_build_version: + if not install_xcode(xcode_build_version, mac_toolchain, xcode_path): + raise XcodeVersionNotFoundError(xcode_build_version) + elif not find_xcode.find_xcode(xcode_version)['found']: raise XcodeVersionNotFoundError(xcode_version) if not os.path.exists(out_dir): @@ -409,10 +485,13 @@ platform, version, xcode_version, + xcode_build_version, out_dir, env_vars=None, + mac_toolchain='', retries=None, test_args=None, + xcode_path='', xctest=False, ): """Initializes a new instance of this class. @@ -424,12 +503,16 @@ by running "iossim -l". e.g. "iPhone 5s", "iPad Retina". version: Version of iOS the platform should be running. Supported values can be found by running "iossim -l". e.g. "9.3", "8.2", "7.1". - xcode_version: Version of Xcode to use when running the test. + xcode_version: (deprecated by xcode_build_version) Version of Xcode to use + when running the test. + xcode_build_version: Xcode build version to install before running tests. out_dir: Directory to emit test data into. env_vars: List of environment variables to pass to the test itself. + mac_toolchain: Command to run `mac_toolchain` tool. retries: Number of times to retry failed test cases. test_args: List of strings to pass as arguments to the test when launching. + xcode_path: Path to Xcode.app folder where its contents will be installed. xctest: Whether or not this is an XCTest. Raises: @@ -441,10 +524,13 @@ super(SimulatorTestRunner, self).__init__( app_path, xcode_version, + xcode_build_version, out_dir, env_vars=env_vars, + mac_toolchain=mac_toolchain, retries=retries, test_args=test_args, + xcode_path=xcode_path, xctest=xctest, ) @@ -628,25 +714,32 @@ self, app_path, xcode_version, + xcode_build_version, out_dir, env_vars=None, + mac_toolchain='', restart=False, retries=None, test_args=None, xctest=False, + xcode_path='', ): """Initializes a new instance of this class. Args: app_path: Path to the compiled .app to run. - xcode_version: Version of Xcode to use when running the test. + xcode_version: (deprecated by xcode_build_version) Version of Xcode to use + when running the test. + xcode_build_version: Xcode build version to install before running tests. out_dir: Directory to emit test data into. env_vars: List of environment variables to pass to the test itself. + mac_toolchain: Command to run `mac_toolchain` tool. restart: Whether or not restart device when test app crashes on startup. retries: Number of times to retry failed test cases. test_args: List of strings to pass as arguments to the test when launching. xctest: Whether or not this is an XCTest. + xcode_path: Path to Xcode.app folder where its contents will be installed. Raises: AppNotFoundError: If the given app does not exist. @@ -657,11 +750,14 @@ super(DeviceTestRunner, self).__init__( app_path, xcode_version, + xcode_build_version, out_dir, env_vars=env_vars, retries=retries, test_args=test_args, xctest=xctest, + mac_toolchain=mac_toolchain, + xcode_path=xcode_path, ) self.udid = subprocess.check_output(['idevice_id', '--list']).rstrip()
diff --git a/ios/build/bots/scripts/test_runner_test.py b/ios/build/bots/scripts/test_runner_test.py index a9eef717..d00d2c1 100755 --- a/ios/build/bots/scripts/test_runner_test.py +++ b/ios/build/bots/scripts/test_runner_test.py
@@ -96,102 +96,85 @@ test_runner.get_gtest_filter(tests, invert=True), expected) +class InstallXcodeTest(TestCase): + """Tests install_xcode.""" + + def setUp(self): + super(InstallXcodeTest, self).setUp() + self.mock(test_runner, 'xcode_select', lambda _: None) + self.mock(os.path, 'exists', lambda _: True) + + def test_success(self): + self.assertTrue(test_runner.install_xcode('test_build', 'true', 'path')) + + def test_failure(self): + self.assertFalse(test_runner.install_xcode('test_build', 'false', 'path')) + + class SimulatorTestRunnerTest(TestCase): """Tests for test_runner.SimulatorTestRunner.""" - def test_app_not_found(self): - """Ensures AppNotFoundError is raised.""" - def exists(path): - if path == 'fake-app': - return False + def setUp(self): + super(SimulatorTestRunnerTest, self).setUp() + + def install_xcode(build, mac_toolchain_cmd, xcode_app_path): return True - def find_xcode(version): - return {'found': True} + self.mock(test_runner.find_xcode, 'find_xcode', + lambda _: {'found': True}) + self.mock(test_runner, 'install_xcode', install_xcode) + self.mock(test_runner.subprocess, 'check_output', + lambda _: 'fake-bundle-id') + self.mock(os.path, 'abspath', lambda path: '/abs/path/to/%s' % path) + self.mock(os.path, 'exists', lambda _: True) - def check_output(command): - return 'fake-bundle-id' + def test_app_not_found(self): + """Ensures AppNotFoundError is raised.""" - self.mock(test_runner.os.path, 'exists', exists) - self.mock(test_runner.find_xcode, 'find_xcode', find_xcode) - self.mock(test_runner.subprocess, 'check_output', check_output) + self.mock(os.path, 'exists', lambda p: not p.endswith('fake-app')) - self.assertRaises( - test_runner.AppNotFoundError, - test_runner.SimulatorTestRunner, + with self.assertRaises(test_runner.AppNotFoundError): + test_runner.SimulatorTestRunner( 'fake-app', 'fake-iossim', 'platform', 'os', 'xcode-version', + '', # Empty xcode-build 'out-dir', - ) + ) def test_iossim_not_found(self): """Ensures SimulatorNotFoundError is raised.""" - def exists(path): - if path == 'fake-iossim': - return False - return True + self.mock(os.path, 'exists', lambda p: not p.endswith('fake-iossim')) - def find_xcode(version): - return {'found': True} - - def check_output(command): - return 'fake-bundle-id' - - self.mock(test_runner.os.path, 'exists', exists) - self.mock(test_runner.find_xcode, 'find_xcode', find_xcode) - self.mock(test_runner.subprocess, 'check_output', check_output) - - self.assertRaises( - test_runner.SimulatorNotFoundError, - test_runner.SimulatorTestRunner, + with self.assertRaises(test_runner.SimulatorNotFoundError): + test_runner.SimulatorTestRunner( 'fake-app', 'fake-iossim', 'platform', 'os', 'xcode-version', + 'xcode-build', 'out-dir', - ) + ) def test_init(self): """Ensures instance is created.""" - def exists(path): - return True - - def find_xcode(version): - return {'found': True} - - def check_output(command): - return 'fake-bundle-id' - - self.mock(test_runner.os.path, 'exists', exists) - self.mock(test_runner.find_xcode, 'find_xcode', find_xcode) - self.mock(test_runner.subprocess, 'check_output', check_output) - tr = test_runner.SimulatorTestRunner( 'fake-app', 'fake-iossim', 'platform', 'os', 'xcode-version', + 'xcode-build', 'out-dir', ) - self.failUnless(tr) + self.assertTrue(tr) def test_startup_crash(self): """Ensures test is relaunched once on startup crash.""" - def exists(path): - return True - - def find_xcode(version): - return {'found': True} - - def check_output(command): - return 'fake-bundle-id' - def set_up(self): return @@ -203,9 +186,6 @@ def tear_down(self): return - self.mock(test_runner.os.path, 'exists', exists) - self.mock(test_runner.find_xcode, 'find_xcode', find_xcode) - self.mock(test_runner.subprocess, 'check_output', check_output) self.mock(test_runner.SimulatorTestRunner, 'set_up', set_up) self.mock(test_runner.TestRunner, '_run', _run) self.mock(test_runner.SimulatorTestRunner, 'tear_down', tear_down) @@ -216,21 +196,14 @@ 'platform', 'os', 'xcode-version', + 'xcode-build', 'out-dir', ) - self.assertRaises(test_runner.AppLaunchError, tr.launch) + with self.assertRaises(test_runner.AppLaunchError): + tr.launch() def test_relaunch(self): """Ensures test is relaunched on test crash until tests complete.""" - def exists(path): - return True - - def find_xcode(version): - return {'found': True} - - def check_output(command): - return 'fake-bundle-id' - def set_up(self): return @@ -266,9 +239,6 @@ def tear_down(self): return - self.mock(test_runner.os.path, 'exists', exists) - self.mock(test_runner.find_xcode, 'find_xcode', find_xcode) - self.mock(test_runner.subprocess, 'check_output', check_output) self.mock(test_runner.SimulatorTestRunner, 'set_up', set_up) self.mock(test_runner.TestRunner, '_run', _run) self.mock(test_runner.SimulatorTestRunner, 'tear_down', tear_down) @@ -279,10 +249,11 @@ 'platform', 'os', 'xcode-version', + 'xcode-build', 'out-dir', ) tr.launch() - self.failUnless(tr.logs) + self.assertTrue(tr.logs) if __name__ == '__main__':
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index c6a7828..5e8afb2 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -59,7 +59,6 @@ "install_time_util.mm", "installation_notifier.h", "installation_notifier.mm", - "ios_chrome_field_trials.cc", "ios_chrome_field_trials.h", "ios_chrome_flag_descriptions.cc", "ios_chrome_flag_descriptions.h",
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm index c3109d9f..30505b4d 100644 --- a/ios/chrome/browser/about_flags.mm +++ b/ios/chrome/browser/about_flags.mm
@@ -11,6 +11,7 @@ #include <stdint.h> #import <UIKit/UIKit.h> +#include "base/base_switches.h" #include "base/bind.h" #include "base/command_line.h" #include "base/logging.h" @@ -301,7 +302,7 @@ base::CommandLine* command_line) { FlagsStateSingleton::GetFlagsState()->ConvertFlagsToSwitches( flags_storage, command_line, flags_ui::kAddSentinels, - switches::kEnableIOSFeatures, switches::kDisableIOSFeatures); + switches::kEnableFeatures, switches::kDisableFeatures); AppendSwitchesFromExperimentalSettings(command_line); }
diff --git a/ios/chrome/browser/chrome_switches.cc b/ios/chrome/browser/chrome_switches.cc index 7e90c54..c90abab 100644 --- a/ios/chrome/browser/chrome_switches.cc +++ b/ios/chrome/browser/chrome_switches.cc
@@ -15,10 +15,6 @@ // Disables Contextual Search. const char kDisableContextualSearch[] = "disable-contextual-search"; -// Lists separated by commas the name of features to disable. -// See base::FeatureList::InitializeFromCommandLine for details. -const char kDisableIOSFeatures[] = "disable-features"; - // Disable showing available password credentials in the keyboard accessory // view when focused on form fields. const char kDisableIOSPasswordSuggestions[] = @@ -31,10 +27,6 @@ // Enables Contextual Search. const char kEnableContextualSearch[] = "enable-contextual-search"; -// Lists separated by commas the name of features to disable. -// See base::FeatureList::InitializeFromCommandLine for details. -const char kEnableIOSFeatures[] = "enable-features"; - // Enables support for Handoff from Chrome on iOS to the default browser of // other Apple devices. const char kEnableIOSHandoffToOtherDevices[] = @@ -47,11 +39,6 @@ const char kEnableThirdPartyKeyboardWorkaround[] = "enable-third-party-keyboard-workaround"; -// Forces additional Chrome Variation Ids that will be sent in X-Client-Data -// header, specified as a 64-bit encoded list of numeric experiment ids. Ids -// prefixed with the character "t" will be treated as Trigger Variation Ids. -const char kIOSForceVariationIds[] = "force-variation-ids"; - // A string used to override the default user agent with a custom one. const char kUserAgent[] = "user-agent";
diff --git a/ios/chrome/browser/chrome_switches.h b/ios/chrome/browser/chrome_switches.h index 5cbbada0..45a5f6e 100644 --- a/ios/chrome/browser/chrome_switches.h +++ b/ios/chrome/browser/chrome_switches.h
@@ -10,19 +10,16 @@ namespace switches { extern const char kDisableContextualSearch[]; -extern const char kDisableIOSFeatures[]; extern const char kDisableIOSPasswordSuggestions[]; extern const char kDisableNTPFavicons[]; extern const char kDisableThirdPartyKeyboardWorkaround[]; extern const char kEnableContextualSearch[]; -extern const char kEnableIOSFeatures[]; extern const char kEnableIOSHandoffToOtherDevices[]; extern const char kEnableNTPFavicons[]; extern const char kEnableSpotlightActions[]; extern const char kEnableThirdPartyKeyboardWorkaround[]; -extern const char kIOSForceVariationIds[]; extern const char kUserAgent[]; extern const char kIOSHostResolverRules[];
diff --git a/ios/chrome/browser/ios_chrome_field_trials.cc b/ios/chrome/browser/ios_chrome_field_trials.cc deleted file mode 100644 index bd64bfc..0000000 --- a/ios/chrome/browser/ios_chrome_field_trials.cc +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ios/chrome/browser/ios_chrome_field_trials.h" - -#include "base/metrics/field_trial.h" -#include "components/ntp_tiles/field_trial.h" -#include "components/version_info/version_info.h" -#include "ios/chrome/common/channel_info.h" - -void SetupIOSFieldTrials() { - // Activate the iOS tab eviction dynamic field trials. - base::FieldTrialList::FindValue("TabEviction"); -}
diff --git a/ios/chrome/browser/ios_chrome_field_trials.h b/ios/chrome/browser/ios_chrome_field_trials.h index d6824627..f9cb9aa 100644 --- a/ios/chrome/browser/ios_chrome_field_trials.h +++ b/ios/chrome/browser/ios_chrome_field_trials.h
@@ -5,7 +5,24 @@ #ifndef IOS_CHROME_BROWSER_IOS_CHROME_FIELD_TRIALS_H_ #define IOS_CHROME_BROWSER_IOS_CHROME_FIELD_TRIALS_H_ -// Sets up iOS-specific field trials. -void SetupIOSFieldTrials(); +#include "base/macros.h" +#include "components/variations/platform_field_trials.h" + +// Responsible for setting up field trials specific to iOS. Currently all +// functions are stubs, as iOS has no specific field trials. +class IOSChromeFieldTrials : public variations::PlatformFieldTrials { + public: + IOSChromeFieldTrials() {} + ~IOSChromeFieldTrials() override {} + + // variations::PlatformFieldTrials: + void SetupFieldTrials() override {} + void SetupFeatureControllingFieldTrials( + bool has_seed, + base::FeatureList* feature_list) override {} + + private: + DISALLOW_COPY_AND_ASSIGN(IOSChromeFieldTrials); +}; #endif // IOS_CHROME_BROWSER_IOS_CHROME_FIELD_TRIALS_H_
diff --git a/ios/chrome/browser/ios_chrome_main_parts.h b/ios/chrome/browser/ios_chrome_main_parts.h index ac0a4e3..9461ce8 100644 --- a/ios/chrome/browser/ios_chrome_main_parts.h +++ b/ios/chrome/browser/ios_chrome_main_parts.h
@@ -10,6 +10,7 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/metrics/field_trial.h" +#include "ios/chrome/browser/ios_chrome_field_trials.h" #include "ios/web/public/app/web_main_parts.h" class ApplicationContextImpl; @@ -56,6 +57,8 @@ // Initialized in SetupMetricsAndFieldTrials. std::unique_ptr<ios::FieldTrialSynchronizer> field_trial_synchronizer_; + IOSChromeFieldTrials ios_field_trials_; + DISALLOW_COPY_AND_ASSIGN(IOSChromeMainParts); };
diff --git a/ios/chrome/browser/ios_chrome_main_parts.mm b/ios/chrome/browser/ios_chrome_main_parts.mm index 2194894..77d0dd5 100644 --- a/ios/chrome/browser/ios_chrome_main_parts.mm +++ b/ios/chrome/browser/ios_chrome_main_parts.mm
@@ -28,17 +28,14 @@ #include "components/variations/field_trial_config/field_trial_util.h" #include "components/variations/service/variations_service.h" #include "components/variations/variations_http_header_provider.h" -#include "components/variations/variations_switches.h" #include "ios/chrome/browser/about_flags.h" #include "ios/chrome/browser/application_context_impl.h" #include "ios/chrome/browser/browser_state/browser_state_keyed_service_factories.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/browser_state/chrome_browser_state_manager.h" #include "ios/chrome/browser/chrome_paths.h" -#include "ios/chrome/browser/chrome_switches.h" #import "ios/chrome/browser/first_run/first_run.h" #include "ios/chrome/browser/install_time_util.h" -#include "ios/chrome/browser/ios_chrome_field_trials.h" #include "ios/chrome/browser/metrics/field_trial_synchronizer.h" #include "ios/chrome/browser/open_from_clipboard/create_clipboard_recent_content.h" #include "ios/chrome/browser/pref_names.h" @@ -218,30 +215,6 @@ new base::FieldTrialList(application_context_->GetMetricsServicesManager() ->CreateEntropyProvider())); - const base::CommandLine* command_line = - base::CommandLine::ForCurrentProcess(); - - if (command_line->HasSwitch(variations::switches::kForceFieldTrialParams)) { - bool result = - variations::AssociateParamsFromString(command_line->GetSwitchValueASCII( - variations::switches::kForceFieldTrialParams)); - CHECK(result) << "Invalid --" - << variations::switches::kForceFieldTrialParams - << " list specified."; - } - - // Ensure any field trials specified on the command line are initialized. - // Also stop the metrics service so that we don't pollute UMA. - if (command_line->HasSwitch(switches::kForceFieldTrials)) { - // Create field trials without activating them, so that this behaves in a - // consistent manner with field trials created from the server. - bool result = base::FieldTrialList::CreateTrialsFromString( - command_line->GetSwitchValueASCII(switches::kForceFieldTrials), - std::set<std::string>()); - CHECK(result) << "Invalid --" << switches::kForceFieldTrials - << " list specified."; - } - std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); // Associate parameters chosen in about:flags and create trial/group for them. @@ -250,37 +223,13 @@ std::vector<std::string> variation_ids = RegisterAllFeatureVariationParameters(&flags_storage, feature_list.get()); - variations::VariationsHttpHeaderProvider* http_header_provider = - variations::VariationsHttpHeaderProvider::GetInstance(); - // Force the variation ids selected in chrome://flags and/or specified using - // the command-line flag. - bool result = http_header_provider->ForceVariationIds( - command_line->GetSwitchValueASCII(switches::kIOSForceVariationIds), - &variation_ids); - CHECK(result) << "Invalid list of variation ids specified (either in --" - << switches::kIOSForceVariationIds << " or in chrome://flags)"; - - feature_list->InitializeFromCommandLine( - command_line->GetSwitchValueASCII(switches::kEnableIOSFeatures), - command_line->GetSwitchValueASCII(switches::kDisableIOSFeatures)); - -#if defined(FIELDTRIAL_TESTING_ENABLED) - if (!command_line->HasSwitch( - variations::switches::kDisableFieldTrialTestingConfig) && - !command_line->HasSwitch(switches::kForceFieldTrials) && - !command_line->HasSwitch(variations::switches::kVariationsServerURL)) { - variations::AssociateDefaultFieldTrialConfig(feature_list.get()); - } -#endif // defined(FIELDTRIAL_TESTING_ENABLED) - - variations::VariationsService* variations_service = - application_context_->GetVariationsService(); - if (variations_service) - variations_service->CreateTrialsFromSeed(feature_list.get()); - - base::FeatureList::SetInstance(std::move(feature_list)); - - SetupIOSFieldTrials(); + // On iOS, GPU benchmarking is not supported. So, pass in a dummy value for + // the name of the switch that enables gpu benchmarking. + application_context_->GetVariationsService()->SetupFieldTrials( + "dummy-enable-gpu-benchmarking", switches::kEnableFeatures, + switches::kDisableFeatures, + /*unforceable_field_trials=*/std::set<std::string>(), + std::move(feature_list), &variation_ids, &ios_field_trials_); } void IOSChromeMainParts::SetupMetrics() {
diff --git a/ios/chrome/browser/net/ios_chrome_network_delegate.cc b/ios/chrome/browser/net/ios_chrome_network_delegate.cc index 2537e87..f5906216 100644 --- a/ios/chrome/browser/net/ios_chrome_network_delegate.cc +++ b/ios/chrome/browser/net/ios_chrome_network_delegate.cc
@@ -116,9 +116,10 @@ request.site_for_cookies()); } -bool IOSChromeNetworkDelegate::OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, - net::CookieOptions* options) { +bool IOSChromeNetworkDelegate::OnCanSetCookie( + const net::URLRequest& request, + const net::CanonicalCookie& cookie, + net::CookieOptions* options) { // Null during tests, or when we're running in the system context. if (!cookie_settings_) return true;
diff --git a/ios/chrome/browser/net/ios_chrome_network_delegate.h b/ios/chrome/browser/net/ios_chrome_network_delegate.h index 148f3754..fe6407d 100644 --- a/ios/chrome/browser/net/ios_chrome_network_delegate.h +++ b/ios/chrome/browser/net/ios_chrome_network_delegate.h
@@ -61,7 +61,7 @@ bool OnCanGetCookies(const net::URLRequest& request, const net::CookieList& cookie_list) override; bool OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) override; bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& original_path,
diff --git a/ios/chrome/browser/prefs/BUILD.gn b/ios/chrome/browser/prefs/BUILD.gn index 874e57f..3f80d2f 100644 --- a/ios/chrome/browser/prefs/BUILD.gn +++ b/ios/chrome/browser/prefs/BUILD.gn
@@ -69,6 +69,7 @@ "//ios/chrome/browser/net", "//ios/chrome/browser/physical_web", "//ios/chrome/browser/signin", + "//ios/chrome/browser/ui/authentication", "//ios/chrome/browser/ui/bookmarks", "//ios/chrome/browser/voice:prefs", "//ios/public/provider/chrome/browser",
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm index 5259302..4a2f518e 100644 --- a/ios/chrome/browser/prefs/browser_prefs.mm +++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -38,7 +38,6 @@ #include "components/update_client/update_client.h" #include "components/variations/service/variations_service.h" #include "components/web_resource/web_resource_pref_names.h" -#include "ios/chrome/browser/bookmarks/bookmark_new_generation_features.h" #include "ios/chrome/browser/browser_state/browser_state_info_cache.h" #include "ios/chrome/browser/desktop_promotion/desktop_promotion_sync_service.h" #include "ios/chrome/browser/first_run/first_run.h" @@ -49,10 +48,8 @@ #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/bookmarks/bookmark_collection_view.h" +#import "ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_mediator.h" -#import "ios/chrome/browser/ui/bookmarks/bookmark_promo_controller.h" -#import "ios/chrome/browser/ui/bookmarks/bookmark_table_view.h" #include "ios/chrome/browser/voice/voice_search_prefs_registration.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" #include "ui/base/l10n/l10n_util.h" @@ -122,13 +119,8 @@ DesktopPromotionSyncService::RegisterDesktopPromotionUserPrefs(registry); RegisterVoiceSearchBrowserStatePrefs(registry); - if (base::FeatureList::IsEnabled(kBookmarkNewGeneration)) { - [BookmarkTableView registerBrowserStatePrefs:registry]; - } else { - [BookmarkCollectionView registerBrowserStatePrefs:registry]; - } [BookmarkMediator registerBrowserStatePrefs:registry]; - [BookmarkPromoController registerBrowserStatePrefs:registry]; + [SigninPromoViewMediator registerBrowserStatePrefs:registry]; [HandoffManager registerBrowserStatePrefs:registry]; registry->RegisterIntegerPref(prefs::kIosSettingsSigninPromoDisplayedCount, 0); @@ -139,7 +131,7 @@ prefs::kEnableDoNotTrack, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref( - prefs::kEnableTranslate, true, + prefs::kOfferTranslateEnabled, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterStringPref(prefs::kAcceptLanguages, l10n_util::GetStringUTF8(IDS_ACCEPT_LANGUAGES));
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm index 0dc4fc2..d79a547 100644 --- a/ios/chrome/browser/tabs/tab_helper_util.mm +++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -23,7 +23,6 @@ #include "ios/chrome/browser/history/history_tab_helper.h" #include "ios/chrome/browser/history/top_sites_factory.h" #import "ios/chrome/browser/infobars/infobar_manager_impl.h" -#import "ios/chrome/browser/language/url_language_histogram_factory.h" #import "ios/chrome/browser/passwords/password_tab_helper.h" #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #import "ios/chrome/browser/reading_list/reading_list_web_state_observer.h" @@ -82,16 +81,6 @@ ReadingListModelFactory::GetForBrowserState(browser_state); ReadingListWebStateObserver::CreateForWebState(web_state, model); - // The language detection helper accepts a callback from the translate - // client, so must be created after it. - ChromeIOSTranslateClient::CreateForWebState(web_state); - language::IOSLanguageDetectionTabHelper::CreateForWebState( - web_state, - ChromeIOSTranslateClient::FromWebState(web_state) - ->GetTranslateDriver() - ->CreateLanguageDetectionCallback(), - UrlLanguageHistogramFactory::GetForBrowserState(browser_state)); - ios::ChromeBrowserState* original_browser_state = browser_state->GetOriginalChromeBrowserState(); favicon::WebFaviconDriver::CreateForWebState(
diff --git a/ios/chrome/browser/translate/BUILD.gn b/ios/chrome/browser/translate/BUILD.gn index 3a8e58f6..631e76b 100644 --- a/ios/chrome/browser/translate/BUILD.gn +++ b/ios/chrome/browser/translate/BUILD.gn
@@ -11,6 +11,10 @@ "before_translate_infobar_controller.mm", "chrome_ios_translate_client.h", "chrome_ios_translate_client.mm", + "language_selection_context.h", + "language_selection_context.mm", + "language_selection_delegate.h", + "language_selection_handler.h", "never_translate_infobar_controller.h", "never_translate_infobar_controller.mm", "translate_accept_languages_factory.cc", @@ -102,6 +106,7 @@ "//components/translate/core/common", "//components/translate/ios/browser", "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/ui/translate:translate_ui", "//ios/chrome/test/app:test_support", "//ios/chrome/test/earl_grey:test_support", "//ios/testing:ios_test_support",
diff --git a/ios/chrome/browser/translate/before_translate_infobar_controller.h b/ios/chrome/browser/translate/before_translate_infobar_controller.h index ae9991e..39dc3b78 100644 --- a/ios/chrome/browser/translate/before_translate_infobar_controller.h +++ b/ios/chrome/browser/translate/before_translate_infobar_controller.h
@@ -7,16 +7,13 @@ #include "ios/chrome/browser/infobars/infobar_controller.h" -// The accessibility identifier of the cancel button on language picker view. -// NOTE: this should not be used on iOS 9 for testing. -extern NSString* const kLanguagePickerCancelButtonId; - -// The accessibility identifier of the done button on language picker view. -// NOTE: this should not be used on iOS 9 for testing. -extern NSString* const kLanguagePickerDoneButtonId; +@protocol LanguageSelectionHandler; @interface BeforeTranslateInfoBarController : InfoBarController +@property(nonatomic, weak) id<LanguageSelectionHandler> + languageSelectionHandler; + @end #endif // IOS_CHROME_BROWSER_TRANSLATE_BEFORE_TRANSLATE_INFOBAR_CONTROLLER_H_
diff --git a/ios/chrome/browser/translate/before_translate_infobar_controller.mm b/ios/chrome/browser/translate/before_translate_infobar_controller.mm index e15b720..4a6b58a 100644 --- a/ios/chrome/browser/translate/before_translate_infobar_controller.mm +++ b/ios/chrome/browser/translate/before_translate_infobar_controller.mm
@@ -12,6 +12,9 @@ #include "base/strings/utf_string_conversions.h" #include "components/strings/grit/components_strings.h" #include "components/translate/core/browser/translate_infobar_delegate.h" +#include "ios/chrome/browser/translate/language_selection_context.h" +#include "ios/chrome/browser/translate/language_selection_delegate.h" +#include "ios/chrome/browser/translate/language_selection_handler.h" #include "ios/chrome/browser/translate/translate_infobar_tags.h" #import "ios/chrome/browser/ui/infobars/infobar_view.h" #import "ios/chrome/browser/ui/infobars/infobar_view_delegate.h" @@ -23,92 +26,12 @@ #error "This file requires ARC support." #endif -NSString* const kLanguagePickerCancelButtonId = @"LanguagePickerCancelButton"; -NSString* const kLanguagePickerDoneButtonId = @"LanguagePickerDoneButton"; - -namespace { - -CGFloat kNavigationBarHeight = 44; -CGFloat kUIPickerHeight = 216; -CGFloat kUIPickerFontSize = 26; -NSTimeInterval kPickerAnimationDurationInSeconds = 0.2; - -} // namespace - -// The class is a data source and delegate to the UIPickerView that contains the -// language list. -@interface LanguagePickerController - : UIViewController<UIPickerViewDataSource, UIPickerViewDelegate> { - translate::TranslateInfoBarDelegate* _translateInfoBarDelegate; // weak - NSInteger _initialRow; // Displayed in bold font. - NSInteger _disabledRow; // Grayed out. -} -@end - -@implementation LanguagePickerController - -- (instancetype)initWithDelegate:(translate::TranslateInfoBarDelegate*) - translateInfoBarDelegate - initialRow:(NSInteger)initialRow - disabledRow:(NSInteger)disabledRow { - if ((self = [super init])) { - _translateInfoBarDelegate = translateInfoBarDelegate; - _initialRow = initialRow; - _disabledRow = disabledRow; - } - return self; -} - -#pragma mark - -#pragma mark UIPickerViewDataSource - -- (NSInteger)pickerView:(UIPickerView*)pickerView - numberOfRowsInComponent:(NSInteger)component { - NSUInteger numRows = _translateInfoBarDelegate->num_languages(); - return numRows; -} - -- (NSInteger)numberOfComponentsInPickerView:(UIPickerView*)pickerView { - return 1; -} - -#pragma mark - -#pragma mark UIPickerViewDelegate - -- (UIView*)pickerView:(UIPickerView*)pickerView - viewForRow:(NSInteger)row - forComponent:(NSInteger)component - reusingView:(UIView*)view { - DCHECK_EQ(0, component); - UILabel* label = [view isKindOfClass:[UILabel class]] - ? (UILabel*)view - : [[UILabel alloc] init]; - [label setText:base::SysUTF16ToNSString( - _translateInfoBarDelegate->language_name_at(row))]; - [label setTextAlignment:NSTextAlignmentCenter]; - UIFont* font = [UIFont systemFontOfSize:kUIPickerFontSize]; - BOOL enabled = YES; - if (row == _initialRow) - font = [UIFont boldSystemFontOfSize:kUIPickerFontSize]; - else if (row == _disabledRow) - enabled = NO; - [label setFont:font]; - [label setEnabled:enabled]; - return label; -} - -@end - -@interface BeforeTranslateInfoBarController () +@interface BeforeTranslateInfoBarController ()<LanguageSelectionDelegate> // Action for any of the user defined buttons. - (void)infoBarButtonDidPress:(id)sender; // Action for any of the user defined links. - (void)infobarLinkDidPress:(NSUInteger)tag; -// Action for the language selection "Done" button. -- (void)languageSelectionDone; -// Dismisses the language selection view. -- (void)dismissLanguageSelectionView; // Changes the text on the view to match the language. - (void)updateInfobarLabelOnView:(InfoBarView*)view; @@ -116,21 +39,13 @@ @implementation BeforeTranslateInfoBarController { translate::TranslateInfoBarDelegate* _translateInfoBarDelegate; // weak - // A fullscreen view that catches all touch events and contains a UIPickerView - // and a UINavigationBar. - UIView* _languageSelectionView; // Stores whether the user is currently choosing in the UIPickerView the // original language, or the target language. - NSUInteger _languageSelectionType; - // The language picker. - UIPickerView* _languagePicker; - // Navigation bar associated with the picker with "Done" and "Cancel" buttons. - UINavigationBar* _navigationBar; - // The controller of the languagePicker. Needs to be an ivar because - // |_languagePicker| does not retain it. - LanguagePickerController* _languagePickerController; + TranslateInfoBarIOSTag::Tag _languageSelectionType; } +@synthesize languageSelectionHandler = _languageSelectionHandler; + #pragma mark - #pragma mark InfoBarControllerProtocol @@ -187,60 +102,6 @@ }]; } -- (void)languageSelectionDone { - size_t selectedRow = [_languagePicker selectedRowInComponent:0]; - std::string lang = _translateInfoBarDelegate->language_code_at(selectedRow); - if (_languageSelectionType == - TranslateInfoBarIOSTag::BEFORE_SOURCE_LANGUAGE && - lang != _translateInfoBarDelegate->target_language_code()) { - _translateInfoBarDelegate->UpdateOriginalLanguage(lang); - } - if (_languageSelectionType == - TranslateInfoBarIOSTag::BEFORE_TARGET_LANGUAGE && - lang != _translateInfoBarDelegate->original_language_code()) { - _translateInfoBarDelegate->UpdateTargetLanguage(lang); - } - [self updateInfobarLabelOnView:self.view]; - [self dismissLanguageSelectionView]; -} - -- (void)dismissLanguageSelectionView { - DCHECK_EQ(_languagePicker == nil, _navigationBar == nil); - if (_languagePicker == nil) - return; - // Sets the picker's delegate and data source to nil, because the - // |_languagePickerController| may be destroyed before the picker is hidden, - // and even though the interactions with the picker are disabled, it might - // still be turning and requesting data from the data source or calling the - // delegate. - [_languagePicker setDataSource:nil]; - [_languagePicker setDelegate:nil]; - _languagePickerController = nil; - // Animate the picker away. - CGRect languagePickerFrame = [_languagePicker frame]; - CGRect navigationBarFrame = [_navigationBar frame]; - const CGFloat animationHeight = - languagePickerFrame.size.height + navigationBarFrame.size.height; - languagePickerFrame.origin.y += animationHeight; - navigationBarFrame.origin.y += animationHeight; - UIPickerView* blockLanguagePicker = _languagePicker; - UINavigationBar* blockNavigationBar = _navigationBar; - _languagePicker = nil; - _navigationBar = nil; - void (^animations)(void) = ^{ - blockLanguagePicker.frame = languagePickerFrame; - blockNavigationBar.frame = navigationBarFrame; - }; - UIView* blockSelectionView = _languageSelectionView; - _languageSelectionView = nil; - void (^completion)(BOOL finished) = ^(BOOL finished) { - [blockSelectionView removeFromSuperview]; - }; - [UIView animateWithDuration:kPickerAnimationDurationInSeconds - animations:animations - completion:completion]; -} - #pragma mark - Handling of User Events - (void)infoBarButtonDidPress:(id)sender { @@ -259,69 +120,16 @@ } - (void)infobarLinkDidPress:(NSUInteger)tag { - _languageSelectionType = tag; + _languageSelectionType = static_cast<TranslateInfoBarIOSTag::Tag>(tag); DCHECK(_languageSelectionType == TranslateInfoBarIOSTag::BEFORE_SOURCE_LANGUAGE || _languageSelectionType == TranslateInfoBarIOSTag::BEFORE_TARGET_LANGUAGE); - if (_languagePicker != nil) - return; // The UIPickerView is already up. - // Creates and adds the view containing the UIPickerView and the - // UINavigationBar. - UIView* parentView = top_view_controller::TopPresentedViewController().view; - // Convert the parent frame to handle device rotation. - CGRect parentFrame = - CGRectApplyAffineTransform([parentView frame], [parentView transform]); - const CGFloat totalPickerHeight = kUIPickerHeight + kNavigationBarHeight; - CGRect languageSelectionViewFrame = - CGRectMake(0, parentFrame.size.height - totalPickerHeight, - parentFrame.size.width, totalPickerHeight); - _languageSelectionView = - [[UIView alloc] initWithFrame:languageSelectionViewFrame]; - [_languageSelectionView - setAutoresizingMask:UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleTopMargin]; - [parentView addSubview:_languageSelectionView]; - - // Creates the navigation bar and its buttons. - CGRect finalPickerFrame = CGRectMake( - 0, [_languageSelectionView frame].size.height - kUIPickerHeight, - [_languageSelectionView frame].size.width, kUIPickerHeight); - CGRect finalNavigationBarFrame = CGRectMake( - 0, 0, [_languageSelectionView frame].size.width, kNavigationBarHeight); - // The language picker animates from the bottom of the screen. - CGRect initialPickerFrame = finalPickerFrame; - initialPickerFrame.origin.y += totalPickerHeight; - CGRect initialNavigationBarFrame = finalNavigationBarFrame; - initialNavigationBarFrame.origin.y += totalPickerHeight; - - _navigationBar = - [[UINavigationBar alloc] initWithFrame:initialNavigationBarFrame]; - const UIViewAutoresizing resizingMask = - UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; - [_navigationBar setAutoresizingMask:resizingMask]; - UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem:UIBarButtonSystemItemDone - target:self - action:@selector(languageSelectionDone)]; - [doneButton setAccessibilityIdentifier:kLanguagePickerDoneButtonId]; - UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem:UIBarButtonSystemItemCancel - target:self - action:@selector(dismissLanguageSelectionView)]; - [cancelButton setAccessibilityIdentifier:kLanguagePickerCancelButtonId]; - UINavigationItem* item = [[UINavigationItem alloc] initWithTitle:@""]; - [item setRightBarButtonItem:doneButton]; - [item setLeftBarButtonItem:cancelButton]; - [item setHidesBackButton:YES]; - [_navigationBar pushNavigationItem:item animated:NO]; - - // Creates the PickerView and its controller. - NSInteger selectedRow; - NSInteger disabledRow; - NSInteger originalLanguageIndex = -1; - NSInteger targetLanguageIndex = -1; + size_t selectedRow; + size_t disabledRow; + int originalLanguageIndex = -1; + int targetLanguageIndex = -1; for (size_t i = 0; i < _translateInfoBarDelegate->num_languages(); ++i) { if (_translateInfoBarDelegate->language_code_at(i) == @@ -344,40 +152,33 @@ selectedRow = targetLanguageIndex; disabledRow = originalLanguageIndex; } - _languagePickerController = [[LanguagePickerController alloc] - initWithDelegate:_translateInfoBarDelegate - initialRow:selectedRow - disabledRow:disabledRow]; - _languagePicker = [[UIPickerView alloc] initWithFrame:initialPickerFrame]; - [_languagePicker setAutoresizingMask:resizingMask]; - [_languagePicker setShowsSelectionIndicator:YES]; - [_languagePicker setDataSource:_languagePickerController]; - [_languagePicker setDelegate:_languagePickerController]; - [_languagePicker setShowsSelectionIndicator:YES]; - [_languagePicker setBackgroundColor:[self.view backgroundColor]]; - [_languagePicker selectRow:selectedRow inComponent:0 animated:NO]; - - UIPickerView* blockLanguagePicker = _languagePicker; - UINavigationBar* blockNavigationBar = _navigationBar; - [UIView animateWithDuration:kPickerAnimationDurationInSeconds - animations:^{ - blockLanguagePicker.frame = finalPickerFrame; - blockNavigationBar.frame = finalNavigationBarFrame; - }]; - - // Add the subviews. - [_languageSelectionView addSubview:_languagePicker]; - [_languageSelectionView addSubview:_navigationBar]; + LanguageSelectionContext* context = [LanguageSelectionContext + contextWithLanguageData:_translateInfoBarDelegate + initialIndex:selectedRow + unavailableIndex:disabledRow]; + [self.languageSelectionHandler showLanguageSelectorWithContext:context + delegate:self]; } -- (void)removeView { - [super removeView]; - [self dismissLanguageSelectionView]; +#pragma mark - LanguageSelectionDelegate + +- (void)languageSelectorSelectedLanguage:(std::string)languageCode { + if (_languageSelectionType == + TranslateInfoBarIOSTag::BEFORE_SOURCE_LANGUAGE && + languageCode != _translateInfoBarDelegate->target_language_code()) { + _translateInfoBarDelegate->UpdateOriginalLanguage(languageCode); + } + if (_languageSelectionType == + TranslateInfoBarIOSTag::BEFORE_TARGET_LANGUAGE && + languageCode != _translateInfoBarDelegate->original_language_code()) { + _translateInfoBarDelegate->UpdateTargetLanguage(languageCode); + } + [self updateInfobarLabelOnView:self.view]; } -- (void)detachView { - [super detachView]; - [self dismissLanguageSelectionView]; +- (void)languageSelectorClosedWithoutSelection { + // No-op in this implementation, but (for example) metrics for this state + // might be added. } @end
diff --git a/ios/chrome/browser/translate/chrome_ios_translate_client.h b/ios/chrome/browser/translate/chrome_ios_translate_client.h index 7fd9178..64a3f35 100644 --- a/ios/chrome/browser/translate/chrome_ios_translate_client.h +++ b/ios/chrome/browser/translate/chrome_ios_translate_client.h
@@ -5,6 +5,8 @@ #ifndef IOS_CHROME_BROWSER_TRANSLATE_CHROME_IOS_TRANSLATE_CLIENT_H_ #define IOS_CHROME_BROWSER_TRANSLATE_CHROME_IOS_TRANSLATE_CLIENT_H_ +#import <Foundation/Foundation.h> + #include <memory> #include <string> @@ -13,6 +15,7 @@ #include "components/translate/core/browser/translate_step.h" #include "components/translate/core/common/translate_errors.h" #include "components/translate/ios/browser/ios_translate_driver.h" +#include "ios/chrome/browser/translate/language_selection_handler.h" #include "ios/web/public/web_state/web_state_observer.h" #include "ios/web/public/web_state/web_state_user_data.h" @@ -41,6 +44,13 @@ public: ~ChromeIOSTranslateClient() override; + // Creates a translation client tab helper and attaches it to |web_state|. The + // |language_selection_handler| may not be nil, and is not retained by the + // ChromeIOSTranslateClient. + static void CreateForWebState( + web::WebState* web_state, + id<LanguageSelectionHandler> language_selection_handler); + // Helper method to return a new TranslatePrefs instance. static std::unique_ptr<translate::TranslatePrefs> CreateTranslatePrefs( PrefService* prefs); @@ -70,7 +80,9 @@ void ShowReportLanguageDetectionErrorUI(const GURL& report_url) override; private: - explicit ChromeIOSTranslateClient(web::WebState* web_state); + ChromeIOSTranslateClient( + web::WebState* web_state, + id<LanguageSelectionHandler> language_selection_handler); friend class web::WebStateUserData<ChromeIOSTranslateClient>; // web::WebStateObserver implementation. @@ -82,6 +94,7 @@ std::unique_ptr<translate::TranslateManager> translate_manager_; translate::IOSTranslateDriver translate_driver_; + __weak id<LanguageSelectionHandler> language_selection_handler_; DISALLOW_COPY_AND_ASSIGN(ChromeIOSTranslateClient); };
diff --git a/ios/chrome/browser/translate/chrome_ios_translate_client.mm b/ios/chrome/browser/translate/chrome_ios_translate_client.mm index 336849e..05af57e2 100644 --- a/ios/chrome/browser/translate/chrome_ios_translate_client.mm +++ b/ios/chrome/browser/translate/chrome_ios_translate_client.mm
@@ -52,7 +52,21 @@ DEFINE_WEB_STATE_USER_DATA_KEY(ChromeIOSTranslateClient); -ChromeIOSTranslateClient::ChromeIOSTranslateClient(web::WebState* web_state) +// static +void ChromeIOSTranslateClient::CreateForWebState( + web::WebState* web_state, + id<LanguageSelectionHandler> language_selection_handler) { + DCHECK(web_state); + if (!FromWebState(web_state)) { + web_state->SetUserData(UserDataKey(), + base::WrapUnique(new ChromeIOSTranslateClient( + web_state, language_selection_handler))); + } +} + +ChromeIOSTranslateClient::ChromeIOSTranslateClient( + web::WebState* web_state, + id<LanguageSelectionHandler> language_selection_handler) : web_state_(web_state), translate_manager_(base::MakeUnique<translate::TranslateManager>( this, @@ -64,7 +78,9 @@ web_state->GetBrowserState())))), translate_driver_(web_state, web_state->GetNavigationManager(), - translate_manager_.get()) { + translate_manager_.get()), + language_selection_handler_(language_selection_handler) { + DCHECK(language_selection_handler); web_state_->AddObserver(this); } @@ -96,10 +112,14 @@ controller = [[AfterTranslateInfoBarController alloc] initWithDelegate:infobar.get()]; break; - case translate::TRANSLATE_STEP_BEFORE_TRANSLATE: - controller = [[BeforeTranslateInfoBarController alloc] - initWithDelegate:infobar.get()]; + case translate::TRANSLATE_STEP_BEFORE_TRANSLATE: { + BeforeTranslateInfoBarController* beforeController = + [[BeforeTranslateInfoBarController alloc] + initWithDelegate:infobar.get()]; + beforeController.languageSelectionHandler = language_selection_handler_; + controller = beforeController; break; + } case translate::TRANSLATE_STEP_NEVER_TRANSLATE: controller = [[NeverTranslateInfoBarController alloc] initWithDelegate:infobar.get()];
diff --git a/ios/chrome/browser/translate/language_selection_context.h b/ios/chrome/browser/translate/language_selection_context.h new file mode 100644 index 0000000..1af20a6 --- /dev/null +++ b/ios/chrome/browser/translate/language_selection_context.h
@@ -0,0 +1,36 @@ +// 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_TRANSLATE_LANGUAGE_SELECTION_CONTEXT_H_ +#define IOS_CHROME_BROWSER_TRANSLATE_LANGUAGE_SELECTION_CONTEXT_H_ + +#import <Foundation/Foundation.h> + +namespace translate { +class TranslateInfoBarDelegate; +} + +// Context information for a language selection event. +@interface LanguageSelectionContext : NSObject + +// Convenience initializer that populates all of the properties of the returned +// object with the passed parameters. ++ (instancetype)contextWithLanguageData: + (translate::TranslateInfoBarDelegate*)languageData + initialIndex:(size_t)initialLanguageIndex + unavailableIndex:(size_t)unavailableLanguageIndex; + +// The object that provides language data for the selection. +@property(nonatomic, readonly) + const translate::TranslateInfoBarDelegate* languageData; +// The index of the language that's initially selected. +@property(nonatomic, readonly) size_t initialLanguageIndex; +// The index of the language that can't be selected (because this context is +// for source selection and this is the index of the target language, or +// vice-versa). +@property(nonatomic, readonly) size_t unavailableLanguageIndex; + +@end + +#endif // IOS_CHROME_BROWSER_TRANSLATE_LANGUAGE_SELECTION_CONTEXT_H_
diff --git a/ios/chrome/browser/translate/language_selection_context.mm b/ios/chrome/browser/translate/language_selection_context.mm new file mode 100644 index 0000000..dc09b6aa --- /dev/null +++ b/ios/chrome/browser/translate/language_selection_context.mm
@@ -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 "ios/chrome/browser/translate/language_selection_context.h" + +@interface LanguageSelectionContext () +// Redeclare public properties readwrite. +@property(nonatomic, readwrite) + const translate::TranslateInfoBarDelegate* languageData; +@property(nonatomic, readwrite) size_t initialLanguageIndex; +@property(nonatomic, readwrite) size_t unavailableLanguageIndex; +@end + +@implementation LanguageSelectionContext + +@synthesize languageData = _languageData; +@synthesize initialLanguageIndex = _initialLanguageIndex; +@synthesize unavailableLanguageIndex = _unavailableLanguageIndex; + ++ (instancetype)contextWithLanguageData: + (translate::TranslateInfoBarDelegate*)languageData + initialIndex:(size_t)initialLanguageIndex + unavailableIndex:(size_t)unavailableLanguageIndex { + LanguageSelectionContext* context = [[LanguageSelectionContext alloc] init]; + context.languageData = languageData; + context.initialLanguageIndex = initialLanguageIndex; + context.unavailableLanguageIndex = unavailableLanguageIndex; + return context; +} + +@end
diff --git a/ios/chrome/browser/translate/language_selection_delegate.h b/ios/chrome/browser/translate/language_selection_delegate.h new file mode 100644 index 0000000..cdc7537 --- /dev/null +++ b/ios/chrome/browser/translate/language_selection_delegate.h
@@ -0,0 +1,25 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_TRANSLATE_LANGUAGE_SELECTION_DELEGATE_H_ +#define IOS_CHROME_BROWSER_TRANSLATE_LANGUAGE_SELECTION_DELEGATE_H_ + +#import <Foundation/Foundation.h> +#include <string> + +// Protocol adopted by an object that can receive language selection information +// from the UI layer. +@protocol LanguageSelectionDelegate + +// Tells the delegate that the language identified by |languageCode| was +// selected and the language selector was closed. +- (void)languageSelectorSelectedLanguage:(std::string)languageCode; + +// Tells the delegate that the language selector was closed without a selection +// being made. +- (void)languageSelectorClosedWithoutSelection; + +@end + +#endif // IOS_CHROME_BROWSER_TRANSLATE_LANGUAGE_SELECTION_DELEGATE_H_
diff --git a/ios/chrome/browser/translate/language_selection_handler.h b/ios/chrome/browser/translate/language_selection_handler.h new file mode 100644 index 0000000..61283b5 --- /dev/null +++ b/ios/chrome/browser/translate/language_selection_handler.h
@@ -0,0 +1,25 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_TRANSLATE_LANGUAGE_SELECTION_HANDLER_H_ +#define IOS_CHROME_BROWSER_TRANSLATE_LANGUAGE_SELECTION_HANDLER_H_ + +#import <Foundation/Foundation.h> + +@class LanguageSelectionContext; +@protocol LanguageSelectionDelegate; + +// Protocol adopted by an object that can provide an interface for a user to +// select a language from the languages exposed by a translate_infobar_delegate. +@protocol LanguageSelectionHandler + +// Tells the handler to display a language selector using the language +// information in |languages| and telling |delegate| the results of the +// selection. +- (void)showLanguageSelectorWithContext:(LanguageSelectionContext*)context + delegate:(id<LanguageSelectionDelegate>)delegate; + +@end + +#endif // IOS_CHROME_BROWSER_TRANSLATE_LANGUAGE_SELECTION_HANDLER_H_
diff --git a/ios/chrome/browser/translate/translate_egtest.mm b/ios/chrome/browser/translate/translate_egtest.mm index 7a5a2e9..029cb76 100644 --- a/ios/chrome/browser/translate/translate_egtest.mm +++ b/ios/chrome/browser/translate/translate_egtest.mm
@@ -21,8 +21,8 @@ #include "components/translate/ios/browser/ios_translate_driver.h" #import "components/translate/ios/browser/js_translate_manager.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/translate/before_translate_infobar_controller.h" #include "ios/chrome/browser/translate/chrome_ios_translate_client.h" +#include "ios/chrome/browser/ui/translate/language_selection_view_controller.h" #import "ios/chrome/test/app/chrome_test_util.h" #import "ios/chrome/test/app/tab_test_util.h" #include "ios/chrome/test/app/web_view_interaction_test_util.h" @@ -336,8 +336,8 @@ // TODO(crbug.com/642892): Investigate moving into test-specific teardown. // Re-enable translate. chrome_test_util::SetBooleanUserPref( - chrome_test_util::GetOriginalBrowserState(), prefs::kEnableTranslate, - YES); + chrome_test_util::GetOriginalBrowserState(), + prefs::kOfferTranslateEnabled, YES); // Reset translate prefs to default. std::unique_ptr<translate::TranslatePrefs> translatePrefs( ChromeIOSTranslateClient::CreateTranslatePrefs( @@ -574,7 +574,8 @@ // Disable translate. chrome_test_util::SetBooleanUserPref( - chrome_test_util::GetOriginalBrowserState(), prefs::kEnableTranslate, NO); + chrome_test_util::GetOriginalBrowserState(), + prefs::kOfferTranslateEnabled, NO); // Open some webpage. [ChromeEarlGrey loadURL:URL];
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn index 06ee684..e95b2913 100644 --- a/ios/chrome/browser/ui/BUILD.gn +++ b/ios/chrome/browser/ui/BUILD.gn
@@ -258,6 +258,7 @@ "//components/image_fetcher/ios", "//components/infobars/core", "//components/keyed_service/ios", + "//components/language/ios/browser", "//components/payments/core", "//components/prefs", "//components/reading_list/core", @@ -281,6 +282,7 @@ "//ios/chrome/browser/first_run", "//ios/chrome/browser/geolocation:geolocation_internal", "//ios/chrome/browser/infobars", + "//ios/chrome/browser/language", "//ios/chrome/browser/metrics:metrics_internal", "//ios/chrome/browser/net", "//ios/chrome/browser/passwords", @@ -296,6 +298,7 @@ "//ios/chrome/browser/ssl", "//ios/chrome/browser/store_kit", "//ios/chrome/browser/tabs", + "//ios/chrome/browser/translate", "//ios/chrome/browser/ui/activity_services:coordinator", "//ios/chrome/browser/ui/activity_services/requirements", "//ios/chrome/browser/ui/alert_coordinator", @@ -328,6 +331,7 @@ "//ios/chrome/browser/ui/page_info:coordinator", "//ios/chrome/browser/ui/page_info/requirements", "//ios/chrome/browser/ui/payments", + "//ios/chrome/browser/ui/presenters", "//ios/chrome/browser/ui/print", "//ios/chrome/browser/ui/qr_scanner:coordinator", "//ios/chrome/browser/ui/qr_scanner/requirements", @@ -344,6 +348,7 @@ "//ios/chrome/browser/ui/toolbar/public:toolbar_base_feature", "//ios/chrome/browser/ui/tools_menu", "//ios/chrome/browser/ui/tools_menu:configuration", + "//ios/chrome/browser/ui/translate", "//ios/chrome/browser/ui/util", "//ios/chrome/browser/ui/voice", "//ios/chrome/browser/upgrade",
diff --git a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h index 9e07db2..289458f3 100644 --- a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h +++ b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h
@@ -33,6 +33,10 @@ }; } // namespace ios +namespace user_prefs { +class PrefRegistrySyncable; +} // namespace user_prefs + // Class that monitors the available identities and creates // SigninPromoViewConfigurator. This class makes the link between the model and // the view. The consumer will receive notification if default identity is @@ -49,6 +53,16 @@ // Sign-in promo view state. @property(nonatomic) ios::SigninPromoViewState signinPromoViewState; +// Registers the feature preferences. ++ (void)registerBrowserStatePrefs:(user_prefs::PrefRegistrySyncable*)registry; + +// Tests if the sign-in promo view should be displayed according to the number +// of times it has been displayed and if the user closed the sign-in promo view. ++ (BOOL)shouldDisplaySigninPromoViewWithAccessPoint: + (signin_metrics::AccessPoint)accessPoint + browserState:(ios::ChromeBrowserState*) + browserState; + // See -[SigninPromoViewMediator initWithBrowserState:]. - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm index c77136e..b544bf10 100644 --- a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm +++ b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm
@@ -237,6 +237,33 @@ @synthesize signinPromoViewState = _signinPromoViewState; @synthesize presenter = _presenter; ++ (void)registerBrowserStatePrefs:(user_prefs::PrefRegistrySyncable*)registry { + registry->RegisterBooleanPref(prefs::kIosBookmarkPromoAlreadySeen, false); + registry->RegisterIntegerPref(prefs::kIosBookmarkSigninPromoDisplayedCount, + 0); +} + ++ (BOOL)shouldDisplaySigninPromoViewWithAccessPoint: + (signin_metrics::AccessPoint)accessPoint + browserState:(ios::ChromeBrowserState*) + browserState { + PrefService* prefs = browserState->GetPrefs(); + const char* displayedCountPreferenceKey = + DisplayedCountPreferenceKey(accessPoint); + if (displayedCountPreferenceKey && + prefs->GetInteger(displayedCountPreferenceKey) >= + kAutomaticSigninPromoViewDismissCount) { + return NO; + } + const char* alreadySeenSigninViewPreferenceKey = + AlreadySeenSigninViewPreferenceKey(accessPoint); + if (alreadySeenSigninViewPreferenceKey && + prefs->GetBoolean(alreadySeenSigninViewPreferenceKey)) { + return NO; + } + return YES; +} + - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState accessPoint:(signin_metrics::AccessPoint)accessPoint presenter:(id<SigninPresenter>)presenter { @@ -341,12 +368,6 @@ int displayedCount = prefs->GetInteger(displayedCountPreferenceKey); ++displayedCount; prefs->SetInteger(displayedCountPreferenceKey, displayedCount); - const char* alreadySeenSigninViewPreferenceKey = - AlreadySeenSigninViewPreferenceKey(_accessPoint); - if (displayedCount >= kAutomaticSigninPromoViewDismissCount && - alreadySeenSigninViewPreferenceKey) { - prefs->SetBoolean(alreadySeenSigninViewPreferenceKey, true); - } } - (void)signinPromoViewHidden { @@ -357,11 +378,15 @@ - (void)signinPromoViewClosed { DCHECK(_isSigninPromoViewVisible && ![self isInvalidOrClosed]); _signinPromoViewState = ios::SigninPromoViewState::Closed; + const char* alreadySeenSigninViewPreferenceKey = + AlreadySeenSigninViewPreferenceKey(_accessPoint); + DCHECK(alreadySeenSigninViewPreferenceKey); + PrefService* prefs = _browserState->GetPrefs(); + prefs->SetBoolean(alreadySeenSigninViewPreferenceKey, true); const char* displayedCountPreferenceKey = DisplayedCountPreferenceKey(_accessPoint); if (!displayedCountPreferenceKey) return; - PrefService* prefs = _browserState->GetPrefs(); int displayedCount = prefs->GetInteger(displayedCountPreferenceKey); RecordImpressionsTilXButtonHistogramForAccessPoint(_accessPoint, displayedCount);
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.h b/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.h index 09718c4..1741c1c5 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.h +++ b/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.h
@@ -25,9 +25,6 @@ namespace bookmarks { class BookmarkNode; } // namespace bookmarks -namespace user_prefs { -class PrefRegistrySyncable; -} // namespace user_prefs @protocol BookmarkCollectionViewDelegate<NSObject> @@ -94,9 +91,6 @@ @interface BookmarkCollectionView : UIView<BookmarkHomePrimaryView, BookmarkModelBridgeObserver> -// Registers the feature preferences. -+ (void)registerBrowserStatePrefs:(user_prefs::PrefRegistrySyncable*)registry; - // Designated initializer. - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState frame:(CGRect)frame
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm b/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm index 7c7b14d8..54bc7498 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm
@@ -21,12 +21,10 @@ #include "components/favicon/core/large_icon_service.h" #include "components/favicon_base/fallback_icon_style.h" #include "components/favicon_base/favicon_types.h" -#include "components/pref_registry/pref_registry_syncable.h" #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h" #include "ios/chrome/browser/bookmarks/bookmarks_utils.h" #include "ios/chrome/browser/experimental_flags.h" #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" -#include "ios/chrome/browser/pref_names.h" #import "ios/chrome/browser/sync/synced_sessions_bridge.h" #import "ios/chrome/browser/ui/authentication/signin_promo_view.h" #import "ios/chrome/browser/ui/authentication/signin_promo_view_configurator.h" @@ -154,11 +152,6 @@ @synthesize shadow = _shadow; @synthesize presenter = _presenter; -+ (void)registerBrowserStatePrefs:(user_prefs::PrefRegistrySyncable*)registry { - registry->RegisterIntegerPref(prefs::kIosBookmarkSigninPromoDisplayedCount, - 0); -} - #pragma mark - Initialization - (void)setupViews {
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_promo_controller.h b/ios/chrome/browser/ui/bookmarks/bookmark_promo_controller.h index 1dd8311..70b4d17 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_promo_controller.h +++ b/ios/chrome/browser/ui/bookmarks/bookmark_promo_controller.h
@@ -13,10 +13,6 @@ class ChromeBrowserState; } // namespace ios -namespace user_prefs { -class PrefRegistrySyncable; -} // namespace user_prefs - @protocol BookmarkPromoControllerDelegate // Controls the state of the promo. @@ -34,9 +30,6 @@ // call the promoStateChanged: selector on the delegate. @property(nonatomic, assign) BOOL promoState; -// Registers the feature preferences. -+ (void)registerBrowserStatePrefs:(user_prefs::PrefRegistrySyncable*)registry; - - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState delegate: (id<BookmarkPromoControllerDelegate>)delegate
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_promo_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_promo_controller.mm index 263f6bb7..99c77e4 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_promo_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_promo_controller.mm
@@ -13,8 +13,8 @@ #include "components/signin/core/browser/signin_manager.h" #include "google_apis/gaia/google_service_auth_error.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.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" #import "ios/chrome/browser/ui/commands/show_signin_command.h" #import "ios/chrome/browser/ui/signin_interaction/public/signin_presenter.h" #import "ios/chrome/browser/ui/ui_util.h" @@ -99,10 +99,6 @@ @synthesize promoState = _promoState; @synthesize presenter = _presenter; -+ (void)registerBrowserStatePrefs:(user_prefs::PrefRegistrySyncable*)registry { - registry->RegisterBooleanPref(prefs::kIosBookmarkPromoAlreadySeen, false); -} - - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState delegate: (id<BookmarkPromoControllerDelegate>)delegate @@ -155,8 +151,6 @@ UMA_HISTOGRAM_ENUMERATION(kBookmarksPromoActionsHistogram, BOOKMARKS_PROMO_ACTION_DISMISSED, BOOKMARKS_PROMO_ACTION_COUNT); - PrefService* prefs = _browserState->GetPrefs(); - prefs->SetBoolean(prefs::kIosBookmarkPromoAlreadySeen, true); self.promoState = NO; } @@ -173,8 +167,10 @@ return; DCHECK(_browserState); - PrefService* prefs = _browserState->GetPrefs(); - if (!prefs->GetBoolean(prefs::kIosBookmarkPromoAlreadySeen)) { + if ([SigninPromoViewMediator + shouldDisplaySigninPromoViewWithAccessPoint: + signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER + browserState:_browserState]) { SigninManager* signinManager = ios::SigninManagerFactory::GetForBrowserState(_browserState); self.promoState = !signinManager->IsAuthenticated();
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_table_view.h b/ios/chrome/browser/ui/bookmarks/bookmark_table_view.h index 2dfc009..6a85553c 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_table_view.h +++ b/ios/chrome/browser/ui/bookmarks/bookmark_table_view.h
@@ -19,10 +19,6 @@ class ChromeBrowserState; } -namespace user_prefs { -class PrefRegistrySyncable; -} // namespace user_prefs - @class BookmarkTableView; @class MDCFlexibleHeaderView; @@ -93,9 +89,6 @@ - (instancetype)init NS_UNAVAILABLE; + (instancetype) new NS_UNAVAILABLE; -// Registers the feature preferences. -+ (void)registerBrowserStatePrefs:(user_prefs::PrefRegistrySyncable*)registry; - // Called when something outside the view causes the promo state to change. - (void)promoStateChangedAnimated:(BOOL)animated;
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm b/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm index 070d5f6..6c4724b 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm
@@ -11,12 +11,10 @@ #include "components/favicon/core/large_icon_service.h" #include "components/favicon_base/fallback_icon_style.h" #include "components/favicon_base/favicon_types.h" -#include "components/pref_registry/pref_registry_syncable.h" #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h" #include "ios/chrome/browser/bookmarks/bookmarks_utils.h" #include "ios/chrome/browser/experimental_flags.h" #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" -#include "ios/chrome/browser/pref_names.h" #import "ios/chrome/browser/sync/synced_sessions_bridge.h" #import "ios/chrome/browser/ui/authentication/signin_promo_view.h" #import "ios/chrome/browser/ui/authentication/signin_promo_view_configurator.h" @@ -136,11 +134,6 @@ @synthesize addingNewFolder = _addingNewFolder; @synthesize editingFolderCell = _editingFolderCell; -+ (void)registerBrowserStatePrefs:(user_prefs::PrefRegistrySyncable*)registry { - registry->RegisterIntegerPref(prefs::kIosBookmarkSigninPromoDisplayedCount, - 0); -} - - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState delegate:(id<BookmarkTableViewDelegate>)delegate rootNode:(const BookmarkNode*)rootNode
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm index c7029fd..1e30688 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -1248,8 +1248,8 @@ // Check the sign-in promo view is visible. [SigninEarlGreyUtils checkSigninPromoVisibleWithMode:SigninPromoViewModeColdState]; - // Check the sign-in promo will not be shown anymore. - [BookmarksTestCase verifyPromoAlreadySeen:YES]; + // Check the sign-in promo already-seen state didn't change. + [BookmarksTestCase verifyPromoAlreadySeen:NO]; GREYAssertEqual( 20, prefs->GetInteger(prefs::kIosBookmarkSigninPromoDisplayedCount), @"Should have incremented the display count");
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_new_generation_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_new_generation_egtest.mm index e08da14..2f33c135 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_new_generation_egtest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_new_generation_egtest.mm
@@ -1998,8 +1998,8 @@ // Check the sign-in promo view is visible. [SigninEarlGreyUtils checkSigninPromoVisibleWithMode:SigninPromoViewModeColdState]; - // Check the sign-in promo will not be shown anymore. - [BookmarksNewGenTestCase verifyPromoAlreadySeen:YES]; + // Check the sign-in promo already-seen state didn't change. + [BookmarksNewGenTestCase verifyPromoAlreadySeen:NO]; GREYAssertEqual( 20, prefs->GetInteger(prefs::kIosBookmarkSigninPromoDisplayedCount), @"Should have incremented the display count");
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 6bdafcc2..c9c2bdb 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -44,6 +44,7 @@ #include "components/feature_engagement/public/tracker.h" #include "components/image_fetcher/ios/ios_image_data_fetcher_wrapper.h" #include "components/infobars/core/infobar_manager.h" +#import "components/language/ios/browser/ios_language_detection_tab_helper.h" #include "components/payments/core/features.h" #include "components/prefs/pref_service.h" #include "components/reading_list/core/reading_list_model.h" @@ -75,6 +76,7 @@ #include "ios/chrome/browser/infobars/infobar_container_ios.h" #include "ios/chrome/browser/infobars/infobar_container_view.h" #include "ios/chrome/browser/infobars/infobar_manager_impl.h" +#import "ios/chrome/browser/language/url_language_histogram_factory.h" #import "ios/chrome/browser/metrics/new_tab_page_uma.h" #include "ios/chrome/browser/metrics/tab_usage_recorder.h" #import "ios/chrome/browser/open_url_util.h" @@ -107,6 +109,8 @@ #import "ios/chrome/browser/tabs/tab_model_observer.h" #import "ios/chrome/browser/tabs/tab_private.h" #import "ios/chrome/browser/tabs/tab_snapshotting_delegate.h" +#import "ios/chrome/browser/translate/chrome_ios_translate_client.h" +#import "ios/chrome/browser/translate/language_selection_handler.h" #import "ios/chrome/browser/ui/activity_services/activity_service_legacy_coordinator.h" #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_presentation.h" #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" @@ -151,6 +155,7 @@ #import "ios/chrome/browser/ui/page_info/requirements/page_info_presentation.h" #import "ios/chrome/browser/ui/page_not_available_controller.h" #import "ios/chrome/browser/ui/payments/payment_request_manager.h" +#import "ios/chrome/browser/ui/presenters/vertical_animation_container.h" #import "ios/chrome/browser/ui/print/print_controller.h" #import "ios/chrome/browser/ui/qr_scanner/qr_scanner_legacy_coordinator.h" #import "ios/chrome/browser/ui/qr_scanner/requirements/qr_scanner_presenting.h" @@ -179,6 +184,7 @@ #import "ios/chrome/browser/ui/tools_menu/tools_menu_configuration.h" #import "ios/chrome/browser/ui/tools_menu/tools_menu_view_item.h" #import "ios/chrome/browser/ui/tools_menu/tools_popup_controller.h" +#import "ios/chrome/browser/ui/translate/language_selection_coordinator.h" #include "ios/chrome/browser/ui/ui_util.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" #import "ios/chrome/browser/ui/util/pasteboard_util.h" @@ -561,6 +567,9 @@ // Coordinator for the External Search UI. ExternalSearchCoordinator* _externalSearchCoordinator; + // Coordinator for the language selection UI. + LanguageSelectionCoordinator* _languageSelectionCoordinator; + // Fake status bar view used to blend the toolbar into the status bar. UIView* _fakeStatusBarView; @@ -1038,6 +1047,11 @@ _snackbarCoordinator.dispatcher = _dispatcher; [_snackbarCoordinator start]; + _languageSelectionCoordinator = + [[LanguageSelectionCoordinator alloc] initWithBaseViewController:self]; + _languageSelectionCoordinator.presenter = + [[VerticalAnimationContainer alloc] init]; + _javaScriptDialogPresenter.reset( new JavaScriptDialogPresenterImpl(_dialogPresenter)); _webStateDelegate.reset(new web::WebStateDelegateBridge(self)); @@ -2519,6 +2533,23 @@ NetExportTabHelper::CreateForWebState(tab.webState, self); CaptivePortalDetectorTabHelper::CreateForWebState(tab.webState, self); + // The language detection helper accepts a callback from the translate + // client, so must be created after it. + // This will explode if the webState doesn't have a JS injection manager + // (this only comes up in unit tests), so check for that and bypass the + // init of the translation helpers if needed. + // TODO(crbug.com/785238): Remove the need for this check. + if (tab.webState->GetJSInjectionReceiver()) { + ChromeIOSTranslateClient::CreateForWebState(tab.webState, + _languageSelectionCoordinator); + language::IOSLanguageDetectionTabHelper::CreateForWebState( + tab.webState, + ChromeIOSTranslateClient::FromWebState(tab.webState) + ->GetTranslateDriver() + ->CreateLanguageDetectionCallback(), + UrlLanguageHistogramFactory::GetForBrowserState(self.browserState)); + } + if (AccountConsistencyService* accountConsistencyService = ios::AccountConsistencyServiceFactory::GetForBrowserState( self.browserState)) {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm index a64f996..09a209545 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
@@ -148,8 +148,10 @@ #pragma mark - ContentSuggestionsHeaderSynchronizing - (void)updateFakeOmniboxOnCollectionScroll { - // Unfocus the omnibox when the scroll view is scrolled. - if ([self.headerController isOmniboxFocused] && !self.shouldAnimateHeader) { + // Unfocus the omnibox when the scroll view is scrolled by the user (but not + // when a scroll is triggered by layout/UIKit). + if ([self.headerController isOmniboxFocused] && !self.shouldAnimateHeader && + self.collectionView.dragging) { [self.headerController unfocusOmnibox]; }
diff --git a/ios/chrome/browser/ui/fullscreen/BUILD.gn b/ios/chrome/browser/ui/fullscreen/BUILD.gn index 4672fbf2..e37e589 100644 --- a/ios/chrome/browser/ui/fullscreen/BUILD.gn +++ b/ios/chrome/browser/ui/fullscreen/BUILD.gn
@@ -39,6 +39,9 @@ source_set("new_fullscreen_internal") { sources = [ "fullscreen_controller.mm", + "fullscreen_model.h", + "fullscreen_model.mm", + "fullscreen_model_observer.h", "fullscreen_ui_updater.mm", ] @@ -74,6 +77,7 @@ source_set("new_unit_tests") { testonly = true sources = [ + "fullscreen_model_unittest.mm", "fullscreen_ui_updater_unittest.mm", ] @@ -85,6 +89,7 @@ ":new_fullscreen_ui", "//ios/chrome/browser/ui:ui_util", "//ios/chrome/browser/ui/broadcaster", + "//ios/chrome/browser/ui/fullscreen/test", "//ios/web", "//ios/web/public", "//ios/web/public/test/fakes",
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h index 3b6c0c2..4f0b929 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h
@@ -10,6 +10,7 @@ #include "base/macros.h" class FullscreenControllerObserver; +class FullscreenModel; // An object that observes scrolling events in the main content area and // calculates how much of the toolbar should be visible as a result. When the @@ -37,6 +38,9 @@ void DecrementDisabledCounter(); private: + // The model used to calculate fullscreen state. + std::unique_ptr<FullscreenModel> model_; + DISALLOW_COPY_AND_ASSIGN(FullscreenController); };
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm index 09ec8c4..f0c878a9 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm
@@ -4,11 +4,15 @@ #import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h" +#include "base/memory/ptr_util.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 -FullscreenController::FullscreenController() {} +FullscreenController::FullscreenController() + : model_(base::MakeUnique<FullscreenModel>()) {} FullscreenController::~FullscreenController() {} @@ -24,14 +28,13 @@ } bool FullscreenController::IsEnabled() const { - // TODO(crbug.com/785665): Use FullscreenModel to track enabled state. - return false; + return model_->enabled(); } void FullscreenController::IncrementDisabledCounter() { - // TODO(crbug.com/785665): Use FullscreenModel to track enabled state. + model_->IncrementDisabledCounter(); } void FullscreenController::DecrementDisabledCounter() { - // TODO(crbug.com/785665): Use FullscreenModel to track enabled state. + model_->DecrementDisabledCounter(); }
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.h b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h new file mode 100644 index 0000000..7bc4082 --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
@@ -0,0 +1,110 @@ +// 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_CLEAN_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_MODEL_H_ +#define IOS_CLEAN_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_MODEL_H_ + +#import <CoreGraphics/CoreGraphics.h> +#include <cmath> + +#include "base/macros.h" +#include "base/observer_list.h" + +class FullscreenModelObserver; + +// Model object used to calculate fullscreen state. +class FullscreenModel { + public: + FullscreenModel(); + virtual ~FullscreenModel(); + + // Adds and removes FullscreenModelObservers. + void AddObserver(FullscreenModelObserver* observer) { + observers_.AddObserver(observer); + } + void RemoveObserver(FullscreenModelObserver* observer) { + observers_.RemoveObserver(observer); + } + + // The progress value calculated by the model. + CGFloat progress() const { return progress_; } + + // Whether fullscreen is disabled. When disabled, the toolbar is completely + // visible. + bool enabled() const { return disabled_counter_ == 0U; } + + // Whether the base offset has been recorded after state has been invalidated + // by navigations or toolbar height changes. + bool has_base_offset() const { return !std::isnan(base_offset_); } + + // Increments and decrements |disabled_counter_| for features that require the + // toolbar be completely visible. + void IncrementDisabledCounter(); + void DecrementDisabledCounter(); + + // Recalculates the fullscreen progress for a new navigation. + void ResetForNavigation(); + + // Called when a scroll end animation finishes. |progress| is the fullscreen + // progress corresponding to the final state of the aniamtion. + void AnimationEndedWithProgress(CGFloat progress); + + // Setter for the toolbar height to use in calculations. Setting this resets + // the model to a fully visible state. + void SetToolbarHeight(CGFloat toolbar_height); + + // Setter for the current vertical content offset. Setting this will + // recalculate the progress value. + void SetYContentOffset(CGFloat y_content_offset); + + // Setter for whether the scroll view is scrolling. If a scroll event ends + // and the progress value is not 0.0 or 1.0, the model will round to the + // nearest value. + void SetScrollViewIsScrolling(bool scrolling); + + // Setter for whether the scroll view is being dragged. Unlocked base offsets + // will be reset to all y content offset values received while the user is + // not dragging. + void SetScrollViewIsDragging(bool dragging); + + // Setter for whether the base content offset is locked. If the base offset + // is locked, the toolbar's location will be tied with a specific content + // offset of the scroll view, rather than being able to be shown mid-way + // through the page. + void SetBaseOffsetLocked(bool locked); + + private: + // Setter for |progress_|. Notifies observers of the new value if + // |notify_observers| is true. + void SetProgress(CGFloat progress); + + // Updates the base offset given the current y content offset, progress, and + // toolbar height. + void UpdateBaseOffset(); + + // The observers for this model. + base::ObserverList<FullscreenModelObserver> observers_; + // The percentage of the toolbar that should be visible, where 1.0 denotes a + // fully visible toolbar and 0.0 denotes a completely hidden one. + CGFloat progress_ = 0.0; + // The base offset from which to calculate fullscreen state. When |locked_| + // is false, it is reset to the current offset after each scroll event. + CGFloat base_offset_ = NAN; + // The height of the toolbar being shown or hidden by this model. + CGFloat toolbar_height_ = 0.0; + // The current vertical content offset of the main content. + CGFloat y_content_offset_ = 0.0; + // How many currently-running features require the toolbar be visible. + size_t disabled_counter_ = 0; + // Whether the main content is being scrolled. + bool scrolling_ = false; + // Whether the main content is being dragged. + bool dragging_ = false; + // Whether |base_offset_| is locked. + bool locked_ = false; + + DISALLOW_COPY_AND_ASSIGN(FullscreenModel); +}; + +#endif // IOS_CLEAN_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_MODEL_H_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm new file mode 100644 index 0000000..6b453ef --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
@@ -0,0 +1,108 @@ +// 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/fullscreen_model.h" + +#include <algorithm> + +#include "base/logging.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_model_observer.h" +#include "ios/chrome/browser/ui/ui_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +FullscreenModel::FullscreenModel() = default; +FullscreenModel::~FullscreenModel() = default; + +void FullscreenModel::IncrementDisabledCounter() { + if (++disabled_counter_ == 1U) { + for (auto& observer : observers_) { + observer.FullscreenModelEnabledStateChanged(this); + } + } +} + +void FullscreenModel::DecrementDisabledCounter() { + DCHECK_GT(disabled_counter_, 0U); + if (!--disabled_counter_) { + for (auto& observer : observers_) { + observer.FullscreenModelEnabledStateChanged(this); + } + } +} + +void FullscreenModel::ResetForNavigation() { + SetProgress(1.0); + scrolling_ = false; + base_offset_ = NAN; +} + +void FullscreenModel::AnimationEndedWithProgress(CGFloat progress) { + DCHECK_GE(progress, 0.0); + DCHECK_LE(progress, 1.0); + // Since this is being set by the animator instead of by scroll events, do not + // broadcast the new progress value. + progress_ = progress; +} + +void FullscreenModel::SetToolbarHeight(CGFloat toolbar_height) { + DCHECK_GE(toolbar_height, 0.0); + toolbar_height_ = toolbar_height; + ResetForNavigation(); +} + +void FullscreenModel::SetYContentOffset(CGFloat y_content_offset) { + y_content_offset_ = y_content_offset; + + if (!has_base_offset()) + UpdateBaseOffset(); + + if (scrolling_) { + CGFloat delta = base_offset_ - y_content_offset_; + SetProgress(1.0 + delta / toolbar_height_); + } else if (!locked_) { + UpdateBaseOffset(); + } +} + +void FullscreenModel::SetScrollViewIsScrolling(bool scrolling) { + if (scrolling_ == scrolling) + return; + scrolling_ = scrolling; + if (!scrolling_) { + for (auto& observer : observers_) { + observer.FullscreenModelScrollEventEnded(this); + } + } +} + +void FullscreenModel::SetScrollViewIsDragging(bool dragging) { + if (dragging_ == dragging) + return; + dragging_ = dragging; + // Update the base offset when dragging occurs. + if (dragging_ && !locked_) + UpdateBaseOffset(); +} + +void FullscreenModel::SetBaseOffsetLocked(bool locked) { + locked_ = locked; +} + +void FullscreenModel::SetProgress(CGFloat progress) { + progress = std::min(static_cast<CGFloat>(1.0), progress); + progress = std::max(static_cast<CGFloat>(0.0), progress); + if (AreCGFloatsEqual(progress_, progress)) + return; + progress_ = progress; + for (auto& observer : observers_) { + observer.FullscreenModelProgressUpdated(this); + } +} + +void FullscreenModel::UpdateBaseOffset() { + base_offset_ = y_content_offset_ - (1.0 - progress_) * toolbar_height_; +}
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model_observer.h b/ios/chrome/browser/ui/fullscreen/fullscreen_model_observer.h new file mode 100644 index 0000000..d966324 --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model_observer.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_FULLSCREEN_MODEL_OBSERVER_H_ +#define IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_MODEL_OBSERVER_H_ + +#include <CoreGraphics/CoreGraphics.h> + +#include "base/macros.h" + +class FullscreenModel; + +// Interface for listening to FullscreenModel changes. +class FullscreenModelObserver { + public: + FullscreenModelObserver() = default; + virtual ~FullscreenModelObserver() = default; + + // Invoked when |model|'s calculated progress() value is updated. + virtual void FullscreenModelProgressUpdated(FullscreenModel* model) {} + + // Invoked when |model| is enabled or disabled. + virtual void FullscreenModelEnabledStateChanged(FullscreenModel* model) {} + + // Invoked when a scroll event being tracked by |model| has ended. + virtual void FullscreenModelScrollEventEnded(FullscreenModel* model) {} + + private: + DISALLOW_COPY_AND_ASSIGN(FullscreenModelObserver); +}; + +#endif // IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_MODEL_OBSERVER_H_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model_unittest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_model_unittest.mm new file mode 100644 index 0000000..790b29e --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model_unittest.mm
@@ -0,0 +1,184 @@ +// 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/fullscreen_model.h" + +#import "ios/chrome/browser/ui/fullscreen/test/test_fullscreen_model_observer.h" +#include "ios/chrome/browser/ui/ui_util.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +// The toolbar height to use for tests. +const CGFloat kToolbarHeight = 50.0; +} // namespace + +// Test fixture for FullscreenModel. +class FullscreenModelTest : public PlatformTest { + public: + FullscreenModelTest() : PlatformTest() { + model_.AddObserver(&observer_); + // Set the toolbar height to kToolbarHeight, and simulate a page load that + // finishes with a 0.0 y content offset. + set_toolbar_height(kToolbarHeight); + model_.ResetForNavigation(); + set_y_content_offset(0.0); + } + ~FullscreenModelTest() override { model_.RemoveObserver(&observer_); } + + FullscreenModel& model() { return model_; } + TestFullscreenModelObserver& observer() { return observer_; } + + // FullscreenModel setters that store values before passing them to the model. + CGFloat toolbar_height() const { return toolbar_height_; } + void set_toolbar_height(CGFloat toolbar_height) { + toolbar_height_ = toolbar_height; + model_.SetToolbarHeight(toolbar_height_); + } + CGFloat y_content_offset() const { return y_content_offset_; } + void set_y_content_offset(CGFloat y_content_offset) { + y_content_offset_ = y_content_offset; + model_.SetYContentOffset(y_content_offset_); + } + + // The base offset against which fullscreen is being calculated. + CGFloat GetBaseOffsetForProgress(CGFloat progress) { + EXPECT_TRUE(model_.has_base_offset()); + return y_content_offset_ - (1.0 - progress) * toolbar_height_; + } + + // Simulates a user scroll event for a scroll of |offset_delta| points. + void SimulateUserScrollWithDelta(CGFloat offset_delta) { + model_.SetScrollViewIsDragging(true); + model_.SetScrollViewIsScrolling(true); + set_y_content_offset(y_content_offset() + offset_delta); + model_.SetScrollViewIsDragging(false); + model_.SetScrollViewIsScrolling(false); + } + + // Simulates a user scroll that will result in a progress value of |progress|. + void SimulateUserScrollForProgress(CGFloat progress) { + ASSERT_GE(progress, 0.0); + ASSERT_LE(progress, 1.0); + CGFloat final_y_content_offset = + toolbar_height_ * (1.0 - progress) + + GetBaseOffsetForProgress(observer_.progress()); + SimulateUserScrollWithDelta(final_y_content_offset - y_content_offset()); + } + + private: + FullscreenModel model_; + TestFullscreenModelObserver observer_; + CGFloat toolbar_height_ = 0.0; + CGFloat y_content_offset_ = 0.0; +}; + +// Tests that incremending and decrementing the disabled counter correctly +// disabled/enables the model. +TEST_F(FullscreenModelTest, EnableDisable) { + ASSERT_TRUE(model().enabled()); + ASSERT_TRUE(observer().enabled()); + // Increment the disabled counter and check that the model is disabled. + model().IncrementDisabledCounter(); + EXPECT_FALSE(model().enabled()); + EXPECT_FALSE(observer().enabled()); + // Increment again and check that the model is still disabled. + model().IncrementDisabledCounter(); + EXPECT_FALSE(model().enabled()); + EXPECT_FALSE(observer().enabled()); + // Decrement the counter and check that the model is still disabled. + model().DecrementDisabledCounter(); + EXPECT_FALSE(model().enabled()); + EXPECT_FALSE(observer().enabled()); + // Decrement again and check that the model is reenabled. + model().DecrementDisabledCounter(); + EXPECT_TRUE(model().enabled()); + EXPECT_TRUE(observer().enabled()); +} + +// Tests that calling ResetForNavigation() resets the model to a fully-visible +// pre-scroll state. +TEST_F(FullscreenModelTest, ResetForNavigation) { + // Simulate a scroll event and check that progress has been updated. + SimulateUserScrollForProgress(0.5); + ASSERT_EQ(observer().progress(), 0.5); + // Call ResetForNavigation() and verify that the base offset is reset and that + // the toolbar is fully visible. + model().ResetForNavigation(); + EXPECT_FALSE(model().has_base_offset()); + EXPECT_EQ(observer().progress(), 1.0); +} + +// Tests that the end progress value of a scroll adjustment animation is used +// as the model's progress. +TEST_F(FullscreenModelTest, AnimationEnded) { + const CGFloat kAnimationEndProgress = 0.5; + ASSERT_EQ(observer().progress(), 1.0); + model().AnimationEndedWithProgress(kAnimationEndProgress); + // Check that the resulting progress value was not broadcast. + EXPECT_EQ(observer().progress(), 1.0); + // Start dragging to to simulate a touch that occurs while the scroll end + // animation is in progress. This would cancel the scroll animation and call + // AnimationEndedWithProgress(). After this occurs, the base offset should be + // updated to a value corresponding with a 0.5 progress value. + model().SetScrollViewIsDragging(true); + EXPECT_EQ(GetBaseOffsetForProgress(kAnimationEndProgress), + y_content_offset() - kAnimationEndProgress * kToolbarHeight); +} + +// Tests that changing the toolbar height fully shows the new toolbar and +// responds appropriately to content offset changes. +TEST_F(FullscreenModelTest, UpdateToolbarHeight) { + // Reset the toolbar height and verify that the base offset is reset and that + // the toolbar is fully visible. + set_toolbar_height(2.0 * kToolbarHeight); + EXPECT_FALSE(model().has_base_offset()); + EXPECT_EQ(observer().progress(), 1.0); + // Simulate a page load to a 0.0 y content offset. + model().ResetForNavigation(); + set_y_content_offset(0.0); + // Simulate a scroll to -kToolbarHeight. Since toolbar_height() is twice + // that, this should produce a progress value of 0.5. + SimulateUserScrollWithDelta(kToolbarHeight); + ASSERT_EQ(y_content_offset(), kToolbarHeight); + EXPECT_EQ(observer().progress(), 0.5); +} + +// Tests that updating the y content offset produces the expected progress +// value. +TEST_F(FullscreenModelTest, UserScroll) { + const CGFloat final_progress = 0.5; + SimulateUserScrollForProgress(final_progress); + EXPECT_EQ(observer().progress(), final_progress); + EXPECT_EQ(y_content_offset(), final_progress * kToolbarHeight); +} + +// Tests that updating the y content offset programmatically (i.e. while the +// scroll view is not scrolling) does not produce a new progress value for +// observers. +TEST_F(FullscreenModelTest, ProgrammaticScroll) { + // Perform a programmatic scroll that would result in a progress of 0.5, and + // verify that the initial progress value of 1.0 is maintained. + const CGFloat kProgress = 0.5; + set_y_content_offset(kProgress * kToolbarHeight); + EXPECT_EQ(observer().progress(), 1.0); +} + +// Tests that setting scrolling to false sends a scroll end signal to its +// observers. +TEST_F(FullscreenModelTest, ScrollEnded) { + model().SetScrollViewIsScrolling(true); + model().SetScrollViewIsScrolling(false); + EXPECT_TRUE(observer().scroll_end_received()); +} + +// Tests that the base offset is updated when dragging begins. +TEST_F(FullscreenModelTest, DraggingStarted) { + model().ResetForNavigation(); + model().SetScrollViewIsDragging(true); + EXPECT_TRUE(model().has_base_offset()); +}
diff --git a/ios/chrome/browser/ui/fullscreen/test/BUILD.gn b/ios/chrome/browser/ui/fullscreen/test/BUILD.gn new file mode 100644 index 0000000..34832fa --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/test/BUILD.gn
@@ -0,0 +1,17 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("test") { + testonly = true + sources = [ + "test_fullscreen_model_observer.h", + "test_fullscreen_model_observer.mm", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + "//ios/chrome/browser/ui/fullscreen:new_fullscreen_internal", + ] +}
diff --git a/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_model_observer.h b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_model_observer.h new file mode 100644 index 0000000..610b8c7 --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_model_observer.h
@@ -0,0 +1,31 @@ +// 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_MODEL_OBSERVER_H_ +#define IOS_CHROME_BROWSER_UI_FULLSCREEN_TEST_TEST_FULLSCREEN_MODEL_OBSERVER_H_ + +#import "ios/chrome/browser/ui/fullscreen/fullscreen_model_observer.h" + +// Test observer for FullscreenModel. +class TestFullscreenModelObserver : public FullscreenModelObserver { + public: + TestFullscreenModelObserver(); + + // The values provided to the observer. + CGFloat progress() { return progress_; } + bool enabled() { return enabled_; } + bool scroll_end_received() { return scroll_end_received_; } + + private: + // FullscreenModelObserver: + void FullscreenModelProgressUpdated(FullscreenModel* model) override; + void FullscreenModelEnabledStateChanged(FullscreenModel* model) override; + void FullscreenModelScrollEventEnded(FullscreenModel* model) override; + + CGFloat progress_ = 0.0; + bool enabled_ = true; + bool scroll_end_received_ = false; +}; + +#endif // IOS_CHROME_BROWSER_UI_FULLSCREEN_TEST_TEST_FULLSCREEN_MODEL_OBSERVER_H_
diff --git a/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_model_observer.mm b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_model_observer.mm new file mode 100644 index 0000000..49db06e --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_model_observer.mm
@@ -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. + +#import "ios/chrome/browser/ui/fullscreen/test/test_fullscreen_model_observer.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 + +TestFullscreenModelObserver::TestFullscreenModelObserver() = default; + +void TestFullscreenModelObserver::FullscreenModelProgressUpdated( + FullscreenModel* model) { + progress_ = model->progress(); +} + +void TestFullscreenModelObserver::FullscreenModelEnabledStateChanged( + FullscreenModel* model) { + enabled_ = model->enabled(); +} + +void TestFullscreenModelObserver::FullscreenModelScrollEventEnded( + FullscreenModel* model) { + scroll_end_received_ = true; +}
diff --git a/ios/chrome/browser/ui/keyboard_commands_egtest.mm b/ios/chrome/browser/ui/keyboard_commands_egtest.mm index f695e58b..ee6faa80 100644 --- a/ios/chrome/browser/ui/keyboard_commands_egtest.mm +++ b/ios/chrome/browser/ui/keyboard_commands_egtest.mm
@@ -30,8 +30,6 @@ using chrome_test_util::NavigationBarDoneButton; -const CGFloat kScrollDisplacement = 50.0; - // Test cases to verify that keyboard commands are and are not registered when // expected. @interface KeyboardCommandsTestCase : ChromeTestCase @@ -95,18 +93,6 @@ GREYAssert(success, @"The bookmark editor was not displayed."); } -// Open tools menu, find and tap on item specified by |toolsMenuItem| matcher. -// TODO(crbug.com/638674): Evaluate if this can move to shared code. -- (void)selectToolsMenuItem:(id<GREYMatcher>)toolsMenuItem { - [ChromeEarlGreyUI openToolsMenu]; - - id<GREYMatcher> toolsMenuTableView = chrome_test_util::ToolsMenuView(); - [[[EarlGrey selectElementWithMatcher:toolsMenuItem] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, - kScrollDisplacement) - onElementWithMatcher:toolsMenuTableView] performAction:grey_tap()]; -} - #pragma mark - Tests // Tests that keyboard commands are registered when the BVC is showing without @@ -166,7 +152,9 @@ scoped_feature_list.InitAndDisableFeature(kBookmarkNewGeneration); // Open Bookmarks - [self selectToolsMenuItem:grey_accessibilityID(kToolsMenuBookmarksId)]; + [ChromeEarlGreyUI openToolsMenu]; + [ChromeEarlGreyUI + tapToolsMenuButton:grey_accessibilityID(kToolsMenuBookmarksId)]; if (IsIPadIdiom()) { [self verifyKeyboardCommandsAreRegistered]; @@ -183,7 +171,8 @@ - (void)testKeyboardCommands_RecentTabsPresented { // Open Recent Tabs id<GREYMatcher> recentTabs = grey_accessibilityID(kToolsMenuOtherDevicesId); - [self selectToolsMenuItem:recentTabs]; + [ChromeEarlGreyUI openToolsMenu]; + [ChromeEarlGreyUI tapToolsMenuButton:recentTabs]; if (IsIPadIdiom()) { [self verifyKeyboardCommandsAreRegistered];
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h index 1f778df..0ffc3d9 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h +++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h
@@ -63,7 +63,7 @@ void RevertAll() override; void UpdatePopup() override; void OnTemporaryTextMaybeChanged(const base::string16& display_text, - AutocompleteMatch::Type match_type, + const AutocompleteMatch& match, bool save_original_selection, bool notify_text_changed) override; bool OnInlineAutocompleteTextMaybeChanged(const base::string16& display_text,
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm index 3070a85..cab016f4 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
@@ -262,7 +262,7 @@ void OmniboxViewIOS::OnTemporaryTextMaybeChanged( const base::string16& display_text, - AutocompleteMatch::Type match_type, + const AutocompleteMatch& match, bool save_original_selection, bool notify_text_changed) { SetWindowTextAndCaretPos(display_text, display_text.size(), false, false);
diff --git a/ios/chrome/browser/ui/presenters/BUILD.gn b/ios/chrome/browser/ui/presenters/BUILD.gn new file mode 100644 index 0000000..daf12c1 --- /dev/null +++ b/ios/chrome/browser/ui/presenters/BUILD.gn
@@ -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. + +source_set("presenters") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "contained_presenter.h", + "contained_presenter_delegate.h", + "vertical_animation_container.h", + "vertical_animation_container.mm", + ] + deps = [ + "//base", + "//ios/chrome/browser/ui/util:constraints_ui", + ] +} + +source_set("unit_tests") { + testonly = true + configs += [ "//build/config/compiler:enable_arc" ] + + sources = [ + "vertical_animation_container_unittest.mm", + ] + + deps = [ + ":presenters", + "//base", + "//base/test:test_support", + "//ios/chrome/test/base", + "//testing/gtest", + ] +}
diff --git a/ios/chrome/browser/ui/presenters/contained_presenter.h b/ios/chrome/browser/ui/presenters/contained_presenter.h new file mode 100644 index 0000000..13ddf83d --- /dev/null +++ b/ios/chrome/browser/ui/presenters/contained_presenter.h
@@ -0,0 +1,46 @@ +// 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_PRESENTERS_CONTAINED_PRESENTER_H_ +#define IOS_CHROME_BROWSER_UI_PRESENTERS_CONTAINED_PRESENTER_H_ + +#import <UIKit/UIKit.h> + +@protocol ContainedPresenterDelegate; + +// Helper that manages the positioning and presentation of a contained (child) +// view controller. Implementors determine the specifics of the positioning +// and presentation. +@protocol ContainedPresenter + +// The view controller which will contain the presented (child) view controller. +@property(nonatomic, weak) UIViewController* baseViewController; +// The view controller to be presented. +@property(nonatomic, weak) UIViewController* presentedViewController; +// The delegate object which will be told about presentation events. +@property(nonatomic, weak) id<ContainedPresenterDelegate> delegate; + +// Prepares the view controllers for presentation. The presented view controller +// should become a child of the base view controller. +- (void)prepareForPresentation; + +// Presents the presented view controller, animating the presentation if +// |animated| is YES. If |animated| is NO, any layout changes should execute +// synchronously. This is a no-op if the presented view controller is already +// being presented. It's an error to call this without calling +// -prepareForPresentation first. +- (void)presentAnimated:(BOOL)animated; + +// Dismisses the presented view controller, animating the dismissal if +// |animated| is YES. If |animated| is NO, any layout changes should execute +// synchronously. This is a no-op if the presented view controller is already +// dismissed, or hasn't been presented. Once the presentation completes (or +// synchronously if |animated| is NO), |delegate| should have its +// -containedPresenterDidDismiss: method called, and the presented view +// controller should stop being a child of the base view controller. +- (void)dismissAnimated:(BOOL)animated; + +@end + +#endif // IOS_CHROME_BROWSER_UI_PRESENTERS_CONTAINED_PRESENTER_H_
diff --git a/ios/chrome/browser/ui/presenters/contained_presenter_delegate.h b/ios/chrome/browser/ui/presenters/contained_presenter_delegate.h new file mode 100644 index 0000000..c6effe2 --- /dev/null +++ b/ios/chrome/browser/ui/presenters/contained_presenter_delegate.h
@@ -0,0 +1,21 @@ +// 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_PRESENTERS_CONTAINED_PRESENTER_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_PRESENTERS_CONTAINED_PRESENTER_DELEGATE_H_ + +#import <Foundation/Foundation.h> + +@protocol ContainedPresenter; + +// Protocol for an object which acts as a delegate for a contained presenter, +// and which is informed about dismissal events. +@protocol ContainedPresenterDelegate + +// Tells the delegate that |presenter| has finished dismissing. +- (void)containedPresenterDidDismiss:(id<ContainedPresenter>)presenter; + +@end + +#endif // IOS_CHROME_BROWSER_UI_PRESENTERS_CONTAINED_PRESENTER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/presenters/vertical_animation_container.h b/ios/chrome/browser/ui/presenters/vertical_animation_container.h new file mode 100644 index 0000000..9181cb80 --- /dev/null +++ b/ios/chrome/browser/ui/presenters/vertical_animation_container.h
@@ -0,0 +1,17 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_PRESENTERS_VERTICAL_ANIMATION_CONTAINER_H_ +#define IOS_CHROME_BROWSER_UI_PRESENTERS_VERTICAL_ANIMATION_CONTAINER_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/ui/presenters/contained_presenter.h" + +// Helper that manages the positioning and presentation of a view controller, +// anchoring at the bottom of its container, and animating it up from below. +@interface VerticalAnimationContainer : NSObject<ContainedPresenter> +@end + +#endif // IOS_CHROME_BROWSER_UI_PRESENTERS_VERTICAL_ANIMATION_CONTAINER_H_
diff --git a/ios/chrome/browser/ui/presenters/vertical_animation_container.mm b/ios/chrome/browser/ui/presenters/vertical_animation_container.mm new file mode 100644 index 0000000..a5d598a1 --- /dev/null +++ b/ios/chrome/browser/ui/presenters/vertical_animation_container.mm
@@ -0,0 +1,141 @@ +// 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/presenters/vertical_animation_container.h" + +#include "base/logging.h" +#import "ios/chrome/browser/ui/presenters/contained_presenter_delegate.h" +#include "ios/chrome/browser/ui/util/constraints_ui_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +NSTimeInterval kAnimationDuration = 0.2; +} + +@interface VerticalAnimationContainer () +@property(nonatomic) NSArray<NSLayoutConstraint*>* dismissedConstraints; +@property(nonatomic) NSArray<NSLayoutConstraint*>* presentedConstraints; +@end + +@implementation VerticalAnimationContainer + +// Synthesize ContainedPresenter properties. +@synthesize baseViewController = _baseViewController; +@synthesize presentedViewController = _presentedViewController; +@synthesize delegate = _delegate; +// Synthesize private properties. +@synthesize dismissedConstraints = _dismissedConstraints; +@synthesize presentedConstraints = _presentedConstraints; + +- (void)prepareForPresentation { + [self.baseViewController addChildViewController:self.presentedViewController]; + [self.baseViewController.view addSubview:self.presentedViewController.view]; + + // Shorter names for more readable constraint code. + UIView* container = self.baseViewController.view; + UIView* contents = self.presentedViewController.view; + + // The contents view will be sized and positioned by constraints. + contents.translatesAutoresizingMaskIntoConstraints = NO; + + // Sizing constraints never change, so they don't need to be stored. + // Height is sized by the contents of |contents|. + [contents.widthAnchor constraintEqualToAnchor:container.widthAnchor].active = + YES; + + // The horizontal position of the contents in the container also doesn't + // change. + [contents.centerXAnchor constraintEqualToAnchor:container.centerXAnchor] + .active = YES; + + // When dismissed, the top of the contents is just below the bottom of the + // container. + self.dismissedConstraints = @[ + [contents.topAnchor constraintEqualToAnchor:container.bottomAnchor], + ]; + + // When presented, the bottom of the contents matches the bottom of the + // container. + self.presentedConstraints = @[ + [contents.bottomAnchor constraintEqualToAnchor:container.bottomAnchor], + ]; + + // The contents start off dismissed. + [NSLayoutConstraint activateConstraints:self.dismissedConstraints]; + + // Ensure the contents are actually positioned in the dismissed positions. + [self.baseViewController.view layoutIfNeeded]; + + [self.presentedViewController + didMoveToParentViewController:self.baseViewController]; +} + +- (void)presentAnimated:(BOOL)animated { + // An error if -prepareForPresentation hasn't been called yet. + // Simple coherence test: the presented view controller's view has a + // superview. + DCHECK(self.presentedViewController.view.superview); + + // No-op if already presented. + if (self.presentedConstraints[0].active) + return; + + [UIView animateWithDuration:animated ? kAnimationDuration : 0.0 + animations:^{ + [NSLayoutConstraint + deactivateConstraints:self.dismissedConstraints]; + [NSLayoutConstraint + activateConstraints:self.presentedConstraints]; + [self.baseViewController.view layoutIfNeeded]; + }]; +} + +- (void)dismissAnimated:(BOOL)animated { + // No-op if already dismissed. + if (self.dismissedConstraints[0].active) + return; + + void (^animations)() = ^{ + [NSLayoutConstraint deactivateConstraints:self.presentedConstraints]; + [NSLayoutConstraint activateConstraints:self.dismissedConstraints]; + [self.baseViewController.view layoutIfNeeded]; + }; + void (^completion)(BOOL) = ^(BOOL finished) { + [self cleanUpAfterDismissal]; + [self.delegate containedPresenterDidDismiss:self]; + }; + + if (animated) { + // Trigger a layout pass before the animation, so that any pending updates + // aren't animated along with the dismissal. + [self.baseViewController.view layoutIfNeeded]; + + [UIView animateWithDuration:kAnimationDuration + animations:animations + completion:completion]; + } else { + // Just execute everything synchronously if the dismissal isn't animated. + // Note that just using an animation duration of 0 in -animateWithDuration: + // will still call the completion block asynchronously. + animations(); + completion(YES); + } +} + +#pragma mark - private + +- (void)cleanUpAfterDismissal { + if (self.presentedViewController.parentViewController != + self.baseViewController) { + return; + } + [self.presentedViewController willMoveToParentViewController:nil]; + [self.presentedViewController.view removeFromSuperview]; + [self.presentedViewController removeFromParentViewController]; +} + +@end
diff --git a/ios/chrome/browser/ui/presenters/vertical_animation_container_unittest.mm b/ios/chrome/browser/ui/presenters/vertical_animation_container_unittest.mm new file mode 100644 index 0000000..43e79cad0 --- /dev/null +++ b/ios/chrome/browser/ui/presenters/vertical_animation_container_unittest.mm
@@ -0,0 +1,88 @@ +// 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/presenters/vertical_animation_container.h" + +#import "ios/chrome/browser/ui/presenters/contained_presenter.h" +#import "ios/chrome/browser/ui/presenters/contained_presenter_delegate.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// Test delegate helper; the delegate callback sets the |dismissed| property. +@interface TestContainedPresenterDelegate : NSObject<ContainedPresenterDelegate> +@property(nonatomic) BOOL dismissed; +@end + +@implementation TestContainedPresenterDelegate +@synthesize dismissed = _dismissed; + +- (void)containedPresenterDidDismiss:(id<ContainedPresenter>)presenter { + self.dismissed = YES; +} + +@end + +namespace { + +class VerticalAnimationContainerTest : public PlatformTest { + public: + VerticalAnimationContainerTest() + : delegate_([[TestContainedPresenterDelegate alloc] init]), + base_([[UIViewController alloc] init]), + presented_([[UIViewController alloc] init]), + presenter_([[VerticalAnimationContainer alloc] init]) { + presenter_.baseViewController = base_; + presenter_.presentedViewController = presented_; + presenter_.delegate = delegate_; + } + + protected: + __strong TestContainedPresenterDelegate* delegate_; + __strong UIViewController* base_; + __strong UIViewController* presented_; + __strong id<ContainedPresenter> presenter_; +}; + +TEST_F(VerticalAnimationContainerTest, TestPreparation) { + [presenter_ prepareForPresentation]; + + // General expectations for presentation prep. + EXPECT_TRUE([base_.childViewControllers containsObject:presented_]); + EXPECT_TRUE(presented_.view.superview == base_.view); + + // For vertical animation, the presented view should start below the + // base view controller's view, and be the same width. + EXPECT_EQ(base_.view.frame.size.width, presented_.view.bounds.size.width); + EXPECT_EQ(presented_.view.frame.origin.x, 0); + EXPECT_GE(presented_.view.frame.origin.y, base_.view.bounds.size.height); +} + +TEST_F(VerticalAnimationContainerTest, TestPresentation) { + [presenter_ prepareForPresentation]; + [presenter_ presentAnimated:NO]; + + // For vertical animation, the presented view should be entirely contained + // by the base view controller's view, and be aligned with its bottom. + EXPECT_TRUE(CGRectContainsRect(base_.view.bounds, presented_.view.frame)); + EXPECT_EQ(CGRectGetMaxY(base_.view.bounds), + CGRectGetMaxY(presented_.view.frame)); + // The delegate method should not be called here. + EXPECT_FALSE(delegate_.dismissed); +} + +TEST_F(VerticalAnimationContainerTest, TestDismissal) { + [presenter_ prepareForPresentation]; + [presenter_ presentAnimated:NO]; + [presenter_ dismissAnimated:NO]; + + EXPECT_FALSE([base_.childViewControllers containsObject:presented_]); + EXPECT_FALSE(presented_.view.superview == base_.view); + EXPECT_TRUE(delegate_.dismissed); +} + +} // namespace
diff --git a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm index 707cecf..e6195b4 100644 --- a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm
@@ -95,8 +95,8 @@ _prefObserverBridge.reset(new PrefObserverBridge(self)); // Register to observe any changes on Perf backed values displayed by the // screen. - _prefObserverBridge->ObserveChangesForPreference(prefs::kEnableTranslate, - &_prefChangeRegistrar); + _prefObserverBridge->ObserveChangesForPreference( + prefs::kOfferTranslateEnabled, &_prefChangeRegistrar); HostContentSettingsMap* settingsMap = ios::HostContentSettingsMapFactory::GetForBrowserState(browserState); @@ -156,7 +156,8 @@ - (CollectionViewItem*)translateItem { _translateDetailItem = [[CollectionViewDetailItem alloc] initWithType:ItemTypeSettingsTranslate]; - BOOL enabled = browserState_->GetPrefs()->GetBoolean(prefs::kEnableTranslate); + BOOL enabled = + browserState_->GetPrefs()->GetBoolean(prefs::kOfferTranslateEnabled); NSString* subtitle = enabled ? l10n_util::GetNSString(IDS_IOS_SETTING_ON) : l10n_util::GetNSString(IDS_IOS_SETTING_OFF); _translateDetailItem.text = l10n_util::GetNSString(IDS_IOS_TRANSLATE_SETTING); @@ -221,7 +222,7 @@ #pragma mark - PrefObserverDelegate - (void)onPreferenceChanged:(const std::string&)preferenceName { - if (preferenceName == prefs::kEnableTranslate) { + if (preferenceName == prefs::kOfferTranslateEnabled) { BOOL enabled = browserState_->GetPrefs()->GetBoolean(preferenceName); NSString* subtitle = enabled ? l10n_util::GetNSString(IDS_IOS_SETTING_ON) : l10n_util::GetNSString(IDS_IOS_SETTING_OFF);
diff --git a/ios/chrome/browser/ui/settings/translate_collection_view_controller.mm b/ios/chrome/browser/ui/settings/translate_collection_view_controller.mm index 9d44860..57e70205 100644 --- a/ios/chrome/browser/ui/settings/translate_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/translate_collection_view_controller.mm
@@ -78,9 +78,9 @@ self.collectionViewAccessibilityIdentifier = @"translate_settings_view_controller"; _prefs = prefs; - _translationEnabled = - [[PrefBackedBoolean alloc] initWithPrefService:_prefs - prefName:prefs::kEnableTranslate]; + _translationEnabled = [[PrefBackedBoolean alloc] + initWithPrefService:_prefs + prefName:prefs::kOfferTranslateEnabled]; [_translationEnabled setObserver:self]; // TODO(crbug.com/764578): -loadModel should not be called from // initializer. A possible fix is to move this call to -viewDidLoad.
diff --git a/ios/chrome/browser/ui/settings/translate_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/translate_collection_view_controller_unittest.mm index 547df5f..2c6232a 100644 --- a/ios/chrome/browser/ui/settings/translate_collection_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/translate_collection_view_controller_unittest.mm
@@ -58,7 +58,7 @@ std::unique_ptr<PrefService> CreateLocalState() { scoped_refptr<PrefRegistrySyncable> registry = new PrefRegistrySyncable(); - registry->RegisterBooleanPref(prefs::kEnableTranslate, false, + registry->RegisterBooleanPref(prefs::kOfferTranslateEnabled, false, PrefRegistrySyncable::SYNCABLE_PREF); translate::TranslatePrefs::RegisterProfilePrefs(registry.get()); registry->RegisterStringPref( @@ -85,7 +85,7 @@ TEST_F(TranslateCollectionViewControllerTest, TestModelTranslateOn) { BooleanPrefMember translateEnabled; - translateEnabled.Init(prefs::kEnableTranslate, pref_service_.get()); + translateEnabled.Init(prefs::kOfferTranslateEnabled, pref_service_.get()); translateEnabled.SetValue(true); CreateController(); EXPECT_EQ(2, NumberOfSections());
diff --git a/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller_egtest.mm b/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller_egtest.mm index 4b33d6e4..3775eb2d 100644 --- a/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller_egtest.mm +++ b/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller_egtest.mm
@@ -475,14 +475,9 @@ identity); // Open Bookmarks and tap on Sign In promo button. - const CGFloat scroll_displacement = 50.0; [ChromeEarlGreyUI openToolsMenu]; - [[[EarlGrey - selectElementWithMatcher:grey_accessibilityID(kToolsMenuBookmarksId)] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, - scroll_displacement) - onElementWithMatcher:chrome_test_util::ToolsMenuView()] - performAction:grey_tap()]; + [ChromeEarlGreyUI + tapToolsMenuButton:grey_accessibilityID(kToolsMenuBookmarksId)]; if (!IsIPadIdiom()) { // Opens the bookmark manager sidebar on handsets. @@ -514,12 +509,8 @@ // Re-open the sign-in screen. If it wasn't correctly dismissed previously, // this will fail. [ChromeEarlGreyUI openToolsMenu]; - [[[EarlGrey - selectElementWithMatcher:grey_accessibilityID(kToolsMenuBookmarksId)] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, - scroll_displacement) - onElementWithMatcher:chrome_test_util::ToolsMenuView()] - performAction:grey_tap()]; + [ChromeEarlGreyUI + tapToolsMenuButton:grey_accessibilityID(kToolsMenuBookmarksId)]; if (!IsIPadIdiom()) { [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Menu")] performAction:grey_tap()];
diff --git a/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.mm index 8ea713c..097ad97 100644 --- a/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.mm +++ b/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.mm
@@ -70,7 +70,7 @@ } - (void)selectedTabChanged { - [self.toolbarController selectedTabChanged]; + [self.toolbarController cancelOmniboxEdit]; } - (void)setTabCount:(NSInteger)tabCount {
diff --git a/ios/chrome/browser/ui/toolbar/public/abstract_web_toolbar.h b/ios/chrome/browser/ui/toolbar/public/abstract_web_toolbar.h index 702aace..1ce87b91 100644 --- a/ios/chrome/browser/ui/toolbar/public/abstract_web_toolbar.h +++ b/ios/chrome/browser/ui/toolbar/public/abstract_web_toolbar.h
@@ -31,8 +31,6 @@ - (BOOL)isOmniboxFirstResponder; // Returns whether the omnibox popup is currently displayed. - (BOOL)showingOmniboxPopup; -// Called when the current tab changes or is closed. -- (void)selectedTabChanged; // Update the visibility of the toolbar before making a side swipe snapshot so // the toolbar looks appropriate for |tab|. This includes morphing the toolbar // to look like the new tab page header.
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_adapter.mm b/ios/chrome/browser/ui/toolbar/toolbar_adapter.mm index d37c59b..48a15e0a 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_adapter.mm +++ b/ios/chrome/browser/ui/toolbar/toolbar_adapter.mm
@@ -77,10 +77,6 @@ return NO; } -- (void)selectedTabChanged { - return; -} - - (void)updateToolbarForSideSwipeSnapshot:(Tab*)tab { [self.toolbarCoordinator updateToolbarForSideSwipeSnapshot:tab.webState]; }
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm index 460274fe..cb19f6736 100644 --- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm +++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -681,10 +681,6 @@ [self startProgressBar]; } -- (void)selectedTabChanged { - [self cancelOmniboxEdit]; -} - - (CGRect)visibleOmniboxFrame { CGRect frame = _omniboxBackground.frame; frame = [self.view.superview convertRect:frame @@ -2311,6 +2307,14 @@ } } +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + // The popup positions itself as a static frame below the web toolbar. This + // will no longer be necessary post omnibox popup boxing. + _popupView->UpdatePopupAppearance(); +} + @end #pragma mark - Testing only.
diff --git a/ios/chrome/browser/ui/translate/BUILD.gn b/ios/chrome/browser/ui/translate/BUILD.gn new file mode 100644 index 0000000..79af1f9 --- /dev/null +++ b/ios/chrome/browser/ui/translate/BUILD.gn
@@ -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. + +source_set("translate") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "language_selection_coordinator.h", + "language_selection_coordinator.mm", + "language_selection_mediator.h", + "language_selection_mediator.mm", + ] + deps = [ + ":translate_ui", + "//base", + "//components/translate/core/browser", + "//ios/chrome/browser", + "//ios/chrome/browser/translate", + "//ios/chrome/browser/ui/presenters", + ] +} + +source_set("translate_ui") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "language_selection_consumer.h", + "language_selection_provider.h", + "language_selection_view_controller.h", + "language_selection_view_controller.mm", + ] + deps = [ + "//base", + ] +}
diff --git a/ios/chrome/browser/ui/translate/language_selection_consumer.h b/ios/chrome/browser/ui/translate/language_selection_consumer.h new file mode 100644 index 0000000..9c884335 --- /dev/null +++ b/ios/chrome/browser/ui/translate/language_selection_consumer.h
@@ -0,0 +1,27 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_CONSUMER_H_ +#define IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_CONSUMER_H_ + +#import <Foundation/Foundation.h> + +@protocol LanguageSelectionProvider; + +// Consumer protocol for a view controller providing a language selection +// interface. +@protocol LanguageSelectionConsumer +// The language provider that the consumer should use to fetch language +// information for display. +@property(nonatomic, weak) id<LanguageSelectionProvider> provider; +// The number of languages available for display in the interface. +@property(nonatomic) int languageCount; +// The index of the initially selected language. +@property(nonatomic) int initialLanguageIndex; +// The index of a language unavailable for selection (because it has already +// been selected, for example). +@property(nonatomic) int disabledLanguageIndex; +@end + +#endif // IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/translate/language_selection_coordinator.h b/ios/chrome/browser/ui/translate/language_selection_coordinator.h new file mode 100644 index 0000000..8ea1670 --- /dev/null +++ b/ios/chrome/browser/ui/translate/language_selection_coordinator.h
@@ -0,0 +1,35 @@ +// 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_TRANSLATE_LANGUAGE_SELECTION_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_COORDINATOR_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/translate/language_selection_handler.h" + +@protocol ContainedPresenter; + +// A coordinator for a language selection UI. This is intended for display as +// a contained, not presented, view controller. +// The methods defined in the LanguageSelectionHandler protocol will be called +// to start the coordinator. +@interface LanguageSelectionCoordinator : NSObject<LanguageSelectionHandler> + +// Creates a coordinator that will use |viewController| as the base view +// controller for presenting its UI. +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +// The base view controller the receiver was initialized with. +@property(weak, nonatomic, readonly) UIViewController* baseViewController; + +// Presenter to use to for presenting the receiver's view controller. +@property(nonatomic) id<ContainedPresenter> presenter; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/translate/language_selection_coordinator.mm b/ios/chrome/browser/ui/translate/language_selection_coordinator.mm new file mode 100644 index 0000000..de283589 --- /dev/null +++ b/ios/chrome/browser/ui/translate/language_selection_coordinator.mm
@@ -0,0 +1,125 @@ +// 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/translate/language_selection_coordinator.h" + +#import "base/logging.h" +#import "ios/chrome/browser/translate/language_selection_delegate.h" +#import "ios/chrome/browser/ui/presenters/contained_presenter.h" +#import "ios/chrome/browser/ui/presenters/contained_presenter_delegate.h" +#import "ios/chrome/browser/ui/translate/language_selection_mediator.h" +#import "ios/chrome/browser/ui/translate/language_selection_view_controller.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface LanguageSelectionCoordinator ()< + LanguageSelectionViewControllerDelegate, + ContainedPresenterDelegate> +// The view controller this coordinator manages. +@property(nonatomic) LanguageSelectionViewController* selectionViewController; +// A mediator to interoperate with the translation model. +@property(nonatomic) LanguageSelectionMediator* selectionMediator; +// A delegate, provided by showLanguageSelectorWithContext:delegate:. +@property(nonatomic, weak) id<LanguageSelectionDelegate> selectionDelegate; +// YES if the coordinator has started displaying its UI. +@property(nonatomic, readonly) BOOL started; + +// Starts displaying the UI for this coordinator, using self.presenter to handle +// the positioning and display of self.selectionViewController. +// It is an error to call this method when self.presenter is nil. +- (void)start; + +// Cleans up state after the UI for this coordinator has stopped being +// displayed. +- (void)stop; + +@end + +@implementation LanguageSelectionCoordinator + +// Public properties. +@synthesize baseViewController = _baseViewController; +@synthesize presenter = _presenter; +// Private properties. +@synthesize selectionViewController = _selectionViewController; +@synthesize selectionMediator = _selectionMediator; +@synthesize selectionDelegate = _selectionDelegate; + +- (nullable instancetype)initWithBaseViewController: + (UIViewController*)viewController { + if ((self = [super init])) { + _baseViewController = viewController; + } + return self; +} + +#pragma mark - private property implementation + +- (BOOL)started { + return self.presenter.presentedViewController != nil; +} + +#pragma mark - private methods + +- (void)start { + DCHECK(self.presenter); + + self.presenter.baseViewController = self.baseViewController; + self.presenter.presentedViewController = self.selectionViewController; + self.presenter.delegate = self; + + [self.presenter prepareForPresentation]; + + [self.presenter presentAnimated:YES]; +} + +- (void)stop { + self.selectionViewController = nil; + self.selectionMediator = nil; +} + +#pragma mark - LanguageSelectionHandler + +- (void)showLanguageSelectorWithContext:(LanguageSelectionContext*)context + delegate: + (id<LanguageSelectionDelegate>)delegate { + if (self.started) + return; + + self.selectionDelegate = delegate; + + self.selectionMediator = + [[LanguageSelectionMediator alloc] initWithContext:context]; + + self.selectionViewController = [[LanguageSelectionViewController alloc] init]; + self.selectionViewController.delegate = self; + self.selectionMediator.consumer = self.selectionViewController; + + [self start]; +} + +#pragma mark - LanguageSelectionViewControllerDelegate + +- (void)languageSelectedAtIndex:(int)index { + [self.selectionDelegate + languageSelectorSelectedLanguage: + [self.selectionMediator languageCodeForLanguageAtIndex:index]]; + [self.presenter dismissAnimated:YES]; +} + +- (void)languageSelectionCanceled { + [self.selectionDelegate languageSelectorClosedWithoutSelection]; + [self.presenter dismissAnimated:YES]; +} + +#pragma mark - ContainedPresenterDelegate + +- (void)containedPresenterDidDismiss:(id<ContainedPresenter>)presenter { + DCHECK(presenter == self.presenter); + [self stop]; +} + +@end
diff --git a/ios/chrome/browser/ui/translate/language_selection_mediator.h b/ios/chrome/browser/ui/translate/language_selection_mediator.h new file mode 100644 index 0000000..de067951 --- /dev/null +++ b/ios/chrome/browser/ui/translate/language_selection_mediator.h
@@ -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. + +#ifndef IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_MEDIATOR_H_ +#define IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_MEDIATOR_H_ + +#import <Foundation/Foundation.h> +#include <string> + +@protocol LanguageSelectionConsumer; +@class LanguageSelectionContext; + +// Mediator object to configure and provide data for language selection. +@interface LanguageSelectionMediator : NSObject + +// Designated initializer. |context| is the context object provided for language +// selection. +- (instancetype)initWithContext:(LanguageSelectionContext*)context + NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; + +// Consumer for this mediator. +@property(nonatomic, weak) id<LanguageSelectionConsumer> consumer; + +// Utility method for the coordinator to map a selected language index to a +// language name. +- (std::string)languageCodeForLanguageAtIndex:(int)index; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/translate/language_selection_mediator.mm b/ios/chrome/browser/ui/translate/language_selection_mediator.mm new file mode 100644 index 0000000..9cb7dc98 --- /dev/null +++ b/ios/chrome/browser/ui/translate/language_selection_mediator.mm
@@ -0,0 +1,63 @@ +// 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/translate/language_selection_mediator.h" + +#include "base/logging.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "components/translate/core/browser/translate_infobar_delegate.h" +#import "ios/chrome/browser/translate/language_selection_context.h" +#import "ios/chrome/browser/ui/translate/language_selection_consumer.h" +#import "ios/chrome/browser/ui/translate/language_selection_provider.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface LanguageSelectionMediator ()<LanguageSelectionProvider> +@property(nonatomic) LanguageSelectionContext* context; +@end + +@implementation LanguageSelectionMediator + +@synthesize consumer = _consumer; +@synthesize context = _context; + +- (instancetype)initWithContext:(LanguageSelectionContext*)context { + if ((self = [super init])) { + _context = context; + } + return self; +} + +- (void)setConsumer:(id<LanguageSelectionConsumer>)consumer { + _consumer = consumer; + self.consumer.languageCount = self.context.languageData->num_languages(); + self.consumer.initialLanguageIndex = self.context.initialLanguageIndex; + self.consumer.disabledLanguageIndex = self.context.unavailableLanguageIndex; + self.consumer.provider = self; +} + +#pragma mark - Public methods + +- (std::string)languageCodeForLanguageAtIndex:(int)index { + return self.context.languageData->language_code_at(index); +} + +#pragma mark - LanguageSelectionProvider + +- (NSString*)languageNameAtIndex:(int)languageIndex { + if (languageIndex < 0 || + languageIndex >= + static_cast<int>(self.context.languageData->num_languages())) { + NOTREACHED() << "Language index " << languageIndex + << " out of expected range."; + return nil; + } + return base::SysUTF16ToNSString( + self.context.languageData->language_name_at(languageIndex)); +} + +@end
diff --git a/ios/chrome/browser/ui/translate/language_selection_provider.h b/ios/chrome/browser/ui/translate/language_selection_provider.h new file mode 100644 index 0000000..dc94236 --- /dev/null +++ b/ios/chrome/browser/ui/translate/language_selection_provider.h
@@ -0,0 +1,22 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_PROVIDER_H_ +#define IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_PROVIDER_H_ + +#import <Foundation/Foundation.h> + +// Protocol for a provider that can map indexes to language names. An +// implementer of this protocol should be consistent over its lifetime, always +// returning the same language information for a given index. +@protocol LanguageSelectionProvider + +// The name of the language (in the application's locale) of the language at +// index |languageIndex|, or nil if |languageIndex| is outside of the range +// of indices handled by the implementer. +- (NSString*)languageNameAtIndex:(int)languageIndex; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_PROVIDER_H_
diff --git a/ios/chrome/browser/ui/translate/language_selection_view_controller.h b/ios/chrome/browser/ui/translate/language_selection_view_controller.h new file mode 100644 index 0000000..7ab5d9d --- /dev/null +++ b/ios/chrome/browser/ui/translate/language_selection_view_controller.h
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_VIEW_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/ui/translate/language_selection_consumer.h" + +// The accessibility identifier of the cancel button on language picker view. +// NOTE: this should not be used on iOS 9 for testing. +extern NSString* const kLanguagePickerCancelButtonId; + +// The accessibility identifier of the done button on language picker view. +// NOTE: this should not be used on iOS 9 for testing. +extern NSString* const kLanguagePickerDoneButtonId; + +// A delegate for a LanguageSelectionViewController instance, which the view +// controller tells about selection events. +@protocol LanguageSelectionViewControllerDelegate + +// Tells the delegate that a language was selected. |index| will be an index +// in the range provided to the view controller over via the consumer protocol. +- (void)languageSelectedAtIndex:(int)index; + +// Tells the delegate that language selection was cancelled. +- (void)languageSelectionCanceled; + +@end + +// A view controller that displays a picker view for selecting a language from +// a list of provided languages. +@interface LanguageSelectionViewController + : UIViewController<LanguageSelectionConsumer> + +// The delegate for this view controller. +@property(nonatomic, weak) id<LanguageSelectionViewControllerDelegate> delegate; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TRANSLATE_LANGUAGE_SELECTION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/translate/language_selection_view_controller.mm b/ios/chrome/browser/ui/translate/language_selection_view_controller.mm new file mode 100644 index 0000000..b854e57 --- /dev/null +++ b/ios/chrome/browser/ui/translate/language_selection_view_controller.mm
@@ -0,0 +1,139 @@ +// 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/translate/language_selection_view_controller.h" + +#import "base/logging.h" +#import "base/mac/foundation_util.h" +#import "ios/chrome/browser/ui/translate/language_selection_provider.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +NSString* const kLanguagePickerCancelButtonId = @"LanguagePickerCancelButton"; +NSString* const kLanguagePickerDoneButtonId = @"LanguagePickerDoneButton"; + +namespace { +CGFloat kUIPickerFontSize = 26; +} + +@interface LanguageSelectionViewController ()<UIPickerViewDataSource, + UIPickerViewDelegate> +@property(nonatomic, weak) UIPickerView* picker; + +// Action methods for navigation bar buttons. +- (void)languageSelectionDone; +- (void)languageSelectionCancelled; + +@end + +@implementation LanguageSelectionViewController + +// Synthesize properties defined by LanguageSelectionConsumer +@synthesize languageCount = _languageCount; +@synthesize initialLanguageIndex = _initialLanguageIndex; +@synthesize disabledLanguageIndex = _disabledLanguageIndex; +@synthesize provider = _provider; +// Synthesize public properties +@synthesize delegate = _delegate; +// Synthesize private properties +@synthesize picker = _picker; + +#pragma mark - UIViewController + +- (void)viewDidLoad { + DCHECK(_languageCount && _provider); + + UIPickerView* picker = [[UIPickerView alloc] initWithFrame:CGRectZero]; + picker.backgroundColor = UIColor.whiteColor; + picker.translatesAutoresizingMaskIntoConstraints = NO; + picker.showsSelectionIndicator = YES; + picker.dataSource = self; + picker.delegate = self; + [picker selectRow:self.initialLanguageIndex inComponent:0 animated:NO]; + + [self.view addSubview:picker]; + self.picker = picker; + + UINavigationBar* bar = [[UINavigationBar alloc] initWithFrame:CGRectZero]; + bar.translatesAutoresizingMaskIntoConstraints = NO; + + UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(languageSelectionDone)]; + [doneButton setAccessibilityIdentifier:kLanguagePickerDoneButtonId]; + + UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self + action:@selector(languageSelectionCancelled)]; + [cancelButton setAccessibilityIdentifier:kLanguagePickerCancelButtonId]; + + UINavigationItem* item = [[UINavigationItem alloc] initWithTitle:@""]; + [item setRightBarButtonItem:doneButton]; + [item setLeftBarButtonItem:cancelButton]; + [item setHidesBackButton:YES]; + [bar pushNavigationItem:item animated:NO]; + + [self.view addSubview:bar]; + + // Bar sits on top of the picker, both are full width. Constraints don't + // change. Height is entirely determined by the preferred content sizes of + // the bar and picker. + [NSLayoutConstraint activateConstraints:@[ + [bar.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + [picker.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + [bar.widthAnchor constraintEqualToAnchor:self.view.widthAnchor], + [picker.widthAnchor constraintEqualToAnchor:self.view.widthAnchor], + [bar.topAnchor constraintEqualToAnchor:self.view.topAnchor], + [picker.topAnchor constraintEqualToAnchor:bar.bottomAnchor], + [picker.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor], + ]]; +} + +#pragma mark - UIPickerViewDataSource + +- (NSInteger)pickerView:(UIPickerView*)pickerView + numberOfRowsInComponent:(NSInteger)component { + return _languageCount; +} + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView*)pickerView { + return 1; +} + +#pragma mark - UIPickerViewDelegate + +- (UIView*)pickerView:(UIPickerView*)pickerView + viewForRow:(NSInteger)row + forComponent:(NSInteger)component + reusingView:(UIView*)view { + DCHECK_EQ(0, component); + UILabel* label = base::mac::ObjCCast<UILabel>(view) ?: [[UILabel alloc] init]; + label.text = [_provider languageNameAtIndex:row]; + label.textAlignment = NSTextAlignmentCenter; + UIFont* font = [UIFont systemFontOfSize:kUIPickerFontSize]; + if (row == _initialLanguageIndex) { + font = [UIFont boldSystemFontOfSize:kUIPickerFontSize]; + } else if (row == _disabledLanguageIndex) { + label.enabled = NO; + } + label.font = font; + return label; +} + +#pragma mark - Navigation buttons + +- (void)languageSelectionDone { + [self.delegate + languageSelectedAtIndex:[self.picker selectedRowInComponent:0]]; +} + +- (void)languageSelectionCancelled { + [self.delegate languageSelectionCanceled]; +} + +@end
diff --git a/ios/chrome/browser/web/cache_egtest.mm b/ios/chrome/browser/web/cache_egtest.mm index fdce603..cfa1e0d 100644 --- a/ios/chrome/browser/web/cache_egtest.mm +++ b/ios/chrome/browser/web/cache_egtest.mm
@@ -155,22 +155,6 @@ @implementation CacheTestCase -// Reloads the web view and waits for the loading to complete. -// TODO(crbug.com/638674): Evaluate if this can move to shared code -- (void)reloadPage { - [chrome_test_util::BrowserCommandDispatcherForMainBVC() reload]; - - [ChromeEarlGrey waitForPageToFinishLoading]; -} - -// Navigates back to the previous webpage. -// TODO(crbug.com/638674): Evaluate if this can move to shared code. -- (void)goBack { - [chrome_test_util::BrowserCommandDispatcherForMainBVC() goBack]; - - [ChromeEarlGrey waitForPageToFinishLoading]; -} - // Tests caching behavior on navigate back and page reload. Navigate back should // use the cached page. Page reload should use cache-control in the request // header and show updated page. @@ -196,12 +180,12 @@ // Navigate back. This should not hit the server. Verify the page has been // loaded from cache. The serverHitCounter will remain the same. - [self goBack]; + [ChromeEarlGrey goBack]; [ChromeEarlGrey waitForWebViewContainingText:"serverHitCounter: 1"]; // Reload page. 3rd hit to server. Verify that page reload causes the // hitCounter to show updated value. - [self reloadPage]; + [ChromeEarlGrey reload]; [ChromeEarlGrey waitForWebViewContainingText:"serverHitCounter: 3"]; // Verify that page reload causes Cache-Control value to be sent with request.
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index 8542ad3..946070f 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -203,6 +203,7 @@ "//ios/chrome/browser/ui/omnibox:unit_tests", "//ios/chrome/browser/ui/payments:unit_tests", "//ios/chrome/browser/ui/payments/cells:unit_tests", + "//ios/chrome/browser/ui/presenters:unit_tests", "//ios/chrome/browser/ui/promos:unit_tests", "//ios/chrome/browser/ui/reading_list:unit_tests", "//ios/chrome/browser/ui/safe_mode:unit_tests",
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h index cdfb2c8..2525ca06 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h
@@ -22,6 +22,11 @@ // calling this method. + (void)openSettingsMenu; +// Scrolls to find the button in the Tools menu with the corresponding +// |buttonMatcher|, and then taps it. If |buttonMatcher| is not found, or +// the Tools menu is not open when this is called there will be a GREYAssert. ++ (void)tapToolsMenuButton:(id<GREYMatcher>)buttonMatcher; + // Scrolls to find the button in the Settings menu with the corresponding // |buttonMatcher|, and then taps it. If |buttonMatcher| is not found, or // the Settings menu is not open when this is called there will be a GREYAssert.
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm index 6d9ce55d..15e83ec 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
@@ -29,6 +29,7 @@ using chrome_test_util::ButtonWithAccessibilityLabel; using chrome_test_util::ClearBrowsingDataCollectionView; using chrome_test_util::SettingsMenuButton; +using chrome_test_util::ToolsMenuView; using testing::WaitUntilConditionOrTimeout; using testing::kWaitForPageLoadTimeout; @@ -71,12 +72,15 @@ + (void)openSettingsMenu { [ChromeEarlGreyUI openToolsMenu]; + [ChromeEarlGreyUI tapToolsMenuButton:SettingsMenuButton()]; +} + ++ (void)tapToolsMenuButton:(id<GREYMatcher>)buttonMatcher { id<GREYMatcher> interactableSettingsButton = - grey_allOf(SettingsMenuButton(), grey_interactable(), nil); + grey_allOf(buttonMatcher, grey_interactable(), nil); [[[EarlGrey selectElementWithMatcher:interactableSettingsButton] usingSearchAction:ScrollDown() - onElementWithMatcher:grey_accessibilityID(kToolsMenuTableViewId)] - performAction:grey_tap()]; + onElementWithMatcher:ToolsMenuView()] performAction:grey_tap()]; } + (void)tapSettingsMenuButton:(id<GREYMatcher>)buttonMatcher {
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index 05219a7..d26883b 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -40,6 +40,7 @@ ":navigation_resources", ":resources", "//base", + "//ios/web/download", "//ios/web/interstitials", "//ios/web/navigation", "//ios/web/net", @@ -166,6 +167,7 @@ ":ios_web_web_state_unittests", ":ios_web_webui_unittests", "//ios/testing:http_server_bundle_data", + "//ios/web/download:download_unittests", ] assert_no_deps = ios_assert_no_deps
diff --git a/ios/web/download/BUILD.gn b/ios/web/download/BUILD.gn new file mode 100644 index 0000000..3ba542b --- /dev/null +++ b/ios/web/download/BUILD.gn
@@ -0,0 +1,50 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//ios/build/config.gni") + +source_set("download") { + deps = [ + "//base", + "//ios/web/net/cookies", + "//ios/web/public", + "//ios/web/public/download", + "//ios/web/web_state:error_translation_util", + ] + + sources = [ + "download_controller_impl.h", + "download_controller_impl.mm", + "download_task_impl.h", + "download_task_impl.mm", + ] + + libs = [ "UIKit.framework" ] + + configs += [ "//build/config/compiler:enable_arc" ] +} + +source_set("download_unittests") { + configs += [ "//build/config/compiler:enable_arc" ] + testonly = true + deps = [ + "//base", + "//ios/testing:ios_test_support", + "//ios/testing:ocmock_support", + "//ios/web/download", + "//ios/web/net/cookies", + "//ios/web/public/download", + "//ios/web/public/test", + "//ios/web/public/test/fakes", + "//ios/web/test/fakes", + "//net", + "//testing/gmock", + "//testing/gtest", + ] + + sources = [ + "download_controller_impl_unittest.mm", + "download_task_impl_unittest.mm", + ] +}
diff --git a/ios/web/download/OWNERS b/ios/web/download/OWNERS new file mode 100644 index 0000000..f1a8cd4 --- /dev/null +++ b/ios/web/download/OWNERS
@@ -0,0 +1,5 @@ +eugenebut@chromium.org +gchatz@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web/download/download_controller_impl.h b/ios/web/download/download_controller_impl.h new file mode 100644 index 0000000..b739c9d --- /dev/null +++ b/ios/web/download/download_controller_impl.h
@@ -0,0 +1,54 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_DOWNLOAD_DOWNLOAD_CONTROLLER_IMPL_H_ +#define IOS_WEB_DOWNLOAD_DOWNLOAD_CONTROLLER_IMPL_H_ + +#include <Foundation/Foundation.h> + +#include <set> + +#include "base/macros.h" +#include "base/supports_user_data.h" +#import "ios/web/download/download_task_impl.h" +#import "ios/web/public/download/download_controller.h" + +namespace web { + +class DownloadControllerDelegate; +class WebState; + +class DownloadControllerImpl : public DownloadController, + public base::SupportsUserData::Data, + public DownloadTaskImpl::Delegate { + public: + DownloadControllerImpl(); + ~DownloadControllerImpl() override; + + // DownloadController overrides: + void CreateDownloadTask(const WebState* web_state, + NSString* identifier, + const GURL& original_url, + const std::string& content_disposition, + int64_t total_bytes, + const std::string& mime_type) override; + void SetDelegate(DownloadControllerDelegate* delegate) override; + + // DownloadTaskImpl::Delegate overrides: + void OnTaskDestroyed(DownloadTaskImpl* task) override; + NSURLSession* CreateSession(NSString* identifier, + id<NSURLSessionDataDelegate> delegate, + NSOperationQueue* delegate_queue) override; + + private: + // Set of tasks which are currently alive. + std::set<DownloadTaskImpl*> alive_tasks_; + DownloadControllerDelegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(DownloadControllerImpl); +}; + +} // namespace web + +#endif // IOS_WEB_DOWNLOAD_DOWNLOAD_CONTROLLER_IMPL_H_
diff --git a/ios/web/download/download_controller_impl.mm b/ios/web/download/download_controller_impl.mm new file mode 100644 index 0000000..9e76c38f --- /dev/null +++ b/ios/web/download/download_controller_impl.mm
@@ -0,0 +1,89 @@ +// 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/web/download/download_controller_impl.h" + +#include "base/strings/sys_string_conversions.h" +#include "ios/web/public/browser_state.h" +#import "ios/web/public/download/download_controller_delegate.h" +#include "ios/web/public/web_thread.h" +#import "net/base/mac/url_conversions.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +const char kDownloadControllerKey = 0; +} // namespace + +namespace web { + +// static +DownloadController* DownloadController::FromBrowserState( + BrowserState* browser_state) { + DCHECK(browser_state); + if (!browser_state->GetUserData(&kDownloadControllerKey)) { + browser_state->SetUserData(&kDownloadControllerKey, + std::make_unique<DownloadControllerImpl>()); + } + return static_cast<DownloadControllerImpl*>( + browser_state->GetUserData(&kDownloadControllerKey)); +} + +DownloadControllerImpl::DownloadControllerImpl() = default; + +DownloadControllerImpl::~DownloadControllerImpl() { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + for (DownloadTaskImpl* task : alive_tasks_) + task->ShutDown(); + + if (delegate_) + delegate_->OnDownloadControllerDestroyed(this); + + DCHECK(!delegate_); +} + +void DownloadControllerImpl::CreateDownloadTask( + const WebState* web_state, + NSString* identifier, + const GURL& original_url, + const std::string& content_disposition, + int64_t total_bytes, + const std::string& mime_type) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + if (!delegate_) + return; + + auto task = std::make_unique<DownloadTaskImpl>( + web_state, original_url, content_disposition, total_bytes, mime_type, + identifier, this); + alive_tasks_.insert(task.get()); + delegate_->OnDownloadCreated(this, web_state, std::move(task)); +} + +void DownloadControllerImpl::SetDelegate(DownloadControllerDelegate* delegate) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + delegate_ = delegate; +} + +void DownloadControllerImpl::OnTaskDestroyed(DownloadTaskImpl* task) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + auto it = alive_tasks_.find(task); + DCHECK(it != alive_tasks_.end()); + alive_tasks_.erase(it); +} + +NSURLSession* DownloadControllerImpl::CreateSession( + NSString* identifier, + id<NSURLSessionDataDelegate> delegate, + NSOperationQueue* delegate_queue) { + NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration + backgroundSessionConfigurationWithIdentifier:identifier]; + return [NSURLSession sessionWithConfiguration:configuration + delegate:delegate + delegateQueue:delegate_queue]; +} + +} // namespace web
diff --git a/ios/web/download/download_controller_impl_unittest.mm b/ios/web/download/download_controller_impl_unittest.mm new file mode 100644 index 0000000..dcd3c9d --- /dev/null +++ b/ios/web/download/download_controller_impl_unittest.mm
@@ -0,0 +1,88 @@ +// 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/web/download/download_controller_impl.h" + +#include <memory> + +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#import "ios/testing/wait_util.h" +#include "ios/web/public/test/fakes/fake_download_controller_delegate.h" +#include "ios/web/public/test/fakes/test_browser_state.h" +#import "ios/web/public/test/fakes/test_web_state.h" +#include "ios/web/public/test/test_web_thread_bundle.h" +#include "ios/web/public/test/web_test.h" +#include "net/url_request/url_fetcher_response_writer.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace web { + +namespace { +const char kContentDisposition[] = "attachment; filename=file.test"; +const char kMimeType[] = "application/pdf"; +} // namespace + +// Test fixture for testing DownloadControllerImpl class. +class DownloadControllerImplTest : public WebTest { + protected: + DownloadControllerImplTest() : delegate_(download_controller()) { + web_state_.SetBrowserState(GetBrowserState()); + } + + DownloadController* download_controller() { + return DownloadController::FromBrowserState(GetBrowserState()); + } + + TestWebState web_state_; + FakeDownloadControllerDelegate delegate_; +}; + +// Tests that DownloadController::FromBrowserState returns the same object for +// each call. +TEST_F(DownloadControllerImplTest, FromBrowserState) { + DownloadController* controller = download_controller(); + ASSERT_TRUE(controller); + ASSERT_EQ(controller, download_controller()); +} + +// Tests that DownloadController::CreateDownloadTask calls +// DownloadControllerDelegate::OnDownloadCreated. +TEST_F(DownloadControllerImplTest, OnDownloadCreated) { + NSString* identifier = [NSUUID UUID].UUIDString; + GURL url("https://download.test"); + download_controller()->CreateDownloadTask(&web_state_, identifier, url, + kContentDisposition, + /*total_bytes=*/-1, kMimeType); + + ASSERT_EQ(1U, delegate_.alive_download_tasks().size()); + DownloadTask* task = delegate_.alive_download_tasks()[0].second.get(); + EXPECT_EQ(&web_state_, delegate_.alive_download_tasks()[0].first); + EXPECT_NSEQ(identifier, task->GetIndentifier()); + EXPECT_EQ(url, task->GetOriginalUrl()); + EXPECT_FALSE(task->IsDone()); + EXPECT_EQ(0, task->GetErrorCode()); + EXPECT_EQ(-1, task->GetTotalBytes()); + EXPECT_EQ(-1, task->GetPercentComplete()); + EXPECT_EQ(kContentDisposition, task->GetContentDisposition()); + EXPECT_EQ(kMimeType, task->GetMimeType()); + EXPECT_EQ("file.test", base::UTF16ToUTF8(task->GetSuggestedFilename())); +} + +// Tests that DownloadController::FromBrowserState does not crash if used +// without delegate. +TEST_F(DownloadControllerImplTest, NullDelegate) { + download_controller()->SetDelegate(nullptr); + GURL url("https://download.test"); + download_controller()->CreateDownloadTask( + &web_state_, [NSUUID UUID].UUIDString, url, kContentDisposition, + /*total_bytes=*/-1, kMimeType); +} + +} // namespace web
diff --git a/ios/web/download/download_task_impl.h b/ios/web/download/download_task_impl.h new file mode 100644 index 0000000..306c891 --- /dev/null +++ b/ios/web/download/download_task_impl.h
@@ -0,0 +1,122 @@ +// 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_WEB_DOWNLOAD_DOWNLOAD_TASK_IMPL_H_ +#define IOS_WEB_DOWNLOAD_DOWNLOAD_TASK_IMPL_H_ + +#include <string> + +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#import "ios/web/public/download/download_task.h" +#include "url/gurl.h" + +@class NSURLSession; + +namespace net { +class URLFetcherResponseWriter; +} + +namespace web { + +class DownloadTaskObserver; +class WebState; + +// Implements DownloadTask interface. Uses background NSURLSession as +// implementation. +class DownloadTaskImpl : public DownloadTask { + public: + class Delegate { + public: + // Called when download task is about to be destroyed. Delegate should + // remove all references to the given DownloadTask and stop using it. + virtual void OnTaskDestroyed(DownloadTaskImpl* task) = 0; + + // Creates background NSURLSession with given |identifier|, |delegate| and + // |delegate_queue|. + virtual NSURLSession* CreateSession(NSString* identifier, + id<NSURLSessionDataDelegate> delegate, + NSOperationQueue* delegate_queue) = 0; + virtual ~Delegate() = default; + }; + + // Constructs a new DownloadTaskImpl objects. |web_state|, |identifier| and + // |delegate| must be valid. + DownloadTaskImpl(const WebState* web_state, + const GURL& original_url, + const std::string& content_disposition, + int64_t total_bytes, + const std::string& mime_type, + NSString* identifier, + Delegate* delegate); + + // Stops the download operation and clears the delegate. + void ShutDown(); + + // DownloadTask overrides: + void Start(std::unique_ptr<net::URLFetcherResponseWriter> writer) override; + net::URLFetcherResponseWriter* GetResponseWriter() const override; + NSString* GetIndentifier() const override; + const GURL& GetOriginalUrl() const override; + bool IsDone() const override; + int GetErrorCode() const override; + int64_t GetTotalBytes() const override; + int GetPercentComplete() const override; + std::string GetContentDisposition() const override; + std::string GetMimeType() const override; + base::string16 GetSuggestedFilename() const override; + void AddObserver(DownloadTaskObserver* observer) override; + void RemoveObserver(DownloadTaskObserver* observer) override; + ~DownloadTaskImpl() override; + + private: + // Creates background NSURLSession with given |identifier|. + NSURLSession* CreateSession(NSString* identifier); + + // Asynchronously returns cookies for WebState associated with this task (on + // iOS 10 and earlier, the array is always empty as it is not possible to + // access the cookies). Must be called on UI thread. The callback will be + // invoked on the UI thread. + void GetCookies(base::Callback<void(NSArray<NSHTTPCookie*>*)> callback); + + // Asynchronously returns cookies for WebState associated with this task. Must + // be called on UI thread. The callback will be invoked on the UI thread. + void GetWKCookies(base::Callback<void(NSArray<NSHTTPCookie*>*)> callback) + API_AVAILABLE(ios(11.0)); + + // Starts the download with given cookies. + void StartWithCookies(NSArray<NSHTTPCookie*>* cookies); + + // Called when download task was updated. + void OnDownloadUpdated(); + + // Called when download was completed and the data writing was finished. + void OnDownloadFinished(int error_code); + + // A list of observers. Weak references. + base::ObserverList<DownloadTaskObserver, true> observers_; + + // Back up corresponding public methods of DownloadTask interface. + std::unique_ptr<net::URLFetcherResponseWriter> writer_; + GURL original_url_; + bool is_done_ = false; + int error_code_ = 0; + int64_t total_bytes_ = -1; + int percent_complete_ = -1; + std::string content_disposition_; + std::string mime_type_; + + const WebState* web_state_ = nullptr; + Delegate* delegate_ = nullptr; + NSURLSession* session_ = nil; + NSURLSessionTask* session_task_ = nil; + + base::WeakPtrFactory<DownloadTaskImpl> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(DownloadTaskImpl); +}; + +} // namespace web + +#endif // IOS_WEB_DOWNLOAD_DOWNLOAD_TASK_IMPL_H_
diff --git a/ios/web/download/download_task_impl.mm b/ios/web/download/download_task_impl.mm new file mode 100644 index 0000000..d1db0c9 --- /dev/null +++ b/ios/web/download/download_task_impl.mm
@@ -0,0 +1,326 @@ +// 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/web/download/download_task_impl.h" + +#import <Foundation/Foundation.h> +#import <WebKit/WebKit.h> + +#import "base/mac/bind_objc_block.h" +#import "ios/web/net/cookies/wk_cookie_util.h" +#include "ios/web/public/browser_state.h" +#import "ios/web/public/download/download_task_observer.h" +#import "ios/web/public/web_state/web_state.h" +#include "ios/web/public/web_thread.h" +#import "ios/web/web_state/error_translation_util.h" +#include "net/base/filename_util.h" +#include "net/base/io_buffer.h" +#import "net/base/mac/url_conversions.h" +#include "net/base/net_errors.h" +#include "net/url_request/url_fetcher_response_writer.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +// CRWURLSessionDelegate block types. +using PropertiesBlock = void (^)(NSURLSessionTask*, NSError*); +using DataBlock = void (^)(scoped_refptr<net::IOBufferWithSize> buffer); + +// Translates an CFNetwork error code to a net error code. Returns 0 if |error| +// is nil. +int GetNetErrorCodeFromNSError(NSError* error) { + int error_code = 0; + if (error) { + if (!web::GetNetErrorFromIOSErrorCode(error.code, &error_code)) { + error_code = net::ERR_FAILED; + } + } + return error_code; +} + +// Creates a new buffer from raw |data| and |size|. +scoped_refptr<net::IOBufferWithSize> GetBuffer(const void* data, size_t size) { + auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(size); + memcpy(buffer->data(), data, size); + return buffer; +} + +// Percent complete for the given NSURLSessionTask within [0..100] range. +int GetTaskPercentComplete(NSURLSessionTask* task) { + DCHECK(task); + if (!task.countOfBytesExpectedToReceive) { + return 100; + } + DCHECK_GE(task.countOfBytesExpectedToReceive, task.countOfBytesReceived); + return 100.0 * task.countOfBytesReceived / task.countOfBytesExpectedToReceive; +} + +// Used as no-op callback. +void DoNothing(int) {} + +} // namespace + +// NSURLSessionDataDelegate that forwards data and properties task updates to +// the client. Client of this delegate can pass blocks to receive the updates. +@interface CRWURLSessionDelegate : NSObject<NSURLSessionDataDelegate> +- (instancetype)init NS_UNAVAILABLE; +// Initializes delegate with blocks. |propertiesBlock| is called when +// DownloadTaskImpl should update its properties (is_done, error_code, +// total_bytes, and percent_complete) and call OnDownloadUpdated callback. +// |dataBlock| is called when DownloadTaskImpl should write a chunk of +// downloaded data. +- (instancetype)initWithPropertiesBlock:(PropertiesBlock)propertiesBlock + dataBlock:(DataBlock)dataBlock + NS_DESIGNATED_INITIALIZER; +@end + +@implementation CRWURLSessionDelegate { + PropertiesBlock _propertiesBlock; + DataBlock _dataBlock; +} + +- (instancetype)initWithPropertiesBlock:(PropertiesBlock)propertiesBlock + dataBlock:(DataBlock)dataBlock { + DCHECK(propertiesBlock); + DCHECK(dataBlock); + if ((self = [super init])) { + _propertiesBlock = propertiesBlock; + _dataBlock = dataBlock; + } + return self; +} + +- (void)URLSession:(NSURLSession*)session + task:(NSURLSessionTask*)task + didCompleteWithError:(nullable NSError*)error { + _propertiesBlock(task, error); +} + +- (void)URLSession:(NSURLSession*)session + dataTask:(NSURLSessionDataTask*)task + didReceiveData:(NSData*)data { + using Bytes = const void* _Nonnull; + [data enumerateByteRangesUsingBlock:^(Bytes bytes, NSRange range, BOOL*) { + auto buffer = GetBuffer(bytes, range.length); + _dataBlock(std::move(buffer)); + }]; + _propertiesBlock(task, nil); +} + +- (void)URLSession:(NSURLSession*)session + didReceiveChallenge:(NSURLAuthenticationChallenge*)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, + NSURLCredential* _Nullable))handler { + // TODO(crbug.com/780911): use CRWCertVerificationController to get + // CertAcceptPolicy for this |challenge|. + handler(NSURLSessionAuthChallengeRejectProtectionSpace, nil); +} + +@end + +namespace web { + +DownloadTaskImpl::DownloadTaskImpl(const WebState* web_state, + const GURL& original_url, + const std::string& content_disposition, + int64_t total_bytes, + const std::string& mime_type, + NSString* identifier, + Delegate* delegate) + : original_url_(original_url), + total_bytes_(total_bytes), + content_disposition_(content_disposition), + mime_type_(mime_type), + web_state_(web_state), + delegate_(delegate), + weak_factory_(this) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + session_ = CreateSession(identifier); + DCHECK(web_state_); + DCHECK(delegate_); + DCHECK(session_); +} + +DownloadTaskImpl::~DownloadTaskImpl() { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + if (delegate_) { + delegate_->OnTaskDestroyed(this); + } + ShutDown(); +} + +void DownloadTaskImpl::ShutDown() { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + [session_task_ cancel]; + session_task_ = nil; + delegate_ = nullptr; +} + +void DownloadTaskImpl::Start( + std::unique_ptr<net::URLFetcherResponseWriter> writer) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + DCHECK(!writer_); + writer_ = std::move(writer); + GetCookies(base::Bind(&DownloadTaskImpl::StartWithCookies, + weak_factory_.GetWeakPtr())); +} + +net::URLFetcherResponseWriter* DownloadTaskImpl::GetResponseWriter() const { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return writer_.get(); +} + +NSString* DownloadTaskImpl::GetIndentifier() const { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return session_.configuration.identifier; +} + +const GURL& DownloadTaskImpl::GetOriginalUrl() const { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return original_url_; +} + +bool DownloadTaskImpl::IsDone() const { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return is_done_; +} + +int DownloadTaskImpl::GetErrorCode() const { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return error_code_; +} + +int64_t DownloadTaskImpl::GetTotalBytes() const { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return total_bytes_; +} + +int DownloadTaskImpl::GetPercentComplete() const { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return percent_complete_; +} + +std::string DownloadTaskImpl::GetContentDisposition() const { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return content_disposition_; +} + +std::string DownloadTaskImpl::GetMimeType() const { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return mime_type_; +} + +base::string16 DownloadTaskImpl::GetSuggestedFilename() const { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return net::GetSuggestedFilename(GetOriginalUrl(), GetContentDisposition(), + /*referrer_charset=*/std::string(), + /*suggested_name=*/std::string(), + /*mime_type=*/std::string(), + /*default_name=*/"document"); +} + +void DownloadTaskImpl::AddObserver(DownloadTaskObserver* observer) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + DCHECK(!observers_.HasObserver(observer)); + observers_.AddObserver(observer); +} + +void DownloadTaskImpl::RemoveObserver(DownloadTaskObserver* observer) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + DCHECK(observers_.HasObserver(observer)); + observers_.RemoveObserver(observer); +} + +NSURLSession* DownloadTaskImpl::CreateSession(NSString* identifier) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + DCHECK(identifier.length); + base::WeakPtr<DownloadTaskImpl> weak_this = weak_factory_.GetWeakPtr(); + id<NSURLSessionDataDelegate> session_delegate = [[CRWURLSessionDelegate alloc] + initWithPropertiesBlock:^(NSURLSessionTask* task, NSError* error) { + if (!weak_this.get()) { + return; + } + + error_code_ = GetNetErrorCodeFromNSError(error); + percent_complete_ = GetTaskPercentComplete(task); + total_bytes_ = task.countOfBytesExpectedToReceive; + + if (task.state != NSURLSessionTaskStateCompleted) { + OnDownloadUpdated(); + // Download is still in progress, nothing to do here. + return; + } + + // Download has finished, so finalize the writer and signal completion. + auto callback = base::Bind(&DownloadTaskImpl::OnDownloadFinished, + weak_factory_.GetWeakPtr()); + if (writer_->Finish(error_code_, callback) != net::ERR_IO_PENDING) { + OnDownloadFinished(error_code_); + } + } + dataBlock:^(scoped_refptr<net::IOBufferWithSize> buffer) { + if (weak_this.get()) { + // Ignore Write's completion handler. |dataBlock| may be called + // multiple times for a single downloaded chunk of data and there is + // no need to wait for writing completion. + writer_->Write(buffer.get(), buffer->size(), base::Bind(&DoNothing)); + } + }]; + return delegate_->CreateSession(identifier, session_delegate, + NSOperationQueue.currentQueue); +} + +void DownloadTaskImpl::GetCookies( + base::Callback<void(NSArray<NSHTTPCookie*>*)> callback) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + if (@available(iOS 11, *)) { + GetWKCookies(callback); + } else { + WebThread::PostTask(WebThread::UI, FROM_HERE, base::BindBlockArc(^{ + callback.Run([NSArray array]); + })); + } +} + +void DownloadTaskImpl::GetWKCookies( + base::Callback<void(NSArray<NSHTTPCookie*>*)> callback) { + DCHECK_CURRENTLY_ON(WebThread::UI); + auto store = WKCookieStoreForBrowserState(web_state_->GetBrowserState()); + DCHECK(store); + WebThread::PostTask(WebThread::IO, FROM_HERE, base::BindBlockArc(^{ + [store getAllCookies:^(NSArray<NSHTTPCookie*>* cookies) { + // getAllCookies: callback is always called on UI thread. + DCHECK_CURRENTLY_ON(WebThread::UI); + callback.Run(cookies); + }]; + })); +} + +void DownloadTaskImpl::StartWithCookies(NSArray<NSHTTPCookie*>* cookies) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + DCHECK(writer_); + + NSURL* url = net::NSURLWithGURL(GetOriginalUrl()); + session_task_ = [session_ dataTaskWithURL:url]; + [session_.configuration.HTTPCookieStorage storeCookies:cookies + forTask:session_task_]; + [session_task_ resume]; + OnDownloadUpdated(); +} + +void DownloadTaskImpl::OnDownloadUpdated() { + for (auto& observer : observers_) + observer.OnDownloadUpdated(this); +} + +void DownloadTaskImpl::OnDownloadFinished(int error_code) { + is_done_ = true; + session_task_ = nil; + OnDownloadUpdated(); +} + +} // namespace web
diff --git a/ios/web/download/download_task_impl_unittest.mm b/ios/web/download/download_task_impl_unittest.mm new file mode 100644 index 0000000..43cccf0 --- /dev/null +++ b/ios/web/download/download_task_impl_unittest.mm
@@ -0,0 +1,488 @@ +// 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/web/download/download_task_impl.h" + +#import <Foundation/Foundation.h> +#import <WebKit/WebKit.h> + +#include <memory> + +#include "base/compiler_specific.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#import "base/mac/bind_objc_block.h" +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#import "ios/testing/wait_util.h" +#import "ios/web/net/cookies/wk_cookie_util.h" +#import "ios/web/public/download/download_task_observer.h" +#import "ios/web/public/test/fakes/test_web_state.h" +#include "ios/web/public/test/web_test.h" +#import "ios/web/test/fakes/crw_fake_nsurl_session_task.h" +#include "net/base/net_errors.h" +#include "net/url_request/url_fetcher_response_writer.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" +#include "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using testing::kWaitForDownloadTimeout; +using testing::kWaitForFileOperationTimeout; +using testing::WaitUntilConditionOrTimeout; +using base::BindBlockArc; + +namespace web { + +namespace { + +const char kUrl[] = "chromium://download.test/"; +const char kContentDisposition[] = "attachment; filename=file.test"; +const char kMimeType[] = "application/pdf"; + +class MockDownloadTaskObserver : public DownloadTaskObserver { + public: + MOCK_METHOD1(OnDownloadUpdated, void(const DownloadTask* task)); +}; + +// Mocks DownloadTaskImpl::Delegate's OnTaskUpdated and OnTaskDestroyed methods +// and stubs DownloadTaskImpl::Delegate::CreateSession with session mock. +class FakeDownloadTaskImplDelegate : public DownloadTaskImpl::Delegate { + public: + FakeDownloadTaskImplDelegate() + : configuration_([NSURLSessionConfiguration + backgroundSessionConfigurationWithIdentifier: + [NSUUID UUID].UUIDString]) {} + + MOCK_METHOD1(OnTaskDestroyed, void(DownloadTaskImpl* task)); + + // Returns mock, which can be accessed via session() method. + NSURLSession* CreateSession(NSString* identifier, + id<NSURLSessionDataDelegate> delegate, + NSOperationQueue* delegate_queue) { + // Make sure this method is called only once. + EXPECT_FALSE(session_); + EXPECT_FALSE(session_delegate_); + + session_delegate_ = delegate; + session_ = OCMStrictClassMock([NSURLSession class]); + OCMStub([session_ configuration]).andReturn(configuration_); + + return session_; + } + + // These methods return session objects injected into DownloadTaskImpl. + NSURLSessionConfiguration* configuration() { return configuration_; } + id session() { return session_; } + id<NSURLSessionDataDelegate> session_delegate() { return session_delegate_; } + + private: + id<NSURLSessionDataDelegate> session_delegate_; + id configuration_; + id session_; +}; + +} // namespace + +// Test fixture for testing DownloadTaskImplTest class. +class DownloadTaskImplTest : public PlatformTest { + protected: + DownloadTaskImplTest() + : task_(std::make_unique<DownloadTaskImpl>( + &web_state_, + GURL(kUrl), + kContentDisposition, + /*total_bytes=*/-1, + kMimeType, + task_delegate_.configuration().identifier, + &task_delegate_)) { + browser_state_.SetOffTheRecord(true); + web_state_.SetBrowserState(&browser_state_); + task_->AddObserver(&task_observer_); + } + + ~DownloadTaskImplTest() { + if (task_) { + task_->RemoveObserver(&task_observer_); + } + } + + // Starts the download and return NSURLSessionDataTask fake for this task. + CRWFakeNSURLSessionTask* Start( + std::unique_ptr<net::URLFetcherResponseWriter> writer) { + // Inject fake NSURLSessionDataTask into DownloadTaskImpl. + NSURL* url = [NSURL URLWithString:@(kUrl)]; + CRWFakeNSURLSessionTask* session_task = + [[CRWFakeNSURLSessionTask alloc] initWithURL:url]; + OCMExpect([task_delegate_.session() dataTaskWithURL:url]) + .andReturn(session_task); + + // Start the download. + task_->Start(std::move(writer)); + bool success = WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{ + base::RunLoop().RunUntilIdle(); + return session_task.state == NSURLSessionTaskStateRunning; + }); + return success ? session_task : nil; + } + + // Starts the download and return NSURLSessionDataTask fake for this task. + // Same as above, but uses URLFetcherStringWriter as response writer. + CRWFakeNSURLSessionTask* Start() { + return Start(std::make_unique<net::URLFetcherStringWriter>()); + } + + // Sets cookie for the test browser state. + bool SetCookie(NSHTTPCookie* cookie) WARN_UNUSED_RESULT + API_AVAILABLE(ios(11.0)) { + auto store = web::WKCookieStoreForBrowserState(&browser_state_); + __block bool cookie_was_set = false; + [store setCookie:cookie + completionHandler:^{ + cookie_was_set = true; + }]; + return WaitUntilConditionOrTimeout(testing::kWaitForCookiesTimeout, ^{ + return cookie_was_set; + }); + } + + // Session and session delegate injected into DownloadTaskImpl for testing. + NSURLSession* session() { return task_delegate_.session(); } + id<NSURLSessionDataDelegate> session_delegate() { + return task_delegate_.session_delegate(); + } + + // Updates NSURLSessionTask.countOfBytesReceived and calls + // URLSession:dataTask:didReceiveData: callback. |data_str| is null terminated + // C-string that represents the downloaded data. + void SimulateDataDownload(CRWFakeNSURLSessionTask* session_task, + const char data_str[]) { + session_task.countOfBytesReceived += strlen(data_str); + NSData* data = [NSData dataWithBytes:data_str length:strlen(data_str)]; + [session_delegate() URLSession:session() + dataTask:session_task + didReceiveData:data]; + } + + // Sets NSURLSessionTask.state to NSURLSessionTaskStateCompleted and calls + // URLSession:dataTask:didCompleteWithError: callback. + void SimulateDownloadCompletion(CRWFakeNSURLSessionTask* session_task, + NSError* error = nil) { + session_task.state = NSURLSessionTaskStateCompleted; + [session_delegate() URLSession:session() + task:session_task + didCompleteWithError:error]; + } + + web::TestWebThreadBundle thread_bundle_; + TestBrowserState browser_state_; + TestWebState web_state_; + testing::StrictMock<FakeDownloadTaskImplDelegate> task_delegate_; + std::unique_ptr<DownloadTaskImpl> task_; + MockDownloadTaskObserver task_observer_; +}; + +// Tests DownloadTaskImpl default state after construction. +TEST_F(DownloadTaskImplTest, DefaultState) { + EXPECT_FALSE(task_->GetResponseWriter()); + EXPECT_NSEQ(task_delegate_.configuration().identifier, + task_->GetIndentifier()); + EXPECT_EQ(kUrl, task_->GetOriginalUrl()); + EXPECT_FALSE(task_->IsDone()); + EXPECT_EQ(0, task_->GetErrorCode()); + EXPECT_EQ(-1, task_->GetTotalBytes()); + EXPECT_EQ(-1, task_->GetPercentComplete()); + EXPECT_EQ(kContentDisposition, task_->GetContentDisposition()); + EXPECT_EQ(kMimeType, task_->GetMimeType()); + EXPECT_EQ("file.test", base::UTF16ToUTF8(task_->GetSuggestedFilename())); + + EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get())); +} + +// Tests sucessfull download of response without content. +// (No URLSession:dataTask:didReceiveData: callback). +TEST_F(DownloadTaskImplTest, EmptyContentDownload) { + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + CRWFakeNSURLSessionTask* session_task = Start(); + ASSERT_TRUE(session_task); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + + // Download has finished. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + SimulateDownloadCompletion(session_task); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{ + return task_->IsDone(); + })); + EXPECT_EQ(0, task_->GetErrorCode()); + EXPECT_EQ(0, task_->GetTotalBytes()); + EXPECT_EQ(100, task_->GetPercentComplete()); + + EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get())); +} + +// Tests sucessfull download of response with only one +// URLSession:dataTask:didReceiveData: callback. +TEST_F(DownloadTaskImplTest, SmallResponseDownload) { + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + CRWFakeNSURLSessionTask* session_task = Start(); + ASSERT_TRUE(session_task); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + + // The response has arrived. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + const char kData[] = "foo"; + int64_t kDataSize = strlen(kData); + session_task.countOfBytesExpectedToReceive = kDataSize; + SimulateDataDownload(session_task, kData); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + EXPECT_FALSE(task_->IsDone()); + EXPECT_EQ(0, task_->GetErrorCode()); + EXPECT_EQ(kDataSize, task_->GetTotalBytes()); + EXPECT_EQ(100, task_->GetPercentComplete()); + EXPECT_EQ(kData, task_->GetResponseWriter()->AsStringWriter()->data()); + + // Download has finished. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + SimulateDownloadCompletion(session_task); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{ + return task_->IsDone(); + })); + EXPECT_EQ(0, task_->GetErrorCode()); + EXPECT_EQ(kDataSize, task_->GetTotalBytes()); + EXPECT_EQ(100, task_->GetPercentComplete()); + EXPECT_EQ(kData, task_->GetResponseWriter()->AsStringWriter()->data()); + + EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get())); +} + +// Tests sucessfull download of response with multiple +// URLSession:dataTask:didReceiveData: callbacks. +TEST_F(DownloadTaskImplTest, LargeResponseDownload) { + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + CRWFakeNSURLSessionTask* session_task = Start(); + ASSERT_TRUE(session_task); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + + // The first part of the response has arrived. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + const char kData1[] = "foo"; + const char kData2[] = "buzz"; + int64_t kData1Size = strlen(kData1); + int64_t kData2Size = strlen(kData2); + session_task.countOfBytesExpectedToReceive = kData1Size + kData2Size; + SimulateDataDownload(session_task, kData1); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + EXPECT_FALSE(task_->IsDone()); + EXPECT_EQ(0, task_->GetErrorCode()); + EXPECT_EQ(kData1Size + kData2Size, task_->GetTotalBytes()); + EXPECT_EQ(42, task_->GetPercentComplete()); + net::URLFetcherStringWriter* writer = + task_->GetResponseWriter()->AsStringWriter(); + EXPECT_EQ(kData1, writer->data()); + + // The second part of the response has arrived. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + SimulateDataDownload(session_task, kData2); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + EXPECT_FALSE(task_->IsDone()); + EXPECT_EQ(0, task_->GetErrorCode()); + EXPECT_EQ(kData1Size + kData2Size, task_->GetTotalBytes()); + EXPECT_EQ(100, task_->GetPercentComplete()); + EXPECT_EQ(std::string(kData1) + kData2, writer->data()); + + // Download has finished. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + SimulateDownloadCompletion(session_task); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{ + return task_->IsDone(); + })); + EXPECT_EQ(0, task_->GetErrorCode()); + EXPECT_EQ(kData1Size + kData2Size, task_->GetTotalBytes()); + EXPECT_EQ(100, task_->GetPercentComplete()); + EXPECT_EQ(std::string(kData1) + kData2, writer->data()); + + EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get())); +} + +// Tests failed download when URLSession:dataTask:didReceiveData: callback was +// not even called. +TEST_F(DownloadTaskImplTest, FailureInTheBeginning) { + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + CRWFakeNSURLSessionTask* session_task = Start(); + ASSERT_TRUE(session_task); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + + // Download has failed. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + NSError* error = [NSError errorWithDomain:NSURLErrorDomain + code:NSURLErrorNotConnectedToInternet + userInfo:nil]; + SimulateDownloadCompletion(session_task, error); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{ + return task_->IsDone(); + })); + EXPECT_TRUE(task_->GetErrorCode() == net::ERR_INTERNET_DISCONNECTED); + EXPECT_EQ(0, task_->GetTotalBytes()); + EXPECT_EQ(100, task_->GetPercentComplete()); + + EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get())); +} + +// Tests failed download when URLSession:dataTask:didReceiveData: callback was +// called once. +TEST_F(DownloadTaskImplTest, FailureInTheMiddle) { + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + CRWFakeNSURLSessionTask* session_task = Start(); + ASSERT_TRUE(session_task); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + + // A part of the response has arrived. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + const char kReceivedData[] = "foo"; + int64_t kReceivedDataSize = strlen(kReceivedData); + int64_t kExpectedDataSize = kReceivedDataSize + 10; + session_task.countOfBytesExpectedToReceive = kExpectedDataSize; + SimulateDataDownload(session_task, kReceivedData); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + EXPECT_FALSE(task_->IsDone()); + EXPECT_EQ(0, task_->GetErrorCode()); + EXPECT_EQ(kExpectedDataSize, task_->GetTotalBytes()); + EXPECT_EQ(23, task_->GetPercentComplete()); + net::URLFetcherStringWriter* writer = + task_->GetResponseWriter()->AsStringWriter(); + EXPECT_EQ(kReceivedData, writer->data()); + + // Download has failed. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + NSError* error = [NSError errorWithDomain:NSURLErrorDomain + code:NSURLErrorNotConnectedToInternet + userInfo:nil]; + SimulateDownloadCompletion(session_task, error); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{ + return task_->IsDone(); + })); + EXPECT_TRUE(task_->GetErrorCode() == net::ERR_INTERNET_DISCONNECTED); + EXPECT_EQ(kExpectedDataSize, task_->GetTotalBytes()); + EXPECT_EQ(23, task_->GetPercentComplete()); + EXPECT_EQ(kReceivedData, writer->data()); + + EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get())); +} + +// Tests that NSURLSessionConfiguration contains up to date cookie from browser +// state before the download started. +TEST_F(DownloadTaskImplTest, Cookie) { + if (@available(iOS 11, *)) { + // Remove all cookies from the session configuration. + auto storage = task_delegate_.configuration().HTTPCookieStorage; + for (NSHTTPCookie* cookie in storage.cookies) + [storage deleteCookie:cookie]; + + // Add a cookie to BrowserState. + NSURL* cookie_url = [NSURL URLWithString:@(kUrl)]; + NSHTTPCookie* cookie = [NSHTTPCookie cookieWithProperties:@{ + NSHTTPCookieName : @"name", + NSHTTPCookieValue : @"value", + NSHTTPCookiePath : cookie_url.path, + NSHTTPCookieDomain : cookie_url.host, + NSHTTPCookieVersion : @1, + }]; + ASSERT_TRUE(SetCookie(cookie)); + + // Start the download and make sure that all cookie from BrowserState were + // picked up. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + ASSERT_TRUE(Start()); + EXPECT_EQ(1U, storage.cookies.count); + EXPECT_NSEQ(cookie, storage.cookies.firstObject); + } + + EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get())); +} + +// Tests that URLFetcherFileWriter deletes the file if download has failed with +// error. +TEST_F(DownloadTaskImplTest, FileDeletion) { + // Create URLFetcherFileWriter. + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath temp_file = temp_dir.GetPath().AppendASCII("DownloadTaskImpl"); + base::DeleteFile(temp_file, false); + ASSERT_FALSE(base::PathExists(temp_file)); + std::unique_ptr<net::URLFetcherResponseWriter> writer = + std::make_unique<net::URLFetcherFileWriter>( + base::ThreadTaskRunnerHandle::Get(), temp_file); + __block bool initialized_file_writer = false; + ASSERT_EQ(net::ERR_IO_PENDING, writer->Initialize(BindBlockArc(^(int error) { + ASSERT_FALSE(error); + initialized_file_writer = true; + }))); + ASSERT_TRUE(WaitUntilConditionOrTimeout(1.0, ^{ + base::RunLoop().RunUntilIdle(); + return initialized_file_writer; + })); + + // Start the download. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + CRWFakeNSURLSessionTask* session_task = Start(std::move(writer)); + ASSERT_TRUE(session_task); + + // Deliver the response and verify that download file exists. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + const char kReceivedData[] = "foo"; + SimulateDataDownload(session_task, kReceivedData); + ASSERT_TRUE(base::PathExists(temp_file)); + + // Fail the download and verify that the file was deleted. + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + NSError* error = [NSError errorWithDomain:NSURLErrorDomain + code:NSURLErrorNotConnectedToInternet + userInfo:nil]; + SimulateDownloadCompletion(session_task, error); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{ + return task_->IsDone(); + })); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForFileOperationTimeout, ^{ + base::RunLoop().RunUntilIdle(); + return !base::PathExists(temp_file); + })); + + EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get())); +} + +// Tests that destructing DownloadTaskImpl calls -[NSURLSessionDataTask cancel] +// and OnTaskDestroyed(). +TEST_F(DownloadTaskImplTest, DownloadTaskDestruction) { + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + CRWFakeNSURLSessionTask* session_task = Start(); + ASSERT_TRUE(session_task); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get())); + task_->RemoveObserver(&task_observer_); + task_ = nullptr; // Destruct DownloadTaskImpl. + EXPECT_TRUE(session_task.state = NSURLSessionTaskStateCanceling); +} + +// Tests that shutting down DownloadTaskImpl calls +// -[NSURLSessionDataTask cancel], but does not call OnTaskDestroyed(). +TEST_F(DownloadTaskImplTest, DownloadTaskShutdown) { + EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); + CRWFakeNSURLSessionTask* session_task = Start(); + ASSERT_TRUE(session_task); + testing::Mock::VerifyAndClearExpectations(&task_observer_); + + task_->ShutDown(); + EXPECT_TRUE(session_task.state = NSURLSessionTaskStateCanceling); +} + +} // namespace web
diff --git a/ios/web/public/download/download_controller.h b/ios/web/public/download/download_controller.h index 0d31e8d0..67f1245 100644 --- a/ios/web/public/download/download_controller.h +++ b/ios/web/public/download/download_controller.h
@@ -70,7 +70,6 @@ // info.totalBytes, // info.MIMEType); // ); -// task->Start(GetURLFetcherFileWriter(info.fileName)); // } // - (void)applicationWillTerminate:(UIApplication *)application { // for (DownloadTask* task : self.downloadTasks) { @@ -96,14 +95,12 @@ // from DownloadTask, which was suspended when the application has been // terminated. In order to resume the download, clients must persist all // DownloadTask data for each unfinished download on disk. - // Callers do not own the returned pointer and must not hold on it. - virtual DownloadTask* CreateDownloadTask( - const WebState* web_state, - NSString* identifier, - const GURL& original_url, - const std::string& content_disposition, - int64_t total_bytes, - const std::string& mime_type) = 0; + virtual void CreateDownloadTask(const WebState* web_state, + NSString* identifier, + const GURL& original_url, + const std::string& content_disposition, + int64_t total_bytes, + const std::string& mime_type) = 0; // Sets DownloadControllerDelegate. Clients must set the delegate to null in // DownloadControllerDelegate::OnDownloadControllerDestroyed().
diff --git a/ios/web/public/test/fakes/BUILD.gn b/ios/web/public/test/fakes/BUILD.gn index af7b70a..26716da 100644 --- a/ios/web/public/test/fakes/BUILD.gn +++ b/ios/web/public/test/fakes/BUILD.gn
@@ -9,6 +9,7 @@ deps = [ "//base", "//ios/web/public", + "//ios/web/public/download", "//ios/web/test:test_constants", "//ios/web/web_state:navigation_context", "//ios/web/web_state/ui:crw_web_view_navigation_proxy", @@ -24,6 +25,8 @@ "crw_test_js_injection_receiver.mm", "crw_test_web_state_observer.h", "crw_test_web_state_observer.mm", + "fake_download_controller_delegate.h", + "fake_download_controller_delegate.mm", "fake_navigation_context.h", "fake_navigation_context.mm", "test_browser_state.cc",
diff --git a/ios/web/public/test/fakes/fake_download_controller_delegate.h b/ios/web/public/test/fakes/fake_download_controller_delegate.h new file mode 100644 index 0000000..0d813e6 --- /dev/null +++ b/ios/web/public/test/fakes/fake_download_controller_delegate.h
@@ -0,0 +1,46 @@ +// 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_WEB_PUBLIC_TEST_FAKES_FAKE_DOWNLOAD_CONTROLLER_DELEGATE_H_ +#define IOS_WEB_PUBLIC_TEST_FAKES_FAKE_DOWNLOAD_CONTROLLER_DELEGATE_H_ + +#include <memory> +#include <vector> + +#include "ios/web/public/download/download_controller_delegate.h" + +namespace web { + +class DownloadController; +class DownloadTask; +class WebState; + +// DownloadControllerDelegate which captures tasks passed to OnDownloadCreated. +class FakeDownloadControllerDelegate : public DownloadControllerDelegate { + public: + FakeDownloadControllerDelegate(DownloadController* controller); + ~FakeDownloadControllerDelegate() override; + + using AliveDownloadTaskList = + std::vector<std::pair<const WebState*, std::unique_ptr<DownloadTask>>>; + // Returns downloads created via OnDownloadCreated and not yet destroyed. + const AliveDownloadTaskList& alive_download_tasks() const { + return alive_download_tasks_; + } + + private: + // DownloadControllerDelegate overrides: + void OnDownloadCreated(DownloadController*, + const WebState*, + std::unique_ptr<DownloadTask>) override; + void OnDownloadControllerDestroyed(DownloadController*) override; + + AliveDownloadTaskList alive_download_tasks_; + + DISALLOW_COPY_AND_ASSIGN(FakeDownloadControllerDelegate); +}; + +} // namespace web + +#endif // IOS_WEB_PUBLIC_TEST_FAKES_FAKE_DOWNLOAD_CONTROLLER_DELEGATE_H_
diff --git a/ios/web/public/test/fakes/fake_download_controller_delegate.mm b/ios/web/public/test/fakes/fake_download_controller_delegate.mm new file mode 100644 index 0000000..6d2c04a6 --- /dev/null +++ b/ios/web/public/test/fakes/fake_download_controller_delegate.mm
@@ -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 "ios/web/public/test/fakes/fake_download_controller_delegate.h" + +#include "base/logging.h" +#include "ios/web/public/download/download_controller.h" +#include "ios/web/public/download/download_task.h" + +namespace web { + +FakeDownloadControllerDelegate::FakeDownloadControllerDelegate( + DownloadController* controller) { + controller->SetDelegate(this); +} + +FakeDownloadControllerDelegate::~FakeDownloadControllerDelegate() = default; + +void FakeDownloadControllerDelegate::OnDownloadCreated( + DownloadController* download_controller, + const WebState* web_state, + std::unique_ptr<DownloadTask> task) { + alive_download_tasks_.push_back(std::make_pair(web_state, std::move(task))); +} + +void FakeDownloadControllerDelegate::OnDownloadControllerDestroyed( + DownloadController* controller) { + controller->SetDelegate(nullptr); +} + +} // namespace web
diff --git a/ios/web/public/test/fakes/test_web_state.mm b/ios/web/public/test/fakes/test_web_state.mm index 86e336b..3ad4124 100644 --- a/ios/web/public/test/fakes/test_web_state.mm +++ b/ios/web/public/test/fakes/test_web_state.mm
@@ -42,8 +42,6 @@ TestWebState::~TestWebState() { for (auto& observer : observers_) observer.WebStateDestroyed(this); - for (auto& observer : observers_) - observer.ResetWebState(); }; WebStateDelegate* TestWebState::GetDelegate() {
diff --git a/ios/web/public/test/test_redirect_observer.h b/ios/web/public/test/test_redirect_observer.h index 5fae2314..87dc69a 100644 --- a/ios/web/public/test/test_redirect_observer.h +++ b/ios/web/public/test/test_redirect_observer.h
@@ -8,7 +8,9 @@ #include <map> #include <set> +#include "base/macros.h" #include "ios/web/public/web_state/web_state_observer.h" +#import "ios/web/public/web_state/web_state_user_data.h" #include "url/gurl.h" namespace web { @@ -17,12 +19,10 @@ // A utility class that is used to track redirects during tests to enable URL // verification for redirected page loads. -class TestRedirectObserver : public web::WebStateObserver { +class TestRedirectObserver + : public web::WebStateObserver, + public web::WebStateUserData<TestRedirectObserver> { public: - // Getter that lazily instantiates a TestRedirectObserver that is stored in - // |web_state|'s user data. - static TestRedirectObserver* FromWebState(WebState* web_state); - // Notifies the observer that |url| is about to be loaded by the associated // WebState, triggering the TestRedirectObserver to start observing redirects. void BeginObservingRedirectsForUrl(const GURL& url); @@ -31,15 +31,13 @@ GURL GetFinalUrlForUrl(const GURL& url); private: - // TestRedirectObservers must be instantiated using |FromWebState()|. - friend class TestRedirectObserverUserDataWrapper; - TestRedirectObserver(); TestRedirectObserver(WebState* web_state); ~TestRedirectObserver() final; // WebStateObserver: void DidStartNavigation(web::WebState* web_state, NavigationContext* navigation_context) override; + void WebStateDestroyed(web::WebState* web_state) override; // RedirectChains store the original and final redirect URLs for a given page // load. @@ -55,6 +53,8 @@ // be removed and the redirect chain originating from that URL will be stored // in |redirect_chains_|. std::set<GURL> expected_urls_; + + DISALLOW_COPY_AND_ASSIGN(TestRedirectObserver); }; } // namespace web
diff --git a/ios/web/public/test/test_redirect_observer.mm b/ios/web/public/test/test_redirect_observer.mm index 5baa390..544a993 100644 --- a/ios/web/public/test/test_redirect_observer.mm +++ b/ios/web/public/test/test_redirect_observer.mm
@@ -4,8 +4,6 @@ #include "ios/web/public/test/test_redirect_observer.h" -#include "base/memory/ptr_util.h" -#include "base/supports_user_data.h" #import "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h" #include "ios/web/public/web_state/navigation_context.h" @@ -15,57 +13,18 @@ #error "This file requires ARC support." #endif -namespace { -// The key under which TestRedirectObservers are stored in a WebState's user -// data. -const void* const kTestRedirectObserverKey = &kTestRedirectObserverKey; -} // namespace - namespace web { -#pragma mark - TestRedirectObserverUserDataWrapper - -// Wrapper class used to associated TestRedirectObservers with their WebStates. -class TestRedirectObserverUserDataWrapper - : public base::SupportsUserData::Data { - public: - static TestRedirectObserverUserDataWrapper* FromWebState( - web::WebState* web_state) { - DCHECK(web_state); - TestRedirectObserverUserDataWrapper* wrapper = - static_cast<TestRedirectObserverUserDataWrapper*>( - web_state->GetUserData(kTestRedirectObserverKey)); - if (!wrapper) - wrapper = new TestRedirectObserverUserDataWrapper(web_state); - return wrapper; - } - - explicit TestRedirectObserverUserDataWrapper(web::WebState* web_state) - : redirect_observer_(web_state) { - DCHECK(web_state); - web_state->SetUserData(kTestRedirectObserverKey, base::WrapUnique(this)); - } - - web::TestRedirectObserver* redirect_observer() { return &redirect_observer_; } - - private: - web::TestRedirectObserver redirect_observer_; -}; +DEFINE_WEB_STATE_USER_DATA_KEY(TestRedirectObserver); #pragma mark - TestRedirectObserver -TestRedirectObserver::TestRedirectObserver(WebState* web_state) - : WebStateObserver(web_state) {} +TestRedirectObserver::TestRedirectObserver(WebState* web_state) { + web_state->AddObserver(this); +} TestRedirectObserver::~TestRedirectObserver() {} -// static -TestRedirectObserver* TestRedirectObserver::FromWebState( - web::WebState* web_state) { - return TestRedirectObserverUserDataWrapper::FromWebState(web_state) - ->redirect_observer(); -} - void TestRedirectObserver::BeginObservingRedirectsForUrl(const GURL& url) { expected_urls_.insert(url); } @@ -101,4 +60,8 @@ } } +void TestRedirectObserver::WebStateDestroyed(web::WebState* web_state) { + web_state->RemoveObserver(this); +} + } // namespace web
diff --git a/ios/web/public/web_state/web_state_observer.h b/ios/web/public/web_state/web_state_observer.h index 9d8e547..766ffad 100644 --- a/ios/web/public/web_state/web_state_observer.h +++ b/ios/web/public/web_state/web_state_observer.h
@@ -19,8 +19,6 @@ class NavigationContext; struct LoadCommittedDetails; class WebState; -class TestWebState; -class WebStateImpl; enum class PageLoadCompletionStatus : bool { SUCCESS = 0, FAILURE = 1 }; @@ -28,10 +26,7 @@ // load events from WebState. class WebStateObserver { public: - // Returns the web state associated with this observer. - // TODO(crbug.com/775684): this is deprecated. Remove once all observer - // have been converted to manage the registration with WebState directly. - WebState* web_state() const { return web_state_; } + virtual ~WebStateObserver(); // These methods are invoked every time the WebState changes visibility. virtual void WasShown(WebState* web_state) {} @@ -161,39 +156,9 @@ virtual void WebStateDestroyed(WebState* web_state) {} protected: - // Use this constructor when the object wants to observe a WebState for - // part of its lifetime. It can register directly with WebState as an - // observer using AddObserver/RemoveObserver methods. WebStateObserver(); - // Use this constructor when the object is tied to a single WebState for - // its entire lifetime. - // TODO(crbug.com/775684): this is deprecated. Remove once all observer - // have been converted to manage the registration with WebState directly. - explicit WebStateObserver(WebState* web_state); - - virtual ~WebStateObserver(); - - // Start observing a different WebState; used with the default constructor. - // TODO(crbug.com/775684): this is deprecated. Remove once all observer - // have been converted to manage the registration with WebState directly. - void Observe(WebState* web_state); - private: - // TODO(crbug.com/775684): this is deprecated. Remove once all observer - // have been converted to manage the registration with WebState directly. - friend class WebStateImpl; - friend class TestWebState; - - // Stops observing the current web state. - // TODO(crbug.com/775684): this is deprecated. Remove once all observer - // have been converted to manage the registration with WebState directly. - void ResetWebState(); - - // TODO(crbug.com/775684): this is deprecated. Remove once all observer - // have been converted to manage the registration with WebState directly. - WebState* web_state_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(WebStateObserver); };
diff --git a/ios/web/shell/shell_network_delegate.cc b/ios/web/shell/shell_network_delegate.cc index 717aef9..73b6143 100644 --- a/ios/web/shell/shell_network_delegate.cc +++ b/ios/web/shell/shell_network_delegate.cc
@@ -73,7 +73,7 @@ } bool ShellNetworkDelegate::OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) { return true; }
diff --git a/ios/web/shell/shell_network_delegate.h b/ios/web/shell/shell_network_delegate.h index ab7d47d..a74c255a 100644 --- a/ios/web/shell/shell_network_delegate.h +++ b/ios/web/shell/shell_network_delegate.h
@@ -48,7 +48,7 @@ bool OnCanGetCookies(const net::URLRequest& request, const net::CookieList& cookie_list) override; bool OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) override; bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& original_path,
diff --git a/ios/web/test/fakes/BUILD.gn b/ios/web/test/fakes/BUILD.gn index 63bd6194..5db00ea 100644 --- a/ios/web/test/fakes/BUILD.gn +++ b/ios/web/test/fakes/BUILD.gn
@@ -17,6 +17,8 @@ sources = [ "crw_fake_back_forward_list.h", "crw_fake_back_forward_list.mm", + "crw_fake_nsurl_session_task.h", + "crw_fake_nsurl_session_task.mm", "fake_navigation_manager_delegate.h", "fake_navigation_manager_delegate.mm", ]
diff --git a/ios/web/test/fakes/crw_fake_nsurl_session_task.h b/ios/web/test/fakes/crw_fake_nsurl_session_task.h new file mode 100644 index 0000000..5036f655c --- /dev/null +++ b/ios/web/test/fakes/crw_fake_nsurl_session_task.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 IOS_WEB_TEST_FAKES_CRW_FAKE_NSURL_SESSION_TASK_H_ +#define IOS_WEB_TEST_FAKES_CRW_FAKE_NSURL_SESSION_TASK_H_ + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +// Fake NSURLSessionDataTask class which can be used for testing. |cancel| and +// |resume| methods only change the |state| of this task without actually +// starting or stopping the download. +@interface CRWFakeNSURLSessionTask : NSURLSessionDataTask + +// Redefined NSURLSessionTask properties as readwrite. +@property(nonatomic) int64_t countOfBytesReceived; +@property(nonatomic) int64_t countOfBytesExpectedToReceive; +@property(nonatomic) NSURLSessionTaskState state; + +- (nullable instancetype)initWithURL:(NSURL*)URL NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +#endif // IOS_WEB_TEST_FAKES_CRW_FAKE_NSURL_SESSION_TASK_H_
diff --git a/ios/web/test/fakes/crw_fake_nsurl_session_task.mm b/ios/web/test/fakes/crw_fake_nsurl_session_task.mm new file mode 100644 index 0000000..b79737d --- /dev/null +++ b/ios/web/test/fakes/crw_fake_nsurl_session_task.mm
@@ -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. + +#import "ios/web/test/fakes/crw_fake_nsurl_session_task.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface CRWFakeNSURLSessionTask () +// NSURLSessionTask properties. +@property(nullable, readonly, copy) NSURLRequest* originalRequest; +@property(nullable, readonly, copy) NSURLRequest* currentRequest; +@end + +@implementation CRWFakeNSURLSessionTask + +@synthesize countOfBytesReceived = _countOfBytesReceived; +@synthesize countOfBytesExpectedToReceive = _countOfBytesExpectedToReceive; +@synthesize state = _state; +@synthesize originalRequest = _originalRequest; +@synthesize currentRequest = _currentRequest; + +- (instancetype)initWithURL:(NSURL*)URL { + if ((self = [super init])) { + _state = NSURLSessionTaskStateSuspended; + _currentRequest = [NSURLRequest requestWithURL:URL]; + _originalRequest = [NSURLRequest requestWithURL:URL]; + } + return self; +} + +- (void)cancel { + self.state = NSURLSessionTaskStateCanceling; +} +- (void)resume { + self.state = NSURLSessionTaskStateRunning; +} + +// A private method, called by -[NSHTTPCookieStorage storeCookies:forTask:]. +// Requires stubbing in order to use NSHTTPCookieStorage API. +- (NSString*)_storagePartitionIdentifier { + return nil; +} + +@end
diff --git a/ios/web/web_state/ui/crw_web_controller.h b/ios/web/web_state/ui/crw_web_controller.h index 3652484..149506c 100644 --- a/ios/web/web_state/ui/crw_web_controller.h +++ b/ios/web/web_state/ui/crw_web_controller.h
@@ -90,9 +90,6 @@ // Returns the x, y offset the content has been scrolled. @property(nonatomic, readonly) CGPoint scrollPosition; -// Returns whether the top of the content is visible. -@property(nonatomic, readonly) BOOL atTop; - // YES if JavaScript dialogs and window open requests should be suppressed. // Default is NO. When dialog is suppressed // |WebStateObserver::DidSuppressDialog| will be called.
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index df531b8..f8e06e6 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1178,13 +1178,6 @@ return self.webScrollView.contentOffset; } -- (BOOL)atTop { - if (!_webView) - return YES; - UIScrollView* scrollView = self.webScrollView; - return scrollView.contentOffset.y == -scrollView.contentInset.top; -} - - (GURL)currentURLWithTrustLevel:(web::URLVerificationTrustLevel*)trustLevel { DCHECK(trustLevel) << "Verification of the trustLevel state is mandatory";
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm index 94f94511..563376ed 100644 --- a/ios/web/web_state/ui/crw_web_controller_unittest.mm +++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -72,13 +72,6 @@ const char kTestURLString[] = "http://www.google.com/"; const char kTestAppSpecificURL[] = "testwebui://test/"; -// Returns true if the current device is a large iPhone (6 or 6+). -bool IsIPhone6Or6Plus() { - UIUserInterfaceIdiom idiom = [[UIDevice currentDevice] userInterfaceIdiom]; - return (idiom == UIUserInterfaceIdiomPhone && - CGRectGetHeight([[UIScreen mainScreen] nativeBounds]) >= 1334.0); -} - // Returns HTML for an optionally zoomable test page with |zoom_state|. enum PageScalabilityType { PAGE_SCALABILITY_DISABLED = 0, @@ -466,34 +459,6 @@ final_zoom_state.minimum_zoom_scale()); }; -// TODO(crbug/493427): Flaky on the bots. -TEST_F(CRWWebControllerPageScrollStateTest, DISABLED_AtTop) { - // This test fails on iPhone 6/6+; skip until it's fixed. crbug.com/453105 - if (IsIPhone6Or6Plus()) - return; - - PageZoomState zoom_state = PageZoomState(1.0, 5.0, 1.0); - LoadHtml(GetHTMLForZoomState(zoom_state, PAGE_SCALABILITY_ENABLED)); - WaitForZoomRendering(web_controller(), zoom_state); - ASSERT_TRUE(web_controller().atTop); - - NavigationManager* nagivation_manager = web_state()->GetNavigationManager(); - nagivation_manager->GetLastCommittedItem()->SetPageDisplayState( - CreateTestPageDisplayState(CGPointMake(0.0, 30.0), // scroll offset - 5.0, // relative zoom scale - 1.0, // original minimum zoom scale - 5.0, // original maximum zoom scale - 1.0)); // original zoom scale - [web_controller() restoreStateFromHistory]; - - // |-restoreStateFromHistory| is async; wait for its completion. - base::test::ios::WaitUntilCondition(^bool() { - return web_controller().pageDisplayState.scroll_state().offset_y() == 30.0; - }); - - ASSERT_FALSE(web_controller().atTop); -}; - // Test fixture for testing visible security state. typedef WebTestWithWebState CRWWebStateSecurityStateTest;
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm index e596fa9..e540c3d 100644 --- a/ios/web/web_state/web_state_impl.mm +++ b/ios/web/web_state/web_state_impl.mm
@@ -113,8 +113,6 @@ for (auto& observer : observers_) observer.WebStateDestroyed(this); - for (auto& observer : observers_) - observer.ResetWebState(); for (auto& observer : policy_deciders_) observer.WebStateDestroyed(); for (auto& observer : policy_deciders_)
diff --git a/ios/web/web_state/web_state_observer.mm b/ios/web/web_state/web_state_observer.mm index 565548a1..e6ea0d6 100644 --- a/ios/web/web_state/web_state_observer.mm +++ b/ios/web/web_state/web_state_observer.mm
@@ -15,34 +15,6 @@ WebStateObserver::WebStateObserver() = default; -WebStateObserver::WebStateObserver(WebState* web_state) { - Observe(web_state); -} - -WebStateObserver::~WebStateObserver() { - if (web_state_) - web_state_->RemoveObserver(this); -} - -void WebStateObserver::Observe(WebState* web_state) { - if (web_state == web_state_) { - // Early exit to avoid infinite loops if we're in the middle of a callback. - return; - } - if (web_state_) - web_state_->RemoveObserver(this); - web_state_ = web_state; - if (web_state_) - web_state_->AddObserver(this); -} - -void WebStateObserver::ResetWebState() { - // If this DCHECK fails, it mean that the WebStateObserver's subclass manages - // the registration of the observer manually but didn't unregister this object - // in WebStateDestroyed method. This is a bug in the subclass's client code. - DCHECK(web_state_); - web_state_->RemoveObserver(this); - web_state_ = nullptr; -} +WebStateObserver::~WebStateObserver() = default; } // namespace web
diff --git a/ios/web_view/Info.plist b/ios/web_view/Info.plist index e0cebf0f..60366c5 100644 --- a/ios/web_view/Info.plist +++ b/ios/web_view/Info.plist
@@ -16,5 +16,7 @@ <string>${EXECUTABLE_NAME}</string> <key>CFBundleDevelopmentRegion</key> <string>English</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> </dict> </plist>
diff --git a/ios/web_view/internal/cwv_preferences.mm b/ios/web_view/internal/cwv_preferences.mm index 9a3df1c2..73e72314 100644 --- a/ios/web_view/internal/cwv_preferences.mm +++ b/ios/web_view/internal/cwv_preferences.mm
@@ -29,11 +29,11 @@ #pragma mark - Public Methods - (void)setTranslationEnabled:(BOOL)enabled { - _prefService->SetBoolean(prefs::kEnableTranslate, enabled); + _prefService->SetBoolean(prefs::kOfferTranslateEnabled, enabled); } - (BOOL)isTranslationEnabled { - return _prefService->GetBoolean(prefs::kEnableTranslate); + return _prefService->GetBoolean(prefs::kOfferTranslateEnabled); } - (void)resetTranslationSettings {
diff --git a/ios/web_view/internal/cwv_preferences_unittest.mm b/ios/web_view/internal/cwv_preferences_unittest.mm index 2c370e5..8d9ba08 100644 --- a/ios/web_view/internal/cwv_preferences_unittest.mm +++ b/ios/web_view/internal/cwv_preferences_unittest.mm
@@ -30,7 +30,7 @@ scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry = new user_prefs::PrefRegistrySyncable; pref_registry->RegisterBooleanPref(autofill::prefs::kAutofillEnabled, true); - pref_registry->RegisterBooleanPref(prefs::kEnableTranslate, true); + pref_registry->RegisterBooleanPref(prefs::kOfferTranslateEnabled, true); scoped_refptr<PersistentPrefStore> pref_store = new InMemoryPrefStore(); PrefServiceFactory factory;
diff --git a/ios/web_view/internal/web_view_browser_state.mm b/ios/web_view/internal/web_view_browser_state.mm index fed8b31..1630308 100644 --- a/ios/web_view/internal/web_view_browser_state.mm +++ b/ios/web_view/internal/web_view_browser_state.mm
@@ -125,7 +125,7 @@ // the HTTP header. pref_registry->RegisterStringPref(prefs::kAcceptLanguages, l10n_util::GetLocaleOverride()); - pref_registry->RegisterBooleanPref(prefs::kEnableTranslate, true); + pref_registry->RegisterBooleanPref(prefs::kOfferTranslateEnabled, true); translate::TranslatePrefs::RegisterProfilePrefs(pref_registry); // Instantiate all factories to setup dependency graph for pref registration.
diff --git a/ios/web_view/internal/web_view_network_delegate.cc b/ios/web_view/internal/web_view_network_delegate.cc index 3cc278e..d988c09 100644 --- a/ios/web_view/internal/web_view_network_delegate.cc +++ b/ios/web_view/internal/web_view_network_delegate.cc
@@ -71,7 +71,7 @@ } bool WebViewNetworkDelegate::OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) { return true; }
diff --git a/ios/web_view/internal/web_view_network_delegate.h b/ios/web_view/internal/web_view_network_delegate.h index 7937bf8..5db7404 100644 --- a/ios/web_view/internal/web_view_network_delegate.h +++ b/ios/web_view/internal/web_view_network_delegate.h
@@ -48,7 +48,7 @@ bool OnCanGetCookies(const net::URLRequest& request, const net::CookieList& cookie_list) override; bool OnCanSetCookie(const net::URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, net::CookieOptions* options) override; bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& original_path,
diff --git a/mash/BUILD.gn b/mash/BUILD.gn index 6b4ddf1..7f2defe 100644 --- a/mash/BUILD.gn +++ b/mash/BUILD.gn
@@ -98,7 +98,7 @@ "//ash:ash_service_resources", "//ash:mash_unittests", "//ash:test_support_without_content", - "//ash/public/cpp:ash_public_cpp", + "//ash/public/cpp", "//base", "//base/test:test_support", "//cc",
diff --git a/mash/common/BUILD.gn b/mash/common/BUILD.gn index d69c280..62f12b7 100644 --- a/mash/common/BUILD.gn +++ b/mash/common/BUILD.gn
@@ -15,6 +15,6 @@ ] if (is_chromeos) { - deps += [ "//ash/public/cpp:ash_public_cpp" ] + deps += [ "//ash/public/cpp" ] } }
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn index b56339f..8824839 100644 --- a/media/audio/BUILD.gn +++ b/media/audio/BUILD.gn
@@ -376,6 +376,7 @@ "audio_output_controller_unittest.cc", "audio_output_device_unittest.cc", "audio_output_proxy_unittest.cc", + "audio_output_unittest.cc", "audio_power_monitor_unittest.cc", "audio_system_impl_unittest.cc", "power_observer_helper_unittest.cc",
diff --git a/media/audio/audio_output_unittest.cc b/media/audio/audio_output_unittest.cc new file mode 100644 index 0000000..c4a0d902 --- /dev/null +++ b/media/audio/audio_output_unittest.cc
@@ -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. + +#include <stdint.h> + +#include <memory> + +#include "base/memory/aligned_memory.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" +#include "media/audio/audio_device_info_accessor_for_tests.h" +#include "media/audio/audio_io.h" +#include "media/audio/audio_manager.h" +#include "media/audio/audio_unittest_util.h" +#include "media/audio/simple_sources.h" +#include "media/audio/test_audio_thread.h" +#include "media/base/limits.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +class AudioOutputTest : public ::testing::Test { + public: + AudioOutputTest() { + audio_manager_ = + AudioManager::CreateForTesting(base::MakeUnique<TestAudioThread>()); + audio_manager_device_info_ = + base::MakeUnique<AudioDeviceInfoAccessorForTests>(audio_manager_.get()); + base::RunLoop().RunUntilIdle(); + } + ~AudioOutputTest() override { + if (stream_) + stream_->Close(); + audio_manager_->Shutdown(); + } + + void CreateWithDefaultParameters() { + stream_params_ = + audio_manager_device_info_->GetDefaultOutputStreamParameters(); + stream_ = audio_manager_->MakeAudioOutputStream( + stream_params_, std::string(), AudioManager::LogCallback()); + } + + // Runs message loop for the specified amount of time. + void RunMessageLoop(base::TimeDelta delay) { + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), delay); + run_loop.Run(); + } + + protected: + base::MessageLoop message_loop_; + std::unique_ptr<AudioManager> audio_manager_; + std::unique_ptr<AudioDeviceInfoAccessorForTests> audio_manager_device_info_; + AudioParameters stream_params_; + AudioOutputStream* stream_ = nullptr; +}; + +// Test that can it be created and closed. +TEST_F(AudioOutputTest, GetAndClose) { + ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); + CreateWithDefaultParameters(); + ASSERT_TRUE(stream_); +} + +// Test that it can be opened and closed. +TEST_F(AudioOutputTest, OpenAndClose) { + ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); + + CreateWithDefaultParameters(); + ASSERT_TRUE(stream_); + EXPECT_TRUE(stream_->Open()); +} + +// This test produces actual audio for .5 seconds on the default device. +TEST_F(AudioOutputTest, Play200HzTone) { + ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); + + stream_params_ = + audio_manager_device_info_->GetDefaultOutputStreamParameters(); + uint32_t samples_50_ms = stream_params_.sample_rate() / 10; + stream_params_.set_frames_per_buffer(samples_50_ms); + stream_ = audio_manager_->MakeAudioOutputStream(stream_params_, std::string(), + AudioManager::LogCallback()); + ASSERT_TRUE(stream_); + + SineWaveAudioSource source(1, 200.0, stream_params_.sample_rate()); + + EXPECT_TRUE(stream_->Open()); + stream_->SetVolume(1.0); + stream_->Start(&source); + RunMessageLoop(base::TimeDelta::FromMilliseconds(250)); + stream_->Stop(); + + EXPECT_FALSE(source.errors()); + EXPECT_GE(source.callbacks(), 1); +} + +// Test that SetVolume() and GetVolume() work as expected. +TEST_F(AudioOutputTest, VolumeControl) { + ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); + + CreateWithDefaultParameters(); + ASSERT_TRUE(stream_); + EXPECT_TRUE(stream_->Open()); + + double volume = 0.0; + + stream_->GetVolume(&volume); + EXPECT_EQ(volume, 1.0); + + stream_->SetVolume(0.5); + + stream_->GetVolume(&volume); + EXPECT_LT(volume, 0.51); + EXPECT_GT(volume, 0.49); + stream_->Stop(); +} + +} // namespace media
diff --git a/media/audio/mac/audio_auhal_mac.cc b/media/audio/mac/audio_auhal_mac.cc index a26c49b..4cff091 100644 --- a/media/audio/mac/audio_auhal_mac.cc +++ b/media/audio/mac/audio_auhal_mac.cc
@@ -175,7 +175,6 @@ DCHECK(manager_); DCHECK(params_.IsValid()); DCHECK_NE(device, kAudioObjectUnknown); - CHECK(!log_callback_.Equals(AudioManager::LogCallback())); } AUHALStream::~AUHALStream() { @@ -409,10 +408,13 @@ 1, 999999, 100); auto lost_frames_ms = (total_lost_frames_ * 1000) / params_.sample_rate(); + std::string log_message = base::StringPrintf( "AU out: Total glitches=%d. Total frames lost=%d (%d ms).", glitches_detected_, total_lost_frames_, lost_frames_ms); - log_callback_.Run(log_message); + + if (!log_callback_.is_null()) + log_callback_.Run(log_message); if (glitches_detected_ != 0) { UMA_HISTOGRAM_COUNTS("Media.Audio.Render.LostFramesInMs", lost_frames_ms);
diff --git a/media/base/decode_capabilities.cc b/media/base/decode_capabilities.cc index 34d7842..f46345a5 100644 --- a/media/base/decode_capabilities.cc +++ b/media/base/decode_capabilities.cc
@@ -166,7 +166,8 @@ switch (config.codec) { case media::kCodecAV1: #if BUILDFLAG(ENABLE_AV1_DECODER) - return IsColorSpaceSupported(config.color_space); + return base::FeatureList::IsEnabled(kAv1Decoder) && + IsColorSpaceSupported(config.color_space); #else return false; #endif
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc index e5bdf51c..7cf16618 100644 --- a/media/base/mime_util_internal.cc +++ b/media/base/mime_util_internal.cc
@@ -15,6 +15,7 @@ #include "media/base/video_codecs.h" #include "media/base/video_color_space.h" #include "media/media_features.h" +#include "third_party/libaom/av1_features.h" #if defined(OS_ANDROID) #include "base/android/build_info.h" @@ -73,6 +74,11 @@ {"vorbis", MimeUtil::VORBIS}, {"opus", MimeUtil::OPUS}, {"flac", MimeUtil::FLAC}, {"vp8", MimeUtil::VP8}, {"vp8.0", MimeUtil::VP8}, {"theora", MimeUtil::THEORA}, +// TODO(dalecurtis): This is not the correct final string. Fix before enabling +// by default. http://crbug.com/784607 +#if BUILDFLAG(ENABLE_AV1_DECODER) + {"av1", MimeUtil::AV1}, +#endif }, base::KEEP_FIRST_OF_DUPES); @@ -262,7 +268,12 @@ ogg_codecs.insert(ogg_video_codecs.begin(), ogg_video_codecs.end()); const CodecSet webm_audio_codecs{OPUS, VORBIS}; - const CodecSet webm_video_codecs{VP8, VP9}; + CodecSet webm_video_codecs{VP8, VP9}; +#if BUILDFLAG(ENABLE_AV1_DECODER) + if (base::FeatureList::IsEnabled(kAv1Decoder)) + webm_video_codecs.emplace(AV1); +#endif + CodecSet webm_codecs(webm_audio_codecs); webm_codecs.insert(webm_video_codecs.begin(), webm_video_codecs.end()); @@ -292,6 +303,11 @@ #if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) mp4_video_codecs.emplace(DOLBY_VISION); #endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_AV1_DECODER) + if (base::FeatureList::IsEnabled(kAv1Decoder)) + mp4_video_codecs.emplace(AV1); +#endif + CodecSet mp4_codecs(mp4_audio_codecs); mp4_codecs.insert(mp4_video_codecs.begin(), mp4_video_codecs.end()); #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) @@ -526,6 +542,10 @@ case THEORA: return false; + // AV1 is not supported on Android yet. + case AV1: + return false; + // ---------------------------------------------------------------------- // The remaining codecs may be supported depending on platform abilities. // ---------------------------------------------------------------------- @@ -950,6 +970,7 @@ case VP8: case VP9: case THEORA: + case AV1: return false; }
diff --git a/media/base/mime_util_internal.h b/media/base/mime_util_internal.h index 31ce0a5..d8677316 100644 --- a/media/base/mime_util_internal.h +++ b/media/base/mime_util_internal.h
@@ -44,7 +44,8 @@ VP9, THEORA, DOLBY_VISION, - LAST_CODEC = DOLBY_VISION + AV1, + LAST_CODEC = AV1 }; // Platform configuration structure. Controls which codecs are supported at
diff --git a/media/base/mime_util_unittest.cc b/media/base/mime_util_unittest.cc index 503afd2..a358d0a 100644 --- a/media/base/mime_util_unittest.cc +++ b/media/base/mime_util_unittest.cc
@@ -443,6 +443,7 @@ switch (codec) { // These codecs are never supported by the Android platform. case MimeUtil::INVALID_CODEC: + case MimeUtil::AV1: case MimeUtil::THEORA: EXPECT_FALSE(result); break; @@ -502,6 +503,7 @@ // These codecs are never supported by the Android platform. case MimeUtil::INVALID_CODEC: case MimeUtil::THEORA: + case MimeUtil::AV1: EXPECT_FALSE(result); break;
diff --git a/media/blink/watch_time_reporter_unittest.cc b/media/blink/watch_time_reporter_unittest.cc index 4f46e59..62e749d 100644 --- a/media/blink/watch_time_reporter_unittest.cc +++ b/media/blink/watch_time_reporter_unittest.cc
@@ -167,9 +167,10 @@ EXPECT_WATCH_TIME_FINALIZED(); wtr_.reset(new WatchTimeReporter( - mojom::PlaybackProperties::New( - kUnknownAudioCodec, kUnknownVideoCodec, has_audio, has_video_, - is_mse, is_encrypted, false, initial_video_size, url::Origin()), + mojom::PlaybackProperties::New(kUnknownAudioCodec, kUnknownVideoCodec, + has_audio, has_video_, is_mse, + is_encrypted, false, initial_video_size, + url::Origin(), true /* is_top_frame */), base::Bind(&WatchTimeReporterTest::GetCurrentMediaTime, base::Unretained(this)), this));
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 52488f9..bf0d50de 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -89,10 +89,6 @@ namespace { -// TODO(apacible): Remove when crbug/747082 is stable. -const double kMinRate = 0.0625; -const double kMaxRate = 16.0; - void SetSinkIdOnMediaThread(scoped_refptr<WebAudioSourceProviderImpl> sink, const std::string& device_id, const url::Origin& security_origin, @@ -361,13 +357,20 @@ DoLoad(load_type, url, cors_mode); } -void WebMediaPlayerImpl::OnWebLayerUpdated() { +void WebMediaPlayerImpl::OnWebLayerUpdated() {} + +void WebMediaPlayerImpl::RegisterContentsLayer(blink::WebLayer* web_layer) { DCHECK(bridge_); bridge_->GetWebLayer()->CcLayer()->SetContentsOpaque(opaque_); bridge_->GetWebLayer()->SetContentsOpaqueIsFixed(true); // TODO(lethalantidote): Figure out how to pass along rotation information. // https://crbug/750313. - client_->SetWebLayer(bridge_->GetWebLayer()); + client_->SetWebLayer(web_layer); +} + +void WebMediaPlayerImpl::UnregisterContentsLayer(blink::WebLayer* web_layer) { + // |client_| will unregister its WebLayer if given a nullptr. + client_->SetWebLayer(nullptr); } bool WebMediaPlayerImpl::SupportsOverlayFullscreenVideo() { @@ -711,13 +714,6 @@ << rate; } - // TODO(apacible): Remove clamping when crbug/747082 is stable. - // Limit rates to reasonable values by clamping. - if (rate < 0.0) - return; - if (rate != 0.0) - rate = std::min(std::max(rate, kMinRate), kMaxRate); - playback_rate_ = rate; if (!paused_) { pipeline_controller_.SetPlaybackRate(rate); @@ -2553,6 +2549,12 @@ if (!HasVideo() && !HasAudio()) return; + // URL is used for UKM reporting. Privacy requires we only report origin of + // the top frame. |is_top_frame| signals how to interpret the origin. + // TODO(crbug.com/787209): Stop getting origin from the renderer. + bool is_top_frame = frame_ == frame_->Top(); + url::Origin top_origin(frame_->Top()->GetSecurityOrigin()); + // Create the watch time reporter and synchronize its initial state. watch_time_reporter_.reset(new WatchTimeReporter( mojom::PlaybackProperties::New( @@ -2560,8 +2562,7 @@ pipeline_metadata_.video_decoder_config.codec(), pipeline_metadata_.has_audio, pipeline_metadata_.has_video, !!chunk_demuxer_, is_encrypted_, embedded_media_experience_enabled_, - pipeline_metadata_.natural_size, - url::Origin(frame_->GetSecurityOrigin())), + pipeline_metadata_.natural_size, top_origin, is_top_frame), base::BindRepeating(&WebMediaPlayerImpl::GetCurrentTimeInternal, base::Unretained(this)), watch_time_recorder_provider_));
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index 281a8b6..7d03385 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -111,6 +111,8 @@ // WebSurfaceLayerBridgeObserver implementation. void OnWebLayerUpdated() override; + void RegisterContentsLayer(blink::WebLayer* web_layer) override; + void UnregisterContentsLayer(blink::WebLayer* web_layer) override; void Load(LoadType load_type, const blink::WebMediaPlayerSource& source,
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc index 1f91fef3..ab4db16 100644 --- a/media/blink/webmediaplayer_impl_unittest.cc +++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -1013,7 +1013,7 @@ // TODO(lethalantidote): Once |client_| is converted from a dummy to a mock, // test that |web_layer| is actually used by |client_|. // http://crbug/755880. -TEST_F(WebMediaPlayerImplTest, OnWebLayerUpdatedGetsWebLayerFromBridge) { +TEST_F(WebMediaPlayerImplTest, SetContentsLayerGetsWebLayerFromBridge) { base::test::ScopedFeatureList feature_list; feature_list.InitFromCommandLine("UseSurfaceLayerForVideo", ""); surface_layer_bridge_ = new StrictMock<MockSurfaceLayerBridge>(); @@ -1027,7 +1027,7 @@ EXPECT_CALL(*surface_layer_bridge_, GetWebLayer()) .WillRepeatedly(Return(web_layer.get())); - wmpi_->OnWebLayerUpdated(); + wmpi_->RegisterContentsLayer(web_layer.get()); } TEST_F(WebMediaPlayerImplTest, PlaybackRateChangeMediaLogs) {
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn index 77d6977..e12af0df 100644 --- a/media/capture/BUILD.gn +++ b/media/capture/BUILD.gn
@@ -107,6 +107,7 @@ "video/mac/video_capture_device_factory_mac.mm", "video/mac/video_capture_device_mac.h", "video/mac/video_capture_device_mac.mm", + "video/scoped_buffer_pool_reservation.h", "video/shared_memory_buffer_tracker.cc", "video/shared_memory_buffer_tracker.h", "video/shared_memory_handle_provider.cc",
diff --git a/media/capture/video/scoped_buffer_pool_reservation.h b/media/capture/video/scoped_buffer_pool_reservation.h new file mode 100644 index 0000000..1a74e60 --- /dev/null +++ b/media/capture/video/scoped_buffer_pool_reservation.h
@@ -0,0 +1,49 @@ +// 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 MEDIA_CAPTURE_VIDEO_SCOPED_BUFFER_POOL_RESERVATION_H_ +#define MEDIA_CAPTURE_VIDEO_SCOPED_BUFFER_POOL_RESERVATION_H_ + +#include "media/capture/capture_export.h" +#include "media/capture/video/video_capture_buffer_pool.h" +#include "media/capture/video/video_capture_device_client.h" + +namespace media { + +template <typename ReleaseTraits> +class CAPTURE_EXPORT ScopedBufferPoolReservation + : public VideoCaptureDevice::Client::Buffer::ScopedAccessPermission { + public: + ScopedBufferPoolReservation(scoped_refptr<VideoCaptureBufferPool> buffer_pool, + int buffer_id) + : buffer_pool_(std::move(buffer_pool)), buffer_id_(buffer_id) {} + + ~ScopedBufferPoolReservation() { + ReleaseTraits::Release(buffer_pool_, buffer_id_); + } + + private: + const scoped_refptr<VideoCaptureBufferPool> buffer_pool_; + const int buffer_id_; +}; + +class CAPTURE_EXPORT ProducerReleaseTraits { + public: + static void Release(const scoped_refptr<VideoCaptureBufferPool>& buffer_pool, + int buffer_id) { + buffer_pool->RelinquishProducerReservation(buffer_id); + } +}; + +class CAPTURE_EXPORT ConsumerReleaseTraits { + public: + static void Release(const scoped_refptr<VideoCaptureBufferPool>& buffer_pool, + int buffer_id) { + buffer_pool->RelinquishConsumerHold(buffer_id, 1 /* num_clients */); + } +}; + +} // namespace media + +#endif // MEDIA_CAPTURE_VIDEO_SCOPED_BUFFER_POOL_RESERVATION_H_
diff --git a/media/capture/video/video_capture_device_client.cc b/media/capture/video/video_capture_device_client.cc index 212dc56..311605a5 100644 --- a/media/capture/video/video_capture_device_client.cc +++ b/media/capture/video/video_capture_device_client.cc
@@ -16,6 +16,7 @@ #include "build/build_config.h" #include "media/base/bind_to_current_loop.h" #include "media/base/video_frame.h" +#include "media/capture/video/scoped_buffer_pool_reservation.h" #include "media/capture/video/video_capture_buffer_handle.h" #include "media/capture/video/video_capture_buffer_pool.h" #include "media/capture/video/video_capture_jpeg_decoder.h" @@ -37,39 +38,6 @@ namespace media { -template <typename ReleaseTraits> -class ScopedBufferPoolReservation - : public VideoCaptureDevice::Client::Buffer::ScopedAccessPermission { - public: - ScopedBufferPoolReservation(scoped_refptr<VideoCaptureBufferPool> buffer_pool, - int buffer_id) - : buffer_pool_(std::move(buffer_pool)), buffer_id_(buffer_id) {} - - ~ScopedBufferPoolReservation() override { - ReleaseTraits::Release(buffer_pool_, buffer_id_); - } - - private: - const scoped_refptr<VideoCaptureBufferPool> buffer_pool_; - const int buffer_id_; -}; - -class ProducerReleaseTraits { - public: - static void Release(const scoped_refptr<VideoCaptureBufferPool>& buffer_pool, - int buffer_id) { - buffer_pool->RelinquishProducerReservation(buffer_id); - } -}; - -class ConsumerReleaseTraits { - public: - static void Release(const scoped_refptr<VideoCaptureBufferPool>& buffer_pool, - int buffer_id) { - buffer_pool->RelinquishConsumerHold(buffer_id, 1); - } -}; - class BufferPoolBufferHandleProvider : public VideoCaptureDevice::Client::Buffer::HandleProvider { public:
diff --git a/media/filters/BUILD.gn b/media/filters/BUILD.gn index 12c8372..b75e354 100644 --- a/media/filters/BUILD.gn +++ b/media/filters/BUILD.gn
@@ -103,6 +103,7 @@ "//media/formats", "//media/video", "//skia", + "//third_party/libaom:av1_features", "//third_party/libyuv", ]
diff --git a/media/filters/frame_buffer_pool.cc b/media/filters/frame_buffer_pool.cc index 61a6543..96be0739 100644 --- a/media/filters/frame_buffer_pool.cc +++ b/media/filters/frame_buffer_pool.cc
@@ -170,7 +170,7 @@ if (!task_runner->RunsTasksInCurrentSequence()) { task_runner->PostTask( FROM_HERE, base::Bind(&FrameBufferPool::OnVideoFrameDestroyed, this, - std::move(task_runner), frame_buffer)); + task_runner, frame_buffer)); return; }
diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc index a3df694..2effed7 100644 --- a/media/filters/stream_parser_factory.cc +++ b/media/filters/stream_parser_factory.cc
@@ -20,6 +20,7 @@ #include "media/formats/mpeg/mpeg1_audio_stream_parser.h" #include "media/formats/webm/webm_stream_parser.h" #include "media/media_features.h" +#include "third_party/libaom/av1_features.h" #if defined(OS_ANDROID) #include "media/base/android/media_codec_util.h" @@ -39,11 +40,7 @@ MediaLog* media_log); struct CodecInfo { - enum Type { - UNKNOWN, - AUDIO, - VIDEO - }; + enum Type { UNKNOWN, AUDIO, VIDEO }; // Update tools/metrics/histograms/histograms.xml if new values are added. enum HistogramTag { @@ -61,7 +58,8 @@ HISTOGRAM_AC3, HISTOGRAM_DOLBYVISION, HISTOGRAM_FLAC, - HISTOGRAM_MAX = HISTOGRAM_FLAC // Must be equal to largest logged entry. + HISTOGRAM_AV1, + HISTOGRAM_MAX = HISTOGRAM_AV1 // Must be equal to largest logged entry. }; const char* pattern; @@ -80,23 +78,34 @@ const CodecInfo* const* codecs; }; -static const CodecInfo kVP8CodecInfo = { "vp8", CodecInfo::VIDEO, NULL, - CodecInfo::HISTOGRAM_VP8 }; -static const CodecInfo kLegacyVP9CodecInfo = {"vp9", CodecInfo::VIDEO, NULL, +static const CodecInfo kVP8CodecInfo = {"vp8", CodecInfo::VIDEO, nullptr, + CodecInfo::HISTOGRAM_VP8}; +static const CodecInfo kLegacyVP9CodecInfo = {"vp9", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_VP9}; -static const CodecInfo kVP9CodecInfo = {"vp09.*", CodecInfo::VIDEO, NULL, +static const CodecInfo kVP9CodecInfo = {"vp09.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_VP9}; -static const CodecInfo kVorbisCodecInfo = { "vorbis", CodecInfo::AUDIO, NULL, - CodecInfo::HISTOGRAM_VORBIS }; -static const CodecInfo kOpusCodecInfo = { "opus", CodecInfo::AUDIO, NULL, - CodecInfo::HISTOGRAM_OPUS }; +static const CodecInfo kVorbisCodecInfo = {"vorbis", CodecInfo::AUDIO, nullptr, + CodecInfo::HISTOGRAM_VORBIS}; +static const CodecInfo kOpusCodecInfo = {"opus", CodecInfo::AUDIO, nullptr, + CodecInfo::HISTOGRAM_OPUS}; + +#if BUILDFLAG(ENABLE_AV1_DECODER) +// TODO(dalecurtis): This is not the correct final string. Fix before enabling +// by default. http://crbug.com/784607 +static const CodecInfo kAV1CodecInfo = {"av1", CodecInfo::VIDEO, nullptr, + CodecInfo::HISTOGRAM_AV1}; +#endif static const CodecInfo* const kVideoWebMCodecs[] = { - &kVP8CodecInfo, &kLegacyVP9CodecInfo, &kVP9CodecInfo, - &kVorbisCodecInfo, &kOpusCodecInfo, NULL}; + &kVP8CodecInfo, &kLegacyVP9CodecInfo, &kVP9CodecInfo, &kVorbisCodecInfo, + &kOpusCodecInfo, +#if BUILDFLAG(ENABLE_AV1_DECODER) + &kAV1CodecInfo, +#endif + nullptr}; static const CodecInfo* const kAudioWebMCodecs[] = {&kVorbisCodecInfo, - &kOpusCodecInfo, NULL}; + &kOpusCodecInfo, nullptr}; static StreamParser* BuildWebMParser(const std::vector<std::string>& codecs, MediaLog* media_log) { @@ -133,8 +142,8 @@ return audio_object_type; } - MEDIA_LOG(DEBUG, media_log) << "Malformed mimetype codec '" << codec_id - << "'"; + MEDIA_LOG(DEBUG, media_log) + << "Malformed mimetype codec '" << codec_id << "'"; return -1; } @@ -146,42 +155,41 @@ return true; } - MEDIA_LOG(DEBUG, media_log) << "Unsupported audio object type " - << audio_object_type << " in codec '" << codec_id - << "'"; + MEDIA_LOG(DEBUG, media_log) + << "Unsupported audio object type " << audio_object_type << " in codec '" + << codec_id << "'"; return false; } -static const CodecInfo kH264AVC1CodecInfo = { "avc1.*", CodecInfo::VIDEO, NULL, - CodecInfo::HISTOGRAM_H264 }; -static const CodecInfo kH264AVC3CodecInfo = { "avc3.*", CodecInfo::VIDEO, NULL, - CodecInfo::HISTOGRAM_H264 }; +static const CodecInfo kH264AVC1CodecInfo = { + "avc1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_H264}; +static const CodecInfo kH264AVC3CodecInfo = { + "avc3.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_H264}; #if BUILDFLAG(ENABLE_HEVC_DEMUXING) -static const CodecInfo kHEVCHEV1CodecInfo = { "hev1.*", CodecInfo::VIDEO, NULL, - CodecInfo::HISTOGRAM_HEVC }; -static const CodecInfo kHEVCHVC1CodecInfo = { "hvc1.*", CodecInfo::VIDEO, NULL, - CodecInfo::HISTOGRAM_HEVC }; +static const CodecInfo kHEVCHEV1CodecInfo = { + "hev1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_HEVC}; +static const CodecInfo kHEVCHVC1CodecInfo = { + "hvc1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_HEVC}; #endif #if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) static const CodecInfo kDolbyVisionAVCCodecInfo1 = { - "dva1.*", CodecInfo::VIDEO, NULL, CodecInfo::HISTOGRAM_DOLBYVISION}; + "dva1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION}; static const CodecInfo kDolbyVisionAVCCodecInfo2 = { - "dvav.*", CodecInfo::VIDEO, NULL, CodecInfo::HISTOGRAM_DOLBYVISION}; + "dvav.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION}; #if BUILDFLAG(ENABLE_HEVC_DEMUXING) static const CodecInfo kDolbyVisionHEVCCodecInfo1 = { - "dvh1.*", CodecInfo::VIDEO, NULL, CodecInfo::HISTOGRAM_DOLBYVISION}; + "dvh1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION}; static const CodecInfo kDolbyVisionHEVCCodecInfo2 = { - "dvhe.*", CodecInfo::VIDEO, NULL, CodecInfo::HISTOGRAM_DOLBYVISION}; + "dvhe.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION}; #endif #endif -static const CodecInfo kMPEG4VP09CodecInfo = {"vp09.*", CodecInfo::VIDEO, NULL, - CodecInfo::HISTOGRAM_VP9}; -static const CodecInfo kMPEG4AACCodecInfo = { "mp4a.40.*", CodecInfo::AUDIO, - &ValidateMP4ACodecID, - CodecInfo::HISTOGRAM_MPEG4AAC }; -static const CodecInfo kMPEG2AACLCCodecInfo = { "mp4a.67", CodecInfo::AUDIO, - NULL, - CodecInfo::HISTOGRAM_MPEG2AAC }; +static const CodecInfo kMPEG4VP09CodecInfo = { + "vp09.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_VP9}; +static const CodecInfo kMPEG4AACCodecInfo = {"mp4a.40.*", CodecInfo::AUDIO, + &ValidateMP4ACodecID, + CodecInfo::HISTOGRAM_MPEG4AAC}; +static const CodecInfo kMPEG2AACLCCodecInfo = { + "mp4a.67", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MPEG2AAC}; static const CodecInfo kMPEG4FLACCodecInfo = {"flac", CodecInfo::AUDIO, &CheckIfMseFlacInIsobmffEnabled, CodecInfo::HISTOGRAM_FLAC}; @@ -193,17 +201,17 @@ // according to RFC 6381 this corresponds to codec ids 'mp4a.A5' and 'mp4a.A6'. // Codec ids with lower case oti (mp4a.a5 and mp4a.a6) are supported for // backward compatibility. -static const CodecInfo kAC3CodecInfo1 = {"ac-3", CodecInfo::AUDIO, NULL, +static const CodecInfo kAC3CodecInfo1 = {"ac-3", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_AC3}; -static const CodecInfo kAC3CodecInfo2 = {"mp4a.a5", CodecInfo::AUDIO, NULL, +static const CodecInfo kAC3CodecInfo2 = {"mp4a.a5", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_AC3}; -static const CodecInfo kAC3CodecInfo3 = {"mp4a.A5", CodecInfo::AUDIO, NULL, +static const CodecInfo kAC3CodecInfo3 = {"mp4a.A5", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_AC3}; -static const CodecInfo kEAC3CodecInfo1 = {"ec-3", CodecInfo::AUDIO, NULL, +static const CodecInfo kEAC3CodecInfo1 = {"ec-3", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_EAC3}; -static const CodecInfo kEAC3CodecInfo2 = {"mp4a.a6", CodecInfo::AUDIO, NULL, +static const CodecInfo kEAC3CodecInfo2 = {"mp4a.a6", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_EAC3}; -static const CodecInfo kEAC3CodecInfo3 = {"mp4a.A6", CodecInfo::AUDIO, NULL, +static const CodecInfo kEAC3CodecInfo3 = {"mp4a.A6", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_EAC3}; #endif @@ -225,7 +233,10 @@ &kMPEG4AACCodecInfo, &kMPEG2AACLCCodecInfo, &kMPEG4FLACCodecInfo, - NULL}; +#if BUILDFLAG(ENABLE_AV1_DECODER) + &kAV1CodecInfo, +#endif + nullptr}; static const CodecInfo* const kAudioMP4Codecs[] = {&kMPEG4AACCodecInfo, &kMPEG2AACLCCodecInfo, @@ -238,7 +249,7 @@ &kEAC3CodecInfo2, &kEAC3CodecInfo3, #endif - NULL}; + nullptr}; static StreamParser* BuildMP4Parser(const std::vector<std::string>& codecs, MediaLog* media_log) { @@ -286,19 +297,19 @@ return new mp4::MP4StreamParser(audio_object_types, has_sbr, has_flac); } -static const CodecInfo kMP3CodecInfo = { NULL, CodecInfo::AUDIO, NULL, - CodecInfo::HISTOGRAM_MP3 }; +static const CodecInfo kMP3CodecInfo = {nullptr, CodecInfo::AUDIO, nullptr, + CodecInfo::HISTOGRAM_MP3}; -static const CodecInfo* const kAudioMP3Codecs[] = {&kMP3CodecInfo, NULL}; +static const CodecInfo* const kAudioMP3Codecs[] = {&kMP3CodecInfo, nullptr}; static StreamParser* BuildMP3Parser(const std::vector<std::string>& codecs, MediaLog* media_log) { return new MPEG1AudioStreamParser(); } -static const CodecInfo kADTSCodecInfo = { NULL, CodecInfo::AUDIO, NULL, - CodecInfo::HISTOGRAM_MPEG4AAC }; -static const CodecInfo* const kAudioADTSCodecs[] = {&kADTSCodecInfo, NULL}; +static const CodecInfo kADTSCodecInfo = {nullptr, CodecInfo::AUDIO, nullptr, + CodecInfo::HISTOGRAM_MPEG4AAC}; +static const CodecInfo* const kAudioADTSCodecs[] = {&kADTSCodecInfo, nullptr}; static StreamParser* BuildADTSParser(const std::vector<std::string>& codecs, MediaLog* media_log) { @@ -312,9 +323,9 @@ // 69 Audio ISO/IEC 13818-3 // 6B Audio ISO/IEC 11172-3 static const CodecInfo kMPEG2TS_MP3CodecInfo1 = { - "mp4a.69", CodecInfo::AUDIO, NULL, CodecInfo::HISTOGRAM_MP3}; + "mp4a.69", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MP3}; static const CodecInfo kMPEG2TS_MP3CodecInfo2 = { - "mp4a.6B", CodecInfo::AUDIO, NULL, CodecInfo::HISTOGRAM_MP3}; + "mp4a.6B", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MP3}; static const CodecInfo* const kVideoMP2TCodecs[] = {&kH264AVC1CodecInfo, &kH264AVC3CodecInfo, @@ -322,7 +333,7 @@ &kMPEG2TS_MP3CodecInfo2, &kMPEG4AACCodecInfo, &kMPEG2AACLCCodecInfo, - NULL}; + nullptr}; static StreamParser* BuildMP2TParser(const std::vector<std::string>& codecs, MediaLog* media_log) { @@ -361,15 +372,14 @@ // // Returns true if |codec_info| is a valid audio/video codec and is allowed. // |audio_codecs| has |codec_info|.tag added to its list if |codec_info| is an -// audio codec. |audio_codecs| may be NULL, in which case it is not updated. +// audio codec. |audio_codecs| may be nullptr, in which case it is not updated. // |video_codecs| has |codec_info|.tag added to its list if |codec_info| is a -// video codec. |video_codecs| may be NULL, in which case it is not updated. +// video codec. |video_codecs| may be nullptr, in which case it is not updated. // // Returns false otherwise, and |audio_codecs| and |video_codecs| not touched. -static bool VerifyCodec( - const CodecInfo* codec_info, - std::vector<CodecInfo::HistogramTag>* audio_codecs, - std::vector<CodecInfo::HistogramTag>* video_codecs) { +static bool VerifyCodec(const CodecInfo* codec_info, + std::vector<CodecInfo::HistogramTag>* audio_codecs, + std::vector<CodecInfo::HistogramTag>* video_codecs) { switch (codec_info->type) { case CodecInfo::AUDIO: if (audio_codecs) @@ -384,6 +394,14 @@ return false; } #endif + +#if BUILDFLAG(ENABLE_AV1_DECODER) + if (codec_info->tag == CodecInfo::HISTOGRAM_AV1 && + !base::FeatureList::IsEnabled(kAv1Decoder)) { + return false; + } +#endif + if (video_codecs) video_codecs->push_back(codec_info->tag); return true; @@ -399,12 +417,12 @@ // // Returns true if |type| and all codecs listed in |codecs| are supported. // |factory_function| contains a function that can build a StreamParser for this -// type. Value may be NULL, in which case it is not touched. +// type. Value may be nullptr, in which case it is not touched. // |audio_codecs| is updated with the appropriate HistogramTags for matching -// audio codecs specified in |codecs|. Value may be NULL, in which case it is +// audio codecs specified in |codecs|. Value may be nullptr, in which case it is // not touched. // |video_codecs| is updated with the appropriate HistogramTags for matching -// video codecs specified in |codecs|. Value may be NULL, in which case it is +// video codecs specified in |codecs|. Value may be nullptr, in which case it is // not touched. // // Returns false otherwise. The values of |factory_function|, |audio_codecs|, @@ -424,7 +442,6 @@ const CodecInfo* codec_info = type_info.codecs[0]; if (codec_info && !codec_info->pattern && VerifyCodec(codec_info, audio_codecs, video_codecs)) { - if (factory_function) *factory_function = type_info.factory_function; return true; @@ -452,9 +469,9 @@ } if (!found_codec) { - MEDIA_LOG(DEBUG, media_log) << "Codec '" << codec_id - << "' is not supported for '" << type - << "'"; + MEDIA_LOG(DEBUG, media_log) + << "Codec '" << codec_id << "' is not supported for '" << type + << "'"; return false; } } @@ -476,7 +493,8 @@ const std::vector<std::string>& codecs) { // TODO(wolenetz): Questionable MediaLog usage, http://crbug.com/712310 MediaLog media_log; - return CheckTypeAndCodecs(type, codecs, &media_log, NULL, NULL, NULL); + return CheckTypeAndCodecs(type, codecs, &media_log, nullptr, nullptr, + nullptr); } std::unique_ptr<StreamParser> StreamParserFactory::Create( @@ -493,13 +511,11 @@ // Log the number of codecs specified, as well as the details on each one. UMA_HISTOGRAM_COUNTS_100("Media.MSE.NumberOfTracks", codecs.size()); for (size_t i = 0; i < audio_codecs.size(); ++i) { - UMA_HISTOGRAM_ENUMERATION("Media.MSE.AudioCodec", - audio_codecs[i], + UMA_HISTOGRAM_ENUMERATION("Media.MSE.AudioCodec", audio_codecs[i], CodecInfo::HISTOGRAM_MAX + 1); } for (size_t i = 0; i < video_codecs.size(); ++i) { - UMA_HISTOGRAM_ENUMERATION("Media.MSE.VideoCodec", - video_codecs[i], + UMA_HISTOGRAM_ENUMERATION("Media.MSE.VideoCodec", video_codecs[i], CodecInfo::HISTOGRAM_MAX + 1); if (type == "video/mp4") { UMA_HISTOGRAM_ENUMERATION("Media.MSE.VideoCodec.MP4", video_codecs[i],
diff --git a/media/formats/BUILD.gn b/media/formats/BUILD.gn index 05622409..964b6c2 100644 --- a/media/formats/BUILD.gn +++ b/media/formats/BUILD.gn
@@ -51,6 +51,7 @@ deps = [ "//media/base", "//skia", + "//third_party/libaom:av1_features", ] configs += [
diff --git a/media/formats/mp4/box_definitions.cc b/media/formats/mp4/box_definitions.cc index f3e165a..fab76e4 100644 --- a/media/formats/mp4/box_definitions.cc +++ b/media/formats/mp4/box_definitions.cc
@@ -19,6 +19,7 @@ #include "media/formats/mp4/rcheck.h" #include "media/media_features.h" #include "media/video/h264_parser.h" +#include "third_party/libaom/av1_features.h" #if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) #include "media/formats/mp4/dolby_vision.h" @@ -820,6 +821,18 @@ video_codec_profile = vp_config->profile; break; } +#if BUILDFLAG(ENABLE_AV1_DECODER) + case FOURCC_AV01: { + DVLOG(2) << __func__ << " reading AV1 configuration."; + // TODO(dalecurtis): AV1 profiles are not finalized, this needs updating + // to read the actual profile and configuration before enabling for + // release. http://crbug.com/784993 + frame_bitstream_converter = nullptr; + video_codec = kCodecAV1; + video_codec_profile = AV1PROFILE_PROFILE0; + break; + } +#endif default: // Unknown/unsupported format MEDIA_LOG(ERROR, reader->media_log()) << __func__ @@ -856,6 +869,10 @@ #endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) case FOURCC_VP09: return true; +#if BUILDFLAG(ENABLE_AV1_DECODER) + case FOURCC_AV01: + return true; +#endif default: return false; }
diff --git a/media/formats/mp4/fourccs.h b/media/formats/mp4/fourccs.h index db6966b5..c66c92f 100644 --- a/media/formats/mp4/fourccs.h +++ b/media/formats/mp4/fourccs.h
@@ -8,6 +8,7 @@ #include <string> #include "media/media_features.h" +#include "third_party/libaom/av1_features.h" namespace media { namespace mp4 { @@ -18,6 +19,9 @@ FOURCC_AC3 = 0x61632d33, // "ac-3" FOURCC_EAC3 = 0x65632d33, // "ec-3" #endif +#if BUILDFLAG(ENABLE_AV1_DECODER) + FOURCC_AV01 = 0x61763031, // "av01" +#endif FOURCC_AVC1 = 0x61766331, FOURCC_AVC3 = 0x61766333, FOURCC_AVCC = 0x61766343,
diff --git a/media/formats/webm/webm_video_client.cc b/media/formats/webm/webm_video_client.cc index cb1b0dda..be368f6 100644 --- a/media/formats/webm/webm_video_client.cc +++ b/media/formats/webm/webm_video_client.cc
@@ -6,6 +6,7 @@ #include "media/base/video_decoder_config.h" #include "media/formats/webm/webm_constants.h" +#include "third_party/libaom/av1_features.h" namespace media { @@ -47,6 +48,14 @@ // TODO(servolk): Find a way to read actual VP9 profile from WebM. // crbug.com/592074 profile = VP9PROFILE_PROFILE0; +#if BUILDFLAG(ENABLE_AV1_DECODER) + } else if (codec_id == "V_AV1") { + // TODO(dalecurtis): AV1 profiles are not finalized, this needs updating + // to read the actual profile and configuration before enabling for + // release. http://crbug.com/784993 + video_codec = kCodecAV1; + profile = AV1PROFILE_PROFILE0; +#endif } else { MEDIA_LOG(ERROR, media_log_) << "Unsupported video codec_id " << codec_id; return false; @@ -78,7 +87,10 @@ gfx::Rect visible_rect(crop_top_, crop_left_, pixel_width_ - (crop_left_ + crop_right_), pixel_height_ - (crop_top_ + crop_bottom_)); - if (display_unit_ == 0) { + // TODO(dalecurtis): This is not correct, but it's what's muxed in webm + // containers with AV1 right now. So accept it. We won't get here unless the + // build and runtime flags are enabled for AV1. + if (display_unit_ == 0 || (video_codec == kCodecAV1 && display_unit_ == 4)) { if (display_width_ <= 0) display_width_ = visible_rect.width(); if (display_height_ <= 0) @@ -87,8 +99,8 @@ if (display_width_ <= 0 || display_height_ <= 0) return false; } else { - MEDIA_LOG(ERROR, media_log_) << "Unsupported display unit type " - << display_unit_; + MEDIA_LOG(ERROR, media_log_) + << "Unsupported display unit type " << display_unit_; return false; } gfx::Size natural_size = gfx::Size(display_width_, display_height_);
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index ce2dd67..6f2eb91 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -109,7 +109,9 @@ # Only local test code, GPU-related IPC code in the media layer, and # media-related content code should access //media/gpu. visibility = [ + "//components/arc/common:media", "//components/arc/video_accelerator", + "//components/viz/service/main", "//content/gpu:*", "//content/renderer:*", "//media/gpu/ipc/*",
diff --git a/media/gpu/vaapi/vaapi_drm_picture.cc b/media/gpu/vaapi/vaapi_drm_picture.cc index 234eab2..1096260 100644 --- a/media/gpu/vaapi/vaapi_drm_picture.cc +++ b/media/gpu/vaapi/vaapi_drm_picture.cc
@@ -151,7 +151,7 @@ } // static -linked_ptr<VaapiPicture> VaapiPicture::CreatePicture( +std::unique_ptr<VaapiPicture> VaapiPicture::CreatePicture( const scoped_refptr<VaapiWrapper>& vaapi_wrapper, const MakeGLContextCurrentCallback& make_context_current_cb, const BindGLImageCallback& bind_image_cb, @@ -159,9 +159,9 @@ const gfx::Size& size, uint32_t texture_id, uint32_t client_texture_id) { - return make_linked_ptr(new VaapiDrmPicture( + return base::MakeUnique<VaapiDrmPicture>( vaapi_wrapper, make_context_current_cb, bind_image_cb, picture_buffer_id, - size, texture_id, client_texture_id)); + size, texture_id, client_texture_id); } // static
diff --git a/media/gpu/vaapi/vaapi_picture.h b/media/gpu/vaapi/vaapi_picture.h index d2a107f4..222ab54 100644 --- a/media/gpu/vaapi/vaapi_picture.h +++ b/media/gpu/vaapi/vaapi_picture.h
@@ -13,7 +13,6 @@ #include <stdint.h> #include "base/macros.h" -#include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" #include "base/sequence_checker.h" #include "media/gpu/gpu_video_decode_accelerator_helpers.h" @@ -32,7 +31,7 @@ // Create a VaapiPicture of |size| to be associated with |picture_buffer_id|. // If provided, bind it to |texture_id|, as well as to |client_texture_id| // using |bind_image_cb|. - static linked_ptr<VaapiPicture> CreatePicture( + static std::unique_ptr<VaapiPicture> CreatePicture( const scoped_refptr<VaapiWrapper>& vaapi_wrapper, const MakeGLContextCurrentCallback& make_context_current_cb, const BindGLImageCallback& bind_image_cb,
diff --git a/media/gpu/vaapi/vaapi_tfp_picture.cc b/media/gpu/vaapi/vaapi_tfp_picture.cc index 8cf007e6..84957ae 100644 --- a/media/gpu/vaapi/vaapi_tfp_picture.cc +++ b/media/gpu/vaapi/vaapi_tfp_picture.cc
@@ -110,7 +110,7 @@ } // static -linked_ptr<VaapiPicture> VaapiPicture::CreatePicture( +std::unique_ptr<VaapiPicture> VaapiPicture::CreatePicture( const scoped_refptr<VaapiWrapper>& vaapi_wrapper, const MakeGLContextCurrentCallback& make_context_current_cb, const BindGLImageCallback& bind_image_cb, @@ -118,11 +118,9 @@ const gfx::Size& size, uint32_t texture_id, uint32_t client_texture_id) { - linked_ptr<VaapiPicture> picture; - picture.reset(new VaapiTFPPicture(vaapi_wrapper, make_context_current_cb, - bind_image_cb, picture_buffer_id, size, - texture_id, client_texture_id)); - return picture; + return base::MakeUnique<VaapiTFPPicture>( + vaapi_wrapper, make_context_current_cb, bind_image_cb, picture_buffer_id, + size, texture_id, client_texture_id); } // static
diff --git a/media/gpu/vaapi_video_decode_accelerator.cc b/media/gpu/vaapi_video_decode_accelerator.cc index 37b5758..9c627d5a 100644 --- a/media/gpu/vaapi_video_decode_accelerator.cc +++ b/media/gpu/vaapi_video_decode_accelerator.cc
@@ -498,18 +498,20 @@ if (bitstream_buffer.size() == 0) { DCHECK(!base::SharedMemory::IsHandleValid(bitstream_buffer.handle())); // Dummy buffer for flush. - input_buffers_.push(make_linked_ptr(new InputBuffer())); - DCHECK(input_buffers_.back()->IsFlushRequest()); + auto flush_buffer = base::MakeUnique<InputBuffer>(); + DCHECK(flush_buffer->IsFlushRequest()); + input_buffers_.push(std::move(flush_buffer)); } else { std::unique_ptr<SharedMemoryRegion> shm( new SharedMemoryRegion(bitstream_buffer, true)); RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(), "Failed to map input buffer", UNREADABLE_INPUT, ); - input_buffers_.push(make_linked_ptr( - new InputBuffer(bitstream_buffer.id(), std::move(shm), - BindToCurrentLoop(base::Bind( - &Client::NotifyEndOfBitstreamBuffer, client_))))); + auto input_buffer = base::MakeUnique<InputBuffer>( + bitstream_buffer.id(), std::move(shm), + BindToCurrentLoop( + base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_))); + input_buffers_.push(std::move(input_buffer)); TRACE_COUNTER1("Video Decoder", "Input buffers", input_buffers_.size()); } @@ -561,7 +563,7 @@ return false; DCHECK(!input_buffers_.empty()); - curr_input_buffer_ = input_buffers_.front(); + curr_input_buffer_ = std::move(input_buffers_.front()); input_buffers_.pop(); if (curr_input_buffer_->IsFlushRequest()) { @@ -802,22 +804,22 @@ ? buffers[i].service_texture_ids()[0] : 0; - linked_ptr<VaapiPicture> picture(create_vaapi_picture_callback_.Run( + std::unique_ptr<VaapiPicture> picture(create_vaapi_picture_callback_.Run( vaapi_wrapper_, make_context_current_cb_, bind_image_cb_, buffers[i].id(), requested_pic_size_, service_id, client_id)); RETURN_AND_NOTIFY_ON_FAILURE( picture.get(), "Failed creating a VaapiPicture", PLATFORM_FAILURE, ); - bool inserted = - pictures_.insert(std::make_pair(buffers[i].id(), picture)).second; - DCHECK(inserted); - if (output_mode_ == Config::OutputMode::ALLOCATE) { RETURN_AND_NOTIFY_ON_FAILURE( picture->Allocate(output_format_), "Failed to allocate memory for a VaapiPicture", PLATFORM_FAILURE, ); output_buffers_.push(buffers[i].id()); } + bool inserted = + pictures_.insert(std::make_pair(buffers[i].id(), std::move(picture))) + .second; + DCHECK(inserted); available_va_surfaces_.push_back(va_surface_ids[i]); surfaces_available_.Signal();
diff --git a/media/gpu/vaapi_video_decode_accelerator.h b/media/gpu/vaapi_video_decode_accelerator.h index 15a3e2c..5974b47 100644 --- a/media/gpu/vaapi_video_decode_accelerator.h +++ b/media/gpu/vaapi_video_decode_accelerator.h
@@ -214,12 +214,12 @@ Config::OutputMode output_mode_; // Queue of available InputBuffers (picture_buffer_ids). - base::queue<linked_ptr<InputBuffer>> input_buffers_; + base::queue<std::unique_ptr<InputBuffer>> input_buffers_; // Signalled when input buffers are queued onto |input_buffers_| queue. base::ConditionVariable input_ready_; // Current input buffer at decoder. - linked_ptr<InputBuffer> curr_input_buffer_; + std::unique_ptr<InputBuffer> curr_input_buffer_; // Queue for incoming output buffers (texture ids). using OutputBuffers = base::queue<int32_t>; @@ -228,19 +228,20 @@ scoped_refptr<VaapiWrapper> vaapi_wrapper_; // TODO(mcasas): Use a VaapiPicture factory instead, https://crbug.com/784507. - base::Callback<linked_ptr<VaapiPicture>(const scoped_refptr<VaapiWrapper>&, - const MakeGLContextCurrentCallback&, - const BindGLImageCallback&, - int32_t, - const gfx::Size&, - uint32_t, - uint32_t)> + base::Callback<std::unique_ptr<VaapiPicture>( + const scoped_refptr<VaapiWrapper>&, + const MakeGLContextCurrentCallback&, + const BindGLImageCallback&, + int32_t, + const gfx::Size&, + uint32_t, + uint32_t)> create_vaapi_picture_callback_; // All allocated Pictures, regardless of their current state. Pictures are - // allocated once using | create_vaapi_picture_callback_| and destroyed at the + // allocated once using |create_vaapi_picture_callback_| and destroyed at the // end of decode. Comes after |vaapi_wrapper_| to ensure all pictures are // destroyed before said |vaapi_wrapper_| is destroyed. - using Pictures = std::map<int32_t, linked_ptr<VaapiPicture>>; + using Pictures = std::map<int32_t, std::unique_ptr<VaapiPicture>>; Pictures pictures_; // Return a VaapiPicture associated with given client-provided id.
diff --git a/media/gpu/vaapi_video_decode_accelerator_unittest.cc b/media/gpu/vaapi_video_decode_accelerator_unittest.cc index 8873fe3..4ca2d9b 100644 --- a/media/gpu/vaapi_video_decode_accelerator_unittest.cc +++ b/media/gpu/vaapi_video_decode_accelerator_unittest.cc
@@ -5,6 +5,7 @@ #include "media/gpu/vaapi_video_decode_accelerator.h" #include "base/bind.h" +#include "base/memory/ptr_util.h" #include "base/test/scoped_task_environment.h" #include "media/gpu/accelerated_video_decoder.h" #include "media/gpu/vaapi/vaapi_picture.h" @@ -153,7 +154,7 @@ // TODO(mcasas): Use a Mock VaapiPicture factory, https://crbug.com/784507. MOCK_METHOD2(MockCreateVaapiPicture, void(VaapiWrapper*, const gfx::Size&)); - linked_ptr<VaapiPicture> CreateVaapiPicture( + std::unique_ptr<VaapiPicture> CreateVaapiPicture( const scoped_refptr<VaapiWrapper>& vaapi_wrapper, const MakeGLContextCurrentCallback& make_context_current_cb, const BindGLImageCallback& bind_image_cb, @@ -162,9 +163,9 @@ uint32_t texture_id, uint32_t client_texture_id) { MockCreateVaapiPicture(vaapi_wrapper.get(), size); - return make_linked_ptr(new MockVaapiPicture( + return base::MakeUnique<MockVaapiPicture>( vaapi_wrapper, make_context_current_cb, bind_image_cb, - picture_buffer_id, size, texture_id, client_texture_id)); + picture_buffer_id, size, texture_id, client_texture_id); } // VideoDecodeAccelerator::Client methods.
diff --git a/media/gpu/vaapi_wrapper.cc b/media/gpu/vaapi_wrapper.cc index 618f9506..c229f9b3 100644 --- a/media/gpu/vaapi_wrapper.cc +++ b/media/gpu/vaapi_wrapper.cc
@@ -205,12 +205,16 @@ // static bool VADisplayState::PostSandboxInitialization() { + const std::string va_suffix(std::to_string(VA_MAJOR_VERSION + 1)); StubPathMap paths; - paths[kModuleVa].push_back("libva.so.1"); + + paths[kModuleVa].push_back(std::string("libva.so.") + va_suffix); #if defined(USE_X11) - paths[kModuleVa_x11].push_back("libva-x11.so.1"); + // libva-x11 does not exist on libva >= 2 + if (VA_MAJOR_VERSION == 0) + paths[kModuleVa_x11].push_back("libva-x11.so.1"); #elif defined(USE_OZONE) - paths[kModuleVa_drm].push_back("libva-drm.so.1"); + paths[kModuleVa_drm].push_back(std::string("libva-drm.so.") + va_suffix); #endif const bool success = InitializeStubs(paths);
diff --git a/media/mojo/BUILD.gn b/media/mojo/BUILD.gn index 84f4941..e82ecd4 100644 --- a/media/mojo/BUILD.gn +++ b/media/mojo/BUILD.gn
@@ -70,65 +70,28 @@ ] } -source_set("unit_tests") { +source_set("test_support") { testonly = true - sources = [ - "clients/mojo_audio_decoder_unittest.cc", - "clients/mojo_cdm_unittest.cc", - "clients/mojo_decryptor_unittest.cc", - "clients/mojo_renderer_unittest.cc", - "clients/mojo_video_encode_accelerator_unittest.cc", - "common/media_type_converters_unittest.cc", - "common/mojo_decoder_buffer_converter_unittest.cc", - "common/mojo_shared_buffer_video_frame_unittest.cc", - "interfaces/audio_decoder_config_struct_traits_unittest.cc", - "interfaces/encryption_scheme_struct_traits_unittest.cc", - "interfaces/video_decoder_config_struct_traits_unittest.cc", - "interfaces/video_frame_struct_traits_unittest.cc", - "mojo_video_encode_accelerator_integration_test.cc", - "services/mojo_audio_input_stream_unittest.cc", - "services/mojo_audio_output_stream_unittest.cc", - "services/video_decode_perf_history_unittest.cc", - "services/watch_time_recorder_unittest.cc", - ] - - if (is_android) { - sources += [ "clients/mojo_android_overlay_unittest.cc" ] - } - - deps = [ - "//base", - "//base/test:test_support", - "//components/ukm:test_support", - "//media:test_support", + public_deps = [ "//media/mojo/clients", "//media/mojo/common", "//media/mojo/common:mojo_shared_buffer_video_frame", "//media/mojo/interfaces", "//media/mojo/interfaces:test_interfaces", "//media/mojo/services", - "//services/metrics/public/cpp:ukm_builders", - "//services/service_manager/tests:interfaces", - "//testing/gmock", - "//testing/gtest", - "//ui/gfx:test_support", ] +} - if (is_android) { - deps += [ - "//gpu/ipc/common:common", - "//ui/gl:gl", - ] - } +source_set("unit_tests") { + testonly = true - if (enable_library_cdms) { - sources += [ - "services/mojo_cdm_allocator_unittest.cc", - "services/mojo_cdm_file_io_unittest.cc", - "services/mojo_cdm_helper_unittest.cc", - ] - deps += [ "//media/cdm:cdm_api" ] - } + deps = [ + "//media/mojo/clients:unit_tests", + "//media/mojo/common:unit_tests", + "//media/mojo/interfaces:unit_tests", + "//media/mojo/services:unit_tests", + "//media/mojo/test:unit_tests", + ] } test("media_mojo_unittests") {
diff --git a/media/mojo/clients/BUILD.gn b/media/mojo/clients/BUILD.gn index 2d2626d..df57505 100644 --- a/media/mojo/clients/BUILD.gn +++ b/media/mojo/clients/BUILD.gn
@@ -8,12 +8,11 @@ "//chromecast/*", "//content/renderer:*", - # TODO(xhwang): Only allow //media/mojo:media_mojo_unittests - "//media/mojo:*", - # TODO(xhwang): Only allow //media/mojo/services:media_service_unittests "//media/mojo/services:*", + "//media/mojo:test_support", + "//media/test/*", "//content/gpu:*", @@ -79,3 +78,33 @@ ] } } + +source_set("unit_tests") { + testonly = true + + sources = [ + "mojo_audio_decoder_unittest.cc", + "mojo_cdm_unittest.cc", + "mojo_decryptor_unittest.cc", + "mojo_renderer_unittest.cc", + "mojo_video_encode_accelerator_unittest.cc", + ] + + deps = [ + "//base", + "//base/test:test_support", + "//media:test_support", + "//media/mojo:test_support", + "//testing/gmock", + "//testing/gtest", + ] + + if (is_android) { + sources += [ "mojo_android_overlay_unittest.cc" ] + + deps += [ + "//media/mojo/interfaces:test_interfaces", + "//ui/gfx:test_support", + ] + } +}
diff --git a/media/mojo/clients/mojo_video_decoder.cc b/media/mojo/clients/mojo_video_decoder.cc index a838c8e..5d515dcf 100644 --- a/media/mojo/clients/mojo_video_decoder.cc +++ b/media/mojo/clients/mojo_video_decoder.cc
@@ -70,11 +70,22 @@ return; } + // Fail immediately if the stream is encrypted but |cdm_context| is invalid. + int cdm_id = (config.is_encrypted() && cdm_context) + ? cdm_context->GetCdmId() + : CdmContext::kInvalidCdmId; + + if (config.is_encrypted() && CdmContext::kInvalidCdmId == cdm_id) { + DVLOG(1) << __func__ << ": Invalid CdmContext."; + task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false)); + return; + } + initialized_ = false; init_cb_ = init_cb; output_cb_ = output_cb; remote_decoder_->Initialize( - config, low_delay, + config, low_delay, cdm_id, base::Bind(&MojoVideoDecoder::OnInitializeDone, base::Unretained(this))); }
diff --git a/media/mojo/common/BUILD.gn b/media/mojo/common/BUILD.gn index cd16a73c..637252e 100644 --- a/media/mojo/common/BUILD.gn +++ b/media/mojo/common/BUILD.gn
@@ -39,3 +39,22 @@ "//ui/gfx/geometry", ] } + +source_set("unit_tests") { + testonly = true + + sources = [ + "media_type_converters_unittest.cc", + "mojo_decoder_buffer_converter_unittest.cc", + "mojo_shared_buffer_video_frame_unittest.cc", + ] + + deps = [ + "//base", + "//base/test:test_support", + "//media:test_support", + "//media/mojo:test_support", + "//testing/gmock", + "//testing/gtest", + ] +}
diff --git a/media/mojo/interfaces/BUILD.gn b/media/mojo/interfaces/BUILD.gn index 8ed6379..4835523 100644 --- a/media/mojo/interfaces/BUILD.gn +++ b/media/mojo/interfaces/BUILD.gn
@@ -105,3 +105,22 @@ ":interfaces", ] } + +source_set("unit_tests") { + testonly = true + + sources = [ + "audio_decoder_config_struct_traits_unittest.cc", + "encryption_scheme_struct_traits_unittest.cc", + "video_decoder_config_struct_traits_unittest.cc", + "video_frame_struct_traits_unittest.cc", + ] + + deps = [ + "//base", + "//media/mojo:test_support", + "//testing/gmock", + "//testing/gtest", + "//ui/gfx:test_support", + ] +}
diff --git a/media/mojo/interfaces/video_decoder.mojom b/media/mojo/interfaces/video_decoder.mojom index 06b0694a..c34426b 100644 --- a/media/mojo/interfaces/video_decoder.mojom +++ b/media/mojo/interfaces/video_decoder.mojom
@@ -49,7 +49,10 @@ // indicating whether decode buffers need bitstream conversion, and // |max_decode_requests|, the maximum number of concurrent Decode() requests // the implementation supports. - Initialize(VideoDecoderConfig config, bool low_delay) => + // + // |cdm_id| must refer to a valid CDM if |config.is_encrypted()|. It is not + // used for unencrypted streams. + Initialize(VideoDecoderConfig config, bool low_delay, int32 cdm_id) => (bool success, bool needs_bitstream_conversion, int32 max_decode_requests);
diff --git a/media/mojo/interfaces/watch_time_recorder.mojom b/media/mojo/interfaces/watch_time_recorder.mojom index fb16223..1e3492e 100644 --- a/media/mojo/interfaces/watch_time_recorder.mojom +++ b/media/mojo/interfaces/watch_time_recorder.mojom
@@ -20,7 +20,12 @@ bool is_eme; bool is_embedded_media_experience; // Playback from 'Downloads' on Android. gfx.mojom.Size natural_size; // Size of video frame; (0, 0) if audio only. - url.mojom.Origin origin; + + // For privacy, only record the top origin. "Untrusted" signals that this + // value comes from the renderer and should not be used for security checks. + // TODO(crbug.com/787209): Stop getting origin from the renderer. + url.mojom.Origin untrusted_top_origin; + bool is_top_frame; // False for any inner/iframe playbacks. }; // Interface by which the WatchTimeReporter reports watch time. This is used to
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index 3d79b9de..73d788f 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn
@@ -216,3 +216,36 @@ embedded_services = [ ":pipeline_test_manifest" ] standalone_services = [ ":media_manifest" ] } + +source_set("unit_tests") { + testonly = true + + sources = [ + "mojo_audio_input_stream_unittest.cc", + "mojo_audio_output_stream_unittest.cc", + "mojo_video_encode_accelerator_service_unittest.cc", + "video_decode_perf_history_unittest.cc", + "watch_time_recorder_unittest.cc", + ] + + deps = [ + "//base", + "//base/test:test_support", + "//components/ukm:test_support", + "//media:test_support", + "//media/mojo:test_support", + "//services/metrics/public/cpp:ukm_builders", + "//testing/gmock", + "//testing/gtest", + ] + + if (enable_library_cdms) { + sources += [ + "mojo_cdm_allocator_unittest.cc", + "mojo_cdm_file_io_unittest.cc", + "mojo_cdm_helper_unittest.cc", + ] + + deps += [ "//media/cdm:cdm_api" ] + } +}
diff --git a/media/mojo/services/interface_factory_impl.cc b/media/mojo/services/interface_factory_impl.cc index a35eb498f..75e587d3 100644 --- a/media/mojo/services/interface_factory_impl.cc +++ b/media/mojo/services/interface_factory_impl.cc
@@ -123,7 +123,8 @@ mojom::VideoDecoderRequest request) { #if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) video_decoder_bindings_.AddBinding( - base::MakeUnique<MojoVideoDecoderService>(mojo_media_client_), + base::MakeUnique<MojoVideoDecoderService>( + mojo_media_client_, cdm_service_context_.GetWeakPtr()), std::move(request)); #endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) }
diff --git a/media/mojo/services/mojo_video_decoder_service.cc b/media/mojo/services/mojo_video_decoder_service.cc index 0eb1732..24f21565 100644 --- a/media/mojo/services/mojo_video_decoder_service.cc +++ b/media/mojo/services/mojo_video_decoder_service.cc
@@ -9,12 +9,14 @@ #include "base/logging.h" #include "base/optional.h" #include "base/threading/thread_task_runner_handle.h" +#include "media/base/cdm_context.h" #include "media/base/decoder_buffer.h" #include "media/base/video_decoder.h" #include "media/base/video_decoder_config.h" #include "media/base/video_frame.h" #include "media/mojo/common/media_type_converters.h" #include "media/mojo/common/mojo_decoder_buffer_converter.h" +#include "media/mojo/services/mojo_cdm_service_context.h" #include "media/mojo/services/mojo_media_client.h" #include "media/mojo/services/mojo_media_log.h" #include "mojo/public/c/system/types.h" @@ -24,8 +26,11 @@ namespace media { MojoVideoDecoderService::MojoVideoDecoderService( - MojoMediaClient* mojo_media_client) - : mojo_media_client_(mojo_media_client), weak_factory_(this) { + MojoMediaClient* mojo_media_client, + base::WeakPtr<MojoCdmServiceContext> mojo_cdm_service_context) + : mojo_media_client_(mojo_media_client), + mojo_cdm_service_context_(std::move(mojo_cdm_service_context)), + weak_factory_(this) { weak_this_ = weak_factory_.GetWeakPtr(); } @@ -63,6 +68,7 @@ void MojoVideoDecoderService::Initialize(const VideoDecoderConfig& config, bool low_delay, + int32_t cdm_id, InitializeCallback callback) { DVLOG(1) << __func__; @@ -71,10 +77,37 @@ return; } + // Get CdmContext from cdm_id if the stream is encrypted. + // TODO(xhwang): This code is duplicated in mojo_audio_decoder_service. + // crbug.com/786736 . + CdmContext* cdm_context = nullptr; + scoped_refptr<ContentDecryptionModule> cdm; + if (config.is_encrypted()) { + if (!mojo_cdm_service_context_) { + DVLOG(1) << "CDM service context not available."; + std::move(callback).Run(false, false, 1); + return; + } + + cdm = mojo_cdm_service_context_->GetCdm(cdm_id); + if (!cdm) { + DVLOG(1) << "CDM not found for CDM id: " << cdm_id; + std::move(callback).Run(false, false, 1); + return; + } + + cdm_context = cdm->GetCdmContext(); + if (!cdm_context) { + DVLOG(1) << "CDM context not available for CDM id: " << cdm_id; + std::move(callback).Run(false, false, 1); + return; + } + } + decoder_->Initialize( - config, low_delay, nullptr, + config, low_delay, cdm_context, base::Bind(&MojoVideoDecoderService::OnDecoderInitialized, weak_this_, - base::Passed(&callback)), + base::Passed(&callback), cdm), base::Bind(&MojoVideoDecoderService::OnDecoderOutput, weak_this_, base::nullopt)); } @@ -104,10 +137,16 @@ weak_this_, base::Passed(&callback))); } -void MojoVideoDecoderService::OnDecoderInitialized(InitializeCallback callback, - bool success) { +void MojoVideoDecoderService::OnDecoderInitialized( + InitializeCallback callback, + scoped_refptr<ContentDecryptionModule> cdm, + bool success) { DVLOG(1) << __func__; DCHECK(decoder_); + + if (success) + cdm_ = std::move(cdm); + std::move(callback).Run(success, decoder_->NeedsBitstreamConversion(), decoder_->GetMaxDecodeRequests()); }
diff --git a/media/mojo/services/mojo_video_decoder_service.h b/media/mojo/services/mojo_video_decoder_service.h index 054eb94e..e1ee9a3c 100644 --- a/media/mojo/services/mojo_video_decoder_service.h +++ b/media/mojo/services/mojo_video_decoder_service.h
@@ -23,7 +23,9 @@ namespace media { +class ContentDecryptionModule; class DecoderBuffer; +class MojoCdmServiceContext; class MojoDecoderBufferReader; class MojoMediaClient; class MojoMediaLog; @@ -33,7 +35,9 @@ // and wraps a media::VideoDecoder. class MojoVideoDecoderService : public mojom::VideoDecoder { public: - explicit MojoVideoDecoderService(MojoMediaClient* mojo_media_client); + explicit MojoVideoDecoderService( + MojoMediaClient* mojo_media_client, + base::WeakPtr<MojoCdmServiceContext> mojo_cdm_service_context); ~MojoVideoDecoderService() final; // mojom::VideoDecoder implementation @@ -43,6 +47,7 @@ mojom::CommandBufferIdPtr command_buffer_id) final; void Initialize(const VideoDecoderConfig& config, bool low_delay, + int32_t cdm_id, InitializeCallback callback) final; void Decode(mojom::DecoderBufferPtr buffer, DecodeCallback callback) final; void Reset(ResetCallback callback) final; @@ -55,7 +60,9 @@ // running mojom::VideoDecoder callbacks after connection error happens and // |this| is deleted. It's not safe to run the callbacks after a connection // error. - void OnDecoderInitialized(InitializeCallback callback, bool success); + void OnDecoderInitialized(InitializeCallback callback, + scoped_refptr<ContentDecryptionModule> cdm, + bool success); void OnDecoderRead(DecodeCallback callback, scoped_refptr<DecoderBuffer> buffer); void OnDecoderDecoded(DecodeCallback callback, DecodeStatus status); @@ -80,6 +87,13 @@ release_mailbox_cbs_; ProvideOverlayInfoCB provide_overlay_info_cb_; + // A helper object required to get CDM from CDM id. + base::WeakPtr<MojoCdmServiceContext> mojo_cdm_service_context_; + + // Hold a reference to the CDM to keep it alive for the lifetime of the + // |decoder_|. The |cdm_| owns the CdmContext which is passed to |decoder_|. + scoped_refptr<ContentDecryptionModule> cdm_; + base::WeakPtr<MojoVideoDecoderService> weak_this_; base::WeakPtrFactory<MojoVideoDecoderService> weak_factory_;
diff --git a/media/mojo/services/watch_time_recorder.cc b/media/mojo/services/watch_time_recorder.cc index d5760eaf..e857627 100644 --- a/media/mojo/services/watch_time_recorder.cc +++ b/media/mojo/services/watch_time_recorder.cc
@@ -169,9 +169,14 @@ } const int32_t source_id = ukm_recorder->GetNewSourceID(); - ukm_recorder->UpdateSourceURL(source_id, properties_->origin.GetURL()); + + // TODO(crbug.com/787209): Stop getting origin from the renderer. + ukm_recorder->UpdateSourceURL(source_id, + properties_->untrusted_top_origin.GetURL()); ukm::builders::Media_BasicPlayback builder(source_id); + builder.SetIsTopFrame(properties_->is_top_frame); + bool recorded_all_metric = false; for (auto& kv : aggregate_watch_time_info_) { if (kv.first == WatchTimeKey::kAudioAll ||
diff --git a/media/mojo/services/watch_time_recorder_unittest.cc b/media/mojo/services/watch_time_recorder_unittest.cc index 9d701fb..16f3e7db 100644 --- a/media/mojo/services/watch_time_recorder_unittest.cc +++ b/media/mojo/services/watch_time_recorder_unittest.cc
@@ -55,10 +55,10 @@ bool is_mse, bool is_encrypted) { provider_->AcquireWatchTimeRecorder( - mojom::PlaybackProperties::New(kUnknownAudioCodec, kUnknownVideoCodec, - has_audio, has_video, is_mse, - is_encrypted, false, gfx::Size(800, 600), - url::Origin::Create(GURL(kTestOrigin))), + mojom::PlaybackProperties::New( + kUnknownAudioCodec, kUnknownVideoCodec, has_audio, has_video, + is_mse, is_encrypted, false, gfx::Size(800, 600), + url::Origin::Create(GURL(kTestOrigin)), true /* is_top_frame */), mojo::MakeRequest(&wtr_)); } @@ -246,7 +246,7 @@ TEST_F(WatchTimeRecorderTest, BasicUkmAudioVideo) { mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New( kCodecAAC, kCodecH264, true, true, false, false, false, - gfx::Size(800, 600), url::Origin::Create(GURL(kTestOrigin))); + gfx::Size(800, 600), url::Origin::Create(GURL(kTestOrigin)), true); provider_->AcquireWatchTimeRecorder(properties.Clone(), mojo::MakeRequest(&wtr_)); @@ -287,7 +287,7 @@ TEST_F(WatchTimeRecorderTest, BasicUkmAudioVideoWithExtras) { mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New( kCodecOpus, kCodecVP9, true, true, true, true, false, gfx::Size(800, 600), - url::Origin::Create(GURL(kTestOrigin))); + url::Origin::Create(GURL(kTestOrigin)), true); provider_->AcquireWatchTimeRecorder(properties.Clone(), mojo::MakeRequest(&wtr_)); @@ -354,7 +354,7 @@ TEST_F(WatchTimeRecorderTest, BasicUkmAudioVideoBackground) { mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New( kCodecAAC, kCodecH264, true, true, false, false, false, - gfx::Size(800, 600), url::Origin::Create(GURL(kTestOrigin))); + gfx::Size(800, 600), url::Origin::Create(GURL(kTestOrigin)), true); provider_->AcquireWatchTimeRecorder(properties.Clone(), mojo::MakeRequest(&wtr_));
diff --git a/media/mojo/test/BUILD.gn b/media/mojo/test/BUILD.gn new file mode 100644 index 0000000..85d8721 --- /dev/null +++ b/media/mojo/test/BUILD.gn
@@ -0,0 +1,21 @@ +# 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. + +# TODO(sandersd): Split out an "integration_tests" target. +source_set("unit_tests") { + testonly = true + + sources = [ + "mojo_video_encode_accelerator_integration_test.cc", + ] + + deps = [ + "//base", + "//base/test:test_support", + "//media:test_support", + "//media/mojo:test_support", + "//testing/gmock", + "//testing/gtest", + ] +}
diff --git a/media/mojo/mojo_video_encode_accelerator_integration_test.cc b/media/mojo/test/mojo_video_encode_accelerator_integration_test.cc similarity index 100% rename from media/mojo/mojo_video_encode_accelerator_integration_test.cc rename to media/mojo/test/mojo_video_encode_accelerator_integration_test.cc
diff --git a/media/renderers/default_renderer_factory.cc b/media/renderers/default_renderer_factory.cc index 1cf9b101..0796d919 100644 --- a/media/renderers/default_renderer_factory.cc +++ b/media/renderers/default_renderer_factory.cc
@@ -7,13 +7,16 @@ #include <utility> #include "base/bind.h" +#include "base/feature_list.h" #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "build/build_config.h" #include "build/buildflag.h" #include "media/base/decoder_factory.h" #include "media/base/media_log.h" +#include "media/base/media_switches.h" #include "media/filters/gpu_video_decoder.h" +#include "media/media_features.h" #include "media/renderers/audio_renderer_impl.h" #include "media/renderers/renderer_impl.h" #include "media/renderers/video_renderer_impl.h" @@ -99,7 +102,8 @@ #endif #if BUILDFLAG(ENABLE_AV1_DECODER) - video_decoders.push_back(base::MakeUnique<AomVideoDecoder>(media_log_)); + if (base::FeatureList::IsEnabled(kAv1Decoder)) + video_decoders.push_back(base::MakeUnique<AomVideoDecoder>(media_log_)); #endif #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(DISABLE_FFMPEG_VIDEO_DECODERS)
diff --git a/media/test/BUILD.gn b/media/test/BUILD.gn index 581ee2b..d3c0f452 100644 --- a/media/test/BUILD.gn +++ b/media/test/BUILD.gn
@@ -44,6 +44,7 @@ "//media:test_support", "//testing/gmock", "//testing/gtest", + "//third_party/libaom:av1_features", "//url", ] } @@ -68,6 +69,7 @@ "//media:test_support", "//media/mojo/clients", "//services/service_manager/public/cpp:service_test_support", + "//third_party/libaom:av1_features", # Needed for the opus_config "//third_party/opus", @@ -125,6 +127,7 @@ "//media/mojo/services", "//services/service_manager/public/cpp:service_test_support", "//testing/gtest", + "//third_party/libaom:av1_features", "//ui/gfx:test_support", "//ui/gfx/geometry",
diff --git a/media/test/data/bear-av1.mp4 b/media/test/data/bear-av1.mp4 new file mode 100644 index 0000000..da8da62 --- /dev/null +++ b/media/test/data/bear-av1.mp4 Binary files differ
diff --git a/media/test/data/bear-av1.webm b/media/test/data/bear-av1.webm new file mode 100644 index 0000000..7d9d2048 --- /dev/null +++ b/media/test/data/bear-av1.webm Binary files differ
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index a58faf4..d275a81 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -35,6 +35,7 @@ #include "media/test/mock_media_source.h" #include "media/test/pipeline_integration_test_base.h" #include "testing/gmock/include/gmock/gmock.h" +#include "third_party/libaom/av1_features.h" #include "url/gurl.h" #if defined(MOJO_RENDERER) @@ -102,6 +103,12 @@ namespace media { +#if BUILDFLAG(ENABLE_AV1_DECODER) +// TODO(dalecurtis): This is not the correct final string. Fix before enabling +// by default. http://crbug.com/784607 +const char kWebMAV1[] = "video/webm; codecs=\"av1\""; +#endif + const char kWebM[] = "video/webm; codecs=\"vp8,vorbis\""; const char kWebMVP9[] = "video/webm; codecs=\"vp9\""; const char kAudioOnlyWebM[] = "video/webm; codecs=\"vorbis\""; @@ -120,6 +127,11 @@ const char kMP4AudioFlac[] = "audio/mp4; codecs=\"flac\""; const char kMP3[] = "audio/mpeg"; const char kMP2AudioSBR[] = "video/mp2t; codecs=\"avc1.4D4041,mp4a.40.5\""; +#if BUILDFLAG(ENABLE_AV1_DECODER) +// TODO(dalecurtis): This is not the correct final string. Fix before enabling +// by default. http://crbug.com/784607 +const char kMP4AV1[] = "video/mp4; codecs=\"av1\""; +#endif // BUILDFLAG(ENABLE_AV1_DECODER) #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) // Constants for the Media Source config change tests. @@ -1139,6 +1151,28 @@ Stop(); } +#if BUILDFLAG(ENABLE_AV1_DECODER) +TEST_P(MSEPipelineIntegrationTest, BasicPlayback_AV1_WebM) { + base::test::ScopedFeatureList scoped_feature_list_; + scoped_feature_list_.InitAndEnableFeature(kAv1Decoder); + + MockMediaSource source("bear-av1.webm", kWebMAV1, 79943); + EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source)); + source.EndOfStream(); + + EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size()); + EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds()); + EXPECT_EQ(kVP9WebMFileDurationMs, + pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds()); + + Play(); + + ASSERT_TRUE(WaitUntilOnEnded()); + source.Shutdown(); + Stop(); +} +#endif + TEST_P(MSEPipelineIntegrationTest, BasicPlayback_VP9_WebM) { MockMediaSource source("bear-vp9.webm", kWebMVP9, 67504); EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source)); @@ -1528,6 +1562,27 @@ ASSERT_TRUE(WaitUntilOnEnded()); }; +#if BUILDFLAG(ENABLE_AV1_DECODER) +TEST_P(MSEPipelineIntegrationTest, BasicPlayback_AV1_MP4) { + base::test::ScopedFeatureList scoped_feature_list_; + scoped_feature_list_.InitAndEnableFeature(kAv1Decoder); + MockMediaSource source("bear-av1.mp4", kMP4AV1, 80496); + EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source)); + source.EndOfStream(); + + EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size()); + EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds()); + EXPECT_EQ(kVP9WebMFileDurationMs, + pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds()); + + Play(); + + ASSERT_TRUE(WaitUntilOnEnded()); + source.Shutdown(); + Stop(); +} +#endif + TEST_P(MSEPipelineIntegrationTest, FlacInMp4_Hashed) { // The feature is disabled by default. Enable it. base::test::ScopedFeatureList features; @@ -1627,6 +1682,16 @@ EXPECT_HASH_EQ(kSfxLosslessHash, GetAudioHash()); } +#if BUILDFLAG(ENABLE_AV1_DECODER) +TEST_F(PipelineIntegrationTest, BasicPlayback_VideoOnly_AV1_Mp4) { + base::test::ScopedFeatureList scoped_feature_list_; + scoped_feature_list_.InitAndEnableFeature(kAv1Decoder); + ASSERT_EQ(PIPELINE_OK, Start("bear-av1.mp4")); + Play(); + ASSERT_TRUE(WaitUntilOnEnded()); +} +#endif + class Mp3FastSeekParams { public: Mp3FastSeekParams(const char* filename, const char* hash) @@ -2435,6 +2500,16 @@ ASSERT_TRUE(WaitUntilOnEnded()); } +#if BUILDFLAG(ENABLE_AV1_DECODER) +TEST_F(PipelineIntegrationTest, BasicPlayback_VideoOnly_AV1_WebM) { + base::test::ScopedFeatureList scoped_feature_list_; + scoped_feature_list_.InitAndEnableFeature(kAv1Decoder); + ASSERT_EQ(PIPELINE_OK, Start("bear-av1.webm")); + Play(); + ASSERT_TRUE(WaitUntilOnEnded()); +} +#endif + // Verify that VP9 video and Opus audio in the same WebM container can be played // back. TEST_F(PipelineIntegrationTest, BasicPlayback_VP9_Opus_WebM) {
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc index ae9217d..eb82c6a 100644 --- a/media/test/pipeline_integration_test_base.cc +++ b/media/test/pipeline_integration_test_base.cc
@@ -13,23 +13,32 @@ #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "media/base/media_log.h" +#include "media/base/media_switches.h" #include "media/base/media_tracks.h" #include "media/base/test_data_util.h" +#include "media/filters/file_data_source.h" +#include "media/filters/memory_data_source.h" +#include "media/media_features.h" +#include "media/renderers/audio_renderer_impl.h" +#include "media/renderers/renderer_impl.h" +#include "media/test/fake_encrypted_media.h" +#include "media/test/mock_media_source.h" +#include "third_party/libaom/av1_features.h" + #if !defined(MEDIA_DISABLE_FFMPEG) #include "media/filters/ffmpeg_audio_decoder.h" #include "media/filters/ffmpeg_demuxer.h" #include "media/filters/ffmpeg_video_decoder.h" #endif -#include "media/filters/file_data_source.h" -#include "media/filters/memory_data_source.h" -#include "media/renderers/audio_renderer_impl.h" -#include "media/renderers/renderer_impl.h" -#include "media/test/fake_encrypted_media.h" -#include "media/test/mock_media_source.h" + #if !defined(MEDIA_DISABLE_LIBVPX) #include "media/filters/vpx_video_decoder.h" #endif +#if BUILDFLAG(ENABLE_AV1_DECODER) +#include "media/filters/aom_video_decoder.h" +#endif + using ::testing::_; using ::testing::AnyNumber; using ::testing::AtLeast; @@ -56,6 +65,11 @@ video_decoders.push_back(std::make_unique<OffloadingVpxVideoDecoder>()); #endif // !defined(MEDIA_DISABLE_LIBVPX) +#if BUILDFLAG(ENABLE_AV1_DECODER) + if (base::FeatureList::IsEnabled(kAv1Decoder)) + video_decoders.push_back(base::MakeUnique<AomVideoDecoder>(media_log)); +#endif // !defined(MEDIA_DISABLE_LIBVPX) + // Android does not have an ffmpeg video decoder. #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID) && \ !defined(DISABLE_FFMPEG_VIDEO_DECODERS)
diff --git a/mojo/public/cpp/bindings/interface_ptr.h b/mojo/public/cpp/bindings/interface_ptr.h index 274032d..45b1040 100644 --- a/mojo/public/cpp/bindings/interface_ptr.h +++ b/mojo/public/cpp/bindings/interface_ptr.h
@@ -127,8 +127,7 @@ // stimulus. void FlushForTesting() { internal_state_.FlushForTesting(); } - // Closes the bound message pipe (if any) and returns the pointer to the - // unbound state. + // Closes the bound message pipe, if any. void reset() { State doomed; internal_state_.Swap(&doomed);
diff --git a/mojo/public/cpp/bindings/strong_binding.h b/mojo/public/cpp/bindings/strong_binding.h index 5395b37..40c67e7 100644 --- a/mojo/public/cpp/bindings/strong_binding.h +++ b/mojo/public/cpp/bindings/strong_binding.h
@@ -72,6 +72,21 @@ connection_error_handler_.Reset(); } + // Stops processing incoming messages until + // ResumeIncomingMethodCallProcessing(). + // Outgoing messages are still sent. + // + // No errors are detected on the message pipe while paused. + // + // This method may only be called if the object has been bound to a message + // pipe and there are no associated interfaces running. + void PauseIncomingMethodCallProcessing() { + binding_.PauseIncomingMethodCallProcessing(); + } + void ResumeIncomingMethodCallProcessing() { + binding_.ResumeIncomingMethodCallProcessing(); + } + // Forces the binding to close. This destroys the StrongBinding instance. void Close() { delete this; }
diff --git a/mojo/public/js/new_bindings/base.js b/mojo/public/js/new_bindings/base.js index 65f6c05..45740341 100644 --- a/mojo/public/js/new_bindings/base.js +++ b/mojo/public/js/new_bindings/base.js
@@ -4,14 +4,21 @@ 'use strict'; -if (mojo && mojo.internal) { +if ((typeof mojo !== 'undefined') && mojo.bindingsLibraryInitialized) { throw new Error('The Mojo bindings library has been initialized.'); } var mojo = mojo || {}; -mojo.internal = {}; -mojo.internal.global = this; -mojo.config = { +mojo.bindingsLibraryInitialized = true; + +mojo.internal = mojo.internal || {}; + +mojo.config = mojo.config || {}; +if (typeof mojo.config.global === 'undefined') { + mojo.config.global = this; +} + +if (typeof mojo.config.autoLoadMojomDeps === 'undefined') { // Whether to automatically load mojom dependencies. // For example, if foo.mojom imports bar.mojom, |autoLoadMojomDeps| set to // true means that loading foo.mojom.js will insert a <script> tag to load @@ -52,11 +59,12 @@ // <script src="http://example.org/scripts/b/d/bar.mojom.js"></script> // // --> - autoLoadMojomDeps: true -}; + mojo.config.autoLoadMojomDeps = true; +} (function() { var internal = mojo.internal; + var config = mojo.config; var LoadState = { PENDING_LOAD: 1, @@ -66,7 +74,7 @@ var mojomRegistry = new Map(); function exposeNamespace(namespace) { - var current = internal.global; + var current = config.global; var parts = namespace.split('.'); for (var part; parts.length && (part = parts.shift());) { @@ -104,7 +112,7 @@ return; } - if (internal.global.document === undefined) { + if (config.global.document === undefined) { throw new Error( 'Mojom dependency autoloading is not implemented in workers. ' + 'Please see config variable mojo.config.autoLoadMojomDeps for more ' + @@ -113,8 +121,8 @@ markMojomPendingLoad(id); var url = new URL(relativePath, document.currentScript.src).href; - internal.global.document.write('<script type="text/javascript" src="' + - url + '"><' + '/script>'); + config.global.document.write('<script type="text/javascript" src="' + + url + '"><' + '/script>'); } internal.exposeNamespace = exposeNamespace;
diff --git a/net/BUILD.gn b/net/BUILD.gn index 427496b..4f0dc4f 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -994,6 +994,7 @@ "nqe/event_creator.cc", "nqe/event_creator.h", "nqe/external_estimate_provider.h", + "nqe/network_id.cc", "nqe/network_id.h", "nqe/network_qualities_prefs_manager.cc", "nqe/network_qualities_prefs_manager.h", @@ -1457,6 +1458,7 @@ "quic/quartc/quartc_clock_interface.h", "quic/quartc/quartc_factory.cc", "quic/quartc/quartc_factory.h", + "quic/quartc/quartc_factory_interface.cc", "quic/quartc/quartc_factory_interface.h", "quic/quartc/quartc_packet_writer.cc", "quic/quartc/quartc_packet_writer.h", @@ -1662,8 +1664,6 @@ "url_request/data_protocol_handler.cc", "url_request/data_protocol_handler.h", "url_request/http_user_agent_settings.h", - "url_request/network_error_logging_delegate.cc", - "url_request/network_error_logging_delegate.h", "url_request/redirect_info.cc", "url_request/redirect_info.h", "url_request/redirect_util.cc", @@ -1783,6 +1783,8 @@ "reporting/reporting_service.h", "reporting/reporting_uploader.cc", "reporting/reporting_uploader.h", + "url_request/network_error_logging_delegate.cc", + "url_request/network_error_logging_delegate.h", ] }
diff --git a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java index d03fe396..999f399 100644 --- a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java +++ b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
@@ -40,6 +40,7 @@ import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.net.NetworkChangeNotifierAutoDetect.ConnectivityManagerDelegate; import org.chromium.net.NetworkChangeNotifierAutoDetect.NetworkState; import org.chromium.net.NetworkChangeNotifierAutoDetect.WifiManagerDelegate; @@ -820,10 +821,8 @@ @Test @MediumTest @Feature({"Android-AppBase"}) + @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP) public void testNetworkCallbacks() throws Exception { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - return; - } // Setup NetworkChangeNotifierAutoDetect final TestNetworkChangeNotifierAutoDetectObserver observer = new TestNetworkChangeNotifierAutoDetectObserver(); @@ -960,10 +959,8 @@ @Test @MediumTest @Feature({"Android-AppBase"}) + @MinAndroidSdkLevel(Build.VERSION_CODES.M) public void testIsProcessBoundToNetwork() throws Exception { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - return; - } ConnectivityManager connectivityManager = (ConnectivityManager) InstrumentationRegistry.getTargetContext().getSystemService( Context.CONNECTIVITY_SERVICE);
diff --git a/net/base/layered_network_delegate.cc b/net/base/layered_network_delegate.cc index 82eabd24..2831dca8 100644 --- a/net/base/layered_network_delegate.cc +++ b/net/base/layered_network_delegate.cc
@@ -191,17 +191,16 @@ } bool LayeredNetworkDelegate::OnCanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) { - OnCanSetCookieInternal(request, cookie_line, options); - return nested_network_delegate_->CanSetCookie(request, cookie_line, options); + OnCanSetCookieInternal(request, cookie, options); + return nested_network_delegate_->CanSetCookie(request, cookie, options); } void LayeredNetworkDelegate::OnCanSetCookieInternal( const URLRequest& request, - const std::string& cookie_line, - CookieOptions* options) { -} + const net::CanonicalCookie& cookie, + CookieOptions* options) {} bool LayeredNetworkDelegate::OnCanAccessFile( const URLRequest& request,
diff --git a/net/base/layered_network_delegate.h b/net/base/layered_network_delegate.h index d3d0e03..1c68db8a 100644 --- a/net/base/layered_network_delegate.h +++ b/net/base/layered_network_delegate.h
@@ -75,7 +75,7 @@ bool OnCanGetCookies(const URLRequest& request, const CookieList& cookie_list) final; bool OnCanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) final; bool OnCanAccessFile(const URLRequest& request, const base::FilePath& original_path, @@ -146,7 +146,7 @@ const CookieList& cookie_list); virtual void OnCanSetCookieInternal(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options); virtual void OnAuthRequiredInternal(URLRequest* request,
diff --git a/net/base/layered_network_delegate_unittest.cc b/net/base/layered_network_delegate_unittest.cc index 0ec25af..ebf1b41 100644 --- a/net/base/layered_network_delegate_unittest.cc +++ b/net/base/layered_network_delegate_unittest.cc
@@ -121,7 +121,7 @@ } bool OnCanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) override { IncrementAndCompareCounter("on_can_set_cookie_count"); return false; @@ -204,7 +204,7 @@ NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION, OnAuthRequired(request.get(), *auth_challenge, AuthCallback(), NULL)); EXPECT_FALSE(OnCanGetCookies(*request, CookieList())); - EXPECT_FALSE(OnCanSetCookie(*request, std::string(), NULL)); + EXPECT_FALSE(OnCanSetCookie(*request, net::CanonicalCookie(), NULL)); EXPECT_FALSE(OnCanAccessFile(*request, base::FilePath(), base::FilePath())); EXPECT_FALSE(OnCanEnablePrivacyMode(GURL(), GURL())); EXPECT_FALSE(OnCancelURLRequestWithPolicyViolatingReferrerHeader( @@ -304,7 +304,7 @@ } void OnCanSetCookieInternal(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) override { ++(*counters_)["on_can_set_cookie_count"]; EXPECT_EQ(1, (*counters_)["on_can_set_cookie_count"]);
diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc index 3d4c204..55ad2e6 100644 --- a/net/base/network_delegate.cc +++ b/net/base/network_delegate.cc
@@ -149,11 +149,11 @@ } bool NetworkDelegate::CanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!(request.load_flags() & LOAD_DO_NOT_SAVE_COOKIES)); - return OnCanSetCookie(request, cookie_line, options); + return OnCanSetCookie(request, cookie, options); } bool NetworkDelegate::CanAccessFile(const URLRequest& request,
diff --git a/net/base/network_delegate.h b/net/base/network_delegate.h index d3e7fb5..22c428f9 100644 --- a/net/base/network_delegate.h +++ b/net/base/network_delegate.h
@@ -102,7 +102,7 @@ bool CanGetCookies(const URLRequest& request, const CookieList& cookie_list); bool CanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options); bool CanAccessFile(const URLRequest& request, const base::FilePath& original_path, @@ -276,7 +276,7 @@ // to the cookie. This method will never be invoked when // LOAD_DO_NOT_SAVE_COOKIES is specified. virtual bool OnCanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) = 0; // Called when a file access is attempted to allow the network delegate to
diff --git a/net/base/network_delegate_impl.cc b/net/base/network_delegate_impl.cc index 50ce196..66b1247 100644 --- a/net/base/network_delegate_impl.cc +++ b/net/base/network_delegate_impl.cc
@@ -82,7 +82,7 @@ } bool NetworkDelegateImpl::OnCanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) { return true; }
diff --git a/net/base/network_delegate_impl.h b/net/base/network_delegate_impl.h index a32d25e2..51eef4b 100644 --- a/net/base/network_delegate_impl.h +++ b/net/base/network_delegate_impl.h
@@ -85,7 +85,7 @@ const CookieList& cookie_list) override; bool OnCanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) override; bool OnCanAccessFile(const URLRequest& request,
diff --git a/net/cookies/cookie_store_test_helpers.cc b/net/cookies/cookie_store_test_helpers.cc index cf846b8..e6c44ec9 100644 --- a/net/cookies/cookie_store_test_helpers.cc +++ b/net/cookies/cookie_store_test_helpers.cc
@@ -98,7 +98,17 @@ bool secure_source, bool modify_http_only, SetCookiesCallback callback) { - NOTREACHED(); + did_run_ = false; + cookie_monster_->SetCanonicalCookieAsync( + std::move(cookie), secure_source, modify_http_only, + base::Bind(&DelayedCookieMonster::SetCookiesInternalCallback, + base::Unretained(this))); + DCHECK_EQ(did_run_, true); + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&DelayedCookieMonster::InvokeSetCookiesCallback, + base::Unretained(this), std::move(callback)), + base::TimeDelta::FromMilliseconds(kDelayedTime)); } void DelayedCookieMonster::GetCookiesWithOptionsAsync(
diff --git a/net/disk_cache/simple/simple_backend_impl.cc b/net/disk_cache/simple/simple_backend_impl.cc index c9a0c65c..e08ae98f 100644 --- a/net/disk_cache/simple/simple_backend_impl.cc +++ b/net/disk_cache/simple/simple_backend_impl.cc
@@ -202,8 +202,7 @@ public: ~ActiveEntryProxy() override { if (backend_) { - CHECK(backend_->io_thread_checker_.CalledOnValidThread()); - CHECK_EQ(1U, backend_->active_entries_.count(entry_hash_)); + DCHECK_EQ(1U, backend_->active_entries_.count(entry_hash_)); backend_->active_entries_.erase(entry_hash_); } } @@ -243,8 +242,6 @@ ? SimpleEntryImpl::OPTIMISTIC_OPERATIONS : SimpleEntryImpl::NON_OPTIMISTIC_OPERATIONS), net_log_(net_log) { - io_thread_checker_.DetachFromThread(); - // Treat negative passed-in sizes same as SetMaxSize would here and in other // backends, as default (if first call). if (orig_max_size_ < 0) @@ -292,13 +289,13 @@ } void SimpleBackendImpl::OnDoomStart(uint64_t entry_hash) { - CHECK_EQ(0u, entries_pending_doom_.count(entry_hash)); + DCHECK_EQ(0u, entries_pending_doom_.count(entry_hash)); entries_pending_doom_.insert( std::make_pair(entry_hash, std::vector<Closure>())); } void SimpleBackendImpl::OnDoomComplete(uint64_t entry_hash) { - CHECK_EQ(1u, entries_pending_doom_.count(entry_hash)); + DCHECK_EQ(1u, entries_pending_doom_.count(entry_hash)); std::unordered_map<uint64_t, std::vector<Closure>>::iterator it = entries_pending_doom_.find(entry_hash); std::vector<Closure> to_run_closures; @@ -311,7 +308,6 @@ void SimpleBackendImpl::DoomEntries(std::vector<uint64_t>* entry_hashes, const net::CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); std::unique_ptr<std::vector<uint64_t>> mass_doom_entry_hashes( new std::vector<uint64_t>()); mass_doom_entry_hashes->swap(*entry_hashes); @@ -584,7 +580,6 @@ size_t SimpleBackendImpl::DumpMemoryStats( base::trace_event::ProcessMemoryDump* pmd, const std::string& parent_absolute_name) const { - CHECK(io_thread_checker_.CalledOnValidThread()); base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(parent_absolute_name + "/simple_backend"); @@ -688,7 +683,6 @@ const uint64_t entry_hash, const std::string& key, std::vector<Closure>** post_doom) { - CHECK(io_thread_checker_.CalledOnValidThread()); DCHECK_EQ(entry_hash, simple_util::GetEntryHashKey(key)); // If there is a doom pending, we would want to serialize after it. @@ -715,8 +709,8 @@ // currently active entry. if (key != it->second->key()) { it->second->Doom(); - CHECK_EQ(0U, active_entries_.count(entry_hash)); - CHECK_EQ(1U, entries_pending_doom_.count(entry_hash)); + DCHECK_EQ(0U, active_entries_.count(entry_hash)); + DCHECK_EQ(1U, entries_pending_doom_.count(entry_hash)); // Re-run ourselves to handle the now-pending doom. return CreateOrFindActiveOrDoomedEntry(entry_hash, key, post_doom); } @@ -726,7 +720,6 @@ int SimpleBackendImpl::OpenEntryFromHash(uint64_t entry_hash, Entry** entry, const CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); std::unordered_map<uint64_t, std::vector<Closure>>::iterator it = entries_pending_doom_.find(entry_hash); if (it != entries_pending_doom_.end()) { @@ -754,7 +747,6 @@ int SimpleBackendImpl::DoomEntryFromHash(uint64_t entry_hash, const CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); Entry** entry = new Entry*(); std::unique_ptr<Entry*> scoped_entry(entry); @@ -787,7 +779,6 @@ const scoped_refptr<SimpleEntryImpl>& simple_entry, const CompletionCallback& callback, int error_code) { - CHECK(io_thread_checker_.CalledOnValidThread()); if (error_code != net::OK) { callback.Run(error_code); return;
diff --git a/net/disk_cache/simple/simple_backend_impl.h b/net/disk_cache/simple/simple_backend_impl.h index b54afc1..0da30fb 100644 --- a/net/disk_cache/simple/simple_backend_impl.h +++ b/net/disk_cache/simple/simple_backend_impl.h
@@ -237,7 +237,6 @@ std::unique_ptr<SimpleIndex> index_; const scoped_refptr<base::SequencedTaskRunner> cache_runner_; scoped_refptr<base::TaskRunner> worker_pool_; - base::ThreadCheckerImpl io_thread_checker_; int orig_max_size_; const SimpleEntryImpl::OperationsMode entry_operations_mode_;
diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc index 66e72ef..677932e 100644 --- a/net/disk_cache/simple/simple_entry_impl.cc +++ b/net/disk_cache/simple/simple_entry_impl.cc
@@ -223,14 +223,13 @@ void SimpleEntryImpl::SetActiveEntryProxy( std::unique_ptr<ActiveEntryProxy> active_entry_proxy) { - CHECK(!active_entry_proxy_); - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(!active_entry_proxy_); active_entry_proxy_ = std::move(active_entry_proxy); } int SimpleEntryImpl::OpenEntry(Entry** out_entry, const CompletionCallback& callback) { - CHECK(backend_.get()); + DCHECK(backend_.get()); net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_OPEN_CALL); @@ -268,7 +267,7 @@ int SimpleEntryImpl::CreateEntry(Entry** out_entry, const CompletionCallback& callback) { - CHECK(backend_.get()); + DCHECK(backend_.get()); DCHECK_EQ(entry_hash_, simple_util::GetEntryHashKey(key_)); net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_CREATE_CALL); @@ -369,40 +368,40 @@ } void SimpleEntryImpl::Close() { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK_LT(0, open_count_); net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_CLOSE_CALL); if (--open_count_ > 0) { - CHECK(!HasOneRef()); + DCHECK(!HasOneRef()); Release(); // Balanced in ReturnEntryToCaller(). return; } pending_operations_.push(SimpleEntryOperation::CloseOperation(this)); - CHECK(!HasOneRef()); + DCHECK(!HasOneRef()); Release(); // Balanced in ReturnEntryToCaller(). RunNextOperationIfNeeded(); } std::string SimpleEntryImpl::GetKey() const { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); return key_; } Time SimpleEntryImpl::GetLastUsed() const { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); return last_used_; } Time SimpleEntryImpl::GetLastModified() const { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); return last_modified_; } int32_t SimpleEntryImpl::GetDataSize(int stream_index) const { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK_LE(0, data_size_[stream_index]); return data_size_[stream_index]; } @@ -412,7 +411,7 @@ net::IOBuffer* buf, int buf_len, const CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); if (net_log_.IsCapturing()) { net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_CALL, @@ -454,7 +453,7 @@ int buf_len, const CompletionCallback& callback, bool truncate) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); if (net_log_.IsCapturing()) { net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_WRITE_CALL, @@ -536,7 +535,7 @@ net::IOBuffer* buf, int buf_len, const CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); if (net_log_.IsCapturing()) { net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_SPARSE_CALL, @@ -553,7 +552,7 @@ net::IOBuffer* buf, int buf_len, const CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); if (net_log_.IsCapturing()) { net_log_.AddEvent( @@ -571,7 +570,7 @@ int len, int64_t* start, const CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); ScopedOperationRunner operation_runner(this); pending_operations_.push(SimpleEntryOperation::GetAvailableRangeOperation( @@ -580,20 +579,20 @@ } bool SimpleEntryImpl::CouldBeSparse() const { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); // TODO(juliatuttle): Actually check. return true; } void SimpleEntryImpl::CancelSparseIO() { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); // The Simple Cache does not return distinct objects for the same non-doomed // entry, so there's no need to coordinate which object is performing sparse // I/O. Therefore, CancelSparseIO and ReadyForSparseIO succeed instantly. } int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); // The simple Cache does not return distinct objects for the same non-doomed // entry, so there's no need to coordinate which object is performing sparse // I/O. Therefore, CancelSparseIO and ReadyForSparseIO succeed instantly. @@ -611,7 +610,7 @@ } SimpleEntryImpl::~SimpleEntryImpl() { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK_EQ(0U, pending_operations_.size()); DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_FAILURE); DCHECK(!synchronous_entry_); @@ -657,7 +656,6 @@ } void SimpleEntryImpl::MarkAsDoomed() { - CHECK(io_thread_checker_.CalledOnValidThread()); doomed_ = true; if (!backend_.get()) return; @@ -666,7 +664,7 @@ } void SimpleEntryImpl::RunNextOperationIfNeeded() { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); SIMPLE_CACHE_UMA(CUSTOM_COUNTS, "EntryOperationsPending", cache_type_, pending_operations_.size(), 0, 100, 20); @@ -817,7 +815,7 @@ } void SimpleEntryImpl::CloseInternal() { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); typedef SimpleSynchronousEntry::CRCRecord CRCRecord; std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write( new std::vector<CRCRecord>()); @@ -869,7 +867,7 @@ net::IOBuffer* buf, int buf_len, const CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); ScopedOperationRunner operation_runner(this); if (net_log_.IsCapturing()) { @@ -964,7 +962,7 @@ int buf_len, const CompletionCallback& callback, bool truncate) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); ScopedOperationRunner operation_runner(this); if (net_log_.IsCapturing()) { @@ -1062,7 +1060,7 @@ net::IOBuffer* buf, int buf_len, const CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); ScopedOperationRunner operation_runner(this); if (net_log_.IsCapturing()) { @@ -1108,7 +1106,7 @@ net::IOBuffer* buf, int buf_len, const CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); ScopedOperationRunner operation_runner(this); if (net_log_.IsCapturing()) { @@ -1165,7 +1163,7 @@ int len, int64_t* out_start, const CompletionCallback& callback) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); ScopedOperationRunner operation_runner(this); if (state_ == STATE_FAILURE || state_ == STATE_UNINITIALIZED) { @@ -1230,7 +1228,7 @@ std::unique_ptr<SimpleEntryCreationResults> in_results, Entry** out_entry, net::NetLogEventType end_event_type) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK_EQ(state_, STATE_IO_PENDING); DCHECK(in_results); ScopedOperationRunner operation_runner(this); @@ -1295,7 +1293,7 @@ const CompletionCallback& completion_callback, const SimpleEntryStat& entry_stat, std::unique_ptr<int> result) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK(synchronous_entry_); DCHECK_EQ(STATE_IO_PENDING, state_); DCHECK(result); @@ -1321,7 +1319,7 @@ std::unique_ptr<SimpleSynchronousEntry::CRCRequest> crc_request, std::unique_ptr<SimpleEntryStat> entry_stat, std::unique_ptr<int> result) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK(synchronous_entry_); DCHECK_EQ(STATE_IO_PENDING, state_); DCHECK(result); @@ -1385,7 +1383,7 @@ const CompletionCallback& completion_callback, std::unique_ptr<base::Time> last_used, std::unique_ptr<int> result) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK(synchronous_entry_); DCHECK(result); @@ -1403,7 +1401,7 @@ const CompletionCallback& completion_callback, std::unique_ptr<SimpleEntryStat> entry_stat, std::unique_ptr<int> result) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK(synchronous_entry_); DCHECK(result); @@ -1418,7 +1416,7 @@ void SimpleEntryImpl::GetAvailableRangeOperationComplete( const CompletionCallback& completion_callback, std::unique_ptr<int> result) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK(synchronous_entry_); DCHECK(result); @@ -1442,7 +1440,7 @@ void SimpleEntryImpl::RecordReadResultConsideringChecksum( int result, std::unique_ptr<SimpleSynchronousEntry::CRCRequest> crc_result) const { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK(synchronous_entry_); DCHECK_EQ(STATE_IO_PENDING, state_); @@ -1457,7 +1455,7 @@ } void SimpleEntryImpl::CloseOperationComplete() { - CHECK(!synchronous_entry_); + DCHECK(!synchronous_entry_); DCHECK_EQ(0, open_count_); DCHECK(STATE_IO_PENDING == state_ || STATE_FAILURE == state_ || STATE_UNINITIALIZED == state_); @@ -1469,7 +1467,7 @@ void SimpleEntryImpl::UpdateDataFromEntryStat( const SimpleEntryStat& entry_stat) { - CHECK(io_thread_checker_.CalledOnValidThread()); + DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK(synchronous_entry_); DCHECK_EQ(STATE_READY, state_);
diff --git a/net/disk_cache/simple/simple_entry_impl.h b/net/disk_cache/simple/simple_entry_impl.h index a80f00f..e2fddd5b 100644 --- a/net/disk_cache/simple/simple_entry_impl.h +++ b/net/disk_cache/simple/simple_entry_impl.h
@@ -343,7 +343,7 @@ // All nonstatic SimpleEntryImpl methods should always be called on the IO // thread, in all cases. |io_thread_checker_| documents and enforces this. - base::ThreadCheckerImpl io_thread_checker_; + base::ThreadChecker io_thread_checker_; const base::WeakPtr<SimpleBackendImpl> backend_; SimpleFileTracker* const file_tracker_;
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc index d7e8ab6..0d963a8f 100644 --- a/net/dns/host_resolver_impl.cc +++ b/net/dns/host_resolver_impl.cc
@@ -1640,11 +1640,15 @@ } void RecordJobHistograms(int error) { - enum Category { // Used in UMA_HISTOGRAM_ENUMERATION. - RESOLVE_SUCCESS, - RESOLVE_FAIL, - RESOLVE_SPECULATIVE_SUCCESS, - RESOLVE_SPECULATIVE_FAIL, + // Used in UMA_HISTOGRAM_ENUMERATION. Do not renumber entries or reuse + // deprecated values. + enum Category { + RESOLVE_SUCCESS = 0, + RESOLVE_FAIL = 1, + RESOLVE_SPECULATIVE_SUCCESS = 2, + RESOLVE_SPECULATIVE_FAIL = 3, + RESOLVE_ABORT = 4, + RESOLVE_SPECULATIVE_ABORT = 5, RESOLVE_MAX, // Bounding value. }; Category category = RESOLVE_MAX; // Illegal value for later DCHECK only. @@ -1673,21 +1677,25 @@ UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.Speculative", duration); } + } else if (error == ERR_NETWORK_CHANGED || + error == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE) { + category = had_non_speculative_request_ ? RESOLVE_ABORT + : RESOLVE_SPECULATIVE_ABORT; } else { if (had_non_speculative_request_) { category = RESOLVE_FAIL; UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime", duration); switch (key_.address_family) { case ADDRESS_FAMILY_IPV4: - UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV4", + UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.IPV4", duration); break; case ADDRESS_FAMILY_IPV6: - UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV6", + UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.IPV6", duration); break; case ADDRESS_FAMILY_UNSPECIFIED: - UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.UNSPEC", + UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.UNSPEC", duration); break; } @@ -1753,10 +1761,10 @@ bool did_complete = (entry.error() != ERR_NETWORK_CHANGED) && (entry.error() != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); - if (did_complete) { + if (did_complete) resolver_->CacheResult(key_, entry, ttl); - RecordJobHistograms(entry.error()); - } + + RecordJobHistograms(entry.error()); // Complete all of the requests that were attached to the job and // detach them.
diff --git a/net/http/OWNERS b/net/http/OWNERS index 60482fc1..b1590166 100644 --- a/net/http/OWNERS +++ b/net/http/OWNERS
@@ -1,2 +1,2 @@ -per-file transport_security_state_static.*=lgarron@chromium.org +per-file transport_security_state_static.*=elawrence@chromium.org per-file transport_security_state_static.*=palmer@chromium.org \ No newline at end of file
diff --git a/net/http/http_auth_unittest.cc b/net/http/http_auth_unittest.cc index b6a24af..04d415b9 100644 --- a/net/http/http_auth_unittest.cc +++ b/net/http/http_auth_unittest.cc
@@ -29,8 +29,9 @@ namespace { -HttpAuthHandlerMock* CreateMockHandler(bool connection_based) { - HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock(); +std::unique_ptr<HttpAuthHandlerMock> CreateMockHandler(bool connection_based) { + std::unique_ptr<HttpAuthHandlerMock> auth_handler = + std::make_unique<HttpAuthHandlerMock>(); auth_handler->set_connection_based(connection_based); std::string challenge_text = "Basic"; HttpAuthChallengeTokenizer challenge(challenge_text.begin(), @@ -43,20 +44,21 @@ return auth_handler; } -HttpResponseHeaders* HeadersFromResponseText(const std::string& response) { - return new HttpResponseHeaders( - HttpUtil::AssembleRawHeaders(response.c_str(), response.length())); +scoped_refptr<HttpResponseHeaders> HeadersFromResponseText( + const std::string& response) { + return scoped_refptr<HttpResponseHeaders>(new HttpResponseHeaders( + HttpUtil::AssembleRawHeaders(response.c_str(), response.length()))); } HttpAuth::AuthorizationResult HandleChallengeResponse( bool connection_based, const std::string& headers_text, std::string* challenge_used) { - std::unique_ptr<HttpAuthHandlerMock> mock_handler( - CreateMockHandler(connection_based)); + std::unique_ptr<HttpAuthHandlerMock> mock_handler = + CreateMockHandler(connection_based); std::set<HttpAuth::Scheme> disabled_schemes; - scoped_refptr<HttpResponseHeaders> headers( - HeadersFromResponseText(headers_text)); + scoped_refptr<HttpResponseHeaders> headers = + HeadersFromResponseText(headers_text); return HttpAuth::HandleChallengeResponse(mock_handler.get(), *headers, HttpAuth::AUTH_SERVER, disabled_schemes, challenge_used); @@ -133,8 +135,8 @@ // Make a HttpResponseHeaders object. std::string headers_with_status_line("HTTP/1.1 401 Unauthorized\n"); headers_with_status_line += tests[i].headers; - scoped_refptr<HttpResponseHeaders> headers( - HeadersFromResponseText(headers_with_status_line)); + scoped_refptr<HttpResponseHeaders> headers = + HeadersFromResponseText(headers_with_status_line); SSLInfo null_ssl_info; std::unique_ptr<HttpAuthHandler> handler;
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 6799c5fa..93eaf23 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -5,7 +5,7 @@ #include "net/http/http_network_session.h" #include <inttypes.h> - +#include <memory> #include <utility> #include "base/atomic_sequence_num.h" @@ -45,13 +45,13 @@ base::AtomicSequenceNumber g_next_shard_id; -ClientSocketPoolManager* CreateSocketPoolManager( +std::unique_ptr<ClientSocketPoolManager> CreateSocketPoolManager( HttpNetworkSession::SocketPoolType pool_type, const HttpNetworkSession::Context& context, const std::string& ssl_session_cache_shard) { // TODO(yutak): Differentiate WebSocket pool manager and allow more // simultaneous connections for WebSockets. - return new ClientSocketPoolManagerImpl( + return std::make_unique<ClientSocketPoolManagerImpl>( context.net_log, context.client_socket_factory ? context.client_socket_factory : ClientSocketFactory::GetDefaultFactory(), @@ -229,10 +229,10 @@ const std::string ssl_session_cache_shard = "http_network_session/" + base::IntToString(g_next_shard_id.GetNext()); - normal_socket_pool_manager_.reset(CreateSocketPoolManager( - NORMAL_SOCKET_POOL, context, ssl_session_cache_shard)); - websocket_socket_pool_manager_.reset(CreateSocketPoolManager( - WEBSOCKET_SOCKET_POOL, context, ssl_session_cache_shard)); + normal_socket_pool_manager_ = CreateSocketPoolManager( + NORMAL_SOCKET_POOL, context, ssl_session_cache_shard); + websocket_socket_pool_manager_ = CreateSocketPoolManager( + WEBSOCKET_SOCKET_POOL, context, ssl_session_cache_shard); if (params_.enable_http2) { next_protos_.push_back(kProtoHTTP2);
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 7dd5171..594259f 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -16,6 +16,7 @@ #include <vector> #include "base/bind.h" +#include "base/containers/flat_set.h" #include "base/memory/memory_coordinator_client.h" #include "base/memory/memory_pressure_monitor.h" #include "base/memory/ref_counted.h" @@ -180,6 +181,8 @@ bool quic_race_cert_verification; // If true, estimate the initial RTT for QUIC connections based on network. bool quic_estimate_initial_rtt; + // If non-empty, QUIC will only be spoken to hosts in this list. + base::flat_set<std::string> quic_host_whitelist; // Enable support for Token Binding. bool enable_token_binding;
diff --git a/net/http/http_network_session_peer.cc b/net/http/http_network_session_peer.cc index c10795a5..4a42dc2 100644 --- a/net/http/http_network_session_peer.cc +++ b/net/http/http_network_session_peer.cc
@@ -5,7 +5,6 @@ #include "net/http/http_network_session_peer.h" #include "net/base/network_throttle_manager.h" -#include "net/http/http_network_session.h" #include "net/http/http_proxy_client_socket_pool.h" #include "net/proxy/proxy_service.h" #include "net/socket/client_socket_pool_manager.h" @@ -40,4 +39,8 @@ session_->network_stream_throttler_.swap(network_throttle_manager); } +HttpNetworkSession::Params* HttpNetworkSessionPeer::params() { + return &(session_->params_); +} + } // namespace net
diff --git a/net/http/http_network_session_peer.h b/net/http/http_network_session_peer.h index b07d130d..dae4f916 100644 --- a/net/http/http_network_session_peer.h +++ b/net/http/http_network_session_peer.h
@@ -10,11 +10,11 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "net/base/net_export.h" +#include "net/http/http_network_session.h" namespace net { class ClientSocketPoolManager; -class HttpNetworkSession; class HttpStreamFactory; class NetworkThrottleManager; @@ -35,6 +35,8 @@ void SetNetworkStreamThrottler( std::unique_ptr<NetworkThrottleManager> network_throttle_manager); + HttpNetworkSession::Params* params(); + private: HttpNetworkSession* const session_;
diff --git a/net/http/http_stream_factory_impl_job_controller.cc b/net/http/http_stream_factory_impl_job_controller.cc index fd6d73f..bfc0966 100644 --- a/net/http/http_stream_factory_impl_job_controller.cc +++ b/net/http/http_stream_factory_impl_job_controller.cc
@@ -1159,6 +1159,9 @@ destination)) return alternative_service_info; + if (!IsQuicWhitelistedForHost(destination.host())) + continue; + // Cache this entry if we don't have a non-broken Alt-Svc yet. if (first_alternative_service_info.protocol() == kProtoUnknown) first_alternative_service_info = alternative_service_info; @@ -1322,4 +1325,15 @@ return rv; } +bool HttpStreamFactoryImpl::JobController::IsQuicWhitelistedForHost( + const std::string& host) { + const base::flat_set<std::string>& host_whitelist = + session_->params().quic_host_whitelist; + if (host_whitelist.empty()) + return true; + + std::string lowered_host = base::ToLowerASCII(host); + return base::ContainsKey(host_whitelist, lowered_host); +} + } // namespace net
diff --git a/net/http/http_stream_factory_impl_job_controller.h b/net/http/http_stream_factory_impl_job_controller.h index 24a4da31..f64cfbcb 100644 --- a/net/http/http_stream_factory_impl_job_controller.h +++ b/net/http/http_stream_factory_impl_job_controller.h
@@ -312,6 +312,9 @@ // given error code is simply returned. int ReconsiderProxyAfterError(Job* job, int error); + // Returns true if QUIC is whitelisted for |host|. + bool IsQuicWhitelistedForHost(const std::string& host); + HttpStreamFactoryImpl* factory_; HttpNetworkSession* session_; JobFactory* job_factory_;
diff --git a/net/http/http_stream_factory_impl_job_controller_unittest.cc b/net/http/http_stream_factory_impl_job_controller_unittest.cc index 5ffa7a9..99cf4e6d 100644 --- a/net/http/http_stream_factory_impl_job_controller_unittest.cc +++ b/net/http/http_stream_factory_impl_job_controller_unittest.cc
@@ -18,6 +18,7 @@ #include "net/base/test_proxy_delegate.h" #include "net/dns/mock_host_resolver.h" #include "net/http/http_basic_stream.h" +#include "net/http/http_network_session_peer.h" #include "net/http/http_stream_factory_impl.h" #include "net/http/http_stream_factory_impl_job.h" #include "net/http/http_stream_factory_impl_request.h" @@ -2281,6 +2282,50 @@ EXPECT_EQ(0u, alt_svc_info.advertised_versions().size()); } +// Tests that if HttpNetworkSession has a non-empty QUIC host whitelist, +// then GetAlternativeServiceFor() will not return any QUIC alternative service +// that's not on the whitelist. +TEST_F(HttpStreamFactoryImplJobControllerTest, QuicHostWhitelist) { + HttpRequestInfo request_info; + request_info.method = "GET"; + request_info.url = GURL("https://www.google.com"); + + Initialize(request_info); + + // Set HttpNetworkSession's QUIC host whitelist to only have www.example.com + HttpNetworkSessionPeer session_peer(session_.get()); + session_peer.params()->quic_host_whitelist.insert("www.example.com"); + + // Set alternative service for www.google.com to be www.example.com over QUIC. + url::SchemeHostPort server(request_info.url); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); + QuicTransportVersionVector supported_versions = + session_->params().quic_supported_versions; + session_->http_server_properties()->SetQuicAlternativeService( + server, AlternativeService(kProtoQUIC, "www.example.com", 443), + expiration, supported_versions); + + AlternativeServiceInfo alt_svc_info = + JobControllerPeer::GetAlternativeServiceInfoFor( + job_controller_, request_info, &request_delegate_, + HttpStreamRequest::HTTP_STREAM); + + std::sort(supported_versions.begin(), supported_versions.end()); + EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol); + EXPECT_EQ(supported_versions, alt_svc_info.advertised_versions()); + + session_->http_server_properties()->SetQuicAlternativeService( + server, AlternativeService(kProtoQUIC, "www.example.org", 443), + expiration, supported_versions); + + alt_svc_info = JobControllerPeer::GetAlternativeServiceInfoFor( + job_controller_, request_info, &request_delegate_, + HttpStreamRequest::HTTP_STREAM); + + EXPECT_EQ(kProtoUnknown, alt_svc_info.alternative_service().protocol); + EXPECT_EQ(0u, alt_svc_info.advertised_versions().size()); +} + } // namespace test } // namespace net
diff --git a/net/http/url_security_manager.h b/net/http/url_security_manager.h index 218cccb..35bdd87 100644 --- a/net/http/url_security_manager.h +++ b/net/http/url_security_manager.h
@@ -41,7 +41,7 @@ // If the delegate whitelist is NULL no servers can have delegated Kerberos // tickets. // - static URLSecurityManager* Create(); + static std::unique_ptr<URLSecurityManager> Create(); // Returns true if we can send the default credentials to the server at // |auth_origin| for HTTP NTLM or Negotiate authentication.
diff --git a/net/http/url_security_manager_posix.cc b/net/http/url_security_manager_posix.cc index b3e8cd3..a0bc27d 100644 --- a/net/http/url_security_manager_posix.cc +++ b/net/http/url_security_manager_posix.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> + #include "net/http/url_security_manager.h" #include "net/http/http_auth_filter.h" @@ -9,8 +11,8 @@ namespace net { // static -URLSecurityManager* URLSecurityManager::Create() { - return new URLSecurityManagerWhitelist; +std::unique_ptr<URLSecurityManager> URLSecurityManager::Create() { + return std::make_unique<URLSecurityManagerWhitelist>(); } } // namespace net
diff --git a/net/http/url_security_manager_win.cc b/net/http/url_security_manager_win.cc index b9082f2..cafdba41 100644 --- a/net/http/url_security_manager_win.cc +++ b/net/http/url_security_manager_win.cc
@@ -115,8 +115,8 @@ } // static -URLSecurityManager* URLSecurityManager::Create() { - return new URLSecurityManagerWin; +std::unique_ptr<URLSecurityManager> URLSecurityManager::Create() { + return std::make_unique<URLSecurityManagerWin>(); } } // namespace net
diff --git a/net/nqe/network_id.cc b/net/nqe/network_id.cc new file mode 100644 index 0000000..32425b8 --- /dev/null +++ b/net/nqe/network_id.cc
@@ -0,0 +1,87 @@ +// 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 "net/nqe/network_id.h" + +#include <tuple> + +#include "base/strings/string_number_conversions.h" + +namespace { + +const char kValueSeparator = ','; + +// Parses |connection_type_string| as a NetworkChangeNotifier::ConnectionType. +// |connection_type_string| must contain the +// NetworkChangeNotifier::ConnectionType enum as an integer. +net::NetworkChangeNotifier::ConnectionType ConvertStringToConnectionType( + const std::string& connection_type_string) { + int connection_type_int = + static_cast<int>(net::NetworkChangeNotifier::CONNECTION_UNKNOWN); + bool connection_type_available = + base::StringToInt(connection_type_string, &connection_type_int); + + if (!connection_type_available || connection_type_int < 0 || + connection_type_int > + static_cast<int>(net::NetworkChangeNotifier::CONNECTION_LAST)) { + DCHECK(false); + return net::NetworkChangeNotifier::CONNECTION_UNKNOWN; + } + return static_cast<net::NetworkChangeNotifier::ConnectionType>( + connection_type_int); +} + +} // namespace + +namespace net { +namespace nqe { +namespace internal { + +// static +NetworkID NetworkID::FromString(const std::string& network_id) { + size_t separator_index = network_id.find(kValueSeparator); + DCHECK_NE(std::string::npos, separator_index); + if (separator_index == std::string::npos) { + return NetworkID(NetworkChangeNotifier::CONNECTION_UNKNOWN, std::string()); + } + + return NetworkID( + ConvertStringToConnectionType(network_id.substr(separator_index + 1)), + network_id.substr(0, separator_index)); +} + +NetworkID::NetworkID(NetworkChangeNotifier::ConnectionType type, + const std::string& id) + : type(type), id(id) {} + +NetworkID::NetworkID(const NetworkID& other) : type(other.type), id(other.id) {} + +NetworkID::~NetworkID() {} + +bool NetworkID::operator==(const NetworkID& other) const { + return type == other.type && id == other.id; +} + +bool NetworkID::operator!=(const NetworkID& other) const { + return !operator==(other); +} + +NetworkID& NetworkID::operator=(const NetworkID& other) { + type = other.type; + id = other.id; + return *this; +} + +// Overloaded to support ordered collections. +bool NetworkID::operator<(const NetworkID& other) const { + return std::tie(type, id) < std::tie(other.type, other.id); +} + +std::string NetworkID::ToString() const { + return id + kValueSeparator + base::IntToString(static_cast<int>(type)); +} + +} // namespace internal +} // namespace nqe +} // namespace net
diff --git a/net/nqe/network_id.h b/net/nqe/network_id.h index 78b4588..65f52d1 100644 --- a/net/nqe/network_id.h +++ b/net/nqe/network_id.h
@@ -6,38 +6,10 @@ #define NET_NQE_NETWORK_ID_H_ #include <string> -#include <tuple> -#include "base/strings/string_number_conversions.h" #include "net/base/net_export.h" #include "net/base/network_change_notifier.h" -namespace { - -const char kValueSeparator[] = ","; - -// Parses |connection_type_string| as a NetworkChangeNotifier::ConnectionType. -// |connection_type_string| must contain the -// NetworkChangeNotifier::ConnectionType enum as an interger. -net::NetworkChangeNotifier::ConnectionType ConvertStringToConnectionType( - const std::string& connection_type_string) { - int connection_type_int = - static_cast<int>(net::NetworkChangeNotifier::CONNECTION_UNKNOWN); - bool connection_type_available = - base::StringToInt(connection_type_string, &connection_type_int); - - if (!connection_type_available || connection_type_int < 0 || - connection_type_int > - static_cast<int>(net::NetworkChangeNotifier::CONNECTION_LAST)) { - DCHECK(false); - return net::NetworkChangeNotifier::CONNECTION_UNKNOWN; - } - return static_cast<net::NetworkChangeNotifier::ConnectionType>( - connection_type_int); -} - -} // namespace - namespace net { namespace nqe { namespace internal { @@ -49,43 +21,22 @@ // same name (e.g., different Wi-Fi networks with same SSID). // This is a protected member to expose it to tests. struct NET_EXPORT_PRIVATE NetworkID { - static NetworkID FromString(const std::string& network_id) { - size_t separator_index = network_id.find(kValueSeparator); - DCHECK_NE(std::string::npos, separator_index); - if (separator_index == std::string::npos) { - return NetworkID(NetworkChangeNotifier::CONNECTION_UNKNOWN, - std::string()); - } + static NetworkID FromString(const std::string& network_id); - return NetworkID( - ConvertStringToConnectionType(network_id.substr(separator_index + 1)), - network_id.substr(0, separator_index)); - } - NetworkID(NetworkChangeNotifier::ConnectionType type, const std::string& id) - : type(type), id(id) {} - NetworkID(const NetworkID& other) : type(other.type), id(other.id) {} - ~NetworkID() {} + NetworkID(NetworkChangeNotifier::ConnectionType type, const std::string& id); + NetworkID(const NetworkID& other); + ~NetworkID(); - bool operator==(const NetworkID& other) const { - return type == other.type && id == other.id; - } + bool operator==(const NetworkID& other) const; - bool operator!=(const NetworkID& other) const { return !operator==(other); } + bool operator!=(const NetworkID& other) const; - NetworkID& operator=(const NetworkID& other) { - type = other.type; - id = other.id; - return *this; - } + NetworkID& operator=(const NetworkID& other); // Overloaded to support ordered collections. - bool operator<(const NetworkID& other) const { - return std::tie(type, id) < std::tie(other.type, other.id); - } + bool operator<(const NetworkID& other) const; - std::string ToString() const { - return id + kValueSeparator + base::IntToString(static_cast<int>(type)); - } + std::string ToString() const; // Connection type of the network. NetworkChangeNotifier::ConnectionType type;
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc index d7d4538b..11e4488b 100644 --- a/net/nqe/network_quality_estimator.cc +++ b/net/nqe/network_quality_estimator.cc
@@ -278,6 +278,8 @@ params_->min_socket_watcher_notification_interval(), base::Bind(&NetworkQualityEstimator::OnUpdatedTransportRTTAvailable, base::Unretained(this)), + base::Bind(&NetworkQualityEstimator::ShouldSocketWatcherNotifyRTT, + base::Unretained(this)), tick_clock_.get())); // Record accuracy after a 15 second interval. The values used here must @@ -795,6 +797,7 @@ new_rtt_observations_since_last_ect_computation_ = 0; new_throughput_observations_since_last_ect_computation_ = 0; transport_rtt_observation_count_last_ect_computation_ = 0; + last_socket_watcher_rtt_notification_ = base::TimeTicks(); estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality(); cached_estimate_applied_ = false; @@ -1657,6 +1660,7 @@ http_downstream_throughput_kbps_observations_.SetTickClockForTesting( tick_clock_.get()); throughput_analyzer_->SetTickClockForTesting(tick_clock_.get()); + watcher_factory_->SetTickClockForTesting(tick_clock_.get()); } double NetworkQualityEstimator::RandDouble() const { @@ -1705,6 +1709,11 @@ break; } + if (observation.source() == NETWORK_QUALITY_OBSERVATION_SOURCE_TCP || + observation.source() == NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC) { + last_socket_watcher_rtt_notification_ = tick_clock_->NowTicks(); + } + UMA_HISTOGRAM_ENUMERATION("NQE.RTT.ObservationSource", observation.source(), NETWORK_QUALITY_OBSERVATION_SOURCE_MAX); @@ -2029,4 +2038,11 @@ return true; } +bool NetworkQualityEstimator::ShouldSocketWatcherNotifyRTT( + base::TimeTicks now) { + DCHECK(thread_checker_.CalledOnValidThread()); + return (now - last_socket_watcher_rtt_notification_ >= + params_->socket_watchers_min_notification_interval()); +} + } // namespace net
diff --git a/net/nqe/network_quality_estimator.h b/net/nqe/network_quality_estimator.h index 8ac730f..aa311ae0 100644 --- a/net/nqe/network_quality_estimator.h +++ b/net/nqe/network_quality_estimator.h
@@ -551,6 +551,10 @@ // Returns true if |observation| should be added to the observation buffer. bool ShouldAddObservation(const Observation& observation) const; + // Returns true if the socket watcher can run the callback to notify the RTT + // observations. + bool ShouldSocketWatcherNotifyRTT(base::TimeTicks now); + // Determines if the requests to local host can be used in estimating the // network quality. Set to true only for tests. bool use_localhost_requests_; @@ -678,6 +682,9 @@ // Manages the writing of events to the net log. nqe::internal::EventCreator event_creator_; + // Time when the last RTT observation from a socket watcher was received. + base::TimeTicks last_socket_watcher_rtt_notification_; + base::WeakPtrFactory<NetworkQualityEstimator> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(NetworkQualityEstimator);
diff --git a/net/nqe/network_quality_estimator_params.cc b/net/nqe/network_quality_estimator_params.cc index aee09cd4..c63fd8f 100644 --- a/net/nqe/network_quality_estimator_params.cc +++ b/net/nqe/network_quality_estimator_params.cc
@@ -437,6 +437,11 @@ params_, "add_default_platform_observations", "true") == "true"), + socket_watchers_min_notification_interval_( + base::TimeDelta::FromMilliseconds(GetValueForVariationParam( + params_, + "socket_watchers_min_notification_interval_msec", + 200))), use_small_responses_(false) { DCHECK_LE(0.0, correlation_uma_logging_probability_); DCHECK_GE(1.0, correlation_uma_logging_probability_);
diff --git a/net/nqe/network_quality_estimator_params.h b/net/nqe/network_quality_estimator_params.h index e7e79703..3a1b079 100644 --- a/net/nqe/network_quality_estimator_params.h +++ b/net/nqe/network_quality_estimator_params.h
@@ -223,6 +223,12 @@ // ObservationBuffer. size_t observation_buffer_size() const { return 300; } + // Minimun interval between consecutive notifications from socket + // watchers who live on the same thread as the network quality estimator. + base::TimeDelta socket_watchers_min_notification_interval() const { + return socket_watchers_min_notification_interval_; + } + private: // Map containing all field trial parameters related to // NetworkQualityEstimator field trial. @@ -245,6 +251,7 @@ const int hanging_request_duration_http_rtt_multiplier_; const base::TimeDelta hanging_request_min_duration_; const bool add_default_platform_observations_; + const base::TimeDelta socket_watchers_min_notification_interval_; bool use_small_responses_;
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc index 1c7fbc66..3be486e 100644 --- a/net/nqe/network_quality_estimator_unittest.cc +++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -2243,6 +2243,66 @@ estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt, nullptr)); } +TEST(NetworkQualityEstimatorTest, TestGlobalSocketWatcherThrottle) { + std::unique_ptr<base::SimpleTestTickClock> tick_clock( + new base::SimpleTestTickClock()); + base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get(); + tick_clock_ptr->Advance(base::TimeDelta::FromSeconds(1)); + + std::map<std::string, std::string> variation_params; + variation_params["add_default_platform_observations"] = "false"; + TestNetworkQualityEstimator estimator(variation_params); + estimator.SetTickClockForTesting(std::move(tick_clock)); + + TestRTTObserver rtt_observer; + estimator.AddRTTObserver(&rtt_observer); + + const base::TimeDelta tcp_rtt(base::TimeDelta::FromMilliseconds(1)); + + TestDelegate test_delegate; + TestURLRequestContext context(true); + context.set_network_quality_estimator(&estimator); + context.Init(); + + // Use a public IP address so that the socket watcher runs the RTT callback. + IPAddressList ip_list; + IPAddress ip_address; + ASSERT_TRUE(ip_address.AssignFromIPLiteral("157.0.0.1")); + ip_list.push_back(ip_address); + AddressList address_list = + AddressList::CreateFromIPAddressList(ip_list, "canonical.example.com"); + std::unique_ptr<SocketPerformanceWatcher> tcp_watcher = + estimator.GetSocketPerformanceWatcherFactory() + ->CreateSocketPerformanceWatcher( + SocketPerformanceWatcherFactory::PROTOCOL_TCP, address_list); + + EXPECT_EQ(0U, rtt_observer.observations().size()); + EXPECT_TRUE(tcp_watcher->ShouldNotifyUpdatedRTT()); + std::unique_ptr<URLRequest> request( + context.CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY, + &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS)); + request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED); + request->Start(); + base::RunLoop().Run(); + EXPECT_EQ(1U, rtt_observer.observations().size()); + EXPECT_TRUE(tcp_watcher->ShouldNotifyUpdatedRTT()); + + tcp_watcher->OnUpdatedRTTAvailable(tcp_rtt); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(tcp_watcher->ShouldNotifyUpdatedRTT()); + EXPECT_EQ(2U, rtt_observer.observations().size()); + // Advancing the clock should make it possible to notify new RTT + // notifications. + tick_clock_ptr->Advance( + estimator.params()->socket_watchers_min_notification_interval()); + EXPECT_TRUE(tcp_watcher->ShouldNotifyUpdatedRTT()); + + EXPECT_EQ(tcp_rtt.InMilliseconds(), rtt_observer.observations().at(1).rtt_ms); + base::TimeDelta rtt; + EXPECT_TRUE( + estimator.GetRecentTransportRTT(base::TimeTicks(), &rtt, nullptr)); +} + // TestTCPSocketRTT requires kernel support for tcp_info struct, and so it is // enabled only on certain platforms. #if defined(TCP_INFO) || defined(OS_LINUX) @@ -2253,6 +2313,11 @@ // Tests that the TCP socket notifies the Network Quality Estimator of TCP RTTs, // which in turn notifies registered RTT observers. TEST(NetworkQualityEstimatorTest, MAYBE_TestTCPSocketRTT) { + std::unique_ptr<base::SimpleTestTickClock> tick_clock( + new base::SimpleTestTickClock()); + base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get(); + tick_clock_ptr->Advance(base::TimeDelta::FromSeconds(1)); + base::HistogramTester histogram_tester; TestRTTObserver rtt_observer; @@ -2262,6 +2327,7 @@ TestNetworkQualityEstimator estimator( nullptr, variation_params, true, true, std::make_unique<BoundTestNetLog>()); + estimator.SetTickClockForTesting(std::move(tick_clock)); estimator.SimulateNetworkChange( NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test"); @@ -2305,6 +2371,9 @@ &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS)); request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED); request->Start(); + tick_clock_ptr->Advance( + estimator.params()->socket_watchers_min_notification_interval()); + base::RunLoop().Run(); size_t after_count_tcp_rtt_observations = 0;
diff --git a/net/nqe/socket_watcher.cc b/net/nqe/socket_watcher.cc index f07afad..98639b7 100644 --- a/net/nqe/socket_watcher.cc +++ b/net/nqe/socket_watcher.cc
@@ -60,10 +60,12 @@ bool allow_rtt_private_address, scoped_refptr<base::SingleThreadTaskRunner> task_runner, OnUpdatedRTTAvailableCallback updated_rtt_observation_callback, + ShouldNotifyRTTCallback should_notify_rtt_callback, base::TickClock* tick_clock) : protocol_(protocol), task_runner_(std::move(task_runner)), updated_rtt_observation_callback_(updated_rtt_observation_callback), + should_notify_rtt_callback_(should_notify_rtt_callback), rtt_notifications_minimum_interval_(min_notification_interval), run_rtt_callback_(allow_rtt_private_address || (!address_list.empty() && @@ -80,12 +82,25 @@ bool SocketWatcher::ShouldNotifyUpdatedRTT() const { DCHECK(thread_checker_.CalledOnValidThread()); + if (!run_rtt_callback_) + return false; + + const base::TimeTicks now = tick_clock_->NowTicks(); + + if (task_runner_->RunsTasksInCurrentSequence()) { + // Enables socket watcher to send more frequent RTT observations when very + // few sockets are receiving data. + if (should_notify_rtt_callback_.Run(now)) + return true; + } + // Do not allow incoming notifications if the last notification was more // recent than |rtt_notifications_minimum_interval_| ago. This helps in // reducing the overhead of obtaining the RTT values. - return run_rtt_callback_ && - tick_clock_->NowTicks() - last_rtt_notification_ >= - rtt_notifications_minimum_interval_; + // Enables a socket watcher to send RTT observation, helps in reducing + // starvation by allowing every socket watcher to notify at least one RTT + // notification every |rtt_notifications_minimum_interval_| duration. + return now - last_rtt_notification_ >= rtt_notifications_minimum_interval_; } void SocketWatcher::OnUpdatedRTTAvailable(const base::TimeDelta& rtt) {
diff --git a/net/nqe/socket_watcher.h b/net/nqe/socket_watcher.h index 35d0302..52b1d73a 100644 --- a/net/nqe/socket_watcher.h +++ b/net/nqe/socket_watcher.h
@@ -35,6 +35,8 @@ const base::Optional<nqe::internal::IPHash>& host)> OnUpdatedRTTAvailableCallback; +typedef base::Callback<bool(base::TimeTicks)> ShouldNotifyRTTCallback; + } // namespace namespace nqe { @@ -53,12 +55,16 @@ // |allow_rtt_private_address| is true if |updated_rtt_observation_callback| // should be called when RTT observation from a socket connected to private // address is received. |tick_clock| is guaranteed to be non-null. + // |should_notify_rtt_callback| callback should be called back on + // |task_runner| by the created socket watchers to check if RTT observation + // should be taken and notified. SocketWatcher(SocketPerformanceWatcherFactory::Protocol protocol, const AddressList& address_list, base::TimeDelta min_notification_interval, bool allow_rtt_private_address, scoped_refptr<base::SingleThreadTaskRunner> task_runner, OnUpdatedRTTAvailableCallback updated_rtt_observation_callback, + ShouldNotifyRTTCallback should_notify_rtt_callback, base::TickClock* tick_clock); ~SocketWatcher() override; @@ -77,6 +83,10 @@ // Called every time a new RTT observation is available. OnUpdatedRTTAvailableCallback updated_rtt_observation_callback_; + // Called to determine if the RTT notification should be notified using + // |updated_rtt_observation_callback_|. + ShouldNotifyRTTCallback should_notify_rtt_callback_; + // Minimum interval betweeen consecutive incoming notifications. const base::TimeDelta rtt_notifications_minimum_interval_;
diff --git a/net/nqe/socket_watcher_factory.cc b/net/nqe/socket_watcher_factory.cc index 94aeadc..fb8a596 100644 --- a/net/nqe/socket_watcher_factory.cc +++ b/net/nqe/socket_watcher_factory.cc
@@ -17,11 +17,13 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner, base::TimeDelta min_notification_interval, OnUpdatedRTTAvailableCallback updated_rtt_observation_callback, + ShouldNotifyRTTCallback should_notify_rtt_callback, base::TickClock* tick_clock) : task_runner_(std::move(task_runner)), min_notification_interval_(min_notification_interval), allow_rtt_private_address_(false), updated_rtt_observation_callback_(updated_rtt_observation_callback), + should_notify_rtt_callback_(should_notify_rtt_callback), tick_clock_(tick_clock) { DCHECK(tick_clock_); } @@ -35,7 +37,12 @@ return std::make_unique<SocketWatcher>( protocol, address_list, min_notification_interval_, allow_rtt_private_address_, task_runner_, - updated_rtt_observation_callback_, tick_clock_); + updated_rtt_observation_callback_, should_notify_rtt_callback_, + tick_clock_); +} + +void SocketWatcherFactory::SetTickClockForTesting(base::TickClock* tick_clock) { + tick_clock_ = tick_clock; } } // namespace internal
diff --git a/net/nqe/socket_watcher_factory.h b/net/nqe/socket_watcher_factory.h index 3bb9969..7634d6f 100644 --- a/net/nqe/socket_watcher_factory.h +++ b/net/nqe/socket_watcher_factory.h
@@ -26,11 +26,15 @@ namespace net { namespace { + typedef base::Callback<void(SocketPerformanceWatcherFactory::Protocol protocol, const base::TimeDelta& rtt, const base::Optional<nqe::internal::IPHash>& host)> OnUpdatedRTTAvailableCallback; -} + +typedef base::Callback<bool(base::TimeTicks)> ShouldNotifyRTTCallback; + +} // namespace namespace nqe { @@ -45,11 +49,14 @@ // |task_runner| every time a new RTT observation is available. // |min_notification_interval| is the minimum interval betweeen consecutive // notifications to the socket watchers created by this factory. |tick_clock| - // is guaranteed to be non-null. + // is guaranteed to be non-null. |should_notify_rtt_callback| is the callback + // that should be called back on |task_runner| to check if RTT observation + // should be taken and notified. SocketWatcherFactory( scoped_refptr<base::SingleThreadTaskRunner> task_runner, base::TimeDelta min_notification_interval, OnUpdatedRTTAvailableCallback updated_rtt_observation_callback, + ShouldNotifyRTTCallback should_notify_rtt_callback, base::TickClock* tick_clock); ~SocketWatcherFactory() override; @@ -63,6 +70,9 @@ allow_rtt_private_address_ = use_localhost_requests; } + // Overrides the tick clock used by |this| for testing. + void SetTickClockForTesting(base::TickClock* tick_clock); + private: scoped_refptr<base::SingleThreadTaskRunner> task_runner_; @@ -77,6 +87,10 @@ // Called every time a new RTT observation is available. OnUpdatedRTTAvailableCallback updated_rtt_observation_callback_; + // Callback that should be called by socket watchers to determine if the RTT + // notification should be notified using |updated_rtt_observation_callback_|. + ShouldNotifyRTTCallback should_notify_rtt_callback_; + base::TickClock* tick_clock_; DISALLOW_COPY_AND_ASSIGN(SocketWatcherFactory);
diff --git a/net/nqe/socket_watcher_unittest.cc b/net/nqe/socket_watcher_unittest.cc index 81a3bef..0939987 100644 --- a/net/nqe/socket_watcher_unittest.cc +++ b/net/nqe/socket_watcher_unittest.cc
@@ -51,6 +51,14 @@ callback_executed_ = true; } + static void SetShouldNotifyRTTCallback(bool value) { + should_notify_rtt_callback_ = value; + } + + static bool ShouldNotifyRTTCallback(base::TimeTicks now) { + return should_notify_rtt_callback_; + } + static void VerifyCallbackParams(const base::TimeDelta& rtt, const base::Optional<IPHash>& host) { ASSERT_TRUE(callback_executed_); @@ -66,6 +74,7 @@ callback_rtt_ = base::TimeDelta::FromMilliseconds(0); callback_host_ = base::nullopt; callback_executed_ = false; + should_notify_rtt_callback_ = false; } static base::TimeDelta callback_rtt() { return callback_rtt_; } @@ -74,6 +83,7 @@ static base::TimeDelta callback_rtt_; static base::Optional<IPHash> callback_host_; static bool callback_executed_; + static bool should_notify_rtt_callback_; DISALLOW_COPY_AND_ASSIGN(NetworkQualitySocketWatcherTest); }; @@ -86,6 +96,8 @@ bool NetworkQualitySocketWatcherTest::callback_executed_ = false; +bool NetworkQualitySocketWatcherTest::should_notify_rtt_callback_ = false; + // Verify that the buffer size is never exceeded. TEST_F(NetworkQualitySocketWatcherTest, NotificationsThrottled) { base::SimpleTestTickClock tick_clock; @@ -99,11 +111,11 @@ AddressList address_list = AddressList::CreateFromIPAddressList(ip_list, "canonical.example.com"); - SocketWatcher socket_watcher(SocketPerformanceWatcherFactory::PROTOCOL_TCP, - address_list, - base::TimeDelta::FromMilliseconds(2000), false, - base::ThreadTaskRunnerHandle::Get(), - base::Bind(OnUpdatedRTTAvailable), &tick_clock); + SocketWatcher socket_watcher( + SocketPerformanceWatcherFactory::PROTOCOL_TCP, address_list, + base::TimeDelta::FromMilliseconds(2000), false, + base::ThreadTaskRunnerHandle::Get(), base::Bind(OnUpdatedRTTAvailable), + base::Bind(ShouldNotifyRTTCallback), &tick_clock); EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT()); socket_watcher.OnUpdatedRTTAvailable(base::TimeDelta::FromSeconds(10)); @@ -120,6 +132,14 @@ // 2000 msec more than the last time |socket_watcher| received a notification. tick_clock.Advance(base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT()); + ResetExpectedCallbackParams(); + socket_watcher.OnUpdatedRTTAvailable(base::TimeDelta::FromSeconds(10)); + + EXPECT_FALSE(socket_watcher.ShouldNotifyUpdatedRTT()); + + // RTT notification is allowed by the global check. + SetShouldNotifyRTTCallback(true); + EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT()); } TEST_F(NetworkQualitySocketWatcherTest, QuicFirstNotificationDropped) { @@ -138,7 +158,8 @@ SocketPerformanceWatcherFactory::PROTOCOL_QUIC, address_list, base::TimeDelta::FromMilliseconds(2000), false, base::ThreadTaskRunnerHandle::Get(), - base::Bind(OnUpdatedRTTAvailableStoreParams), &tick_clock); + base::Bind(OnUpdatedRTTAvailableStoreParams), + base::Bind(ShouldNotifyRTTCallback), &tick_clock); EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT()); socket_watcher.OnUpdatedRTTAvailable(base::TimeDelta::FromSeconds(10)); @@ -147,6 +168,7 @@ // be possible to notify the |socket_watcher| again. EXPECT_TRUE(NetworkQualitySocketWatcherTest::callback_rtt().is_zero()); EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT()); + ResetExpectedCallbackParams(); socket_watcher.OnUpdatedRTTAvailable(base::TimeDelta::FromSeconds(2)); base::RunLoop().RunUntilIdle(); @@ -191,7 +213,7 @@ SocketPerformanceWatcherFactory::PROTOCOL_TCP, address_list, base::TimeDelta::FromMilliseconds(2000), false, base::ThreadTaskRunnerHandle::Get(), base::Bind(OnUpdatedRTTAvailable), - &tick_clock); + base::Bind(ShouldNotifyRTTCallback), &tick_clock); EXPECT_EQ(test.expect_should_notify_rtt, socket_watcher.ShouldNotifyUpdatedRTT()); @@ -229,7 +251,8 @@ SocketPerformanceWatcherFactory::PROTOCOL_TCP, address_list, base::TimeDelta::FromMilliseconds(2000), false, base::ThreadTaskRunnerHandle::Get(), - base::Bind(OnUpdatedRTTAvailableStoreParams), &tick_clock); + base::Bind(OnUpdatedRTTAvailableStoreParams), + base::Bind(ShouldNotifyRTTCallback), &tick_clock); EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT()); socket_watcher.OnUpdatedRTTAvailable(base::TimeDelta::FromSeconds(10)); base::RunLoop().RunUntilIdle();
diff --git a/net/proxy/network_delegate_error_observer_unittest.cc b/net/proxy/network_delegate_error_observer_unittest.cc index d2833aa..3055340 100644 --- a/net/proxy/network_delegate_error_observer_unittest.cc +++ b/net/proxy/network_delegate_error_observer_unittest.cc
@@ -68,7 +68,7 @@ return true; } bool OnCanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) override { return true; }
diff --git a/net/proxy/polling_proxy_config_service.cc b/net/proxy/polling_proxy_config_service.cc index 1f1aa5fb4..0208979c 100644 --- a/net/proxy/polling_proxy_config_service.cc +++ b/net/proxy/polling_proxy_config_service.cc
@@ -134,10 +134,11 @@ } void LazyInitializeOriginLoop() { - // TODO(eroman): Really this should be done in the constructor, but right - // now chrome is constructing the ProxyConfigService on the - // UI thread so we can't cache the IO thread for the purpose - // of DCHECKs until the first call is made. + // TODO(eroman): Really this should be done in the constructor, but some + // consumers constructing the ProxyConfigService on threads + // other than the ProxyConfigService's main thread, so we + // can't cache the main thread for the purpose of DCHECKs + // until the first call is made. if (!have_initialized_origin_runner_) { origin_task_runner_ = base::ThreadTaskRunnerHandle::Get(); have_initialized_origin_runner_ = true;
diff --git a/net/proxy/proxy_config_service_linux.cc b/net/proxy/proxy_config_service_linux.cc index ba3e253f..a28ed5b4 100644 --- a/net/proxy/proxy_config_service_linux.cc +++ b/net/proxy/proxy_config_service_linux.cc
@@ -1576,21 +1576,21 @@ void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig( const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner, - const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) { + const scoped_refptr<base::SequencedTaskRunner>& main_task_runner) { // We should be running on the default glib main loop thread right // now. gconf can only be accessed from this thread. DCHECK(glib_task_runner->RunsTasksInCurrentSequence()); glib_task_runner_ = glib_task_runner; - io_task_runner_ = io_task_runner; + main_task_runner_ = main_task_runner; - // If we are passed a NULL |io_task_runner|, then don't set up proxy + // If we are passed a NULL |main_task_runner|, then don't set up proxy // setting change notifications. This should not be the usual case but is // intended to/ simplify test setups. - if (!io_task_runner_.get()) + if (!main_task_runner_.get()) VLOG(1) << "Monitoring of proxy setting changes is disabled"; // Fetch and cache the current proxy config. The config is left in - // cached_config_, where GetLatestProxyConfig() running on the IO thread + // cached_config_, where GetLatestProxyConfig() running on the main TaskRunner // will expect to find it. This is safe to do because we return // before this ProxyConfigServiceLinux is passed on to // the ProxyService. @@ -1620,14 +1620,15 @@ reference_config_ = cached_config_; reference_config_.set_id(1); // Mark it as valid. - // We only set up notifications if we have IO and file loops available. - // We do this after getting the initial configuration so that we don't have - // to worry about cancelling it if the initial fetch above fails. Note that - // setting up notifications has the side effect of simulating a change, so - // that we won't lose any updates that may have happened after the initial - // fetch and before setting up notifications. We'll detect the common case - // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it. - if (io_task_runner.get()) { + // We only set up notifications if we have the main and file loops + // available. We do this after getting the initial configuration so that we + // don't have to worry about cancelling it if the initial fetch above fails. + // Note that setting up notifications has the side effect of simulating a + // change, so that we won't lose any updates that may have happened after + // the initial fetch and before setting up notifications. We'll detect the + // common case of no changes in OnCheckProxyConfigSettings() (or sooner) and + // ignore it. + if (main_task_runner.get()) { scoped_refptr<base::SequencedTaskRunner> required_loop = setting_getter_->GetNotificationTaskRunner(); if (!required_loop.get() || required_loop->RunsTasksInCurrentSequence()) { @@ -1675,9 +1676,9 @@ ProxyConfigService::ConfigAvailability ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig( ProxyConfig* config) { - // This is called from the IO thread. - DCHECK(!io_task_runner_.get() || - io_task_runner_->RunsTasksInCurrentSequence()); + // This is called from the main TaskRunner. + DCHECK(!main_task_runner_.get() || + main_task_runner_->RunsTasksInCurrentSequence()); // Simply return the last proxy configuration that glib_default_loop // notified us of. @@ -1710,11 +1711,12 @@ // See if it is different from what we had before. if (new_config.is_valid() != reference_config_.is_valid() || !new_config.Equals(reference_config_)) { - // Post a task to the IO thread with the new configuration, so it can + // Post a task to the main TaskRunner with the new configuration, so it can // update |cached_config_|. - io_task_runner_->PostTask(FROM_HERE, base::Bind( - &ProxyConfigServiceLinux::Delegate::SetNewProxyConfig, - this, new_config)); + main_task_runner_->PostTask( + FROM_HERE, + base::Bind(&ProxyConfigServiceLinux::Delegate::SetNewProxyConfig, this, + new_config)); // Update the thread-private copy in |reference_config_| as well. reference_config_ = new_config; } else { @@ -1724,7 +1726,7 @@ void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig( const ProxyConfig& new_config) { - DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); VLOG(1) << "Proxy configuration changed"; cached_config_ = new_config; for (auto& observer : observers_)
diff --git a/net/proxy/proxy_config_service_linux.h b/net/proxy/proxy_config_service_linux.h index 78cde0d..8f54bb1 100644 --- a/net/proxy/proxy_config_service_linux.h +++ b/net/proxy/proxy_config_service_linux.h
@@ -142,30 +142,30 @@ DISALLOW_COPY_AND_ASSIGN(SettingGetter); }; - // ProxyConfigServiceLinux is created on the UI thread, and + // ProxyConfigServiceLinux is created on the glib thread, and // SetUpAndFetchInitialConfig() is immediately called to synchronously // fetch the original configuration and set up change notifications on - // the UI thread. + // the ProxyConfigService's main SequencedTaskRunner, which is passed to its + // constructor (Which may or may not run tasks on the glib thread). // // Past that point, it is accessed periodically through the // ProxyConfigService interface (GetLatestProxyConfig, AddObserver, - // RemoveObserver) from the IO thread. + // RemoveObserver) from the main TaskRunner. // // Setting change notification callbacks can occur at any time and are - // run on either the UI thread (gconf/gsettings) or the sequenced task - // runner (KDE). The new settings are fetched on that thread, and the - // resulting proxy config is posted to the IO thread through - // Delegate::SetNewProxyConfig(). We then notify observers on the IO - // thread of the configuration change. + // run on either the glib thread (gconf/gsettings) or a separate file thread + // (KDE). The new settings are fetched on that thread, and the resulting proxy + // config is posted to the main TaskRunner through + // Delegate::SetNewProxyConfig(). We then notify observers on that TaskRunner + // of the configuration change. // - // ProxyConfigServiceLinux is deleted from the IO thread. + // ProxyConfigServiceLinux is deleted from the main TaskRunner. // // The substance of the ProxyConfigServiceLinux implementation is // wrapped in the Delegate ref counted class. On deleting the // ProxyConfigServiceLinux, Delegate::OnDestroy() is posted to either - // the UI thread (gconf/gsettings) or a sequenced task runner (KDE) - // where change notifications will be safely stopped before releasing - // Delegate. + // the glib thread (gconf/gsettings) or a file thread (KDE) where change + // notifications will be safely stopped before releasing Delegate. class Delegate : public base::RefCountedThreadSafe<Delegate> { public: @@ -180,12 +180,12 @@ // gsettings, or kioslaverc are used, also enables notifications for // setting changes. gconf/gsettings must only be accessed from the // thread running the default glib main loop, and so this method - // must be called from the UI thread. The message loop for the IO - // thread is specified so that notifications can post tasks to it - // (and for assertions). + // must be called from the glib thread. The message loop for the + // ProxyConfigService's main SequencedTaskRunner is specified so that + // notifications can post tasks to it (and for assertions). void SetUpAndFetchInitialConfig( const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner, - const scoped_refptr<base::SequencedTaskRunner>& io_task_runner); + const scoped_refptr<base::SequencedTaskRunner>& main_task_runner); // Handler for setting change notifications: fetches a new proxy // configuration from settings, and if this config is different @@ -194,17 +194,17 @@ // Left public for simplicity. void OnCheckProxyConfigSettings(); - // Called from IO thread. + // Called on the service's main TaskRunner. void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); ProxyConfigService::ConfigAvailability GetLatestProxyConfig( ProxyConfig* config); - // Posts a call to OnDestroy() to the UI or sequenced task runner, + // Posts a call to OnDestroy() to the glib or a file task runner, // depending on the setting getter in use. Called from // ProxyConfigServiceLinux's destructor. void PostDestroyTask(); - // Safely stops change notifications. Posted to either the UI or + // Safely stops change notifications. Posted to either the glib thread or // sequenced task runner, depending on the setting getter in use. void OnDestroy(); @@ -235,7 +235,7 @@ // and the configuration is valid. bool GetConfigFromSettings(ProxyConfig* config); - // This method is posted from the UI thread to the IO thread to + // This method is posted from the glib thread to the main TaskRunner to // carry the new config information. void SetNewProxyConfig(const ProxyConfig& new_config); @@ -246,11 +246,11 @@ std::unique_ptr<SettingGetter> setting_getter_; // Cached proxy configuration, to be returned by - // GetLatestProxyConfig. Initially populated from the UI thread, but - // afterwards only accessed from the IO thread. + // GetLatestProxyConfig. Initially populated from the glib thread, but + // afterwards only accessed from the main TaskRunner. ProxyConfig cached_config_; - // A copy kept on the UI thread of the last seen proxy config, so as + // A copy kept on the glib thread of the last seen proxy config, so as // to avoid posting a call to SetNewProxyConfig when we get a // notification but the config has not actually changed. ProxyConfig reference_config_; @@ -265,9 +265,9 @@ // is not thread safe, any use of gconf must be done on the thread running // this loop. scoped_refptr<base::SingleThreadTaskRunner> glib_task_runner_; - // Task runner for the IO thread. GetLatestProxyConfig() is called from - // the thread running this loop. - scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + // Task runner for the main TaskRunner. GetLatestProxyConfig() is called + // from the thread running this loop. + scoped_refptr<base::SequencedTaskRunner> main_task_runner_; base::ObserverList<Observer> observers_; @@ -297,7 +297,7 @@ } // ProxyConfigService methods: - // Called from IO thread. + // Called from main TaskRunner. void AddObserver(Observer* observer) override; void RemoveObserver(Observer* observer) override; ProxyConfigService::ConfigAvailability GetLatestProxyConfig(
diff --git a/net/proxy/proxy_config_service_linux_unittest.cc b/net/proxy/proxy_config_service_linux_unittest.cc index 0bda1a45..795b266 100644 --- a/net/proxy/proxy_config_service_linux_unittest.cc +++ b/net/proxy/proxy_config_service_linux_unittest.cc
@@ -270,7 +270,7 @@ }; // This helper class runs ProxyConfigServiceLinux::GetLatestProxyConfig() on -// the IO thread and synchronously waits for the result. +// the main TaskRunner and synchronously waits for the result. // Some code duplicated from proxy_script_fetcher_unittest.cc. class SyncConfigGetter : public ProxyConfigService::Observer { public: @@ -278,25 +278,25 @@ explicit SyncConfigGetter(ProxyConfigServiceLinux* config_service) : event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), - io_thread_("IO_Thread"), + main_thread_("Main_Thread"), config_service_(config_service), matches_pac_url_event_( base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED) { - // Start an IO thread. + // Start the main IO thread. base::Thread::Options options; options.message_loop_type = base::MessageLoop::TYPE_IO; - io_thread_.StartWithOptions(options); + main_thread_.StartWithOptions(options); // Make sure the thread started. - io_thread_.task_runner()->PostTask( + main_thread_.task_runner()->PostTask( FROM_HERE, base::Bind(&SyncConfigGetter::Init, base::Unretained(this))); Wait(); } ~SyncConfigGetter() override { - // Clean up the IO thread. - io_thread_.task_runner()->PostTask( + // Clean up the main thread. + main_thread_.task_runner()->PostTask( FROM_HERE, base::Bind(&SyncConfigGetter::CleanUp, base::Unretained(this))); Wait(); @@ -304,15 +304,15 @@ // Does gconf setup and initial fetch of the proxy config, // all on the calling thread (meant to be the thread with the - // default glib main loop, which is the UI thread). + // default glib main loop, which is the glib thread). void SetupAndInitialFetch() { config_service_->SetupAndFetchInitialConfig( - base::ThreadTaskRunnerHandle::Get(), io_thread_.task_runner()); + base::ThreadTaskRunnerHandle::Get(), main_thread_.task_runner()); } // Synchronously gets the proxy config. ProxyConfigService::ConfigAvailability SyncGetLatestProxyConfig( ProxyConfig* config) { - io_thread_.task_runner()->PostTask( + main_thread_.task_runner()->PostTask( FROM_HERE, base::Bind(&SyncConfigGetter::GetLatestConfigOnIOThread, base::Unretained(this))); Wait(); @@ -354,13 +354,13 @@ } } - // [Runs on |io_thread_|] + // [Runs on |main_thread_|] void Init() { config_service_->AddObserver(this); event_.Signal(); } - // Calls GetLatestProxyConfig, running on |io_thread_| Signals |event_| + // Calls GetLatestProxyConfig, running on |main_thread_| Signals |event_| // on completion. void GetLatestConfigOnIOThread() { get_latest_config_result_ = @@ -368,7 +368,7 @@ event_.Signal(); } - // [Runs on |io_thread_|] Signals |event_| on cleanup completion. + // [Runs on |main_thread_|] Signals |event_| on cleanup completion. void CleanUp() { config_service_->RemoveObserver(this); delete config_service_; @@ -382,11 +382,11 @@ } base::WaitableEvent event_; - base::Thread io_thread_; + base::Thread main_thread_; ProxyConfigServiceLinux* config_service_; - // The config obtained by |io_thread_| and read back by the main + // The config obtained by |main_thread_| and read back by the main // thread. ProxyConfig proxy_config_;
diff --git a/net/proxy/proxy_config_service_mac.cc b/net/proxy/proxy_config_service_mac.cc index c69cd7e..055912f6 100644 --- a/net/proxy/proxy_config_service_mac.cc +++ b/net/proxy/proxy_config_service_mac.cc
@@ -198,17 +198,17 @@ } ProxyConfigServiceMac::ProxyConfigServiceMac( - const scoped_refptr<base::SequencedTaskRunner>& io_thread_task_runner) + const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner) : forwarder_(this), has_fetched_config_(false), helper_(new Helper(this)), - io_thread_task_runner_(io_thread_task_runner) { - DCHECK(io_thread_task_runner_.get()); + sequenced_task_runner_(sequenced_task_runner) { + DCHECK(sequenced_task_runner_.get()); config_watcher_.reset(new NetworkConfigWatcherMac(&forwarder_)); } ProxyConfigServiceMac::~ProxyConfigServiceMac() { - DCHECK(io_thread_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(sequenced_task_runner_->RunsTasksInCurrentSequence()); // Delete the config_watcher_ to ensure the notifier thread finishes before // this object is destroyed. config_watcher_.reset(); @@ -216,18 +216,18 @@ } void ProxyConfigServiceMac::AddObserver(Observer* observer) { - DCHECK(io_thread_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(sequenced_task_runner_->RunsTasksInCurrentSequence()); observers_.AddObserver(observer); } void ProxyConfigServiceMac::RemoveObserver(Observer* observer) { - DCHECK(io_thread_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(sequenced_task_runner_->RunsTasksInCurrentSequence()); observers_.RemoveObserver(observer); } ProxyConfigService::ConfigAvailability ProxyConfigServiceMac::GetLatestProxyConfig(ProxyConfig* config) { - DCHECK(io_thread_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(sequenced_task_runner_->RunsTasksInCurrentSequence()); // Lazy-initialize by fetching the proxy setting from this thread. if (!has_fetched_config_) { @@ -262,15 +262,15 @@ ProxyConfig new_config; GetCurrentProxyConfig(&new_config); - // Call OnProxyConfigChanged() on the IO thread to notify our observers. - io_thread_task_runner_->PostTask( + // Call OnProxyConfigChanged() on the TakeRunner to notify our observers. + sequenced_task_runner_->PostTask( FROM_HERE, base::Bind(&Helper::OnProxyConfigChanged, helper_.get(), new_config)); } void ProxyConfigServiceMac::OnProxyConfigChanged( const ProxyConfig& new_config) { - DCHECK(io_thread_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(sequenced_task_runner_->RunsTasksInCurrentSequence()); // Keep track of the last value we have seen. has_fetched_config_ = true;
diff --git a/net/proxy/proxy_config_service_mac.h b/net/proxy/proxy_config_service_mac.h index d9d08c7..a210e6a 100644 --- a/net/proxy/proxy_config_service_mac.h +++ b/net/proxy/proxy_config_service_mac.h
@@ -24,10 +24,10 @@ class ProxyConfigServiceMac : public ProxyConfigService { public: // Constructs a ProxyConfigService that watches the Mac OS system settings. - // This instance is expected to be operated and deleted on the - // same sequenced task runner (however it may be constructed elsewhere). + // This instance is expected to be operated and deleted on + // |sequenced_task_runner| (however it may be constructed elsewhere). explicit ProxyConfigServiceMac( - const scoped_refptr<base::SequencedTaskRunner>& io_thread_task_runner); + const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner); ~ProxyConfigServiceMac() override; public: @@ -75,7 +75,7 @@ scoped_refptr<Helper> helper_; // The task runner that |this| will be operated on. - const scoped_refptr<base::SequencedTaskRunner> io_thread_task_runner_; + const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceMac); };
diff --git a/net/proxy/proxy_config_service_win.cc b/net/proxy/proxy_config_service_win.cc index e7b51dcd..bc9408e 100644 --- a/net/proxy/proxy_config_service_win.cc +++ b/net/proxy/proxy_config_service_win.cc
@@ -44,7 +44,7 @@ ProxyConfigServiceWin::~ProxyConfigServiceWin() { // The registry functions below will end up going to disk. TODO: Do this on - // another thread to avoid slowing the IO thread. http://crbug.com/61453 + // another thread to avoid slowing the current thread. http://crbug.com/61453 base::ThreadRestrictions::ScopedAllowIO allow_io; keys_to_watch_.clear(); } @@ -62,7 +62,7 @@ return; // Already initialized. // The registry functions below will end up going to disk. Do this on another - // thread to avoid slowing the IO thread. http://crbug.com/61453 + // thread to avoid slowing the current thread. http://crbug.com/61453 base::ThreadRestrictions::ScopedAllowIO allow_io; // There are a number of different places where proxy settings can live
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc index be32fe0c..c7d1f53 100644 --- a/net/proxy/proxy_script_fetcher_impl_unittest.cc +++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -195,7 +195,7 @@ } bool OnCanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) override { return true; }
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc index 016b0a6..c633a75 100644 --- a/net/quic/chromium/quic_network_transaction_unittest.cc +++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -5157,6 +5157,71 @@ EXPECT_TRUE(mock_quic_data.AllWriteDataConsumed()); } +TEST_P(QuicNetworkTransactionTest, HostInWhitelist) { + session_params_.quic_host_whitelist.insert("mail.example.org"); + + MockRead http_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), MockRead(kQuicAlternativeServiceHeader), + MockRead("hello world"), + MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), + MockRead(ASYNC, OK)}; + + StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr, + 0); + socket_factory_.AddSocketDataProvider(&http_data); + AddCertificate(&ssl_data_); + socket_factory_.AddSSLSocketDataProvider(&ssl_data_); + + MockQuicData mock_quic_data; + QuicStreamOffset header_stream_offset = 0; + mock_quic_data.AddWrite( + ConstructInitialSettingsPacket(1, &header_stream_offset)); + mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket( + 2, GetNthClientInitiatedStreamId(0), true, true, + GetRequestHeaders("GET", "https", "/"), &header_stream_offset)); + mock_quic_data.AddRead(ConstructServerResponseHeadersPacket( + 1, GetNthClientInitiatedStreamId(0), false, false, + GetResponseHeaders("200 OK"))); + mock_quic_data.AddRead(ConstructServerDataPacket( + 2, GetNthClientInitiatedStreamId(0), false, true, 0, "hello!")); + mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1, 1)); + mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read + mock_quic_data.AddRead(ASYNC, 0); // EOF + + mock_quic_data.AddSocketDataToFactory(&socket_factory_); + + AddHangingNonAlternateProtocolSocketData(); + CreateSession(); + + SendRequestAndExpectHttpResponse("hello world"); + SendRequestAndExpectQuicResponse("hello!"); +} + +TEST_P(QuicNetworkTransactionTest, HostNotInWhitelist) { + session_params_.quic_host_whitelist.insert("mail.example.com"); + + MockRead http_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), MockRead(kQuicAlternativeServiceHeader), + MockRead("hello world"), + MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), + MockRead(ASYNC, OK)}; + + StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr, + 0); + socket_factory_.AddSocketDataProvider(&http_data); + AddCertificate(&ssl_data_); + socket_factory_.AddSSLSocketDataProvider(&ssl_data_); + socket_factory_.AddSocketDataProvider(&http_data); + AddCertificate(&ssl_data_); + socket_factory_.AddSSLSocketDataProvider(&ssl_data_); + + AddHangingNonAlternateProtocolSocketData(); + CreateSession(); + + SendRequestAndExpectHttpResponse("hello world"); + SendRequestAndExpectHttpResponse("hello world"); +} + class QuicNetworkTransactionWithDestinationTest : public PlatformTest, public ::testing::WithParamInterface<PoolingTestParams> {
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h index a8017ec0..b901d6e 100644 --- a/net/quic/core/quic_flags_list.h +++ b/net/quic/core/quic_flags_list.h
@@ -127,7 +127,7 @@ // If true, QUIC can take ownership of data provided in a reference counted // memory to avoid data copy. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_mem_slices, true) +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_mem_slices, false) // Allow QUIC to accept initial packet numbers that are random, not 1. QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_enable_accept_random_ipn, false)
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc index 62d6360..4957c633 100644 --- a/net/quic/core/quic_session.cc +++ b/net/quic/core/quic_session.cc
@@ -140,9 +140,7 @@ stream->OnStreamReset(frame); } -void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) { - DCHECK(frame.last_good_stream_id < next_outgoing_stream_id_); -} +void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) {} void QuicSession::OnConnectionClosed(QuicErrorCode error, const string& error_details,
diff --git a/net/quic/core/quic_session_test.cc b/net/quic/core/quic_session_test.cc index cf4ff52..dc867bc 100644 --- a/net/quic/core/quic_session_test.cc +++ b/net/quic/core/quic_session_test.cc
@@ -231,6 +231,7 @@ } using QuicSession::closed_streams; + using QuicSession::next_outgoing_stream_id; using QuicSession::PostProcessAfterData; using QuicSession::zombie_streams; @@ -817,6 +818,12 @@ EXPECT_TRUE(session_.GetOrCreateDynamicStream(kTestStreamId)); } +TEST_P(QuicSessionTestServer, InvalidGoAway) { + QuicGoAwayFrame go_away(QUIC_PEER_GOING_AWAY, + session_.next_outgoing_stream_id(), ""); + session_.OnGoAway(go_away); +} + // Test that server session will send a connectivity probe in response to a // connectivity probe on the same path. TEST_P(QuicSessionTestServer, ServerReplyToConnecitivityProbe) {
diff --git a/net/quic/quartc/quartc_factory.cc b/net/quic/quartc/quartc_factory.cc index 9d6485d..b45011d 100644 --- a/net/quic/quartc/quartc_factory.cc +++ b/net/quic/quartc/quartc_factory.cc
@@ -116,6 +116,32 @@ if (quartc_session_config.congestion_control == QuartcCongestionControl::kBBR) { copt.push_back(kTBBR); + + FLAGS_quic_reloadable_flag_quic_bbr_slower_startup = true; + FLAGS_quic_reloadable_flag_quic_bbr_fully_drain_queue = true; + FLAGS_quic_reloadable_flag_quic_bbr_less_probe_rtt = true; + for (const auto option : quartc_session_config.bbr_options) { + switch (option) { + case (QuartcBbrOptions::kSlowerStartup): + copt.push_back(kBBRS); + break; + case (QuartcBbrOptions::kFullyDrainQueue): + copt.push_back(kBBR3); + break; + case (QuartcBbrOptions::kReduceProbeRtt): + copt.push_back(kBBR6); + break; + case (QuartcBbrOptions::kSkipProbeRtt): + copt.push_back(kBBR7); + break; + case (QuartcBbrOptions::kSkipProbeRttAggressively): + copt.push_back(kBBR8); + break; + case (QuartcBbrOptions::kFillUpLinkDuringProbing): + quic_connection->set_fill_up_link_during_probing(true); + break; + } + } } QuicConfig quic_config; quic_config.SetConnectionOptionsToSend(copt);
diff --git a/net/quic/quartc/quartc_factory_interface.cc b/net/quic/quartc/quartc_factory_interface.cc new file mode 100644 index 0000000..cbdacae --- /dev/null +++ b/net/quic/quartc/quartc_factory_interface.cc
@@ -0,0 +1,12 @@ +// 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 "net/quic/quartc/quartc_factory_interface.h" + +namespace net { + +QuartcFactoryInterface::QuartcSessionConfig::QuartcSessionConfig() = default; +QuartcFactoryInterface::QuartcSessionConfig::~QuartcSessionConfig() = default; + +} // namespace net
diff --git a/net/quic/quartc/quartc_factory_interface.h b/net/quic/quartc/quartc_factory_interface.h index 1bd8d768..33dd6aa1 100644 --- a/net/quic/quartc/quartc_factory_interface.h +++ b/net/quic/quartc/quartc_factory_interface.h
@@ -23,12 +23,31 @@ kBBR, // Use BBR. }; +// Options that control the BBR algorithm. +enum class QuartcBbrOptions { + kSlowerStartup, // Once a loss is encountered in STARTUP, + // switches startup to a 1.5x pacing gain. + kFullyDrainQueue, // Fully drains the queue once per cycle. + kReduceProbeRtt, // Probe RTT reduces CWND to 0.75 * BDP instead of 4 + // packets. + kSkipProbeRtt, // Skip Probe RTT and extend the existing min_rtt if a + // recent min_rtt is within 12.5% of the current min_rtt. + kSkipProbeRttAggressively, // Skip ProbeRTT and extend the existing min_rtt + // as long as you've been app limited at least + // once. + kFillUpLinkDuringProbing, // Sends probing retransmissions whenever we + // become application limited. +}; + // Used to create instances for Quartc objects such as QuartcSession. class QUIC_EXPORT_PRIVATE QuartcFactoryInterface { public: virtual ~QuartcFactoryInterface() {} struct QuartcSessionConfig { + QuartcSessionConfig(); + ~QuartcSessionConfig(); + // When using Quartc, there are two endpoints. The QuartcSession on one // endpoint must act as a server and the one on the other side must act as a // client. @@ -47,6 +66,9 @@ // congestion control algorithm chosen by QUIC. QuartcCongestionControl congestion_control = QuartcCongestionControl::kDefault; + // Options to control the BBR algorithm. In case the congestion control is + // set to anything but BBR, these options are ignored. + std::vector<QuartcBbrOptions> bbr_options; // Timeouts for the crypto handshake. Set them to higher values to // prevent closing the session before it started on a slow network. // Zero entries are ignored and QUIC defaults are used in that case.
diff --git a/net/spdy/chromium/spdy_network_transaction_unittest.cc b/net/spdy/chromium/spdy_network_transaction_unittest.cc index a4a9090b..5dcea3a 100644 --- a/net/spdy/chromium/spdy_network_transaction_unittest.cc +++ b/net/spdy/chromium/spdy_network_transaction_unittest.cc
@@ -4065,6 +4065,28 @@ helper.VerifyDataConsumed(); } +TEST_F(SpdyNetworkTransactionTest, GoAwayImmediately) { + SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(1)); + MockRead reads[] = {CreateMockRead(goaway, 0, SYNCHRONOUS)}; + SequencedSocketData data(reads, arraysize(reads), nullptr, 0); + + NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr); + helper.RunPreTestSetup(); + helper.AddData(&data); + helper.StartDefaultTest(); + EXPECT_THAT(helper.output().rv, IsError(ERR_IO_PENDING)); + + helper.WaitForCallbackToComplete(); + EXPECT_THAT(helper.output().rv, IsError(ERR_CONNECTION_CLOSED)); + + const HttpResponseInfo* response = helper.trans()->GetResponseInfo(); + EXPECT_FALSE(response->headers); + EXPECT_TRUE(response->was_fetched_via_spdy); + + // Verify that we consumed all test data. + helper.VerifyDataConsumed(); +} + // Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual // protocol negotiation happens, instead this test forces protocols for both // sockets.
diff --git a/net/spdy/chromium/spdy_session_unittest.cc b/net/spdy/chromium/spdy_session_unittest.cc index 3df9057..05d1b22 100644 --- a/net/spdy/chromium/spdy_session_unittest.cc +++ b/net/spdy/chromium/spdy_session_unittest.cc
@@ -347,9 +347,7 @@ AddSSLSocketData(); CreateNetworkSession(); - - session_ = TryCreateSpdySessionExpectingFailure( - http_session_.get(), key_, ERR_CONNECTION_CLOSED, NetLogWithSource()); + CreateSpdySession(); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(session_);
diff --git a/net/spdy/chromium/spdy_test_util_common.cc b/net/spdy/chromium/spdy_test_util_common.cc index 1b408a1..cd431917 100644 --- a/net/spdy/chromium/spdy_test_util_common.cc +++ b/net/spdy/chromium/spdy_test_util_common.cc
@@ -4,8 +4,6 @@ #include "net/spdy/chromium/spdy_test_util_common.h" -#include <stdint.h> - #include <cstddef> #include <utility> @@ -20,18 +18,14 @@ #include "net/cert/mock_cert_verifier.h" #include "net/cert/signed_certificate_timestamp_and_status.h" #include "net/http/http_cache.h" -#include "net/http/http_network_session.h" #include "net/http/http_network_transaction.h" -#include "net/http/http_server_properties_impl.h" #include "net/log/net_log_with_source.h" #include "net/socket/client_socket_handle.h" #include "net/socket/next_proto.h" -#include "net/socket/socket_test_util.h" #include "net/socket/ssl_client_socket.h" #include "net/socket/transport_client_socket_pool.h" #include "net/spdy/chromium/buffered_spdy_framer.h" #include "net/spdy/chromium/spdy_http_utils.h" -#include "net/spdy/chromium/spdy_session.h" #include "net/spdy/chromium/spdy_session_pool.h" #include "net/spdy/chromium/spdy_stream.h" #include "net/spdy/core/spdy_alt_svc_wire_format.h" @@ -40,6 +34,7 @@ #include "net/url_request/url_request_job_factory_impl.h" #include "testing/gmock/include/gmock/gmock.h" +using net::test::IsError; using net::test::IsOk; namespace net { @@ -89,25 +84,23 @@ void AppendToHeaderBlock(const char* const extra_headers[], int extra_header_count, SpdyHeaderBlock* headers) { - SpdyString this_header; - SpdyString this_value; - if (!extra_header_count) return; // Sanity check: Non-NULL header list. - DCHECK(NULL != extra_headers) << "NULL header value pair list"; + DCHECK(extra_headers) << "NULL header value pair list"; // Sanity check: Non-NULL header map. - DCHECK(NULL != headers) << "NULL header map"; + DCHECK(headers) << "NULL header map"; + // Copy in the headers. for (int i = 0; i < extra_header_count; i++) { // Sanity check: Non-empty header. DCHECK_NE('\0', *extra_headers[i * 2]) << "Empty header value pair"; - this_header = extra_headers[i * 2]; + SpdyString this_header = extra_headers[i * 2]; SpdyString::size_type header_len = this_header.length(); if (!header_len) continue; - this_value = extra_headers[1 + (i * 2)]; + SpdyString this_value = extra_headers[1 + (i * 2)]; SpdyString new_value; if (headers->find(this_header) != headers->end()) { // More than one entry in the header. @@ -329,18 +322,18 @@ SpdySessionDependencies::SpdySessionDependencies( std::unique_ptr<ProxyService> proxy_service) - : host_resolver(new MockCachingHostResolver), - cert_verifier(new MockCertVerifier), + : host_resolver(std::make_unique<MockCachingHostResolver>()), + cert_verifier(std::make_unique<MockCertVerifier>()), channel_id_service(nullptr), - transport_security_state(new TransportSecurityState), - cert_transparency_verifier(new DoNothingCTVerifier), - ct_policy_enforcer(new CTPolicyEnforcer), + transport_security_state(std::make_unique<TransportSecurityState>()), + cert_transparency_verifier(std::make_unique<DoNothingCTVerifier>()), + ct_policy_enforcer(std::make_unique<CTPolicyEnforcer>()), proxy_service(std::move(proxy_service)), - ssl_config_service(new SSLConfigServiceDefaults), - socket_factory(new MockClientSocketFactory), + ssl_config_service(base::MakeRefCounted<SSLConfigServiceDefaults>()), + socket_factory(std::make_unique<MockClientSocketFactory>()), http_auth_handler_factory( HttpAuthHandlerFactory::CreateDefault(host_resolver.get())), - http_server_properties(new HttpServerPropertiesImpl), + http_server_properties(std::make_unique<HttpServerPropertiesImpl>()), enable_ip_pooling(true), enable_ping(false), enable_user_alternate_protocol_ports(false), @@ -443,8 +436,7 @@ }; SpdyURLRequestContext::SpdyURLRequestContext() : storage_(this) { - storage_.set_host_resolver( - std::unique_ptr<HostResolver>(new MockHostResolver)); + storage_.set_host_resolver(std::make_unique<MockHostResolver>()); storage_.set_cert_verifier(std::make_unique<MockCertVerifier>()); storage_.set_transport_security_state( std::make_unique<TransportSecurityState>()); @@ -457,7 +449,7 @@ storage_.set_http_auth_handler_factory( HttpAuthHandlerFactory::CreateDefault(host_resolver())); storage_.set_http_server_properties( - std::unique_ptr<HttpServerProperties>(new HttpServerPropertiesImpl())); + std::make_unique<HttpServerPropertiesImpl>()); storage_.set_job_factory(std::make_unique<URLRequestJobFactoryImpl>()); HttpNetworkSession::Params session_params; session_params.enable_spdy_ping_based_connection_checking = false; @@ -498,33 +490,28 @@ HttpNetworkSession* http_session, const SpdySessionKey& key, const NetLogWithSource& net_log, - Error expected_status, bool enable_ip_based_pooling) { EXPECT_FALSE(http_session->spdy_session_pool()->FindAvailableSession( key, enable_ip_based_pooling, NetLogWithSource())); - scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams( - key.host_port_pair(), false, OnHostResolutionCallback(), - TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); + auto transport_params = base::MakeRefCounted<TransportSocketParams>( + key.host_port_pair(), /* disable_resolver_cache = */ false, + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT); auto connection = std::make_unique<ClientSocketHandle>(); TestCompletionCallback callback; - int rv = ERR_UNEXPECTED; SSLConfig ssl_config; - scoped_refptr<SSLSocketParams> ssl_params( - new SSLSocketParams(transport_params, NULL, NULL, key.host_port_pair(), - ssl_config, key.privacy_mode(), 0, false)); - rv = connection->Init( + auto ssl_params = base::MakeRefCounted<SSLSocketParams>( + transport_params, nullptr, nullptr, key.host_port_pair(), ssl_config, + key.privacy_mode(), 0, /* expect_spdy = */ false); + int rv = connection->Init( key.host_port_pair().ToString(), ssl_params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED, callback.callback(), http_session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL), net_log); - - if (rv == ERR_IO_PENDING) - rv = callback.WaitForResult(); - + rv = callback.GetResult(rv); EXPECT_THAT(rv, IsOk()); base::WeakPtr<SpdySession> spdy_session = @@ -538,20 +525,10 @@ } // namespace -base::WeakPtr<SpdySession> TryCreateSpdySessionExpectingFailure( - HttpNetworkSession* http_session, - const SpdySessionKey& key, - Error expected_error, - const NetLogWithSource& net_log) { - DCHECK_LT(expected_error, ERR_IO_PENDING); - return CreateSpdySessionHelper(http_session, key, net_log, expected_error, - /* enable_ip_based_pooling = */ true); -} - base::WeakPtr<SpdySession> CreateSpdySession(HttpNetworkSession* http_session, const SpdySessionKey& key, const NetLogWithSource& net_log) { - return CreateSpdySessionHelper(http_session, key, net_log, OK, + return CreateSpdySessionHelper(http_session, key, net_log, /* enable_ip_based_pooling = */ true); } @@ -559,7 +536,7 @@ HttpNetworkSession* http_session, const SpdySessionKey& key, const NetLogWithSource& net_log) { - return CreateSpdySessionHelper(http_session, key, net_log, OK, + return CreateSpdySessionHelper(http_session, key, net_log, /* enable_ip_based_pooling = */ false); } @@ -647,9 +624,9 @@ base::WeakPtr<SpdySession> TryCreateFakeSpdySessionExpectingFailure( SpdySessionPool* pool, const SpdySessionKey& key, - Error expected_error) { - DCHECK_LT(expected_error, ERR_IO_PENDING); - return CreateFakeSpdySessionHelper(pool, key, expected_error); + Error expected_status) { + DCHECK_LT(expected_status, ERR_IO_PENDING); + return CreateFakeSpdySessionHelper(pool, key, expected_status); } SpdySessionPoolPeer::SpdySessionPoolPeer(SpdySessionPool* pool) : pool_(pool) { @@ -682,7 +659,7 @@ // static SpdyHeaderBlock SpdyTestUtil::ConstructGetHeaderBlock(SpdyStringPiece url) { - return ConstructHeaderBlock("GET", url, NULL); + return ConstructHeaderBlock("GET", url, nullptr); } // static @@ -974,7 +951,7 @@ } SpdySerializedFrame SpdyTestUtil::ConstructSpdyReplyError(int stream_id) { - return ConstructSpdyReplyError("500", NULL, 0, 1); + return ConstructSpdyReplyError("500", nullptr, 0, 1); } SpdySerializedFrame SpdyTestUtil::ConstructSpdyGetReply(
diff --git a/net/spdy/chromium/spdy_test_util_common.h b/net/spdy/chromium/spdy_test_util_common.h index 830ec523..316a8b9 100644 --- a/net/spdy/chromium/spdy_test_util_common.h +++ b/net/spdy/chromium/spdy_test_util_common.h
@@ -30,6 +30,7 @@ #include "net/proxy/proxy_server.h" #include "net/proxy/proxy_service.h" #include "net/socket/socket_test_util.h" +#include "net/spdy/chromium/spdy_session.h" #include "net/spdy/core/spdy_protocol.h" #include "net/spdy/platform/api/spdy_string.h" #include "net/spdy/platform/api/spdy_string_piece.h" @@ -46,7 +47,6 @@ class CTPolicyEnforcer; class HostPortPair; class NetLogWithSource; -class SpdySession; class SpdySessionKey; class SpdySessionPool; class SpdyStream; @@ -238,16 +238,6 @@ // NULL. bool HasSpdySession(SpdySessionPool* pool, const SpdySessionKey& key); -// Tries to create a SPDY session for the given key but expects the -// attempt to fail with the given error. A SPDY session for |key| must -// not already exist. The session will be created but close in the -// next event loop iteration. -base::WeakPtr<SpdySession> TryCreateSpdySessionExpectingFailure( - HttpNetworkSession* http_session, - const SpdySessionKey& key, - Error expected_error, - const NetLogWithSource& net_log); - // Creates a SPDY session for the given key and puts it in the SPDY // session pool in |http_session|. A SPDY session for |key| must not // already exist. @@ -276,7 +266,7 @@ base::WeakPtr<SpdySession> TryCreateFakeSpdySessionExpectingFailure( SpdySessionPool* pool, const SpdySessionKey& key, - Error expected_error); + Error expected_status); class SpdySessionPoolPeer { public:
diff --git a/net/tools/transport_security_state_generator/BUILD.gn b/net/tools/transport_security_state_generator/BUILD.gn index 73c07c4..f0fa6c8 100644 --- a/net/tools/transport_security_state_generator/BUILD.gn +++ b/net/tools/transport_security_state_generator/BUILD.gn
@@ -66,4 +66,11 @@ "//crypto", "//third_party/boringssl", ] + + if (is_win) { + # Work around incremental linking randomly creating corrupt binaries, + # crbug.com/644525. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } }
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 78035d8..9176353 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -32,7 +32,6 @@ #include "net/log/net_log_event_type.h" #include "net/log/net_log_source_type.h" #include "net/ssl/ssl_cert_request_info.h" -#include "net/url_request/network_error_logging_delegate.h" #include "net/url_request/redirect_info.h" #include "net/url_request/redirect_util.h" #include "net/url_request/url_request_context.h" @@ -44,6 +43,10 @@ #include "url/gurl.h" #include "url/origin.h" +#if BUILDFLAG(ENABLE_REPORTING) +#include "net/url_request/network_error_logging_delegate.h" +#endif // BUILDFLAG(ENABLE_REPORTING) + using base::Time; using std::string; @@ -1055,11 +1058,11 @@ return g_default_can_use_cookies; } -bool URLRequest::CanSetCookie(const std::string& cookie_line, +bool URLRequest::CanSetCookie(const net::CanonicalCookie& cookie, CookieOptions* options) const { DCHECK(!(load_flags_ & LOAD_DO_NOT_SAVE_COOKIES)); if (network_delegate_) { - return network_delegate_->CanSetCookie(*this, cookie_line, options); + return network_delegate_->CanSetCookie(*this, cookie, options); } return g_default_can_use_cookies; } @@ -1135,7 +1138,9 @@ network_delegate_->NotifyCompleted(this, job_.get() != NULL, status_.error()); +#if BUILDFLAG(ENABLE_REPORTING) MaybeGenerateNetworkErrorLoggingReport(); +#endif // BUILDFLAG(ENABLE_REPORTING) } void URLRequest::OnCallToDelegate() { @@ -1154,6 +1159,7 @@ net_log_.EndEvent(NetLogEventType::URL_REQUEST_DELEGATE); } +#if BUILDFLAG(ENABLE_REPORTING) void URLRequest::MaybeGenerateNetworkErrorLoggingReport() { NetworkErrorLoggingDelegate* delegate = context()->network_error_logging_delegate(); @@ -1186,6 +1192,7 @@ delegate->OnNetworkError(details); } +#endif // BUILDFLAG(ENABLE_REPORTING) void URLRequest::GetConnectionAttempts(ConnectionAttempts* out) const { if (job_)
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index 25fb079..0635448 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h
@@ -34,6 +34,7 @@ #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" #include "net/log/net_log_with_source.h" +#include "net/net_features.h" #include "net/proxy/proxy_server.h" #include "net/socket/connection_attempts.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -764,7 +765,7 @@ // If |network_delegate_| is NULL, cookies can be used unless // SetDefaultCookiePolicyToBlock() has been called. bool CanGetCookies(const CookieList& cookie_list) const; - bool CanSetCookie(const std::string& cookie_line, + bool CanSetCookie(const net::CanonicalCookie& cookie, CookieOptions* options) const; bool CanEnablePrivacyMode() const; @@ -774,7 +775,9 @@ // cancellation. void OnCallToDelegateComplete(); +#if BUILDFLAG(ENABLE_REPORTING) void MaybeGenerateNetworkErrorLoggingReport(); +#endif // BUILDFLAG(ENABLE_REPORTING) // Contextual information used for this request. Cannot be NULL. This contains // most of the dependencies which are shared between requests (disk cache,
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc index b9237be..b19870f 100644 --- a/net/url_request/url_request_context.cc +++ b/net/url_request/url_request_context.cc
@@ -45,8 +45,10 @@ job_factory_(nullptr), throttler_manager_(nullptr), network_quality_estimator_(nullptr), +#if BUILDFLAG(ENABLE_REPORTING) reporting_service_(nullptr), network_error_logging_delegate_(nullptr), +#endif // BUILDFLAG(ENABLE_REPORTING) enable_brotli_(false), check_cleartext_permitted_(false), name_("unknown"), @@ -82,8 +84,10 @@ set_throttler_manager(other->throttler_manager_); set_http_user_agent_settings(other->http_user_agent_settings_); set_network_quality_estimator(other->network_quality_estimator_); +#if BUILDFLAG(ENABLE_REPORTING) set_reporting_service(other->reporting_service_); set_network_error_logging_delegate(other->network_error_logging_delegate_); +#endif // BUILDFLAG(ENABLE_REPORTING) set_enable_brotli(other->enable_brotli_); set_check_cleartext_permitted(other->check_cleartext_permitted_); }
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h index f21ba46b..c498ad2 100644 --- a/net/url_request/url_request_context.h +++ b/net/url_request/url_request_context.h
@@ -22,6 +22,7 @@ #include "net/http/http_network_session.h" #include "net/http/http_server_properties.h" #include "net/http/transport_security_state.h" +#include "net/net_features.h" #include "net/ssl/ssl_config_service.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request.h" @@ -44,14 +45,17 @@ class HttpUserAgentSettings; class NetLog; class NetworkDelegate; -class NetworkErrorLoggingDelegate; class NetworkQualityEstimator; -class ReportingService; class ProxyService; class URLRequest; class URLRequestJobFactory; class URLRequestThrottlerManager; +#if BUILDFLAG(ENABLE_REPORTING) +class NetworkErrorLoggingDelegate; +class ReportingService; +#endif // BUILDFLAG(ENABLE_REPORTING) + // Subclass to provide application-specific context for URLRequest // instances. URLRequestContext does not own these member variables, since they // may be shared with other contexts. URLRequestContextStorage can be used for @@ -244,6 +248,7 @@ network_quality_estimator_ = network_quality_estimator; } +#if BUILDFLAG(ENABLE_REPORTING) ReportingService* reporting_service() const { return reporting_service_; } void set_reporting_service(ReportingService* reporting_service) { reporting_service_ = reporting_service; @@ -256,6 +261,7 @@ NetworkErrorLoggingDelegate* network_error_logging_delegate) { network_error_logging_delegate_ = network_error_logging_delegate; } +#endif // BUILDFLAG(ENABLE_REPORTING) void set_enable_brotli(bool enable_brotli) { enable_brotli_ = enable_brotli; } @@ -312,8 +318,10 @@ const URLRequestJobFactory* job_factory_; URLRequestThrottlerManager* throttler_manager_; NetworkQualityEstimator* network_quality_estimator_; +#if BUILDFLAG(ENABLE_REPORTING) ReportingService* reporting_service_; NetworkErrorLoggingDelegate* network_error_logging_delegate_; +#endif // BUILDFLAG(ENABLE_REPORTING) // --------------------------------------------------------------------------- // Important: When adding any new members below, consider whether they need to
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc index cbcf9eef..fb354c3a 100644 --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc
@@ -59,8 +59,10 @@ #endif #if BUILDFLAG(ENABLE_REPORTING) +#include "net/network_error_logging/network_error_logging_service.h" #include "net/reporting/reporting_policy.h" #include "net/reporting/reporting_service.h" +#include "net/url_request/network_error_logging_delegate.h" #endif // BUILDFLAG(ENABLE_REPORTING) namespace net { @@ -123,7 +125,7 @@ } bool OnCanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) override { return true; } @@ -205,7 +207,12 @@ pac_quick_check_enabled_(true), pac_sanitize_url_policy_(ProxyService::SanitizeUrlPolicy::SAFE), shared_proxy_delegate_(nullptr), - shared_http_auth_handler_factory_(nullptr) { +#if BUILDFLAG(ENABLE_REPORTING) + shared_http_auth_handler_factory_(nullptr), + network_error_logging_enabled_(false) { +#else // !BUILDFLAG(ENABLE_REPORTING) + shared_http_auth_handler_factory_(nullptr){ +#endif // !BUILDFLAG(ENABLE_REPORTING) } URLRequestContextBuilder::~URLRequestContextBuilder() {} @@ -616,10 +623,27 @@ storage->set_job_factory(std::move(top_job_factory)); #if BUILDFLAG(ENABLE_REPORTING) + // Note: ReportingService::Create and NetworkErrorLoggingService::Create can + // both return nullptr if the corresponding base::Feature is disabled. + if (reporting_policy_) { storage->set_reporting_service( ReportingService::Create(*reporting_policy_, context.get())); } + + if (network_error_logging_enabled_) { + storage->set_network_error_logging_delegate( + NetworkErrorLoggingService::Create()); + } + + // If both Reporting and Network Error Logging are actually enabled, then + // connect them so Network Error Logging can use Reporting to deliver error + // reports. + if (context->reporting_service() && + context->network_error_logging_delegate()) { + context->network_error_logging_delegate()->SetReportingService( + context->reporting_service()); + } #endif // BUILDFLAG(ENABLE_REPORTING) return std::move(context);
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h index eee4163..f8109d39 100644 --- a/net/url_request/url_request_context_builder.h +++ b/net/url_request/url_request_context_builder.h
@@ -56,10 +56,13 @@ class HttpServerProperties; class NetworkQualityEstimator; class ProxyConfigService; -struct ReportingPolicy; class URLRequestContext; class URLRequestInterceptor; +#if BUILDFLAG(ENABLE_REPORTING) +struct ReportingPolicy; +#endif // BUILDFLAG(ENABLE_REPORTING) + // A URLRequestContextBuilder creates a single URLRequestContext. It provides // methods to manage various URLRequestContext components which should be called // before creating the Context. Once configuration is complete, calling Build() @@ -294,6 +297,10 @@ #if BUILDFLAG(ENABLE_REPORTING) void set_reporting_policy( std::unique_ptr<net::ReportingPolicy> reporting_policy); + + void set_network_error_logging_enabled(bool network_error_logging_enabled) { + network_error_logging_enabled_ = network_error_logging_enabled; + } #endif // BUILDFLAG(ENABLE_REPORTING) void SetInterceptors(std::vector<std::unique_ptr<URLRequestInterceptor>> @@ -395,6 +402,7 @@ std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer_; #if BUILDFLAG(ENABLE_REPORTING) std::unique_ptr<net::ReportingPolicy> reporting_policy_; + bool network_error_logging_enabled_; #endif // BUILDFLAG(ENABLE_REPORTING) std::vector<std::unique_ptr<URLRequestInterceptor>> url_request_interceptors_; CreateInterceptingJobFactory create_intercepting_job_factory_;
diff --git a/net/url_request/url_request_context_storage.cc b/net/url_request/url_request_context_storage.cc index d191fffa..703bf56 100644 --- a/net/url_request/url_request_context_storage.cc +++ b/net/url_request/url_request_context_storage.cc
@@ -21,13 +21,13 @@ #include "net/proxy/proxy_service.h" #include "net/ssl/channel_id_service.h" #include "net/url_request/http_user_agent_settings.h" -#include "net/url_request/network_error_logging_delegate.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job_factory.h" #include "net/url_request/url_request_throttler_manager.h" #if BUILDFLAG(ENABLE_REPORTING) #include "net/reporting/reporting_service.h" +#include "net/url_request/network_error_logging_delegate.h" #endif // BUILDFLAG(ENABLE_REPORTING) namespace net { @@ -156,7 +156,6 @@ context_->set_reporting_service(reporting_service.get()); reporting_service_ = std::move(reporting_service); } -#endif // BUILDFLAG(ENABLE_REPORTING) void URLRequestContextStorage::set_network_error_logging_delegate( std::unique_ptr<NetworkErrorLoggingDelegate> @@ -165,5 +164,6 @@ network_error_logging_delegate.get()); network_error_logging_delegate_ = std::move(network_error_logging_delegate); } +#endif // BUILDFLAG(ENABLE_REPORTING) } // namespace net
diff --git a/net/url_request/url_request_context_storage.h b/net/url_request/url_request_context_storage.h index 2557cf91..e019405 100644 --- a/net/url_request/url_request_context_storage.h +++ b/net/url_request/url_request_context_storage.h
@@ -28,16 +28,19 @@ class HttpUserAgentSettings; class NetLog; class NetworkDelegate; -class NetworkErrorLoggingDelegate; class ProxyDelegate; class ProxyService; -class ReportingService; class SSLConfigService; class TransportSecurityState; class URLRequestContext; class URLRequestJobFactory; class URLRequestThrottlerManager; +#if BUILDFLAG(ENABLE_REPORTING) +class NetworkErrorLoggingDelegate; +class ReportingService; +#endif // BUILDFLAG(ENABLE_REPORTING) + // URLRequestContextStorage is a helper class that provides storage for unowned // member variables of URLRequestContext. class NET_EXPORT URLRequestContextStorage { @@ -84,11 +87,11 @@ #if BUILDFLAG(ENABLE_REPORTING) void set_reporting_service( std::unique_ptr<ReportingService> reporting_service); -#endif // BUILDFLAG(ENABLE_REPORTING) void set_network_error_logging_delegate( std::unique_ptr<NetworkErrorLoggingDelegate> network_error_logging_delegate); +#endif // BUILDFLAG(ENABLE_REPORTING) // Everything else can be access through the URLRequestContext, but this // cannot. Having an accessor for it makes usage a little cleaner. @@ -126,10 +129,11 @@ std::unique_ptr<HttpTransactionFactory> http_transaction_factory_; std::unique_ptr<URLRequestJobFactory> job_factory_; std::unique_ptr<URLRequestThrottlerManager> throttler_manager_; + #if BUILDFLAG(ENABLE_REPORTING) std::unique_ptr<ReportingService> reporting_service_; -#endif // BUILDFLAG(ENABLE_REPORTING) std::unique_ptr<NetworkErrorLoggingDelegate> network_error_logging_delegate_; +#endif // BUILDFLAG(ENABLE_REPORTING) DISALLOW_COPY_AND_ASSIGN(URLRequestContextStorage); };
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index d6402281..fb6b6a3 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -60,7 +60,6 @@ #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_config_service.h" #include "net/url_request/http_user_agent_settings.h" -#include "net/url_request/network_error_logging_delegate.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_error_job.h" @@ -77,6 +76,7 @@ #if BUILDFLAG(ENABLE_REPORTING) #include "net/reporting/reporting_header_parser.h" #include "net/reporting/reporting_service.h" +#include "net/url_request/network_error_logging_delegate.h" #endif // BUILDFLAG(ENABLE_REPORTING) namespace { @@ -370,8 +370,10 @@ ProcessStrictTransportSecurityHeader(); ProcessPublicKeyPinsHeader(); ProcessExpectCTHeader(); +#if BUILDFLAG(ENABLE_REPORTING) ProcessReportToHeader(); ProcessNetworkErrorLoggingHeader(); +#endif // BUILDFLAG(ENABLE_REPORTING) // The HTTP transaction may be restarted several times for the purposes // of sending authorization information. Each time it restarts, we get @@ -648,14 +650,17 @@ // Set all cookies, without waiting for them to be set. Any subsequent read // will see the combined result of all cookie operation. const base::StringPiece name("Set-Cookie"); - std::string cookie; + std::string cookie_line; size_t iter = 0; HttpResponseHeaders* headers = GetResponseHeaders(); - while (headers->EnumerateHeader(&iter, name, &cookie)) { - if (cookie.empty() || !CanSetCookie(cookie, &options)) + while (headers->EnumerateHeader(&iter, name, &cookie_line)) { + std::unique_ptr<CanonicalCookie> cookie = net::CanonicalCookie::Create( + request_->url(), cookie_line, base::Time::Now(), options); + if (!cookie || !CanSetCookie(*cookie, &options)) continue; - request_->context()->cookie_store()->SetCookieWithOptionsAsync( - request_->url(), cookie, options, CookieStore::SetCookiesCallback()); + request_->context()->cookie_store()->SetCanonicalCookieAsync( + std::move(cookie), request_->url().SchemeIsCryptographic(), + !options.exclude_httponly(), net::CookieStore::SetCookiesCallback()); } } @@ -746,10 +751,10 @@ } } +#if BUILDFLAG(ENABLE_REPORTING) void URLRequestHttpJob::ProcessReportToHeader() { DCHECK(response_info_); -#if BUILDFLAG(ENABLE_REPORTING) HttpResponseHeaders* headers = GetResponseHeaders(); std::string value; if (!headers->GetNormalizedHeader("Report-To", &value)) @@ -775,7 +780,6 @@ } service->ProcessHeader(request_info_.url.GetOrigin(), value); -#endif // BUILDFLAG(ENABLE_REPORTING) } void URLRequestHttpJob::ProcessNetworkErrorLoggingHeader() { @@ -801,6 +805,7 @@ delegate->OnHeader(url::Origin::Create(request_info_.url), value); } +#endif // BUILDFLAG(ENABLE_REPORTING) void URLRequestHttpJob::OnStartCompleted(int result) { TRACE_EVENT0(kNetTracingCategory, "URLRequestHttpJob::OnStartCompleted");
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h index 307c594f..1f050c2c 100644 --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h
@@ -21,6 +21,7 @@ #include "net/base/net_export.h" #include "net/cookies/cookie_store.h" #include "net/http/http_request_info.h" +#include "net/net_features.h" #include "net/socket/connection_attempts.h" #include "net/url_request/url_request_job.h" #include "net/url_request/url_request_throttler_entry_interface.h" @@ -93,6 +94,7 @@ // when a connection violates the Expect CT policy. void ProcessExpectCTHeader(); +#if BUILDFLAG(ENABLE_REPORTING) // Processes the Report-To header, if one exists. This header configures where // the Reporting API (in //net/reporting) will send reports for the origin. void ProcessReportToHeader(); @@ -101,6 +103,7 @@ // network errors will be reported to a specified group of endpoints using the // Reporting API. void ProcessNetworkErrorLoggingHeader(); +#endif // BUILDFLAG(ENABLE_REPORTING) // |result| should be OK, or the request is canceled. void OnHeadersReceivedCallback(int result);
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index 871c375..706696d 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -356,9 +356,9 @@ return request_->CanGetCookies(cookie_list); } -bool URLRequestJob::CanSetCookie(const std::string& cookie_line, +bool URLRequestJob::CanSetCookie(const net::CanonicalCookie& cookie, CookieOptions* options) const { - return request_->CanSetCookie(cookie_line, options); + return request_->CanSetCookie(cookie, options); } bool URLRequestJob::CanEnablePrivacyMode() const {
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h index 5a8d24fc..389315a 100644 --- a/net/url_request/url_request_job.h +++ b/net/url_request/url_request_job.h
@@ -261,7 +261,7 @@ bool CanGetCookies(const CookieList& cookie_list) const; // Delegates to URLRequest::Delegate. - bool CanSetCookie(const std::string& cookie_line, + bool CanSetCookie(const net::CanonicalCookie& cookie, CookieOptions* options) const; // Delegates to URLRequest::Delegate.
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index 58cdf2d4..17cd976 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc
@@ -634,7 +634,7 @@ } bool TestNetworkDelegate::OnCanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) { bool allow = true; if (cookie_options_bit_mask_ & NO_SET_COOKIE)
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h index 6f8c1869..9955074 100644 --- a/net/url_request/url_request_test_util.h +++ b/net/url_request/url_request_test_util.h
@@ -354,7 +354,7 @@ bool OnCanGetCookies(const URLRequest& request, const CookieList& cookie_list) override; bool OnCanSetCookie(const URLRequest& request, - const std::string& cookie_line, + const net::CanonicalCookie& cookie, CookieOptions* options) override; bool OnCanAccessFile(const URLRequest& request, const base::FilePath& original_path,
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 9db68697..f7c592d 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -110,7 +110,6 @@ #include "net/test/url_request/url_request_failed_job.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/data_protocol_handler.h" -#include "net/url_request/network_error_logging_delegate.h" #include "net/url_request/static_http_user_agent_settings.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_filter.h" @@ -146,6 +145,7 @@ #if BUILDFLAG(ENABLE_REPORTING) #include "net/reporting/reporting_service.h" +#include "net/url_request/network_error_logging_delegate.h" #endif // BUILDFLAG(ENABLE_REPORTING) #if defined(USE_BUILTIN_CERT_VERIFIER) @@ -2523,19 +2523,19 @@ namespace { // Less verbose way of running a simple testserver for the tests below. -class LocalHttpTestServer : public EmbeddedTestServer { +class HttpTestServer : public EmbeddedTestServer { public: - explicit LocalHttpTestServer(const base::FilePath& document_root) { + explicit HttpTestServer(const base::FilePath& document_root) { AddDefaultHandlers(document_root); } - LocalHttpTestServer() { AddDefaultHandlers(base::FilePath()); } + HttpTestServer() { AddDefaultHandlers(base::FilePath()); } }; } // namespace TEST_F(URLRequestTest, DelayedCookieCallback) { - LocalHttpTestServer test_server; + HttpTestServer test_server; ASSERT_TRUE(test_server.Start()); TestURLRequestContext context; @@ -2576,7 +2576,7 @@ } TEST_F(URLRequestTest, DoNotSendCookies) { - LocalHttpTestServer test_server; + HttpTestServer test_server; ASSERT_TRUE(test_server.Start()); // Set up a cookie. @@ -2632,7 +2632,7 @@ } TEST_F(URLRequestTest, DoNotSaveCookies) { - LocalHttpTestServer test_server; + HttpTestServer test_server; ASSERT_TRUE(test_server.Start()); // Set up a cookie. @@ -2693,7 +2693,7 @@ } TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy) { - LocalHttpTestServer test_server; + HttpTestServer test_server; ASSERT_TRUE(test_server.Start()); // Set up a cookie. @@ -2756,7 +2756,7 @@ #define MAYBE_DoNotSaveCookies_ViaPolicy DoNotSaveCookies_ViaPolicy #endif TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy) { - LocalHttpTestServer test_server; + HttpTestServer test_server; ASSERT_TRUE(test_server.Start()); // Set up a cookie. @@ -2813,7 +2813,7 @@ } TEST_F(URLRequestTest, DoNotSaveEmptyCookies) { - LocalHttpTestServer test_server; + HttpTestServer test_server; ASSERT_TRUE(test_server.Start()); // Set up an empty cookie. @@ -2834,7 +2834,7 @@ } TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy_Async) { - LocalHttpTestServer test_server; + HttpTestServer test_server; ASSERT_TRUE(test_server.Start()); // Set up a cookie. @@ -2891,7 +2891,7 @@ } TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) { - LocalHttpTestServer test_server; + HttpTestServer test_server; ASSERT_TRUE(test_server.Start()); // Set up a cookie. @@ -2948,7 +2948,7 @@ } TEST_F(URLRequestTest, SameSiteCookies) { - LocalHttpTestServer test_server; + HttpTestServer test_server; ASSERT_TRUE(test_server.Start()); TestNetworkDelegate network_delegate; @@ -3438,7 +3438,7 @@ // skew and that we handle incorrect timezone specifier "UTC" in HTTP Date // headers by defaulting to GMT. (crbug.com/135131) TEST_F(URLRequestTest, AcceptClockSkewCookieWithWrongDateTimezone) { - LocalHttpTestServer test_server; + HttpTestServer test_server; ASSERT_TRUE(test_server.Start()); // Set up an expired cookie. @@ -3497,7 +3497,7 @@ // Check that it is impossible to change the referrer in the extra headers of // an URLRequest. TEST_F(URLRequestTest, DoNotOverrideReferrer) { - LocalHttpTestServer test_server; + HttpTestServer test_server; ASSERT_TRUE(test_server.Start()); // If extra headers contain referer and the request contains a referer, @@ -3691,10 +3691,10 @@ return true; } - LocalHttpTestServer* http_test_server() { return &test_server_; } + HttpTestServer* http_test_server() { return &test_server_; } private: - LocalHttpTestServer test_server_; + HttpTestServer test_server_; }; namespace {
diff --git a/printing/printed_document.cc b/printing/printed_document.cc index f923d09..f541f3df 100644 --- a/printing/printed_document.cc +++ b/printing/printed_document.cc
@@ -132,7 +132,7 @@ base::AutoLock lock(lock_); mutable_.pages_[page_number] = page; -#if defined(OS_POSIX) && !defined(OS_MACOSX) +#if defined(OS_POSIX) mutable_.first_page = std::min(mutable_.first_page, page_number); #endif } @@ -164,7 +164,7 @@ return false; for (; page != PageNumber::npos(); ++page) { -#if defined(OS_WIN) || defined(OS_MACOSX) +#if defined(OS_WIN) const bool metafile_must_be_valid = true; #elif defined(OS_POSIX) const bool metafile_must_be_valid = (page.ToInt() == mutable_.first_page);
diff --git a/printing/printed_document.h b/printing/printed_document.h index db782105..3ccfb064 100644 --- a/printing/printed_document.h +++ b/printing/printed_document.h
@@ -132,7 +132,7 @@ // The total number of pages in the document. int page_count_ = 0; -#if defined(OS_POSIX) && !defined(OS_MACOSX) +#if defined(OS_POSIX) // Page number of the first page. int first_page = INT_MAX; #endif
diff --git a/printing/printed_document_mac.cc b/printing/printed_document_mac.cc index f7addc52..3224d12 100644 --- a/printing/printed_document_mac.cc +++ b/printing/printed_document_mac.cc
@@ -16,26 +16,47 @@ void PrintedDocument::RenderPrintedPage( const PrintedPage& page, printing::NativeDrawingContext context) const { -#ifndef NDEBUG - { - // Make sure the page is from our list. - base::AutoLock lock(lock_); - DCHECK(&page == mutable_.pages_.find(page.page_number() - 1)->second.get()); - } -#endif - DCHECK(context); - const PageSetup& page_setup(immutable_.settings_.page_setup_device_units()); + // |mutable_.pages_| is 0-based, whereas the page number is 1-based. + const int page_index = page.page_number() - 1; + + const MetafilePlayer* metafile; + size_t metafile_page_number; + { + base::AutoLock lock(lock_); + + // Make sure |page| is from our list. + DCHECK(&page == mutable_.pages_.find(page_index)->second.get()); + + // Make sure the first page exists in the list too. + DCHECK_GE(mutable_.first_page, 0); + DCHECK_NE(mutable_.first_page, INT_MAX); + DCHECK(mutable_.pages_.find(mutable_.first_page)->second.get()); + + // Always use the metafile from the first page. + metafile = mutable_.pages_.find(mutable_.first_page)->second->metafile(); + + // Figure out the mapping from |page| to the page inside |metafile|. + // e.g. If |metafile| contains 3 pages that corresponds to pages 1, 5, 7, + // then page 5 has index 1, which is page number 2. + // Use 1-based page number here because that is what RenderPage() takes. + metafile_page_number = 1; + for (const auto& it : mutable_.pages_) { + if (it.first == page_index) + break; + ++metafile_page_number; + } + } + + const PageSetup& page_setup = immutable_.settings_.page_setup_device_units(); gfx::Rect content_area = page.GetCenteredPageContentRect(page_setup.physical_size()); - const MetafilePlayer* metafile = page.metafile(); - // Each Metafile is a one-page PDF, and pages use 1-based indexing. - const int page_number = 1; struct Metafile::MacRenderPageParams params; params.autorotate = true; - metafile->RenderPage(page_number, context, content_area.ToCGRect(), params); + metafile->RenderPage(metafile_page_number, context, content_area.ToCGRect(), + params); } } // namespace printing
diff --git a/remoting/base/session_options.cc b/remoting/base/session_options.cc index e39c436f9..b152274 100644 --- a/remoting/base/session_options.cc +++ b/remoting/base/session_options.cc
@@ -33,12 +33,19 @@ } // namespace SessionOptions::SessionOptions() = default; -SessionOptions::~SessionOptions() = default; +SessionOptions::SessionOptions(const SessionOptions& other) = default; +SessionOptions::SessionOptions(SessionOptions&& other) = default; SessionOptions::SessionOptions(const std::string& parameter) { Import(parameter); } +SessionOptions::~SessionOptions() = default; + +SessionOptions& SessionOptions::operator=( + const SessionOptions& other) = default; +SessionOptions& SessionOptions::operator=(SessionOptions&& other) = default; + void SessionOptions::Append(const std::string& key, const std::string& value) { DCHECK(KeyIsValid(key));
diff --git a/remoting/base/session_options.h b/remoting/base/session_options.h index 86f7d64..bc2c3fdc 100644 --- a/remoting/base/session_options.h +++ b/remoting/base/session_options.h
@@ -8,7 +8,6 @@ #include <map> #include <string> -#include "base/macros.h" #include "base/optional.h" namespace remoting { @@ -19,9 +18,14 @@ class SessionOptions final { public: SessionOptions(); + SessionOptions(const SessionOptions& other); + SessionOptions(SessionOptions&& other); + explicit SessionOptions(const std::string& parameter); + ~SessionOptions(); - SessionOptions(const std::string& parameter); + SessionOptions& operator=(const SessionOptions& other); + SessionOptions& operator=(SessionOptions&& other); // Appends one key-value pair into current instance. void Append(const std::string& key, const std::string& value); @@ -51,10 +55,6 @@ private: std::map<std::string, std::string> options_; - - SessionOptions(SessionOptions&&) = delete; - SessionOptions& operator=(SessionOptions&&) = delete; - DISALLOW_COPY_AND_ASSIGN(SessionOptions); }; } // namespace remoting
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc index 66dad79..a9026a7 100644 --- a/remoting/host/client_session.cc +++ b/remoting/host/client_session.cc
@@ -247,11 +247,7 @@ const SessionOptions session_options( host_experiment_session_plugin_.configuration()); - base::Optional<std::string> video_codec = - session_options.Get("Video-Codec"); - if (video_codec) { - connection_->SetPreferredVideoCodec(*video_codec); - } + connection_->ApplySessionOptions(session_options); DesktopEnvironmentOptions options = desktop_environment_options_; options.ApplySessionOptions(session_options);
diff --git a/remoting/ios/app/remoting_view_controller.mm b/remoting/ios/app/remoting_view_controller.mm index c469cb4..fbb8f80 100644 --- a/remoting/ios/app/remoting_view_controller.mm +++ b/remoting/ios/app/remoting_view_controller.mm
@@ -57,12 +57,11 @@ struct sockaddr_in addr = {0}; addr.sin_len = sizeof(addr); addr.sin_family = AF_INET; - SCNetworkReachabilityRef reachability = + base::ScopedCFTypeRef<SCNetworkReachabilityRef> reachability( SCNetworkReachabilityCreateWithAddress( - kCFAllocatorDefault, reinterpret_cast<struct sockaddr*>(&addr)); + kCFAllocatorDefault, reinterpret_cast<struct sockaddr*>(&addr))); SCNetworkReachabilityFlags flags; BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags); - CFRelease(reachability); if (!success) { return ConnectionType::UNKNOWN; }
diff --git a/remoting/ios/keychain_wrapper.mm b/remoting/ios/keychain_wrapper.mm index 1c3ed25e..593c7ab 100644 --- a/remoting/ios/keychain_wrapper.mm +++ b/remoting/ios/keychain_wrapper.mm
@@ -9,6 +9,7 @@ #import "remoting/ios/keychain_wrapper.h" #include "base/logging.h" +#include "base/mac/scoped_cftyperef.h" #import "remoting/ios/domain/host_info.h" @@ -53,25 +54,23 @@ [_userInfoQuery setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes]; - // TODO(crbug.com/773503): Use ScopedCFTypeRef. - CFMutableDictionaryRef outDictionary = nil; - keychainErr = SecItemCopyMatching((__bridge CFDictionaryRef)_userInfoQuery, - (CFTypeRef*)&outDictionary); + base::ScopedCFTypeRef<CFMutableDictionaryRef> outDictionary; + keychainErr = + SecItemCopyMatching((__bridge CFDictionaryRef)_userInfoQuery, + (CFTypeRef*)outDictionary.InitializeInto()); if (keychainErr == noErr) { _keychainData = [self secItemFormatToDictionary:(__bridge_transfer NSMutableDictionary*) - outDictionary]; + outDictionary.release()]; } else if (keychainErr == errSecItemNotFound) { [self resetKeychainItem]; if (outDictionary) { - CFRelease(outDictionary); _keychainData = nil; } } else { LOG(FATAL) << "Serious error: " << keychainErr; if (outDictionary) { - CFRelease(outDictionary); _keychainData = nil; } } @@ -230,42 +229,36 @@ [returnDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; - CFDataRef passwordData = NULL; + base::ScopedCFTypeRef<CFDataRef> passwordData; OSStatus keychainError = noErr; - keychainError = SecItemCopyMatching( - (__bridge CFDictionaryRef)returnDictionary, (CFTypeRef*)&passwordData); + keychainError = + SecItemCopyMatching((__bridge CFDictionaryRef)returnDictionary, + (CFTypeRef*)passwordData.InitializeInto()); if (keychainError == noErr) { [returnDictionary removeObjectForKey:(__bridge id)kSecReturnData]; - NSString* password = [[NSString alloc] - initWithBytes:[(__bridge_transfer NSData*)passwordData bytes] - length:[(__bridge NSData*)passwordData length] - encoding:NSUTF8StringEncoding]; + NSString* password = + [[NSString alloc] initWithBytes:CFDataGetBytePtr(passwordData) + length:CFDataGetLength(passwordData) + encoding:NSUTF8StringEncoding]; [returnDictionary setObject:password forKey:(__bridge id)kSecValueData]; } else if (keychainError == errSecItemNotFound) { LOG(WARNING) << "Nothing was found in the keychain."; - if (passwordData) { - CFRelease(passwordData); - passwordData = nil; - } } else { LOG(FATAL) << "Serious error: " << keychainError; - if (passwordData) { - CFRelease(passwordData); - passwordData = nil; - } } return returnDictionary; } - (void)writeToKeychain { - CFDictionaryRef attributes = nil; + base::ScopedCFTypeRef<CFDictionaryRef> attributes; NSMutableDictionary* updateItem = nil; if (SecItemCopyMatching((__bridge CFDictionaryRef)_userInfoQuery, - (CFTypeRef*)&attributes) == noErr) { + (CFTypeRef*)attributes.InitializeInto()) == noErr) { updateItem = [NSMutableDictionary - dictionaryWithDictionary:(__bridge_transfer NSDictionary*)attributes]; + dictionaryWithDictionary:(__bridge_transfer NSDictionary*) + attributes.release()]; [updateItem setObject:[_userInfoQuery objectForKey:(__bridge id)kSecClass] forKey:(__bridge id)kSecClass]; @@ -288,10 +281,6 @@ if (errorcode != noErr) { LOG(FATAL) << "Couldn't add the Keychain Item. errorcode: " << errorcode; } - if (attributes) { - CFRelease(attributes); - attributes = nil; - } } }
diff --git a/remoting/protocol/connection_to_client.h b/remoting/protocol/connection_to_client.h index 9de3b861..8d1a6ab 100644 --- a/remoting/protocol/connection_to_client.h +++ b/remoting/protocol/connection_to_client.h
@@ -9,6 +9,7 @@ #include <string> +#include "remoting/base/session_options.h" #include "remoting/protocol/message_pipe.h" #include "remoting/protocol/transport.h" @@ -100,9 +101,10 @@ virtual void set_host_stub(HostStub* host_stub) = 0; virtual void set_input_stub(InputStub* input_stub) = 0; - // Set the preferred video codec for the connection. Implementations can - // ignore this function if no extra codec can be chosen from. - virtual void SetPreferredVideoCodec(const std::string& codec) {} + // Applies the |options| to current session. SessionOptions usually controls + // experimental behaviors, implementations can ignore this function if no + // control logic can be applied. + virtual void ApplySessionOptions(const SessionOptions& options) {} }; } // namespace protocol
diff --git a/remoting/protocol/webrtc_connection_to_client.cc b/remoting/protocol/webrtc_connection_to_client.cc index c53893a..7b951e0 100644 --- a/remoting/protocol/webrtc_connection_to_client.cc +++ b/remoting/protocol/webrtc_connection_to_client.cc
@@ -82,7 +82,8 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(transport_); - std::unique_ptr<WebrtcVideoStream> stream(new WebrtcVideoStream()); + std::unique_ptr<WebrtcVideoStream> stream( + new WebrtcVideoStream(session_options_)); stream->Start(std::move(desktop_capturer), transport_.get(), video_encode_task_runner_); stream->SetEventTimestampsSource( @@ -122,10 +123,11 @@ event_dispatcher_->set_input_stub(input_stub); } -void WebrtcConnectionToClient::SetPreferredVideoCodec( - const std::string& codec) { +void WebrtcConnectionToClient::ApplySessionOptions( + const SessionOptions& options) { + session_options_ = options; DCHECK(transport_); - transport_->SetPreferredVideoCodec(codec); + transport_->ApplySessionOptions(options); } void WebrtcConnectionToClient::OnSessionStateChange(Session::State state) {
diff --git a/remoting/protocol/webrtc_connection_to_client.h b/remoting/protocol/webrtc_connection_to_client.h index da364cf..7e027cd 100644 --- a/remoting/protocol/webrtc_connection_to_client.h +++ b/remoting/protocol/webrtc_connection_to_client.h
@@ -50,7 +50,7 @@ void set_clipboard_stub(ClipboardStub* clipboard_stub) override; void set_host_stub(HostStub* host_stub) override; void set_input_stub(InputStub* input_stub) override; - void SetPreferredVideoCodec(const std::string& codec) override; + void ApplySessionOptions(const SessionOptions& options) override; // Session::EventHandler interface. void OnSessionStateChange(Session::State state) override; @@ -84,6 +84,8 @@ scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_; + SessionOptions session_options_; + std::unique_ptr<HostControlDispatcher> control_dispatcher_; std::unique_ptr<HostEventDispatcher> event_dispatcher_; base::WeakPtrFactory<WebrtcConnectionToClient> weak_factory_;
diff --git a/remoting/protocol/webrtc_frame_scheduler_simple.cc b/remoting/protocol/webrtc_frame_scheduler_simple.cc index 8fcc08d..7a34f976 100644 --- a/remoting/protocol/webrtc_frame_scheduler_simple.cc +++ b/remoting/protocol/webrtc_frame_scheduler_simple.cc
@@ -55,8 +55,9 @@ } // namespace -// TODO(zijiehe): Make the bandwidth estimator configurable. -WebrtcFrameSchedulerSimple::WebrtcFrameSchedulerSimple() +// TODO(zijiehe): Use |options| to select bandwidth estimator. +WebrtcFrameSchedulerSimple::WebrtcFrameSchedulerSimple( + const SessionOptions& options) : pacing_bucket_(LeakyBucket::kUnlimitedDepth, 0), updated_region_area_(kStatsWindow), bandwidth_estimator_(new WebrtcBandwidthEstimator()),
diff --git a/remoting/protocol/webrtc_frame_scheduler_simple.h b/remoting/protocol/webrtc_frame_scheduler_simple.h index 1dd90f69..e270ba8 100644 --- a/remoting/protocol/webrtc_frame_scheduler_simple.h +++ b/remoting/protocol/webrtc_frame_scheduler_simple.h
@@ -14,6 +14,7 @@ #include "base/timer/timer.h" #include "remoting/base/leaky_bucket.h" #include "remoting/base/running_samples.h" +#include "remoting/base/session_options.h" #include "remoting/codec/frame_processing_time_estimator.h" #include "remoting/protocol/video_channel_state_observer.h" @@ -29,7 +30,7 @@ class WebrtcFrameSchedulerSimple : public VideoChannelStateObserver, public WebrtcFrameScheduler { public: - WebrtcFrameSchedulerSimple(); + explicit WebrtcFrameSchedulerSimple(const SessionOptions& options); ~WebrtcFrameSchedulerSimple() override; // VideoChannelStateObserver implementation.
diff --git a/remoting/protocol/webrtc_frame_scheduler_unittest.cc b/remoting/protocol/webrtc_frame_scheduler_unittest.cc index 9ffc4f6c..5ac4b5f 100644 --- a/remoting/protocol/webrtc_frame_scheduler_unittest.cc +++ b/remoting/protocol/webrtc_frame_scheduler_unittest.cc
@@ -6,6 +6,7 @@ #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "remoting/base/session_options.h" #include "remoting/protocol/webrtc_dummy_video_encoder.h" #include "remoting/protocol/webrtc_frame_scheduler_simple.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,7 +26,7 @@ task_runner_handle_(task_runner_.get()), now_(base::TimeTicks::Now()) { video_encoder_factory_.reset(new WebrtcDummyVideoEncoderFactory()); - scheduler_.reset(new WebrtcFrameSchedulerSimple()); + scheduler_.reset(new WebrtcFrameSchedulerSimple(SessionOptions())); scheduler_->SetCurrentTimeForTest(now_); scheduler_->Start(video_encoder_factory_.get(), base::Bind(&WebrtcFrameSchedulerTest::CaptureCallback,
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc index e7718c50b..dafc9f2 100644 --- a/remoting/protocol/webrtc_transport.cc +++ b/remoting/protocol/webrtc_transport.cc
@@ -13,6 +13,7 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/optional.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -489,7 +490,9 @@ SdpMessage sdp_message(description_sdp); UpdateCodecParameters(&sdp_message, /*incoming=*/false); - if (!preferred_video_codec_.empty()) { + if (preferred_video_codec_.empty()) { + sdp_message.PreferVideoCodec("VP8"); + } else { sdp_message.PreferVideoCodec(preferred_video_codec_); } description_sdp = sdp_message.ToString(); @@ -737,8 +740,11 @@ event_handler_->OnWebrtcTransportError(error); } -void WebrtcTransport::SetPreferredVideoCodec(const std::string& codec) { - preferred_video_codec_ = codec; +void WebrtcTransport::ApplySessionOptions(const SessionOptions& options) { + base::Optional<std::string> video_codec = options.Get("Video-Codec"); + if (video_codec) { + preferred_video_codec_ = *video_codec; + } } } // namespace protocol
diff --git a/remoting/protocol/webrtc_transport.h b/remoting/protocol/webrtc_transport.h index 99a6cd1d..21e56ceb6 100644 --- a/remoting/protocol/webrtc_transport.h +++ b/remoting/protocol/webrtc_transport.h
@@ -15,6 +15,7 @@ #include "base/threading/thread_checker.h" #include "base/timer/timer.h" #include "crypto/hmac.h" +#include "remoting/base/session_options.h" #include "remoting/protocol/transport.h" #include "remoting/protocol/webrtc_data_stream_adapter.h" #include "remoting/protocol/webrtc_dummy_video_encoder.h" @@ -84,7 +85,7 @@ bool ProcessTransportInfo(buzz::XmlElement* transport_info) override; void Close(ErrorCode error); - void SetPreferredVideoCodec(const std::string& codec); + void ApplySessionOptions(const SessionOptions& options); private: // PeerConnectionWrapper is responsible for PeerConnection creation,
diff --git a/remoting/protocol/webrtc_video_stream.cc b/remoting/protocol/webrtc_video_stream.cc index 04a20cb..4b83060 100644 --- a/remoting/protocol/webrtc_video_stream.cc +++ b/remoting/protocol/webrtc_video_stream.cc
@@ -66,8 +66,10 @@ uint32_t capturer_id = 0; }; -WebrtcVideoStream::WebrtcVideoStream() - : video_stats_dispatcher_(kStreamLabel), weak_factory_(this) { +WebrtcVideoStream::WebrtcVideoStream(const SessionOptions& session_options) + : video_stats_dispatcher_(kStreamLabel), + session_options_(session_options), + weak_factory_(this) { encoder_selector_.RegisterEncoder( base::Bind(&WebrtcVideoEncoderVpx::IsSupportedByVP8), base::Bind(&WebrtcVideoEncoderVpx::CreateForVP8)); @@ -139,7 +141,7 @@ result = peer_connection_->AddStream(stream_.get()); DCHECK(result); - scheduler_.reset(new WebrtcFrameSchedulerSimple()); + scheduler_.reset(new WebrtcFrameSchedulerSimple(session_options_)); scheduler_->Start( webrtc_transport_->video_encoder_factory(), base::Bind(&WebrtcVideoStream::CaptureNextFrame, base::Unretained(this)));
diff --git a/remoting/protocol/webrtc_video_stream.h b/remoting/protocol/webrtc_video_stream.h index a743fef..aef5ed7f 100644 --- a/remoting/protocol/webrtc_video_stream.h +++ b/remoting/protocol/webrtc_video_stream.h
@@ -15,6 +15,7 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" +#include "remoting/base/session_options.h" #include "remoting/codec/webrtc_video_encoder.h" #include "remoting/codec/webrtc_video_encoder_selector.h" #include "remoting/protocol/host_video_stats_dispatcher.h" @@ -38,7 +39,7 @@ public webrtc::DesktopCapturer::Callback, public HostVideoStatsDispatcher::EventHandler { public: - WebrtcVideoStream(); + explicit WebrtcVideoStream(const SessionOptions& options); ~WebrtcVideoStream() override; void Start(std::unique_ptr<webrtc::DesktopCapturer> desktop_capturer, @@ -101,6 +102,8 @@ base::ThreadChecker thread_checker_; + const SessionOptions session_options_; + base::WeakPtrFactory<WebrtcVideoStream> weak_factory_; DISALLOW_COPY_AND_ASSIGN(WebrtcVideoStream);
diff --git a/services/service_manager/sandbox/linux/sandbox_linux.cc b/services/service_manager/sandbox/linux/sandbox_linux.cc index 31c94ae..db37946 100644 --- a/services/service_manager/sandbox/linux/sandbox_linux.cc +++ b/services/service_manager/sandbox/linux/sandbox_linux.cc
@@ -198,15 +198,18 @@ pre_initialized_ = true; } -void SandboxLinux::EngageNamespaceSandbox() { +void SandboxLinux::EngageNamespaceSandbox(bool from_zygote) { CHECK(pre_initialized_); - // Check being in a new PID namespace created by the namespace sandbox and - // being the init process. - CHECK(sandbox::NamespaceSandbox::InNewPidNamespace()); - const pid_t pid = getpid(); - CHECK_EQ(1, pid); + if (from_zygote) { + // Check being in a new PID namespace created by the namespace sandbox and + // being the init process. + CHECK(sandbox::NamespaceSandbox::InNewPidNamespace()); + const pid_t pid = getpid(); + CHECK_EQ(1, pid); + } CHECK(sandbox::Credentials::MoveToNewUserNS()); + // Note: this requires SealSandbox() to be called later in this process to be // safe, as this class is keeping a file descriptor to /proc/. CHECK(sandbox::Credentials::DropFileSystemAccess(proc_fd_)); @@ -387,7 +390,7 @@ // Turn on the namespace sandbox if the zygote hasn't done so already. if (options.engage_namespace_sandbox) - EngageNamespaceSandbox(); + EngageNamespaceSandbox(false /* from_zygote */); DCHECK(!HasOpenDirectories()) << "InitializeSandbox() called after unexpected directories have been "
diff --git a/services/service_manager/sandbox/linux/sandbox_linux.h b/services/service_manager/sandbox/linux/sandbox_linux.h index 922b24b..0c75d26 100644 --- a/services/service_manager/sandbox/linux/sandbox_linux.h +++ b/services/service_manager/sandbox/linux/sandbox_linux.h
@@ -128,7 +128,7 @@ // a new unprivileged namespace. This is a layer-1 sandbox. // In order for this sandbox to be effective, it must be "sealed" by calling // InitializeSandbox(). - void EngageNamespaceSandbox(); + void EngageNamespaceSandbox(bool from_zygote); // Return a list of file descriptors to close if PreinitializeSandbox() ran // but InitializeSandbox() won't. Avoid using.
diff --git a/services/shape_detection/BUILD.gn b/services/shape_detection/BUILD.gn index 37104ed..27a7805 100644 --- a/services/shape_detection/BUILD.gn +++ b/services/shape_detection/BUILD.gn
@@ -28,10 +28,14 @@ ] libs = [ "QuartzCore.framework" ] } else if (is_win) { + sources -= [ "face_detection_provider_impl.h" ] sources += [ "barcode_detection_impl.cc", + "detection_utils_win.h", "face_detection_impl_win.cc", "face_detection_impl_win.h", + "face_detection_provider_win.cc", + "face_detection_provider_win.h", "text_detection_impl.cc", ] } else { @@ -124,6 +128,7 @@ deps = [ ":lib", "//base", + "//base/test:test_support", "//skia", "//testing/gmock", "//testing/gtest",
diff --git a/services/shape_detection/detection_utils_win.h b/services/shape_detection/detection_utils_win.h new file mode 100644 index 0000000..0950482 --- /dev/null +++ b/services/shape_detection/detection_utils_win.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 SERVICES_SHAPE_DETECTION_DETECTION_UTILS_WIN_H_ +#define SERVICES_SHAPE_DETECTION_DETECTION_UTILS_WIN_H_ + +#include <wrl\event.h> +#include <wrl\implements.h> +#include <utility> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/location.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" + +using ABI::Windows::Foundation::IAsyncOperation; +using ABI::Windows::Foundation::IAsyncOperationCompletedHandler; + +namespace shape_detection { + +namespace WRL = Microsoft::WRL; + +// This template represents an asynchronous operation which returns a result +// upon completion, internal async callback will be not called if the instance +// is deleted. RuntimeType is Windows Runtime APIs that have a result. +template <typename RuntimeType> +class AsyncOperation { + public: + using IAsyncOperationPtr = + Microsoft::WRL::ComPtr<IAsyncOperation<RuntimeType*>>; + // A callback run when the asynchronous operation completes. The callback is + // run with the IAsyncOperation that completed on success, or with an empty + // pointer in case of failure. + using Callback = base::OnceCallback<void(IAsyncOperationPtr)>; + + ~AsyncOperation() = default; + + // Creates an AsyncOperation instance which set Callback to be called when the + // asynchronous action completes. + static std::unique_ptr<AsyncOperation<RuntimeType>> Create( + Callback callback, + IAsyncOperationPtr async_op_ptr) { + auto instance = base::WrapUnique( + new AsyncOperation<RuntimeType>(std::move(callback), async_op_ptr)); + + base::WeakPtr<AsyncOperation> weak_ptr = + instance->weak_factory_.GetWeakPtr(); + scoped_refptr<base::SequencedTaskRunner> task_runner = + base::SequencedTaskRunnerHandle::Get(); + + typedef WRL::Implements<WRL::RuntimeClassFlags<WRL::ClassicCom>, + IAsyncOperationCompletedHandler<RuntimeType*>, + WRL::FtmBase> + AsyncCallback; + auto async_callback = WRL::Callback<AsyncCallback>( + [weak_ptr, task_runner](IAsyncOperation<RuntimeType*>* async_op, + AsyncStatus status) { + // A reference to |async_op| is kept in |async_op_ptr_|, safe to pass + // outside. This is happening on an OS thread. + task_runner->PostTask( + FROM_HERE, base::Bind(&AsyncOperation::AsyncCallbackInternal, + std::move(weak_ptr), async_op, status)); + + return S_OK; + }); + + const HRESULT hr = async_op_ptr->put_Completed(async_callback.Get()); + if (FAILED(hr)) { + DLOG(ERROR) << "Async put completed failed: " + << logging::SystemErrorCodeToString(hr); + return nullptr; + } + + return instance; + } + + private: + AsyncOperation(Callback callback, IAsyncOperationPtr async_op_ptr) + : async_op_ptr_(std::move(async_op_ptr)), + callback_(std::move(callback)), + weak_factory_(this) {} + + void AsyncCallbackInternal(IAsyncOperation<RuntimeType*>* async_op, + AsyncStatus status) { + DCHECK_EQ(async_op, async_op_ptr_.Get()); + + std::move(callback_).Run((async_op && status == AsyncStatus::Completed) + ? std::move(async_op_ptr_) + : nullptr); + } + + IAsyncOperationPtr async_op_ptr_; + Callback callback_; + base::WeakPtrFactory<AsyncOperation<RuntimeType>> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(AsyncOperation); +}; + +} // namespace shape_detection + +#endif // SERVICES_SHAPE_DETECTION_DETECTION_UTILS_WIN_H_ \ No newline at end of file
diff --git a/services/shape_detection/face_detection_impl_win.cc b/services/shape_detection/face_detection_impl_win.cc index 1f2704b..6b5b4df 100644 --- a/services/shape_detection/face_detection_impl_win.cc +++ b/services/shape_detection/face_detection_impl_win.cc
@@ -6,69 +6,25 @@ #include <windows.media.faceanalysis.h> -#include "base/scoped_generic.h" -#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" -#include "services/shape_detection/face_detection_provider_impl.h" - namespace shape_detection { -using base::win::ScopedHString; -using base::win::GetActivationFactory; - -void FaceDetectionProviderImpl::CreateFaceDetection( - shape_detection::mojom::FaceDetectionRequest request, - shape_detection::mojom::FaceDetectorOptionsPtr options) { - auto impl = FaceDetectionImplWin::Create(); - if (!impl) - return; - - mojo::MakeStrongBinding(std::move(impl), std::move(request)); -} - -// static -std::unique_ptr<FaceDetectionImplWin> FaceDetectionImplWin::Create() { - // FaceDetector class is only available in Win 10 onwards (v10.0.10240.0). - if (base::win::GetVersion() < base::win::VERSION_WIN10) { - DVLOG(1) << "FaceDetector not supported before Windows 10"; - return nullptr; - } - // Loads functions dynamically at runtime to prevent library dependencies. - if (!(base::win::ResolveCoreWinRTDelayload() && - ScopedHString::ResolveCoreWinRTStringDelayload())) { - DLOG(ERROR) << "Failed loading functions from combase.dll"; - return nullptr; - } - - Microsoft::WRL::ComPtr<IFaceDetectorStatics> factory; - const HRESULT hr = GetActivationFactory< - IFaceDetectorStatics, - RuntimeClass_Windows_Media_FaceAnalysis_FaceDetector>(&factory); - if (FAILED(hr)) { - DLOG(ERROR) << "IFaceDetectorStatics factory failed: " - << logging::SystemErrorCodeToString(hr); - return nullptr; - } - - boolean is_supported = FALSE; - factory->get_IsSupported(&is_supported); - return (is_supported == FALSE) - ? nullptr - : std::make_unique<FaceDetectionImplWin>(std::move(factory)); -} +base::OnceCallback<void(bool)> g_callback_for_testing; FaceDetectionImplWin::FaceDetectionImplWin( - Microsoft::WRL::ComPtr<IFaceDetectorStatics> factory) - : face_detector_factory_(std::move(factory)) {} - + Microsoft::WRL::ComPtr<IFaceDetectorStatics> factory, + Microsoft::WRL::ComPtr<IFaceDetector> face_detector) + : face_detector_factory_(std::move(factory)), + face_detector_(std::move(face_detector)) {} FaceDetectionImplWin::~FaceDetectionImplWin() = default; void FaceDetectionImplWin::Detect(const SkBitmap& bitmap, DetectCallback callback) { DCHECK_EQ(kN32_SkColorType, bitmap.colorType()); + + if (g_callback_for_testing) { + std::move(g_callback_for_testing).Run(face_detector_ ? true : false); + std::move(callback).Run(std::vector<mojom::FaceDetectionResultPtr>()); + } } } // namespace shape_detection \ No newline at end of file
diff --git a/services/shape_detection/face_detection_impl_win.h b/services/shape_detection/face_detection_impl_win.h index 4c76729..0bd3d30 100644 --- a/services/shape_detection/face_detection_impl_win.h +++ b/services/shape_detection/face_detection_impl_win.h
@@ -5,8 +5,10 @@ #ifndef SERVICES_SHAPE_DETECTION_FACE_DETECTION_IMPL_WIN_H_ #define SERVICES_SHAPE_DETECTION_FACE_DETECTION_IMPL_WIN_H_ +#include <windows.foundation.h> #include <wrl/client.h> +#include "detection_utils_win.h" #include "services/shape_detection/public/interfaces/facedetection.mojom.h" class SkBitmap; @@ -15,7 +17,9 @@ namespace Windows { namespace Media { namespace FaceAnalysis { -struct IFaceDetectorStatics; +interface IFaceDetectorStatics; +interface IFaceDetector; +class FaceDetector; } // namespace FaceAnalysis } // namespace Media } // namespace Windows @@ -23,22 +27,26 @@ namespace shape_detection { +extern base::OnceCallback<void(bool)> g_callback_for_testing; + class FaceDetectionImplWin : public mojom::FaceDetection { public: using IFaceDetectorStatics = ABI::Windows::Media::FaceAnalysis::IFaceDetectorStatics; + using FaceDetector = ABI::Windows::Media::FaceAnalysis::FaceDetector; + using IFaceDetector = ABI::Windows::Media::FaceAnalysis::IFaceDetector; - static std::unique_ptr<FaceDetectionImplWin> Create(); - - explicit FaceDetectionImplWin( - Microsoft::WRL::ComPtr<IFaceDetectorStatics> factory); + FaceDetectionImplWin(Microsoft::WRL::ComPtr<IFaceDetectorStatics> factory, + Microsoft::WRL::ComPtr<IFaceDetector> face_detector); ~FaceDetectionImplWin() override; + // mojom::FaceDetection implementation. void Detect(const SkBitmap& bitmap, mojom::FaceDetection::DetectCallback callback) override; private: Microsoft::WRL::ComPtr<IFaceDetectorStatics> face_detector_factory_; + Microsoft::WRL::ComPtr<IFaceDetector> face_detector_; DISALLOW_COPY_AND_ASSIGN(FaceDetectionImplWin); };
diff --git a/services/shape_detection/face_detection_impl_win_unittest.cc b/services/shape_detection/face_detection_impl_win_unittest.cc index 025f2d5..6c813bf 100644 --- a/services/shape_detection/face_detection_impl_win_unittest.cc +++ b/services/shape_detection/face_detection_impl_win_unittest.cc
@@ -4,7 +4,11 @@ #include "services/shape_detection/face_detection_impl_win.h" +#include "base/test/scoped_task_environment.h" #include "base/win/scoped_com_initializer.h" +#include "face_detection_impl_win.h" +#include "face_detection_provider_win.h" +#include "services/shape_detection/public/interfaces/facedetection_provider.mojom.h" #include "testing/gtest/include/gtest/gtest.h" namespace shape_detection { @@ -17,12 +21,52 @@ ASSERT_TRUE(scoped_com_initializer_->Succeeded()); } + public: + void CreateFaceDetectorCallback(bool succeeded) { EXPECT_TRUE(succeeded); } + + void DetectCallback(base::Closure quit_closure, + std::vector<mojom::FaceDetectionResultPtr> results) { + CloseConnection(quit_closure); + } + + void CloseConnection(base::Closure quit_closure) { quit_closure.Run(); } + private: std::unique_ptr<base::win::ScopedCOMInitializer> scoped_com_initializer_; + + base::test::ScopedTaskEnvironment scoped_task_environment_; }; -TEST_F(FaceDetectionImplWinTest, CreateAndDestroy) { - auto impl = FaceDetectionImplWin::Create(); +TEST_F(FaceDetectionImplWinTest, CreateFaceDetector) { + mojom::FaceDetectionProviderPtr provider; + mojom::FaceDetectionPtr face_service; + + auto request = mojo::MakeRequest(&provider); + auto providerWin = base::MakeUnique<FaceDetectionProviderWin>(); + auto* provider_ptr = providerWin.get(); + provider_ptr->binding_ = + mojo::MakeStrongBinding(std::move(providerWin), std::move(request)); + + auto options = shape_detection::mojom::FaceDetectorOptions::New(); + provider->CreateFaceDetection(mojo::MakeRequest(&face_service), + std::move(options)); + + SkBitmap bitmap; + bitmap.allocN32Pixels(100, 100); + bitmap.eraseColor(SK_ColorBLUE); + + base::RunLoop run_loop; + g_callback_for_testing = + base::BindOnce(&FaceDetectionImplWinTest::CreateFaceDetectorCallback, + base::Unretained(this)); + + face_service.set_connection_error_handler( + base::Bind(&FaceDetectionImplWinTest::CloseConnection, + base::Unretained(this), run_loop.QuitClosure())); + face_service->Detect( + bitmap, base::BindOnce(&FaceDetectionImplWinTest::DetectCallback, + base::Unretained(this), run_loop.QuitClosure())); + run_loop.Run(); } } // namespace shape_detection
diff --git a/services/shape_detection/face_detection_provider_win.cc b/services/shape_detection/face_detection_provider_win.cc new file mode 100644 index 0000000..30d7a000 --- /dev/null +++ b/services/shape_detection/face_detection_provider_win.cc
@@ -0,0 +1,110 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/shape_detection/face_detection_provider_win.h" + +#include <windows.media.faceanalysis.h> + +#include "base/scoped_generic.h" +#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 { + +using ABI::Windows::Media::FaceAnalysis::FaceDetector; +using base::win::ScopedHString; +using base::win::GetActivationFactory; + +void FaceDetectionProviderWin::CreateFaceDetection( + shape_detection::mojom::FaceDetectionRequest request, + shape_detection::mojom::FaceDetectorOptionsPtr options) { + if (async_create_detector_ops_) { + mojo::ReportBadMessage( + "FaceDetectionProvider client may only create one FaceDetection at a " + "time."); + return; + } + + // FaceDetector class is only available in Win 10 onwards (v10.0.10240.0). + if (base::win::GetVersion() < base::win::VERSION_WIN10) { + DVLOG(1) << "FaceDetector not supported before Windows 10"; + return; + } + // Loads functions dynamically at runtime to prevent library dependencies. + if (!(base::win::ResolveCoreWinRTDelayload() && + ScopedHString::ResolveCoreWinRTStringDelayload())) { + DLOG(ERROR) << "Failed loading functions from combase.dll"; + return; + } + + Microsoft::WRL::ComPtr<IFaceDetectorStatics> factory; + HRESULT hr = GetActivationFactory< + IFaceDetectorStatics, + RuntimeClass_Windows_Media_FaceAnalysis_FaceDetector>(&factory); + if (FAILED(hr)) { + DLOG(ERROR) << "IFaceDetectorStatics factory failed: " + << logging::SystemErrorCodeToString(hr); + return; + } + + boolean is_supported = FALSE; + factory->get_IsSupported(&is_supported); + if (is_supported == FALSE) + return; + + // Create an instance of FaceDetector asynchronously. + AsyncOperation<FaceDetector>::IAsyncOperationPtr async_op; + hr = factory->CreateAsync(&async_op); + if (FAILED(hr)) { + DLOG(ERROR) << "Create FaceDetector failed: " + << logging::SystemErrorCodeToString(hr); + return; + } + + // The once callback will not be called if this object is deleted, so it's + // fine to use Unretained to bind the callback. + auto async_operation = AsyncOperation<FaceDetector>::Create( + base::BindOnce(&FaceDetectionProviderWin::OnFaceDetectorCreated, + base::Unretained(this), std::move(request), + std::move(factory)), + std::move(async_op)); + if (!async_operation) + return; + + async_create_detector_ops_ = std::move(async_operation); + // When |provider| goes out of scope it will immediately closes its end of + // the message pipe, then |async_create_detector_ops_| will be deleted and the + // callback OnFaceDetectorCreated will be not called. This prevents this + // object from being destroyed before the AsyncOperation completes. + binding_->PauseIncomingMethodCallProcessing(); +} + +FaceDetectionProviderWin::FaceDetectionProviderWin() = default; +FaceDetectionProviderWin::~FaceDetectionProviderWin() = default; + +void FaceDetectionProviderWin::OnFaceDetectorCreated( + shape_detection::mojom::FaceDetectionRequest request, + Microsoft::WRL::ComPtr<IFaceDetectorStatics> factory, + AsyncOperation<FaceDetector>::IAsyncOperationPtr async_op) { + binding_->ResumeIncomingMethodCallProcessing(); + async_create_detector_ops_.reset(); + + Microsoft::WRL::ComPtr<IFaceDetector> face_detector; + const HRESULT hr = + async_op ? async_op->GetResults(face_detector.GetAddressOf()) : E_FAIL; + if (FAILED(hr)) { + DLOG(ERROR) << "GetResults failed: " + << logging::SystemErrorCodeToString(hr); + return; + } + + mojo::MakeStrongBinding(base::MakeUnique<FaceDetectionImplWin>( + std::move(factory), std::move(face_detector)), + std::move(request)); +} + +} // namespace shape_detection
diff --git a/services/shape_detection/face_detection_provider_win.h b/services/shape_detection/face_detection_provider_win.h new file mode 100644 index 0000000..249ec308 --- /dev/null +++ b/services/shape_detection/face_detection_provider_win.h
@@ -0,0 +1,55 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_SHAPE_DETECTION_FACE_DETECTION_WIN_PROVIDER_H_ +#define SERVICES_SHAPE_DETECTION_FACE_DETECTION_WIN_PROVIDER_H_ + +#include <windows.foundation.h> + +#include "detection_utils_win.h" +#include "face_detection_impl_win.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "services/shape_detection/public/interfaces/facedetection_provider.mojom.h" + +namespace shape_detection { + +class FaceDetectionProviderWin + : public shape_detection::mojom::FaceDetectionProvider { + public: + using IFaceDetectorStatics = + ABI::Windows::Media::FaceAnalysis::IFaceDetectorStatics; + using FaceDetector = ABI::Windows::Media::FaceAnalysis::FaceDetector; + using IFaceDetector = ABI::Windows::Media::FaceAnalysis::IFaceDetector; + + FaceDetectionProviderWin(); + ~FaceDetectionProviderWin() override; + + static void Create( + shape_detection::mojom::FaceDetectionProviderRequest request) { + auto provider = base::MakeUnique<FaceDetectionProviderWin>(); + auto* provider_ptr = provider.get(); + provider_ptr->binding_ = + mojo::MakeStrongBinding(std::move(provider), std::move(request)); + } + + void CreateFaceDetection( + shape_detection::mojom::FaceDetectionRequest request, + shape_detection::mojom::FaceDetectorOptionsPtr options) override; + + private: + void OnFaceDetectorCreated( + shape_detection::mojom::FaceDetectionRequest request, + Microsoft::WRL::ComPtr<IFaceDetectorStatics> factory, + AsyncOperation<FaceDetector>::IAsyncOperationPtr async_op); + + FRIEND_TEST_ALL_PREFIXES(FaceDetectionImplWinTest, CreateFaceDetector); + mojo::StrongBindingPtr<mojom::FaceDetectionProvider> binding_; + std::unique_ptr<AsyncOperation<FaceDetector>> async_create_detector_ops_; + + DISALLOW_COPY_AND_ASSIGN(FaceDetectionProviderWin); +}; + +} // namespace shape_detection + +#endif // SERVICES_SHAPE_DETECTION_FACE_DETECTION_WIN_PROVIDER_H_
diff --git a/services/shape_detection/shape_detection_service.cc b/services/shape_detection/shape_detection_service.cc index 048ce650..492ad06 100644 --- a/services/shape_detection/shape_detection_service.cc +++ b/services/shape_detection/shape_detection_service.cc
@@ -5,9 +5,14 @@ #include "services/shape_detection/shape_detection_service.h" #include "base/macros.h" +#include "build/build_config.h" #include "services/service_manager/public/cpp/service_context.h" #include "services/shape_detection/barcode_detection_impl.h" +#if defined(OS_WIN) +#include "services/shape_detection/face_detection_provider_win.h" +#else #include "services/shape_detection/face_detection_provider_impl.h" +#endif #include "services/shape_detection/text_detection_impl.h" #if defined(OS_ANDROID) @@ -38,6 +43,10 @@ ->CreateInterfaceFactory<mojom::FaceDetectionProvider>()); registry_.AddInterface( GetJavaInterfaces()->CreateInterfaceFactory<mojom::TextDetection>()); +#elif defined(OS_WIN) + registry_.AddInterface(base::Bind(&BarcodeDetectionImpl::Create)); + registry_.AddInterface(base::Bind(&TextDetectionImpl::Create)); + registry_.AddInterface(base::Bind(&FaceDetectionProviderWin::Create)); #else registry_.AddInterface(base::Bind(&BarcodeDetectionImpl::Create)); registry_.AddInterface(base::Bind(&TextDetectionImpl::Create));
diff --git a/services/ui/manifest.json b/services/ui/manifest.json index 2c578fe..3e7df926 100644 --- a/services/ui/manifest.json +++ b/services/ui/manifest.json
@@ -18,9 +18,12 @@ "ui::mojom::InputDeviceServer", "ui::mojom::WindowTreeFactory" ], - "video_detector": [ - "ui::mojom::VideoDetector" - ], + "arc_manager" : [ + "ui::mojom::Arc" + ], + "video_detector": [ + "ui::mojom::VideoDetector" + ], // Interfaces provided by mus-gpu for mus-ws. "ozone": [ "ui::ozone::mojom::DeviceCursor",
diff --git a/services/ui/public/cpp/gpu/DEPS b/services/ui/public/cpp/gpu/DEPS index 446f64fa6..01136b5 100644 --- a/services/ui/public/cpp/gpu/DEPS +++ b/services/ui/public/cpp/gpu/DEPS
@@ -1,3 +1,4 @@ include_rules = [ + "+components/arc/common", "-services/ui/common", ]
diff --git a/services/ui/public/cpp/gpu/gpu.cc b/services/ui/public/cpp/gpu/gpu.cc index 4329f3fb..393fbb5 100644 --- a/services/ui/public/cpp/gpu/gpu.cc +++ b/services/ui/public/cpp/gpu/gpu.cc
@@ -182,7 +182,12 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner) { GpuPtrFactory factory = base::BindRepeating(&DefaultFactory, connector, service_name); - return base::WrapUnique(new Gpu(std::move(factory), std::move(task_runner))); + auto gpu = + base::WrapUnique(new Gpu(std::move(factory), std::move(task_runner))); +#if defined(OS_CHROMEOS) + gpu->InitializeArc(connector, service_name); +#endif // defined(OS_CHROMEOS) + return gpu; } scoped_refptr<viz::ContextProvider> Gpu::CreateContextProvider( @@ -209,6 +214,26 @@ shared_context_provider, command_buffer_metrics::MUS_CLIENT_CONTEXT); } +#if defined(OS_CHROMEOS) +void Gpu::CreateArcVideoDecodeAccelerator( + arc::mojom::VideoDecodeAcceleratorRequest vda_request) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + arc_->CreateVideoDecodeAccelerator(std::move(vda_request)); +} + +void Gpu::CreateArcVideoEncodeAccelerator( + arc::mojom::VideoEncodeAcceleratorRequest vea_request) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + arc_->CreateVideoEncodeAccelerator(std::move(vea_request)); +} + +void Gpu::CreateArcProtectedBufferManager( + arc::mojom::ProtectedBufferManagerRequest pbm_request) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + arc_->CreateProtectedBufferManager(std::move(pbm_request)); +} +#endif // OS_CHROMEOS + void Gpu::CreateJpegDecodeAccelerator( media::mojom::GpuJpegDecodeAcceleratorRequest jda_request) { DCHECK(main_task_runner_->BelongsToCurrentThread()); @@ -331,4 +356,12 @@ return std::make_unique<base::SharedMemory>(platform_handle, readonly); } +#if defined(OS_CHROMEOS) +void Gpu::InitializeArc(service_manager::Connector* connector, + const std::string& service_name) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + connector->BindInterface(service_name, &arc_); +} +#endif // defined(OS_CHROMEOS) + } // namespace ui
diff --git a/services/ui/public/cpp/gpu/gpu.h b/services/ui/public/cpp/gpu/gpu.h index 3aeff615..8589637 100644 --- a/services/ui/public/cpp/gpu/gpu.h +++ b/services/ui/public/cpp/gpu/gpu.h
@@ -11,11 +11,19 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" +#include "build/build_config.h" #include "components/viz/common/gpu/context_provider.h" #include "gpu/ipc/client/gpu_channel_host.h" #include "services/ui/public/cpp/gpu/client_gpu_memory_buffer_manager.h" #include "services/ui/public/interfaces/gpu.mojom.h" +#if defined(OS_CHROMEOS) +#include "components/arc/common/protected_buffer_manager.mojom.h" // nogncheck https://crbug.com/784179 +#include "components/arc/common/video_decode_accelerator.mojom.h" // nogncheck https://crbug.com/784179 +#include "components/arc/common/video_encode_accelerator.mojom.h" // nogncheck https://crbug.com/784179 +#include "services/ui/public/interfaces/arc.mojom.h" +#endif // defined(OS_CHROMEOS) + namespace service_manager { class Connector; } @@ -40,7 +48,14 @@ scoped_refptr<viz::ContextProvider> CreateContextProvider( scoped_refptr<gpu::GpuChannelHost> gpu_channel); - +#if defined(OS_CHROMEOS) + void CreateArcVideoDecodeAccelerator( + arc::mojom::VideoDecodeAcceleratorRequest vda_request); + void CreateArcVideoEncodeAccelerator( + arc::mojom::VideoEncodeAcceleratorRequest vea_request); + void CreateArcProtectedBufferManager( + arc::mojom::ProtectedBufferManagerRequest pbm_request); +#endif void CreateJpegDecodeAccelerator( media::mojom::GpuJpegDecodeAcceleratorRequest jda_request); void CreateVideoEncodeAcceleratorProvider( @@ -78,6 +93,11 @@ std::unique_ptr<base::SharedMemory> AllocateSharedMemory( size_t size) override; +#if defined(OS_CHROMEOS) + void InitializeArc(service_manager::Connector* connector, + const std::string& service_name); +#endif // defined(OS_CHROMEOS) + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; std::unique_ptr<ClientGpuMemoryBufferManager> gpu_memory_buffer_manager_; @@ -87,6 +107,10 @@ scoped_refptr<gpu::GpuChannelHost> gpu_channel_; std::vector<gpu::GpuChannelEstablishedCallback> establish_callbacks_; +#if defined(OS_CHROMEOS) + ui::mojom::ArcPtr arc_; +#endif // defined(OS_CHROMEOS) + DISALLOW_COPY_AND_ASSIGN(Gpu); };
diff --git a/services/ui/public/interfaces/BUILD.gn b/services/ui/public/interfaces/BUILD.gn index fd32355..c8cc1b7 100644 --- a/services/ui/public/interfaces/BUILD.gn +++ b/services/ui/public/interfaces/BUILD.gn
@@ -51,6 +51,11 @@ "//ui/platform_window/mojo:interfaces", ] + if (is_chromeos) { + sources += [ "arc.mojom" ] + public_deps += [ "//components/arc/common:media" ] + } + # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. use_once_callback = false }
diff --git a/services/ui/public/interfaces/arc.mojom b/services/ui/public/interfaces/arc.mojom new file mode 100644 index 0000000..12af2d90 --- /dev/null +++ b/services/ui/public/interfaces/arc.mojom
@@ -0,0 +1,20 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module ui.mojom; + +import "components/arc/common/protected_buffer_manager.mojom"; +import "components/arc/common/video_decode_accelerator.mojom"; +import "components/arc/common/video_encode_accelerator.mojom"; + +interface Arc { + // Create a new VideoDecodeAccelerator and binds it to |vda|. + CreateVideoDecodeAccelerator(arc.mojom.VideoDecodeAccelerator& vda); + + // Create a new VideoEncodeAccelerator and binds it to |vea|. + CreateVideoEncodeAccelerator(arc.mojom.VideoEncodeAccelerator& vea); + + // Create a new ProtectedBufferManager and binds it to |pbm|. + CreateProtectedBufferManager(arc.mojom.ProtectedBufferManager& pbm); +};
diff --git a/services/ui/public/interfaces/window_manager.mojom b/services/ui/public/interfaces/window_manager.mojom index 79aff55..4b0c4b6a 100644 --- a/services/ui/public/interfaces/window_manager.mojom +++ b/services/ui/public/interfaces/window_manager.mojom
@@ -4,6 +4,7 @@ module ui.mojom; +import "gpu/ipc/common/surface_handle.mojom"; import "services/ui/public/interfaces/cursor/cursor.mojom"; import "services/ui/public/interfaces/event_matcher.mojom"; import "services/ui/public/interfaces/window_manager_constants.mojom"; @@ -163,6 +164,12 @@ // Called immediately when the WindowManager is obtained. OnConnect(); + // Called to notify about the real AcceleratedWidget associated with a + // display. This is called only when mus is not hosting viz, and requires the + // window manager to instead host viz. + WmOnAcceleratedWidgetForDisplay(int64 display_id, + gpu.mojom.SurfaceHandle surface_handle); + // Called when a new display is added. |root| gives the root window specific // to this WindowManager for |display|. |local_surface_id| identifies the ID // to use to submit CompositorFrames.
diff --git a/services/ui/service.cc b/services/ui/service.cc index 7494c57..246360a 100644 --- a/services/ui/service.cc +++ b/services/ui/service.cc
@@ -146,7 +146,8 @@ test_config_(false), ime_registrar_(&ime_driver_), discardable_shared_memory_manager_(config ? config->memory_manager - : nullptr) {} + : nullptr), + should_host_viz_(!config || config->should_host_viz) {} Service::~Service() { in_destructor_ = true; @@ -276,10 +277,22 @@ // so keep this line below both of those. input_device_server_.RegisterAsObserver(); - window_server_ = std::make_unique<ws::WindowServer>(this); - std::unique_ptr<ws::GpuHost> gpu_host = std::make_unique<ws::DefaultGpuHost>( - window_server_.get(), context()->connector()); - window_server_->SetGpuHost(std::move(gpu_host)); + window_server_ = base::MakeUnique<ws::WindowServer>(this, should_host_viz_); + if (should_host_viz_) { + std::unique_ptr<ws::GpuHost> gpu_host = + base::MakeUnique<ws::DefaultGpuHost>(window_server_.get(), + context()->connector()); + window_server_->SetGpuHost(std::move(gpu_host)); + + registry_.AddInterface<mojom::Gpu>( + base::Bind(&Service::BindGpuRequest, base::Unretained(this))); + registry_.AddInterface<mojom::VideoDetector>( + base::Bind(&Service::BindVideoDetectorRequest, base::Unretained(this))); +#if defined(OS_CHROMEOS) + registry_.AddInterface<mojom::Arc>( + base::Bind(&Service::BindArcRequest, base::Unretained(this))); +#endif // defined(OS_CHROMEOS) + } ime_driver_.Init(context()->connector(), test_config_); @@ -296,8 +309,6 @@ base::Bind(&Service::BindClipboardRequest, base::Unretained(this))); registry_with_source_info_.AddInterface<mojom::DisplayManager>( base::Bind(&Service::BindDisplayManagerRequest, base::Unretained(this))); - registry_.AddInterface<mojom::Gpu>( - base::Bind(&Service::BindGpuRequest, base::Unretained(this))); registry_.AddInterface<mojom::IMERegistrar>( base::Bind(&Service::BindIMERegistrarRequest, base::Unretained(this))); registry_.AddInterface<mojom::IMEDriver>( @@ -325,8 +336,6 @@ } registry_.AddInterface<mojom::RemoteEventDispatcher>(base::Bind( &Service::BindRemoteEventDispatcherRequest, base::Unretained(this))); - registry_.AddInterface<mojom::VideoDetector>( - base::Bind(&Service::BindVideoDetectorRequest, base::Unretained(this))); // On non-Linux platforms there will be no DeviceDataManager instance and no // purpose in adding the Mojo interface to connect to. @@ -548,4 +557,10 @@ window_server_->video_detector()->AddBinding(std::move(request)); } +#if defined(OS_CHROMEOS) +void Service::BindArcRequest(mojom::ArcRequest request) { + window_server_->gpu_host()->AddArc(std::move(request)); +} +#endif // defined(OS_CHROMEOS) + } // namespace ui
diff --git a/services/ui/service.h b/services/ui/service.h index 0213de0..936455d 100644 --- a/services/ui/service.h +++ b/services/ui/service.h
@@ -43,6 +43,10 @@ #include "ui/ozone/public/client_native_pixmap_factory_ozone.h" #endif +#if defined(OS_CHROMEOS) +#include "services/ui/public/interfaces/arc.mojom.h" +#endif // defined(OS_CHROMEOS) + namespace discardable_memory { class DiscardableSharedMemoryManager; } @@ -86,6 +90,10 @@ discardable_memory::DiscardableSharedMemoryManager* memory_manager = nullptr; + // Whether mus should host viz, or whether an external client (e.g. the + // window manager) would be responsible for hosting viz. + bool should_host_viz = true; + private: DISALLOW_COPY_AND_ASSIGN(InProcessConfig); }; @@ -181,6 +189,10 @@ void BindVideoDetectorRequest(mojom::VideoDetectorRequest request); +#if defined(OS_CHROMEOS) + void BindArcRequest(mojom::ArcRequest request); +#endif // defined(OS_CHROMEOS) + std::unique_ptr<ws::WindowServer> window_server_; std::unique_ptr<PlatformEventSource> event_source_; using PendingRequests = std::vector<std::unique_ptr<PendingRequest>>; @@ -224,6 +236,8 @@ std::unique_ptr<discardable_memory::DiscardableSharedMemoryManager> owned_discardable_shared_memory_manager_; + const bool should_host_viz_; + service_manager::BinderRegistryWithArgs< const service_manager::BindSourceInfo&> registry_with_source_info_;
diff --git a/services/ui/ws/BUILD.gn b/services/ui/ws/BUILD.gn index de757f4..36af449b 100644 --- a/services/ui/ws/BUILD.gn +++ b/services/ui/ws/BUILD.gn
@@ -167,6 +167,10 @@ public_deps += [ "//ui/ozone" ] } if (is_chromeos) { + sources += [ + "arc_client.cc", + "arc_client.h", + ] public_deps += [ "//ui/chromeos/events" ] if (use_ozone) { public_deps += [ "//ui/events/ozone:events_ozone" ]
diff --git a/services/ui/ws/arc_client.cc b/services/ui/ws/arc_client.cc new file mode 100644 index 0000000..a758246 --- /dev/null +++ b/services/ui/ws/arc_client.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 "services/ui/ws/arc_client.h" + +#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h" + +namespace ui { +namespace ws { + +ArcClient::ArcClient(viz::mojom::GpuService* gpu_service) + : gpu_service_(gpu_service) {} + +ArcClient::~ArcClient() {} + +// mojom::Arc overrides: +void ArcClient::CreateVideoDecodeAccelerator( + arc::mojom::VideoDecodeAcceleratorRequest vda_request) { + gpu_service_->CreateArcVideoDecodeAccelerator(std::move(vda_request)); +} + +void ArcClient::CreateVideoEncodeAccelerator( + arc::mojom::VideoEncodeAcceleratorRequest vea_request) { + gpu_service_->CreateArcVideoEncodeAccelerator(std::move(vea_request)); +} + +void ArcClient::CreateProtectedBufferManager( + arc::mojom::ProtectedBufferManagerRequest pbm_request) { + gpu_service_->CreateArcProtectedBufferManager(std::move(pbm_request)); +} + +} // namespace ws +} // namespace ui
diff --git a/services/ui/ws/arc_client.h b/services/ui/ws/arc_client.h new file mode 100644 index 0000000..2a88cf4 --- /dev/null +++ b/services/ui/ws/arc_client.h
@@ -0,0 +1,44 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_UI_WS_ARC_CLIENT_H_ +#define SERVICES_UI_WS_ARC_CLIENT_H_ + +#include "services/ui/public/interfaces/arc.mojom.h" + +namespace viz { +namespace mojom { +class GpuService; +} // namespace mojom +} // namespace viz + +namespace ui { +namespace ws { + +// The implementation that relays requests from clients to the real +// service implementation in the GPU process over mojom.GpuService. +class ArcClient : public mojom::Arc { + public: + explicit ArcClient(viz::mojom::GpuService* gpu_service); + ~ArcClient() override; + + private: + // mojom::Arc overrides: + void CreateVideoDecodeAccelerator( + arc::mojom::VideoDecodeAcceleratorRequest vda_request) override; + void CreateVideoEncodeAccelerator( + arc::mojom::VideoEncodeAcceleratorRequest vea_request) override; + void CreateProtectedBufferManager( + arc::mojom::ProtectedBufferManagerRequest pbm_request) override; + + // The objects these pointers refer to are owned by the GpuHost object. + viz::mojom::GpuService* gpu_service_; + + DISALLOW_COPY_AND_ASSIGN(ArcClient); +}; + +} // namespace ws +} // namespace ui + +#endif // SERVICES_UI_WS_ARC_CLIENT_H_
diff --git a/services/ui/ws/display.cc b/services/ui/ws/display.cc index 849da06e..13cd723 100644 --- a/services/ui/ws/display.cc +++ b/services/ui/ws/display.cc
@@ -307,6 +307,10 @@ #endif } +bool Display::IsHostingViz() const { + return window_server_->is_hosting_viz(); +} + void Display::OnViewportMetricsChanged( const display::ViewportMetrics& metrics) { platform_display_->UpdateViewportMetrics(metrics);
diff --git a/services/ui/ws/display.h b/services/ui/ws/display.h index 1c56b5d9..0978068 100644 --- a/services/ui/ws/display.h +++ b/services/ui/ws/display.h
@@ -191,6 +191,7 @@ void OnAcceleratedWidgetAvailable() override; void OnNativeCaptureLost() override; OzonePlatform* GetOzonePlatform() override; + bool IsHostingViz() const override; // FocusControllerObserver: void OnActivationChanged(ServerWindow* old_active_window,
diff --git a/services/ui/ws/drag_controller_unittest.cc b/services/ui/ws/drag_controller_unittest.cc index 1dc9462..764e1c6 100644 --- a/services/ui/ws/drag_controller_unittest.cc +++ b/services/ui/ws/drag_controller_unittest.cc
@@ -217,7 +217,7 @@ testing::Test::SetUp(); window_delegate_ = std::make_unique<TestServerWindowDelegate>( - ws_test_helper_.window_server()->GetHostFrameSinkManager()); + ws_test_helper_.window_server()->GetVizHostProxy()); root_window_ = std::make_unique<ServerWindow>(window_delegate_.get(), WindowId(1, 2)); window_delegate_->set_root_window(root_window_.get());
diff --git a/services/ui/ws/event_dispatcher_unittest.cc b/services/ui/ws/event_dispatcher_unittest.cc index 0ba4925..ac2e3bd 100644 --- a/services/ui/ws/event_dispatcher_unittest.cc +++ b/services/ui/ws/event_dispatcher_unittest.cc
@@ -295,8 +295,8 @@ return test_event_dispatcher_delegate_.get(); } EventDispatcher* event_dispatcher() { return event_dispatcher_.get(); } - viz::HostFrameSinkManager* host_frame_sink_manager() { - return ws_test_helper_.window_server()->GetHostFrameSinkManager(); + VizHostProxy* viz_host_proxy() { + return ws_test_helper_.window_server()->GetVizHostProxy(); } TestServerWindowDelegate* window_delegate() { return window_delegate_.get(); } @@ -445,7 +445,7 @@ testing::TestWithParam<bool>::SetUp(); window_delegate_ = - std::make_unique<TestServerWindowDelegate>(host_frame_sink_manager()); + std::make_unique<TestServerWindowDelegate>(viz_host_proxy()); root_window_ = std::make_unique<ServerWindow>(window_delegate_.get(), WindowId(1, 2)); root_window_->set_is_activation_parent(true); @@ -471,8 +471,8 @@ return test_event_dispatcher_delegate_.get(); } EventDispatcher* event_dispatcher() { return event_dispatcher_.get(); } - viz::HostFrameSinkManager* host_frame_sink_manager() { - return ws_test_helper_.window_server()->GetHostFrameSinkManager(); + VizHostProxy* viz_host_proxy() { + return ws_test_helper_.window_server()->GetVizHostProxy(); } viz::AggregatedHitTestRegion* aggregated_hit_test_region() { return static_cast<viz::AggregatedHitTestRegion*>(active_buffer_.get()); @@ -531,7 +531,7 @@ testing::Test::SetUp(); window_delegate_ = - std::make_unique<TestServerWindowDelegate>(host_frame_sink_manager()); + std::make_unique<TestServerWindowDelegate>(viz_host_proxy()); root_window_ = std::make_unique<ServerWindow>(window_delegate_.get(), WindowId(1, 2)); root_window_->set_is_activation_parent(true); @@ -2322,7 +2322,7 @@ } TEST_P(EventDispatcherTest, DontCancelWhenMovedToSeparateDisplay) { - TestServerWindowDelegate window_delegate2(host_frame_sink_manager()); + TestServerWindowDelegate window_delegate2(viz_host_proxy()); ServerWindow root2(&window_delegate2, WindowId(1, 100)); root2.set_is_activation_parent(true); window_delegate2.set_root_window(&root2);
diff --git a/services/ui/ws/focus_controller_unittest.cc b/services/ui/ws/focus_controller_unittest.cc index 6e983c5..985334d 100644 --- a/services/ui/ws/focus_controller_unittest.cc +++ b/services/ui/ws/focus_controller_unittest.cc
@@ -80,8 +80,8 @@ FocusControllerTest() {} ~FocusControllerTest() override {} - viz::HostFrameSinkManager* host_frame_sink_manager() { - return ws_test_helper_.window_server()->GetHostFrameSinkManager(); + VizHostProxy* viz_host_proxy() { + return ws_test_helper_.window_server()->GetVizHostProxy(); } private: @@ -91,7 +91,7 @@ }; TEST_F(FocusControllerTest, Basic) { - TestServerWindowDelegate server_window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate server_window_delegate(viz_host_proxy()); ServerWindow root(&server_window_delegate, WindowId(1, 1)); server_window_delegate.set_root_window(&root); root.SetVisible(true); @@ -165,15 +165,12 @@ // returns the last ancestor as the root of a window. class TestServerWindowDelegate2 : public ServerWindowDelegate { public: - explicit TestServerWindowDelegate2( - viz::HostFrameSinkManager* host_frame_sink_manager) - : host_frame_sink_manager_(host_frame_sink_manager) {} + explicit TestServerWindowDelegate2(VizHostProxy* viz_host_proxy) + : viz_host_proxy_(viz_host_proxy) {} ~TestServerWindowDelegate2() override = default; // ServerWindowDelegate: - viz::HostFrameSinkManager* GetHostFrameSinkManager() override { - return host_frame_sink_manager_; - } + VizHostProxy* GetVizHostProxy() override { return viz_host_proxy_; } ServerWindow* GetRootWindowForDrawn(const ServerWindow* window) override { const ServerWindow* root = window; while (root && root->parent()) @@ -185,7 +182,7 @@ ServerWindow* window) override {} private: - viz::HostFrameSinkManager* host_frame_sink_manager_ = nullptr; + VizHostProxy* viz_host_proxy_ = nullptr; DISALLOW_COPY_AND_ASSIGN(TestServerWindowDelegate2); }; @@ -193,7 +190,7 @@ } // namespace TEST_F(FocusControllerTest, ActiveWindowMovesToDifferentDisplay) { - TestServerWindowDelegate2 server_window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate2 server_window_delegate(viz_host_proxy()); ServerWindow root1(&server_window_delegate, WindowId(1, 1)); root1.SetVisible(true); root1.set_is_activation_parent(true);
diff --git a/services/ui/ws/gpu_host.cc b/services/ui/ws/gpu_host.cc index 6ac2a32..928aa43 100644 --- a/services/ui/ws/gpu_host.cc +++ b/services/ui/ws/gpu_host.cc
@@ -26,6 +26,10 @@ #include "ui/gfx/win/rendering_window_manager.h" #endif +#if defined(OS_CHROMEOS) +#include "services/ui/ws/arc_client.h" +#endif + namespace ui { namespace ws { @@ -108,6 +112,13 @@ viz_main_->CreateFrameSinkManager(std::move(params)); } +#if defined(OS_CHROMEOS) +void DefaultGpuHost::AddArc(mojom::ArcRequest request) { + arc_bindings_.AddBinding(std::make_unique<ArcClient>(gpu_service_.get()), + std::move(request)); +} +#endif // defined(OS_CHROMEOS) + GpuClient* DefaultGpuHost::AddInternal(mojom::GpuRequest request) { auto client(std::make_unique<GpuClient>( next_client_id_++, &gpu_info_, &gpu_feature_info_,
diff --git a/services/ui/ws/gpu_host.h b/services/ui/ws/gpu_host.h index eb5c62d..361a2632 100644 --- a/services/ui/ws/gpu_host.h +++ b/services/ui/ws/gpu_host.h
@@ -8,6 +8,7 @@ #include "base/single_thread_task_runner.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" +#include "build/build_config.h" #include "components/viz/service/main/viz_main_impl.h" #include "gpu/config/gpu_feature_info.h" #include "gpu/config/gpu_info.h" @@ -19,6 +20,10 @@ #include "services/viz/privileged/interfaces/gl/gpu_host.mojom.h" #include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h" +#if defined(OS_CHROMEOS) +#include "services/ui/public/interfaces/arc.mojom.h" +#endif // defined(OS_CHROMEOS) + namespace service_manager { class Connector; } @@ -53,6 +58,10 @@ // Requests a viz::mojom::FrameSinkManager interface from viz. virtual void CreateFrameSinkManager( viz::mojom::FrameSinkManagerParamsPtr params) = 0; + +#if defined(OS_CHROMEOS) + virtual void AddArc(mojom::ArcRequest request) = 0; +#endif // defined(OS_CHROMEOS) }; class DefaultGpuHost : public GpuHost, public viz::mojom::GpuHost { @@ -76,6 +85,9 @@ void OnAcceleratedWidgetDestroyed(gfx::AcceleratedWidget widget) override; void CreateFrameSinkManager( viz::mojom::FrameSinkManagerParamsPtr params) override; +#if defined(OS_CHROMEOS) + void AddArc(mojom::ArcRequest request) override; +#endif // defined(OS_CHROMEOS) // viz::mojom::GpuHost: void DidInitialize(const gpu::GPUInfo& gpu_info, @@ -115,6 +127,9 @@ base::WaitableEvent viz_main_wait_; mojo::StrongBindingSet<mojom::Gpu> gpu_bindings_; +#if defined(OS_CHROMEOS) + mojo::StrongBindingSet<mojom::Arc> arc_bindings_; +#endif // defined(OS_CHROMEOS) DISALLOW_COPY_AND_ASSIGN(DefaultGpuHost); };
diff --git a/services/ui/ws/modal_window_controller_unittest.cc b/services/ui/ws/modal_window_controller_unittest.cc index 28077ff..d254f6a 100644 --- a/services/ui/ws/modal_window_controller_unittest.cc +++ b/services/ui/ws/modal_window_controller_unittest.cc
@@ -17,8 +17,8 @@ ModalWindowControllerTest() {} ~ModalWindowControllerTest() override {} - viz::HostFrameSinkManager* host_frame_sink_manager() { - return ws_test_helper_.window_server()->GetHostFrameSinkManager(); + VizHostProxy* viz_host_proxy() { + return ws_test_helper_.window_server()->GetVizHostProxy(); } private: @@ -28,7 +28,7 @@ }; TEST_F(ModalWindowControllerTest, MinContainer) { - TestServerWindowDelegate window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate window_delegate(viz_host_proxy()); ServerWindow root_window(&window_delegate, WindowId(1, 1)); window_delegate.set_root_window(&root_window); ServerWindow container1(&window_delegate, WindowId(1, 2)); @@ -74,7 +74,7 @@ } TEST_F(ModalWindowControllerTest, SystemModalContainer) { - TestServerWindowDelegate window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate window_delegate(viz_host_proxy()); ServerWindow root_window(&window_delegate, WindowId(1, 1)); window_delegate.set_root_window(&root_window); ServerWindow container1(&window_delegate, WindowId(1, 2));
diff --git a/services/ui/ws/platform_display_default.cc b/services/ui/ws/platform_display_default.cc index 4bbba874..74149f68 100644 --- a/services/ui/ws/platform_display_default.cc +++ b/services/ui/ws/platform_display_default.cc
@@ -242,6 +242,9 @@ widget_ = widget; delegate_->OnAcceleratedWidgetAvailable(); + if (!delegate_->IsHostingViz()) + return; + viz::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink; viz::mojom::DisplayPrivateAssociatedPtr display_private; viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client;
diff --git a/services/ui/ws/platform_display_default_unittest.cc b/services/ui/ws/platform_display_default_unittest.cc index 045d4f8d..e34b8d0 100644 --- a/services/ui/ws/platform_display_default_unittest.cc +++ b/services/ui/ws/platform_display_default_unittest.cc
@@ -58,6 +58,7 @@ void OnAcceleratedWidgetAvailable() override {} void OnNativeCaptureLost() override {} OzonePlatform* GetOzonePlatform() override { return ozone_platform_; } + bool IsHostingViz() const override { return true; } private: TestEventSink* event_sink_;
diff --git a/services/ui/ws/platform_display_delegate.h b/services/ui/ws/platform_display_delegate.h index cc185b9..2e64d00 100644 --- a/services/ui/ws/platform_display_delegate.h +++ b/services/ui/ws/platform_display_delegate.h
@@ -42,6 +42,8 @@ // for non-Ozone platforms. virtual OzonePlatform* GetOzonePlatform() = 0; + virtual bool IsHostingViz() const = 0; + protected: virtual ~PlatformDisplayDelegate() {} };
diff --git a/services/ui/ws/server_window.cc b/services/ui/ws/server_window.cc index f419e69..dcb7489 100644 --- a/services/ui/ws/server_window.cc +++ b/services/ui/ws/server_window.cc
@@ -77,7 +77,7 @@ for (auto& observer : observers_) observer.OnWindowDestroyed(this); - auto* host_frame_sink_manager = delegate_->GetHostFrameSinkManager(); + auto* host_frame_sink_manager = delegate_->GetVizHostProxy(); if (host_frame_sink_manager) host_frame_sink_manager->InvalidateFrameSinkId(frame_sink_id_); } @@ -104,7 +104,7 @@ // TODO(fsamuel): AcceleratedWidget cannot be transported over IPC for Mac // or Android. We should instead use GpuSurfaceTracker here on those // platforms. - delegate_->GetHostFrameSinkManager()->CreateRootCompositorFrameSink( + delegate_->GetVizHostProxy()->CreateRootCompositorFrameSink( frame_sink_id_, widget, viz::CreateRendererSettings(viz::BufferToTextureTargetMap()), std::move(sink_request), std::move(client), std::move(display_request)); @@ -114,13 +114,13 @@ viz::mojom::CompositorFrameSinkRequest request, viz::mojom::CompositorFrameSinkClientPtr client) { has_created_compositor_frame_sink_ = true; - delegate_->GetHostFrameSinkManager()->CreateCompositorFrameSink( + delegate_->GetVizHostProxy()->CreateCompositorFrameSink( frame_sink_id_, std::move(request), std::move(client)); } void ServerWindow::UpdateFrameSinkId(const viz::FrameSinkId& frame_sink_id) { DCHECK(frame_sink_id.is_valid()); - auto* host_frame_sink_manager = delegate_->GetHostFrameSinkManager(); + auto* host_frame_sink_manager = delegate_->GetVizHostProxy(); DCHECK(host_frame_sink_manager); host_frame_sink_manager->RegisterFrameSinkId(frame_sink_id, this); #if DCHECK_IS_ON() @@ -401,7 +401,7 @@ properties_.erase(it); } #if DCHECK_IS_ON() - auto* host_frame_sink_manager = delegate_->GetHostFrameSinkManager(); + auto* host_frame_sink_manager = delegate_->GetVizHostProxy(); if (host_frame_sink_manager && name == mojom::WindowManager::kName_Property) host_frame_sink_manager->SetFrameSinkDebugLabel(frame_sink_id_, GetName()); #endif
diff --git a/services/ui/ws/server_window_delegate.h b/services/ui/ws/server_window_delegate.h index 0945d71..32073df 100644 --- a/services/ui/ws/server_window_delegate.h +++ b/services/ui/ws/server_window_delegate.h
@@ -9,9 +9,11 @@ #include "services/ui/public/interfaces/mus_constants.mojom.h" #include "services/ui/public/interfaces/window_tree.mojom.h" +#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h" namespace viz { -class HostFrameSinkManager; +class HitTestQuery; +class HostFrameSinkClient; } namespace ui { @@ -20,9 +22,50 @@ class ServerWindow; +// A proxy to communicate to the viz host (usually viz::HostFrameSinkManager). +// If mus is hosting viz, then it forwards all the calls to the appropriate viz +// host. If mus is not hosting viz, then it drops all calls. It is always safe +// to call any method on this proxy. See documentation in +// viz::HostFrameSinkManager for the documentation for the methods. +class VizHostProxy { + public: + virtual ~VizHostProxy() {} + + virtual void RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id, + viz::HostFrameSinkClient* client) = 0; + + virtual void SetFrameSinkDebugLabel(const viz::FrameSinkId& frame_sink_id, + const std::string& name) = 0; + + virtual void InvalidateFrameSinkId(const viz::FrameSinkId& frame_sink_id) = 0; + + virtual void RegisterFrameSinkHierarchy(const viz::FrameSinkId& new_parent, + const viz::FrameSinkId& child) = 0; + virtual void UnregisterFrameSinkHierarchy(const viz::FrameSinkId& old_parent, + const viz::FrameSinkId& child) = 0; + + virtual void CreateRootCompositorFrameSink( + const viz::FrameSinkId& frame_sink_id, + gpu::SurfaceHandle surface_handle, + const viz::RendererSettings& renderer_settings, + viz::mojom::CompositorFrameSinkAssociatedRequest request, + viz::mojom::CompositorFrameSinkClientPtr client, + viz::mojom::DisplayPrivateAssociatedRequest display_private_request) = 0; + + virtual void CreateCompositorFrameSink( + const viz::FrameSinkId& frame_sink_id, + viz::mojom::CompositorFrameSinkRequest request, + viz::mojom::CompositorFrameSinkClientPtr client) = 0; + + virtual viz::HitTestQuery* GetHitTestQuery( + const viz::FrameSinkId& frame_sink_id) = 0; +}; + class ServerWindowDelegate { public: - virtual viz::HostFrameSinkManager* GetHostFrameSinkManager() = 0; + // Returns a proxy to communicate to the viz host. This must always return + // non-null. + virtual VizHostProxy* GetVizHostProxy() = 0; // Returns the root of the window tree to which this |window| is attached. // Returns null if this window is not attached up through to a root window.
diff --git a/services/ui/ws/server_window_drawn_tracker_unittest.cc b/services/ui/ws/server_window_drawn_tracker_unittest.cc index d3f794d..55f589bd 100644 --- a/services/ui/ws/server_window_drawn_tracker_unittest.cc +++ b/services/ui/ws/server_window_drawn_tracker_unittest.cc
@@ -83,8 +83,8 @@ ServerWindowDrawnTrackerTest() {} ~ServerWindowDrawnTrackerTest() override {} - viz::HostFrameSinkManager* host_frame_sink_manager() { - return ws_test_helper_.window_server()->GetHostFrameSinkManager(); + VizHostProxy* viz_host_proxy() { + return ws_test_helper_.window_server()->GetVizHostProxy(); } private: @@ -94,7 +94,7 @@ }; TEST_F(ServerWindowDrawnTrackerTest, ChangeBecauseOfDeletionAndVisibility) { - TestServerWindowDelegate server_window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate server_window_delegate(viz_host_proxy()); std::unique_ptr<ServerWindow> window( new ServerWindow(&server_window_delegate, MakeWindowId())); server_window_delegate.set_root_window(window.get()); @@ -138,7 +138,7 @@ } TEST_F(ServerWindowDrawnTrackerTest, ChangeBecauseOfRemovingFromRoot) { - TestServerWindowDelegate server_window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate server_window_delegate(viz_host_proxy()); ServerWindow root(&server_window_delegate, MakeWindowId()); server_window_delegate.set_root_window(&root); root.SetVisible(true); @@ -167,7 +167,7 @@ } TEST_F(ServerWindowDrawnTrackerTest, ChangeBecauseOfRemovingAncestorFromRoot) { - TestServerWindowDelegate server_window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate server_window_delegate(viz_host_proxy()); ServerWindow root(&server_window_delegate, MakeWindowId()); server_window_delegate.set_root_window(&root); root.SetVisible(true); @@ -200,7 +200,7 @@ } TEST_F(ServerWindowDrawnTrackerTest, VisibilityChangeFromNonParentAncestor) { - TestServerWindowDelegate server_window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate server_window_delegate(viz_host_proxy()); ServerWindow root(&server_window_delegate, MakeWindowId()); ServerWindow child1(&server_window_delegate, MakeWindowId()); ServerWindow child2(&server_window_delegate, MakeWindowId()); @@ -243,7 +243,7 @@ } TEST_F(ServerWindowDrawnTrackerTest, TreeHierarchyChangeFromNonParentAncestor) { - TestServerWindowDelegate server_window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate server_window_delegate(viz_host_proxy()); ServerWindow root(&server_window_delegate, MakeWindowId()); ServerWindow child1(&server_window_delegate, MakeWindowId()); ServerWindow child2(&server_window_delegate, MakeWindowId());
diff --git a/services/ui/ws/test_gpu_host.h b/services/ui/ws/test_gpu_host.h index 85b875f..b459546 100644 --- a/services/ui/ws/test_gpu_host.h +++ b/services/ui/ws/test_gpu_host.h
@@ -23,6 +23,9 @@ void OnAcceleratedWidgetDestroyed(gfx::AcceleratedWidget widget) override {} void CreateFrameSinkManager( viz::mojom::FrameSinkManagerParamsPtr params) override; +#if defined(OS_CHROMEOS) + void AddArc(mojom::ArcRequest request) override {} +#endif // defined(OS_CHROMEOS) std::unique_ptr<viz::TestFrameSinkManagerImpl> frame_sink_manager_;
diff --git a/services/ui/ws/test_server_window_delegate.cc b/services/ui/ws/test_server_window_delegate.cc index 306c2d3..87a8ae3 100644 --- a/services/ui/ws/test_server_window_delegate.cc +++ b/services/ui/ws/test_server_window_delegate.cc
@@ -9,9 +9,8 @@ namespace ui { namespace ws { -TestServerWindowDelegate::TestServerWindowDelegate( - viz::HostFrameSinkManager* host_frame_sink_manager) - : host_frame_sink_manager_(host_frame_sink_manager) {} +TestServerWindowDelegate::TestServerWindowDelegate(VizHostProxy* viz_host_proxy) + : viz_host_proxy_(viz_host_proxy) {} TestServerWindowDelegate::~TestServerWindowDelegate() {} @@ -19,8 +18,8 @@ roots_.insert(window); } -viz::HostFrameSinkManager* TestServerWindowDelegate::GetHostFrameSinkManager() { - return host_frame_sink_manager_; +VizHostProxy* TestServerWindowDelegate::GetVizHostProxy() { + return viz_host_proxy_; } ServerWindow* TestServerWindowDelegate::GetRootWindowForDrawn(
diff --git a/services/ui/ws/test_server_window_delegate.h b/services/ui/ws/test_server_window_delegate.h index cdd9e2d5..f0e6fc2 100644 --- a/services/ui/ws/test_server_window_delegate.h +++ b/services/ui/ws/test_server_window_delegate.h
@@ -15,8 +15,7 @@ class TestServerWindowDelegate : public ServerWindowDelegate { public: - explicit TestServerWindowDelegate( - viz::HostFrameSinkManager* host_frame_sink_manager); + explicit TestServerWindowDelegate(VizHostProxy* viz_host_proxy); ~TestServerWindowDelegate() override; // GetRootWindowForDrawn() returns the first ServerWindow added by way of @@ -28,13 +27,13 @@ private: // ServerWindowDelegate: - viz::HostFrameSinkManager* GetHostFrameSinkManager() override; + VizHostProxy* GetVizHostProxy() override; ServerWindow* GetRootWindowForDrawn(const ServerWindow* window) override; void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info, ServerWindow* window) override; ServerWindow* root_window_ = nullptr; - viz::HostFrameSinkManager* host_frame_sink_manager_ = nullptr; + VizHostProxy* viz_host_proxy_ = nullptr; std::set<ServerWindow*> roots_; DISALLOW_COPY_AND_ASSIGN(TestServerWindowDelegate);
diff --git a/services/ui/ws/test_utils.cc b/services/ui/ws/test_utils.cc index ce5001f..7f1c890 100644 --- a/services/ui/ws/test_utils.cc +++ b/services/ui/ws/test_utils.cc
@@ -221,6 +221,10 @@ connect_count_++; } +void TestWindowManager::WmOnAcceleratedWidgetForDisplay( + int64_t display, + gpu::SurfaceHandle surface_handle) {} + void TestWindowManager::WmNewDisplayAdded( const display::Display& display, ui::mojom::WindowDataPtr root, @@ -580,7 +584,8 @@ if (!base::MessageLoop::current()) message_loop_ = std::make_unique<base::MessageLoop>(); PlatformDisplay::set_factory_for_testing(&platform_display_factory_); - window_server_ = std::make_unique<WindowServer>(&window_server_delegate_); + window_server_ = std::make_unique<WindowServer>(&window_server_delegate_, + true /* should_host_viz */); std::unique_ptr<GpuHost> gpu_host = std::make_unique<TestGpuHost>(); window_server_->SetGpuHost(std::move(gpu_host)); window_server_delegate_.set_window_server(window_server_.get());
diff --git a/services/ui/ws/test_utils.h b/services/ui/ws/test_utils.h index 3efe7ff4d..7262682 100644 --- a/services/ui/ws/test_utils.h +++ b/services/ui/ws/test_utils.h
@@ -394,6 +394,9 @@ private: // WindowManager: void OnConnect() override; + void WmOnAcceleratedWidgetForDisplay( + int64_t display, + gpu::SurfaceHandle surface_handle) override; void WmNewDisplayAdded( const display::Display& display, ui::mojom::WindowDataPtr root,
diff --git a/services/ui/ws/transient_windows_unittest.cc b/services/ui/ws/transient_windows_unittest.cc index f5e2783..5ca7da2 100644 --- a/services/ui/ws/transient_windows_unittest.cc +++ b/services/ui/ws/transient_windows_unittest.cc
@@ -72,8 +72,8 @@ TransientWindowsTest() {} ~TransientWindowsTest() override {} - viz::HostFrameSinkManager* host_frame_sink_manager() { - return ws_test_helper_.window_server()->GetHostFrameSinkManager(); + VizHostProxy* viz_host_proxy() { + return ws_test_helper_.window_server()->GetVizHostProxy(); } private: @@ -83,7 +83,7 @@ }; TEST_F(TransientWindowsTest, TransientChildren) { - TestServerWindowDelegate server_window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate server_window_delegate(viz_host_proxy()); std::unique_ptr<ServerWindow> parent( CreateTestWindow(&server_window_delegate, WindowId(1, 0), nullptr)); @@ -109,7 +109,7 @@ // Verifies adding doesn't restack at all. TEST_F(TransientWindowsTest, DontStackUponCreation) { - TestServerWindowDelegate delegate(host_frame_sink_manager()); + TestServerWindowDelegate delegate(viz_host_proxy()); std::unique_ptr<ServerWindow> parent( CreateTestWindow(&delegate, WindowId(0, 1), nullptr)); std::unique_ptr<ServerWindow> window0( @@ -126,7 +126,7 @@ // More variations around verifying ordering doesn't change when // adding/removing transients. TEST_F(TransientWindowsTest, RestackUponAddOrRemoveTransientWindow) { - TestServerWindowDelegate delegate(host_frame_sink_manager()); + TestServerWindowDelegate delegate(viz_host_proxy()); std::unique_ptr<ServerWindow> parent( CreateTestWindow(&delegate, WindowId(0, 1), nullptr)); std::unique_ptr<ServerWindow> windows[4]; @@ -163,7 +163,7 @@ // Verifies TransientWindowObserver is notified appropriately. TEST_F(TransientWindowsTest, TransientWindowObserverNotified) { - TestServerWindowDelegate delegate(host_frame_sink_manager()); + TestServerWindowDelegate delegate(viz_host_proxy()); std::unique_ptr<ServerWindow> parent( CreateTestWindow(&delegate, WindowId(0, 1), nullptr)); std::unique_ptr<ServerWindow> w1(
diff --git a/services/ui/ws/window_coordinate_conversions_unittest.cc b/services/ui/ws/window_coordinate_conversions_unittest.cc index 5e079b66..9978c9c7 100644 --- a/services/ui/ws/window_coordinate_conversions_unittest.cc +++ b/services/ui/ws/window_coordinate_conversions_unittest.cc
@@ -17,8 +17,8 @@ WindowCoordinateConversions() {} ~WindowCoordinateConversions() override {} - viz::HostFrameSinkManager* host_frame_sink_manager() { - return ws_test_helper_.window_server()->GetHostFrameSinkManager(); + VizHostProxy* viz_host_proxy() { + return ws_test_helper_.window_server()->GetVizHostProxy(); } private: @@ -28,7 +28,7 @@ }; TEST_F(WindowCoordinateConversions, Transform) { - TestServerWindowDelegate window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate window_delegate(viz_host_proxy()); ServerWindow root(&window_delegate, WindowId(1, 2)); root.set_event_targeting_policy( mojom::EventTargetingPolicy::DESCENDANTS_ONLY);
diff --git a/services/ui/ws/window_finder_unittest.cc b/services/ui/ws/window_finder_unittest.cc index ea0a1cee..8e87df9 100644 --- a/services/ui/ws/window_finder_unittest.cc +++ b/services/ui/ws/window_finder_unittest.cc
@@ -17,8 +17,8 @@ WindowFinderTest() {} ~WindowFinderTest() override {} - viz::HostFrameSinkManager* host_frame_sink_manager() { - return ws_test_helper_.window_server()->GetHostFrameSinkManager(); + VizHostProxy* viz_host_proxy() { + return ws_test_helper_.window_server()->GetVizHostProxy(); } private: @@ -28,7 +28,7 @@ }; TEST_F(WindowFinderTest, FindDeepestVisibleWindow) { - TestServerWindowDelegate window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate window_delegate(viz_host_proxy()); ServerWindow root(&window_delegate, WindowId(1, 2)); root.set_event_targeting_policy( mojom::EventTargetingPolicy::DESCENDANTS_ONLY); @@ -73,7 +73,7 @@ } TEST_F(WindowFinderTest, FindDeepestVisibleWindowNonClientArea) { - TestServerWindowDelegate window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate window_delegate(viz_host_proxy()); ServerWindow root(&window_delegate, WindowId(1, 2)); window_delegate.set_root_window(&root); root.SetVisible(true); @@ -124,7 +124,7 @@ } TEST_F(WindowFinderTest, FindDeepestVisibleWindowHitTestMask) { - TestServerWindowDelegate window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate window_delegate(viz_host_proxy()); ServerWindow root(&window_delegate, WindowId(1, 2)); window_delegate.set_root_window(&root); root.SetVisible(true); @@ -148,7 +148,7 @@ } TEST_F(WindowFinderTest, FindDeepestVisibleWindowOverNonTarget) { - TestServerWindowDelegate window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate window_delegate(viz_host_proxy()); ServerWindow root(&window_delegate, WindowId(1, 2)); window_delegate.set_root_window(&root); root.SetVisible(true); @@ -175,7 +175,7 @@ } TEST_F(WindowFinderTest, NonClientPreferredOverChild) { - TestServerWindowDelegate window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate window_delegate(viz_host_proxy()); ServerWindow root(&window_delegate, WindowId(1, 2)); window_delegate.set_root_window(&root); root.SetVisible(true); @@ -202,7 +202,7 @@ } TEST_F(WindowFinderTest, FindDeepestVisibleWindowWithTransform) { - TestServerWindowDelegate window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate window_delegate(viz_host_proxy()); ServerWindow root(&window_delegate, WindowId(1, 2)); root.set_event_targeting_policy( mojom::EventTargetingPolicy::DESCENDANTS_ONLY); @@ -248,7 +248,7 @@ } TEST_F(WindowFinderTest, FindDeepestVisibleWindowWithTransformOnParent) { - TestServerWindowDelegate window_delegate(host_frame_sink_manager()); + TestServerWindowDelegate window_delegate(viz_host_proxy()); ServerWindow root(&window_delegate, WindowId(1, 2)); root.set_event_targeting_policy( mojom::EventTargetingPolicy::DESCENDANTS_ONLY);
diff --git a/services/ui/ws/window_manager_state.cc b/services/ui/ws/window_manager_state.cc index 73df0ec8..6de4266 100644 --- a/services/ui/ws/window_manager_state.cc +++ b/services/ui/ws/window_manager_state.cc
@@ -927,12 +927,8 @@ if (!display) return nullptr; - const auto& display_hit_test_query_map = - window_server()->GetHostFrameSinkManager()->display_hit_test_query(); - const auto iter = - display_hit_test_query_map.find(display->root_window()->frame_sink_id()); - return (iter != display_hit_test_query_map.end()) ? iter->second.get() - : nullptr; + return window_server()->GetVizHostProxy()->GetHitTestQuery( + display->root_window()->frame_sink_id()); } ServerWindow* WindowManagerState::GetWindowFromFrameSinkId(
diff --git a/services/ui/ws/window_server.cc b/services/ui/ws/window_server.cc index 743944d..3409c31f 100644 --- a/services/ui/ws/window_server.cc +++ b/services/ui/ws/window_server.cc
@@ -44,6 +44,84 @@ return display_root && display_root->GetClientVisibleRoot() == window; } +class VizHostProxyImpl : public VizHostProxy { + public: + explicit VizHostProxyImpl(viz::HostFrameSinkManager* manager) + : manager_(manager) {} + + ~VizHostProxyImpl() override = default; + + // VizHostProxy: + void RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id, + viz::HostFrameSinkClient* client) override { + if (manager_) + manager_->RegisterFrameSinkId(frame_sink_id, client); + } + + void SetFrameSinkDebugLabel(const viz::FrameSinkId& frame_sink_id, + const std::string& name) override { + if (manager_) + manager_->SetFrameSinkDebugLabel(frame_sink_id, name); + } + + void InvalidateFrameSinkId(const viz::FrameSinkId& frame_sink_id) override { + if (manager_) + manager_->InvalidateFrameSinkId(frame_sink_id); + } + + void RegisterFrameSinkHierarchy(const viz::FrameSinkId& new_parent, + const viz::FrameSinkId& child) override { + if (manager_) + manager_->RegisterFrameSinkHierarchy(new_parent, child); + } + + void UnregisterFrameSinkHierarchy(const viz::FrameSinkId& old_parent, + const viz::FrameSinkId& child) override { + if (manager_) + manager_->UnregisterFrameSinkHierarchy(old_parent, child); + } + + void CreateRootCompositorFrameSink( + const viz::FrameSinkId& frame_sink_id, + gpu::SurfaceHandle surface_handle, + const viz::RendererSettings& renderer_settings, + viz::mojom::CompositorFrameSinkAssociatedRequest request, + viz::mojom::CompositorFrameSinkClientPtr client, + viz::mojom::DisplayPrivateAssociatedRequest display_private_request) + override { + if (manager_) { + manager_->CreateRootCompositorFrameSink( + frame_sink_id, surface_handle, renderer_settings, std::move(request), + std::move(client), std::move(display_private_request)); + } + } + + void CreateCompositorFrameSink( + const viz::FrameSinkId& frame_sink_id, + viz::mojom::CompositorFrameSinkRequest request, + viz::mojom::CompositorFrameSinkClientPtr client) override { + if (manager_) { + manager_->CreateCompositorFrameSink(frame_sink_id, std::move(request), + std::move(client)); + } + } + + viz::HitTestQuery* GetHitTestQuery( + const viz::FrameSinkId& frame_sink_id) override { + if (!manager_) + return nullptr; + const auto& display_hit_test_query_map = manager_->display_hit_test_query(); + const auto iter = display_hit_test_query_map.find(frame_sink_id); + return (iter != display_hit_test_query_map.end()) ? iter->second.get() + : nullptr; + } + + private: + viz::HostFrameSinkManager* const manager_; + + DISALLOW_COPY_AND_ASSIGN(VizHostProxyImpl); +}; + } // namespace struct WindowServer::CurrentMoveLoopState { @@ -59,7 +137,7 @@ WindowTree* initiator; }; -WindowServer::WindowServer(WindowServerDelegate* delegate) +WindowServer::WindowServer(WindowServerDelegate* delegate, bool should_host_viz) : delegate_(delegate), next_client_id_(kWindowServerClientId + 1), display_manager_(new DisplayManager(this, &user_id_tracker_)), @@ -67,7 +145,11 @@ in_destructor_(false), next_wm_change_id_(0), window_manager_window_tree_factory_set_(this, &user_id_tracker_), - host_frame_sink_manager_(std::make_unique<viz::HostFrameSinkManager>()), + host_frame_sink_manager_( + should_host_viz ? std::make_unique<viz::HostFrameSinkManager>() + : nullptr), + viz_host_proxy_( + std::make_unique<VizHostProxyImpl>(host_frame_sink_manager_.get())), video_detector_(host_frame_sink_manager_.get()), display_creation_config_(DisplayCreationConfig::UNKNOWN) { user_id_tracker_.AddObserver(this); @@ -104,6 +186,7 @@ } void WindowServer::SetGpuHost(std::unique_ptr<GpuHost> gpu_host) { + DCHECK(host_frame_sink_manager_); gpu_host_ = std::move(gpu_host); CreateFrameSinkManager(); } @@ -568,8 +651,19 @@ void WindowServer::OnDisplayReady(Display* display, bool is_first) { if (is_first) delegate_->OnFirstDisplayReady(); - gpu_host_->OnAcceleratedWidgetAvailable( - display->platform_display()->GetAcceleratedWidget()); + bool wm_is_hosting_viz = !gpu_host_; + if (wm_is_hosting_viz) { + // Notify WM about the AcceleratedWidget if it is hosting viz. + for (auto& pair : tree_map_) { + if (pair.second->window_manager_state()) { + auto& wm_tree = pair.second; + wm_tree->OnAcceleratedWidgetAvailableForDisplay(display); + } + } + } else { + gpu_host_->OnAcceleratedWidgetAvailable( + display->platform_display()->GetAcceleratedWidget()); + } } void WindowServer::OnDisplayDestroyed(Display* display) { @@ -589,13 +683,14 @@ user_id); } -viz::HostFrameSinkManager* WindowServer::GetHostFrameSinkManager() { - return host_frame_sink_manager_.get(); +VizHostProxy* WindowServer::GetVizHostProxy() { + return viz_host_proxy_.get(); } void WindowServer::OnFirstSurfaceActivation( const viz::SurfaceInfo& surface_info, ServerWindow* window) { + DCHECK(host_frame_sink_manager_); // This is only used for testing to observe that a window has a // CompositorFrame. if (!window_paint_callback_.is_null()) @@ -704,6 +799,7 @@ void WindowServer::HandleTemporaryReferenceForNewSurface( const viz::SurfaceId& surface_id, ServerWindow* window) { + DCHECK(host_frame_sink_manager_); // TODO(kylechar): Investigate adding tests for this. const ClientSpecificId window_client_id = window->id().client_id; @@ -732,6 +828,7 @@ } void WindowServer::CreateFrameSinkManager() { + DCHECK(host_frame_sink_manager_); viz::mojom::FrameSinkManagerPtr frame_sink_manager; viz::mojom::FrameSinkManagerRequest frame_sink_manager_request = mojo::MakeRequest(&frame_sink_manager); @@ -785,12 +882,12 @@ ProcessWindowHierarchyChanged(window, new_parent, old_parent); if (old_parent) { - host_frame_sink_manager_->UnregisterFrameSinkHierarchy( - old_parent->frame_sink_id(), window->frame_sink_id()); + viz_host_proxy_->UnregisterFrameSinkHierarchy(old_parent->frame_sink_id(), + window->frame_sink_id()); } if (new_parent) { - host_frame_sink_manager_->RegisterFrameSinkHierarchy( - new_parent->frame_sink_id(), window->frame_sink_id()); + viz_host_proxy_->RegisterFrameSinkHierarchy(new_parent->frame_sink_id(), + window->frame_sink_id()); } if (!pending_system_modal_windows_.windows().empty()) {
diff --git a/services/ui/ws/window_server.h b/services/ui/ws/window_server.h index b14e20e..e4c291d 100644 --- a/services/ui/ws/window_server.h +++ b/services/ui/ws/window_server.h
@@ -58,7 +58,7 @@ public UserDisplayManagerDelegate, public UserIdTrackerObserver { public: - explicit WindowServer(WindowServerDelegate* delegate); + WindowServer(WindowServerDelegate* delegate, bool should_host_viz); ~WindowServer() override; WindowServerDelegate* delegate() { return delegate_; } @@ -71,14 +71,15 @@ return display_manager_.get(); } - GpuHost* gpu_host() { return gpu_host_.get(); } - void SetDisplayCreationConfig(DisplayCreationConfig config); DisplayCreationConfig display_creation_config() const { return display_creation_config_; } void SetGpuHost(std::unique_ptr<GpuHost> gpu_host); + GpuHost* gpu_host() { return gpu_host_.get(); } + + bool is_hosting_viz() const { return !!host_frame_sink_manager_; } ThreadedImageCursorsFactory* GetThreadedImageCursorsFactory(); @@ -252,7 +253,7 @@ VideoDetectorImpl* video_detector() { return &video_detector_; } // ServerWindowDelegate: - viz::HostFrameSinkManager* GetHostFrameSinkManager() override; + VizHostProxy* GetVizHostProxy() override; void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info, ServerWindow* window) override; @@ -419,6 +420,7 @@ // Provides interfaces to create and manage FrameSinks. std::unique_ptr<viz::HostFrameSinkManager> host_frame_sink_manager_; + std::unique_ptr<VizHostProxy> viz_host_proxy_; VideoDetectorImpl video_detector_;
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc index f30067d6..510efc78 100644 --- a/services/ui/ws/window_tree.cc +++ b/services/ui/ws/window_tree.cc
@@ -12,6 +12,7 @@ #include "base/callback_helpers.h" #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "build/build_config.h" #include "mojo/public/cpp/bindings/map.h" #include "services/ui/display/screen_manager.h" #include "services/ui/ws/cursor_location_manager.h" @@ -180,6 +181,14 @@ drawn, root->current_local_surface_id()); } +void WindowTree::OnAcceleratedWidgetAvailableForDisplay(Display* display) { + DCHECK(window_manager_internal_); + // TODO(sad): Use GpuSurfaceTracker on platforms where a gpu::SurfaceHandle is + // not the same as a gfx::AcceleratedWidget. + window_manager_internal_->WmOnAcceleratedWidgetForDisplay( + display->GetId(), display->platform_display()->GetAcceleratedWidget()); +} + void WindowTree::ConfigureWindowManager( bool automatically_create_display_roots) { // ConfigureWindowManager() should be called early on, before anything
diff --git a/services/ui/ws/window_tree.h b/services/ui/ws/window_tree.h index 7d6f7f1..fe3a1d64 100644 --- a/services/ui/ws/window_tree.h +++ b/services/ui/ws/window_tree.h
@@ -28,6 +28,7 @@ #include "services/ui/ws/user_id.h" #include "services/ui/ws/window_tree_binding.h" #include "services/viz/public/interfaces/compositing/surface_id.mojom.h" +#include "ui/gfx/native_widget_types.h" namespace display { struct ViewportMetrics; @@ -92,6 +93,8 @@ return automatically_create_display_roots_; } + void OnAcceleratedWidgetAvailableForDisplay(Display* display); + ClientSpecificId id() const { return id_; } void set_embedder_intercepts_events() { embedder_intercepts_events_ = true; }
diff --git a/services/ui/ws/window_tree_client_unittest.cc b/services/ui/ws/window_tree_client_unittest.cc index c936c3a5..a2326c28 100644 --- a/services/ui/ws/window_tree_client_unittest.cc +++ b/services/ui/ws/window_tree_client_unittest.cc
@@ -475,6 +475,9 @@ // mojom::WindowManager: void OnConnect() override {} + void WmOnAcceleratedWidgetForDisplay( + int64_t display, + gpu::SurfaceHandle surface_handle) override {} void WmNewDisplayAdded( const display::Display& display, mojom::WindowDataPtr root_data,
diff --git a/services/ui/ws/window_tree_unittest.cc b/services/ui/ws/window_tree_unittest.cc index c48f22d..92d4d9e 100644 --- a/services/ui/ws/window_tree_unittest.cc +++ b/services/ui/ws/window_tree_unittest.cc
@@ -1211,7 +1211,7 @@ ServerWindow* window = nullptr; EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - TestServerWindowDelegate delegate(window_server()->GetHostFrameSinkManager()); + TestServerWindowDelegate delegate(window_server()->GetVizHostProxy()); WindowId window_id(42, 1337); ServerWindow unknown_window(&delegate, window_id); const float new_opacity = 0.5f;
diff --git a/services/video_capture/BUILD.gn b/services/video_capture/BUILD.gn index 8e06e0b..f875609 100644 --- a/services/video_capture/BUILD.gn +++ b/services/video_capture/BUILD.gn
@@ -35,10 +35,16 @@ "device_media_to_mojo_adapter.h", "receiver_mojo_to_media_adapter.cc", "receiver_mojo_to_media_adapter.h", + "scoped_access_permission_media_to_mojo_adapter.cc", + "scoped_access_permission_media_to_mojo_adapter.h", "service_impl.cc", "service_impl.h", "testing_controls_impl.cc", "testing_controls_impl.h", + "virtual_device_enabled_device_factory.cc", + "virtual_device_enabled_device_factory.h", + "virtual_device_mojo_adapter.cc", + "virtual_device_mojo_adapter.h", ] public_deps = [ @@ -75,8 +81,11 @@ "test/mock_device_test.cc", "test/mock_device_test.h", "test/mock_device_unittest.cc", + "test/mock_producer.cc", + "test/mock_producer.h", "test/mock_receiver.cc", "test/mock_receiver.h", + "test/virtual_device_unittest.cc", ] deps = [
diff --git a/services/video_capture/device_factory_media_to_mojo_adapter.cc b/services/video_capture/device_factory_media_to_mojo_adapter.cc index bde0cf29..b3fbcec1 100644 --- a/services/video_capture/device_factory_media_to_mojo_adapter.cc +++ b/services/video_capture/device_factory_media_to_mojo_adapter.cc
@@ -132,6 +132,13 @@ base::Passed(&create_and_add_new_device_cb))); } +void DeviceFactoryMediaToMojoAdapter::AddVirtualDevice( + const media::VideoCaptureDeviceInfo& device_info, + mojom::ProducerPtr producer, + mojom::VirtualDeviceRequest virtual_device_request) { + NOTIMPLEMENTED(); +} + void DeviceFactoryMediaToMojoAdapter::CreateAndAddNewDevice( const std::string& device_id, mojom::DeviceRequest device_request,
diff --git a/services/video_capture/device_factory_media_to_mojo_adapter.h b/services/video_capture/device_factory_media_to_mojo_adapter.h index a62b8e3..655eed2b 100644 --- a/services/video_capture/device_factory_media_to_mojo_adapter.h +++ b/services/video_capture/device_factory_media_to_mojo_adapter.h
@@ -35,6 +35,9 @@ void CreateDevice(const std::string& device_id, mojom::DeviceRequest device_request, CreateDeviceCallback callback) override; + void AddVirtualDevice(const media::VideoCaptureDeviceInfo& device_info, + mojom::ProducerPtr producer, + mojom::VirtualDeviceRequest virtual_device) override; private: struct ActiveDeviceEntry {
diff --git a/services/video_capture/device_factory_provider_impl.cc b/services/video_capture/device_factory_provider_impl.cc index f21b59e..40b7a757 100644 --- a/services/video_capture/device_factory_provider_impl.cc +++ b/services/video_capture/device_factory_provider_impl.cc
@@ -11,6 +11,7 @@ #include "media/capture/video/video_capture_jpeg_decoder.h" #include "media/capture/video/video_capture_system_impl.h" #include "services/video_capture/device_factory_media_to_mojo_adapter.h" +#include "services/video_capture/virtual_device_enabled_device_factory.h" namespace { @@ -59,9 +60,11 @@ auto video_capture_system = std::make_unique<media::VideoCaptureSystemImpl>( std::move(media_device_factory)); - device_factory_ = std::make_unique<DeviceFactoryMediaToMojoAdapter>( - service_ref_->Clone(), std::move(video_capture_system), - base::Bind(CreateJpegDecoder)); + device_factory_ = std::make_unique<VirtualDeviceEnabledDeviceFactory>( + service_ref_->Clone(), + std::make_unique<DeviceFactoryMediaToMojoAdapter>( + service_ref_->Clone(), std::move(video_capture_system), + base::Bind(CreateJpegDecoder))); } } // namespace video_capture
diff --git a/services/video_capture/device_factory_provider_impl.h b/services/video_capture/device_factory_provider_impl.h index 6669c78..c179f2da 100644 --- a/services/video_capture/device_factory_provider_impl.h +++ b/services/video_capture/device_factory_provider_impl.h
@@ -14,8 +14,6 @@ namespace video_capture { -class DeviceFactoryMediaToMojoAdapter; - class DeviceFactoryProviderImpl : public mojom::DeviceFactoryProvider { public: DeviceFactoryProviderImpl( @@ -31,7 +29,7 @@ void LazyInitializeDeviceFactory(); mojo::BindingSet<mojom::DeviceFactory> factory_bindings_; - std::unique_ptr<DeviceFactoryMediaToMojoAdapter> device_factory_; + std::unique_ptr<mojom::DeviceFactory> device_factory_; const std::unique_ptr<service_manager::ServiceContextRef> service_ref_; base::Callback<void(float)> set_shutdown_delay_cb_;
diff --git a/services/video_capture/public/interfaces/BUILD.gn b/services/video_capture/public/interfaces/BUILD.gn index 9228f30..48946afe 100644 --- a/services/video_capture/public/interfaces/BUILD.gn +++ b/services/video_capture/public/interfaces/BUILD.gn
@@ -9,8 +9,10 @@ "device.mojom", "device_factory.mojom", "device_factory_provider.mojom", + "producer.mojom", "receiver.mojom", "testing_controls.mojom", + "virtual_device.mojom", ] deps = [
diff --git a/services/video_capture/public/interfaces/constants.mojom b/services/video_capture/public/interfaces/constants.mojom index 5ac0201..5a5404e 100644 --- a/services/video_capture/public/interfaces/constants.mojom +++ b/services/video_capture/public/interfaces/constants.mojom
@@ -6,3 +6,4 @@ const string kServiceName = "video_capture"; const float kDefaultShutdownDelayInSeconds = 5; +const int32 kInvalidBufferId = -1;
diff --git a/services/video_capture/public/interfaces/device_factory.mojom b/services/video_capture/public/interfaces/device_factory.mojom index a66434b..9c0e744 100644 --- a/services/video_capture/public/interfaces/device_factory.mojom +++ b/services/video_capture/public/interfaces/device_factory.mojom
@@ -6,6 +6,8 @@ import "media/capture/mojo/video_capture_types.mojom"; import "services/video_capture/public/interfaces/device.mojom"; +import "services/video_capture/public/interfaces/producer.mojom"; +import "services/video_capture/public/interfaces/virtual_device.mojom"; enum DeviceAccessResultCode { NOT_INITIALIZED, @@ -37,4 +39,15 @@ // in use. CreateDevice(string device_id, Device& device_request) => (DeviceAccessResultCode result_code); + + // Creates a new virtual capture device, which will be exposed by the device + // factory using the given |device_info|. The returned |virtual_device| is to + // be used by the caller to subsequently push video frames. These frames will + // appear to clients of the device as if they were produced by the device. + // The virtual device is removed either when the caller releases + // |virtual_device| or the given |producer| is closed. + AddVirtualDevice( + media.mojom.VideoCaptureDeviceInfo device_info, + Producer producer, + VirtualDevice& virtual_device); };
diff --git a/services/video_capture/public/interfaces/producer.mojom b/services/video_capture/public/interfaces/producer.mojom new file mode 100644 index 0000000..6f927aa --- /dev/null +++ b/services/video_capture/public/interfaces/producer.mojom
@@ -0,0 +1,15 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module video_capture.mojom; + +import "media/mojo/interfaces/media_types.mojom"; + +// An interface for providing buffer info updates to the producer of +// video frames for the associated |VirtualDevice| interface. +interface Producer { + OnNewBufferHandle(int32 buffer_id, handle<shared_buffer> buffer_handle) + => (); + OnBufferRetired(int32 buffer_id); +};
diff --git a/services/video_capture/public/interfaces/virtual_device.mojom b/services/video_capture/public/interfaces/virtual_device.mojom new file mode 100644 index 0000000..34c52b4 --- /dev/null +++ b/services/video_capture/public/interfaces/virtual_device.mojom
@@ -0,0 +1,46 @@ +// 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 video_capture.mojom; + +import "media/capture/mojo/video_capture_types.mojom"; +import "media/mojo/interfaces/media_types.mojom"; +import "services/video_capture/public/interfaces/producer.mojom"; +import "ui/gfx/geometry/mojo/geometry.mojom"; + +// Interface for a producer to feed video frames into a virtual +// device. These frames will appear to the consumer of the device +// as if they were produced by a real device. +// +// The buffers used for transporting video frames are managed by +// this interface, and are obtained from a finite size buffer pool. +// When the producer wants to push a frame, it will first request a buffer +// via |RequestFrameBuffer|, and a buffer ID will be provided in the +// response. In the process of assigning a buffer to the producer, a new +// buffer might be created and/or an old buffer might be retired. +// +// To avoid the remapping of buffers in producer after each buffer +// request, a separate interface |Producer| is used for notifying the +// producer with the buffer information changes. It is producer's +// responsibility for caching the buffer information. +interface VirtualDevice { + // This is used by the producer for requesting a buffer to store frame + // data. The frame can subsequently be pushed via |OnFrameReadyInBuffer|. + // An invalid buffer ID |Constants.kInvalidBufferId| will be returned + // if no buffer is available. + // + // Note: A new buffer might be created and/or an old buffer might be + // retired as a side-effect of the request. In that case, + // |Producer.OnNewBufferHandle| and/or |Producer.OnBufferRetired| + // will be invoked. + RequestFrameBuffer(gfx.mojom.Size dimension, + media.mojom.VideoPixelFormat pixel_format, + media.mojom.VideoPixelStorage pixel_storage) + => (int32 buffer_id); + + // Called to indicate that a video frame is ready in the given buffer + // |buffer_id|. + OnFrameReadyInBuffer(int32 buffer_id, + media.mojom.VideoFrameInfo frame_info); +};
diff --git a/services/video_capture/receiver_mojo_to_media_adapter.cc b/services/video_capture/receiver_mojo_to_media_adapter.cc index 2883b4f..ed3b1fa 100644 --- a/services/video_capture/receiver_mojo_to_media_adapter.cc +++ b/services/video_capture/receiver_mojo_to_media_adapter.cc
@@ -5,25 +5,7 @@ #include "services/video_capture/receiver_mojo_to_media_adapter.h" #include "mojo/public/cpp/bindings/strong_binding.h" - -namespace { - -class ScopedAccessPermissionMediaToMojoAdapter - : public video_capture::mojom::ScopedAccessPermission { - public: - ScopedAccessPermissionMediaToMojoAdapter( - std::unique_ptr< - media::VideoCaptureDevice::Client::Buffer::ScopedAccessPermission> - access_permission) - : access_permission_(std::move(access_permission)) {} - - private: - std::unique_ptr< - media::VideoCaptureDevice::Client::Buffer::ScopedAccessPermission> - access_permission_; -}; - -} // anonymous namespace +#include "services/video_capture/scoped_access_permission_media_to_mojo_adapter.h" namespace video_capture {
diff --git a/services/video_capture/scoped_access_permission_media_to_mojo_adapter.cc b/services/video_capture/scoped_access_permission_media_to_mojo_adapter.cc new file mode 100644 index 0000000..9b55e31f --- /dev/null +++ b/services/video_capture/scoped_access_permission_media_to_mojo_adapter.cc
@@ -0,0 +1,19 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/video_capture/scoped_access_permission_media_to_mojo_adapter.h" + +namespace video_capture { + +ScopedAccessPermissionMediaToMojoAdapter:: + ScopedAccessPermissionMediaToMojoAdapter( + std::unique_ptr< + media::VideoCaptureDevice::Client::Buffer::ScopedAccessPermission> + access_permission) + : access_permission_(std::move(access_permission)) {} + +ScopedAccessPermissionMediaToMojoAdapter:: + ~ScopedAccessPermissionMediaToMojoAdapter() {} + +} // namespace video_capture
diff --git a/services/video_capture/scoped_access_permission_media_to_mojo_adapter.h b/services/video_capture/scoped_access_permission_media_to_mojo_adapter.h new file mode 100644 index 0000000..bfe1135 --- /dev/null +++ b/services/video_capture/scoped_access_permission_media_to_mojo_adapter.h
@@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_VIDEO_CAPTURE_SCOPED_ACCESS_PERMISSION_MEDIA_TO_MOJO_ADAPTER_H_ +#define SERVICES_VIDEO_CAPTURE_SCOPED_ACCESS_PERMISSION_MEDIA_TO_MOJO_ADAPTER_H_ + +#include "media/capture/video/video_capture_device_client.h" +#include "services/video_capture/public/interfaces/receiver.mojom.h" + +namespace video_capture { + +class ScopedAccessPermissionMediaToMojoAdapter + : public video_capture::mojom::ScopedAccessPermission { + public: + explicit ScopedAccessPermissionMediaToMojoAdapter( + std::unique_ptr< + media::VideoCaptureDevice::Client::Buffer::ScopedAccessPermission> + access_permission); + ~ScopedAccessPermissionMediaToMojoAdapter() override; + + private: + std::unique_ptr< + media::VideoCaptureDevice::Client::Buffer::ScopedAccessPermission> + access_permission_; +}; + +} // namespace video_capture + +#endif // SERVICES_VIDEO_CAPTURE_SCOPED_ACCESS_PERMISSION_MEDIA_TO_MOJO_ADAPTER_H_
diff --git a/services/video_capture/test/device_factory_provider_unittest.cc b/services/video_capture/test/device_factory_provider_unittest.cc index 8aa3b36b..1cec6f0 100644 --- a/services/video_capture/test/device_factory_provider_unittest.cc +++ b/services/video_capture/test/device_factory_provider_unittest.cc
@@ -8,6 +8,7 @@ #include "services/video_capture/public/interfaces/constants.mojom.h" #include "services/video_capture/public/interfaces/device_factory.mojom.h" #include "services/video_capture/test/device_factory_provider_test.h" +#include "services/video_capture/test/mock_producer.h" using testing::Exactly; using testing::_; @@ -51,6 +52,38 @@ ASSERT_EQ(1u, num_devices_enumerated); } +// Tests that an added virtual device will be returned in the callback +// when calling GetDeviceInfos. +TEST_F(VideoCaptureServiceDeviceFactoryProviderTest, + VirtualDeviceEnumeratedAfterAdd) { + base::RunLoop wait_loop; + const std::string virtual_device_id = "/virtual/device"; + media::VideoCaptureDeviceInfo info; + info.descriptor.device_id = virtual_device_id; + mojom::VirtualDevicePtr virtual_device_proxy; + mojom::ProducerPtr producer_proxy; + MockProducer producer(mojo::MakeRequest(&producer_proxy)); + EXPECT_CALL(device_info_receiver_, Run(_)) + .Times(Exactly(1)) + .WillOnce( + Invoke([&wait_loop, virtual_device_id]( + const std::vector<media::VideoCaptureDeviceInfo>& infos) { + bool virtual_device_enumerated = false; + for (const auto& info : infos) { + if (info.descriptor.device_id == virtual_device_id) { + virtual_device_enumerated = true; + break; + } + } + EXPECT_TRUE(virtual_device_enumerated); + wait_loop.Quit(); + })); + factory_->AddVirtualDevice(info, std::move(producer_proxy), + mojo::MakeRequest(&virtual_device_proxy)); + factory_->GetDeviceInfos(device_info_receiver_.Get()); + wait_loop.Run(); +} + // Tests that VideoCaptureDeviceFactory::CreateDeviceProxy() returns an error // code when trying to create a device for an invalid descriptor. TEST_F(VideoCaptureServiceDeviceFactoryProviderTest, @@ -71,6 +104,31 @@ wait_loop.Run(); } +// Test that CreateDevice will succeed when trying to create a device +// for an added virtual device. +TEST_F(VideoCaptureServiceDeviceFactoryProviderTest, + CreateDeviceSuccessForVirtualDevice) { + base::RunLoop wait_loop; + const std::string virtual_device_id = "/virtual/device"; + media::VideoCaptureDeviceInfo info; + info.descriptor.device_id = virtual_device_id; + mojom::DevicePtr device_proxy; + mojom::VirtualDevicePtr virtual_device_proxy; + mojom::ProducerPtr producer_proxy; + MockProducer producer(mojo::MakeRequest(&producer_proxy)); + base::MockCallback<mojom::DeviceFactory::CreateDeviceCallback> + create_device_proxy_callback; + EXPECT_CALL(create_device_proxy_callback, + Run(mojom::DeviceAccessResultCode::SUCCESS)) + .Times(1) + .WillOnce(InvokeWithoutArgs([&wait_loop]() { wait_loop.Quit(); })); + factory_->AddVirtualDevice(info, std::move(producer_proxy), + mojo::MakeRequest(&virtual_device_proxy)); + factory_->CreateDevice(virtual_device_id, mojo::MakeRequest(&device_proxy), + create_device_proxy_callback.Get()); + wait_loop.Run(); +} + // Tests that the service requests to be closed when the only client disconnects // after not having done anything other than obtaining a connection to the // fake device factory.
diff --git a/services/video_capture/test/mock_producer.cc b/services/video_capture/test/mock_producer.cc new file mode 100644 index 0000000..2dda15c --- /dev/null +++ b/services/video_capture/test/mock_producer.cc
@@ -0,0 +1,21 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/video_capture/test/mock_producer.h" + +namespace video_capture { + +MockProducer::MockProducer(mojom::ProducerRequest request) + : binding_(this, std::move(request)) {} + +MockProducer::~MockProducer() = default; + +void MockProducer::OnNewBufferHandle( + int32_t buffer_id, + mojo::ScopedSharedBufferHandle buffer_handle, + OnNewBufferHandleCallback callback) { + DoOnNewBufferHandle(buffer_id, &buffer_handle, callback); +} + +} // namespace video_capture
diff --git a/services/video_capture/test/mock_producer.h b/services/video_capture/test/mock_producer.h new file mode 100644 index 0000000..2dd7304 --- /dev/null +++ b/services/video_capture/test/mock_producer.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 SERVICES_VIDEO_CAPTURE_TEST_MOCK_PRODUCER_H_ +#define SERVICES_VIDEO_CAPTURE_TEST_MOCK_PRODUCER_H_ + +#include "media/mojo/interfaces/media_types.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "services/video_capture/public/interfaces/producer.mojom.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace video_capture { + +class MockProducer : public mojom::Producer { + public: + MockProducer(mojom::ProducerRequest request); + ~MockProducer() override; + + // Use forwarding method to work around gmock not supporting move-only types. + void OnNewBufferHandle(int32_t buffer_id, + mojo::ScopedSharedBufferHandle buffer_handle, + OnNewBufferHandleCallback callback) override; + + MOCK_METHOD3(DoOnNewBufferHandle, + void(int32_t, + mojo::ScopedSharedBufferHandle*, + OnNewBufferHandleCallback& callback)); + MOCK_METHOD1(OnBufferRetired, void(int32_t)); + + private: + const mojo::Binding<mojom::Producer> binding_; +}; + +} // namespace video_capture + +#endif // SERVICES_VIDEO_CAPTURE_TEST_MOCK_PRODUCER_H_
diff --git a/services/video_capture/test/virtual_device_unittest.cc b/services/video_capture/test/virtual_device_unittest.cc new file mode 100644 index 0000000..c9c471ef --- /dev/null +++ b/services/video_capture/test/virtual_device_unittest.cc
@@ -0,0 +1,172 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/test/mock_callback.h" +#include "media/capture/video/video_capture_device_info.h" +#include "services/service_manager/public/cpp/service_context_ref.h" +#include "services/video_capture/test/mock_producer.h" +#include "services/video_capture/test/mock_receiver.h" +#include "services/video_capture/virtual_device_mojo_adapter.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::Invoke; +using testing::Mock; + +namespace video_capture { + +namespace { + +const std::string kTestDeviceId = "/test/device"; +const std::string kTestDeviceName = "Test Device"; +const gfx::Size kTestFrameSize = {640 /* width */, 480 /* height */}; +const media::VideoPixelFormat kTestPixelFormat = + media::VideoPixelFormat::PIXEL_FORMAT_I420; +const media::VideoPixelStorage kTestPixelStorage = + media::VideoPixelStorage::PIXEL_STORAGE_CPU; + +} // anonymous namespace + +class VirtualDeviceTest : public ::testing::Test { + public: + VirtualDeviceTest() : ref_factory_(base::Bind(&base::DoNothing)) {} + ~VirtualDeviceTest() override {} + + void SetUp() override { + device_info_.descriptor.device_id = kTestDeviceId; + device_info_.descriptor.display_name = kTestDeviceName; + mojom::ProducerPtr producer_proxy; + producer_ = + std::make_unique<MockProducer>(mojo::MakeRequest(&producer_proxy)); + device_adapter_ = std::make_unique<VirtualDeviceMojoAdapter>( + ref_factory_.CreateRef(), device_info_, std::move(producer_proxy)); + } + + void OnFrameBufferReceived(bool valid_buffer_expected, int32_t buffer_id) { + if (!valid_buffer_expected) { + EXPECT_EQ(-1, buffer_id); + return; + } + + EXPECT_NE(-1, buffer_id); + received_buffer_ids_.push_back(buffer_id); + } + + void VerifyAndGetMaxFrameBuffers() { + base::RunLoop wait_loop; + EXPECT_CALL(*producer_, DoOnNewBufferHandle(_, _, _)) + .Times(VirtualDeviceMojoAdapter::max_buffer_pool_buffer_count()) + .WillRepeatedly( + Invoke([](int32_t buffer_id, mojo::ScopedSharedBufferHandle* handle, + mojom::Producer::OnNewBufferHandleCallback& callback) { + std::move(callback).Run(); + })); + // Should receive valid buffer for up to the maximum buffer count. + for (int i = 0; + i < VirtualDeviceMojoAdapter::max_buffer_pool_buffer_count(); i++) { + device_adapter_->RequestFrameBuffer( + kTestFrameSize, kTestPixelFormat, kTestPixelStorage, + base::Bind(&VirtualDeviceTest::OnFrameBufferReceived, + base::Unretained(this), true /* valid_buffer_expected */)); + } + + // No more buffer available. Invalid buffer id should be returned. + device_adapter_->RequestFrameBuffer( + kTestFrameSize, kTestPixelFormat, kTestPixelStorage, + base::Bind(&VirtualDeviceTest::OnFrameBufferReceived, + base::Unretained(this), false /* valid_buffer_expected */)); + + wait_loop.RunUntilIdle(); + Mock::VerifyAndClearExpectations(producer_.get()); + EXPECT_EQ(VirtualDeviceMojoAdapter::max_buffer_pool_buffer_count(), + static_cast<int>(received_buffer_ids_.size())); + } + + protected: + std::unique_ptr<VirtualDeviceMojoAdapter> device_adapter_; + // ID of buffers received and owned by the producer. + std::vector<int> received_buffer_ids_; + std::unique_ptr<MockProducer> producer_; + + private: + base::MessageLoop loop_; + service_manager::ServiceContextRefFactory ref_factory_; + media::VideoCaptureDeviceInfo device_info_; +}; + +TEST_F(VirtualDeviceTest, VerifyDeviceInfo) { + EXPECT_EQ(kTestDeviceId, device_adapter_->device_info().descriptor.device_id); + EXPECT_EQ(kTestDeviceName, + device_adapter_->device_info().descriptor.display_name); +} + +TEST_F(VirtualDeviceTest, OnFrameReadyInBufferWithoutReceiver) { + // Obtain maximum number of buffers. + VerifyAndGetMaxFrameBuffers(); + + base::RunLoop wait_loop; + + // Release one buffer back to the pool, no consumer hold since there is no + // receiver. + device_adapter_->OnFrameReadyInBuffer(received_buffer_ids_.at(0), + media::mojom::VideoFrameInfo::New()); + + // Verify there is a buffer available now, without creating a new + // buffer. + EXPECT_CALL(*producer_, DoOnNewBufferHandle(_, _, _)).Times(0); + device_adapter_->RequestFrameBuffer( + kTestFrameSize, kTestPixelFormat, kTestPixelStorage, + base::Bind(&VirtualDeviceTest::OnFrameBufferReceived, + base::Unretained(this), true /* valid_buffer_expected */)); + + wait_loop.RunUntilIdle(); +} + +TEST_F(VirtualDeviceTest, OnFrameReadyInBufferWithReceiver) { + // Obtain maximum number of buffers for the producer. + VerifyAndGetMaxFrameBuffers(); + + // Release all buffers back to consumer, then back to the pool + // after |Receiver::OnFrameReadyInBuffer| is invoked. + base::RunLoop wait_loop; + mojom::ReceiverPtr receiver_proxy; + MockReceiver receiver(mojo::MakeRequest(&receiver_proxy)); + EXPECT_CALL(receiver, OnStarted()); + EXPECT_CALL(receiver, DoOnNewBufferHandle(_, _)) + .Times(VirtualDeviceMojoAdapter::max_buffer_pool_buffer_count()); + EXPECT_CALL(receiver, DoOnFrameReadyInBuffer(_, _, _, _)) + .Times(VirtualDeviceMojoAdapter::max_buffer_pool_buffer_count()); + device_adapter_->Start(media::VideoCaptureParams(), + std::move(receiver_proxy)); + for (auto buffer_id : received_buffer_ids_) { + media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New(); + // |info->metadata| cannot be a nullptr when going over mojo boundary. + info->metadata = std::make_unique<base::DictionaryValue>(); + device_adapter_->OnFrameReadyInBuffer(buffer_id, std::move(info)); + } + wait_loop.RunUntilIdle(); + Mock::VerifyAndClearExpectations(&receiver); + + // Verify that requesting a buffer doesn't create a new one, will reuse + // the available buffer in the pool. + base::RunLoop wait_loop2; + EXPECT_CALL(*producer_, DoOnNewBufferHandle(_, _, _)).Times(0); + base::MockCallback<mojom::VirtualDevice::RequestFrameBufferCallback> + request_frame_buffer_callback; + EXPECT_CALL(request_frame_buffer_callback, Run(_)) + .Times(1) + .WillOnce(Invoke([this](int32_t buffer_id) { + // Verify that the returned |buffer_id| is a known buffer ID. + EXPECT_TRUE(base::ContainsValue(received_buffer_ids_, buffer_id)); + })); + device_adapter_->RequestFrameBuffer(kTestFrameSize, kTestPixelFormat, + kTestPixelStorage, + request_frame_buffer_callback.Get()); + wait_loop2.RunUntilIdle(); +} + +} // namespace video_capture
diff --git a/services/video_capture/virtual_device_enabled_device_factory.cc b/services/video_capture/virtual_device_enabled_device_factory.cc new file mode 100644 index 0000000..d86d89b --- /dev/null +++ b/services/video_capture/virtual_device_enabled_device_factory.cc
@@ -0,0 +1,126 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/video_capture/virtual_device_enabled_device_factory.h" + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "media/capture/video/video_capture_device_info.h" +#include "services/video_capture/virtual_device_mojo_adapter.h" + +namespace video_capture { + +VirtualDeviceEnabledDeviceFactory::VirtualDeviceEntry::VirtualDeviceEntry() = + default; + +VirtualDeviceEnabledDeviceFactory::VirtualDeviceEntry::~VirtualDeviceEntry() = + default; + +VirtualDeviceEnabledDeviceFactory::VirtualDeviceEntry::VirtualDeviceEntry( + VirtualDeviceEnabledDeviceFactory::VirtualDeviceEntry&& other) = default; + +VirtualDeviceEnabledDeviceFactory::VirtualDeviceEntry& +VirtualDeviceEnabledDeviceFactory::VirtualDeviceEntry::operator=( + VirtualDeviceEnabledDeviceFactory::VirtualDeviceEntry&& other) = default; + +VirtualDeviceEnabledDeviceFactory::VirtualDeviceEnabledDeviceFactory( + std::unique_ptr<service_manager::ServiceContextRef> service_ref, + std::unique_ptr<mojom::DeviceFactory> device_factory) + : service_ref_(std::move(service_ref)), + device_factory_(std::move(device_factory)), + weak_factory_(this) {} + +VirtualDeviceEnabledDeviceFactory::~VirtualDeviceEnabledDeviceFactory() = + default; + +void VirtualDeviceEnabledDeviceFactory::GetDeviceInfos( + GetDeviceInfosCallback callback) { + device_factory_->GetDeviceInfos( + base::BindOnce(&VirtualDeviceEnabledDeviceFactory::OnGetDeviceInfos, + weak_factory_.GetWeakPtr(), base::Passed(&callback))); +} + +void VirtualDeviceEnabledDeviceFactory::CreateDevice( + const std::string& device_id, + mojom::DeviceRequest device_request, + CreateDeviceCallback callback) { + auto virtual_device_iter = virtual_devices_by_id_.find(device_id); + if (virtual_device_iter != virtual_devices_by_id_.end()) { + VirtualDeviceEntry& device_entry = virtual_device_iter->second; + if (device_entry.consumer_binding) { + // The requested virtual device is already used by another client. + // Revoke the access for the current client, then bind to the new request. + device_entry.consumer_binding.reset(); + device_entry.device->Stop(); + } + device_entry.consumer_binding = + std::make_unique<mojo::Binding<mojom::Device>>( + device_entry.device.get(), std::move(device_request)); + device_entry.consumer_binding->set_connection_error_handler( + base::Bind(&VirtualDeviceEnabledDeviceFactory:: + OnVirtualDeviceConsumerConnectionErrorOrClose, + base::Unretained(this), device_id)); + std::move(callback).Run(mojom::DeviceAccessResultCode::SUCCESS); + return; + } + + device_factory_->CreateDevice(device_id, std::move(device_request), + std::move(callback)); +} + +void VirtualDeviceEnabledDeviceFactory::AddVirtualDevice( + const media::VideoCaptureDeviceInfo& device_info, + mojom::ProducerPtr producer, + mojom::VirtualDeviceRequest virtual_device_request) { + auto device_id = device_info.descriptor.device_id; + auto virtual_device_iter = virtual_devices_by_id_.find(device_id); + if (virtual_device_iter != virtual_devices_by_id_.end()) { + // Revoke the access for the current producer and consumer by + // removing it from the list. + virtual_devices_by_id_.erase(virtual_device_iter); + } + + VirtualDeviceEntry device_entry; + producer.set_connection_error_handler( + base::Bind(&VirtualDeviceEnabledDeviceFactory:: + OnVirtualDeviceProducerConnectionErrorOrClose, + base::Unretained(this), device_id)); + device_entry.device = std::make_unique<VirtualDeviceMojoAdapter>( + service_ref_->Clone(), device_info, std::move(producer)); + device_entry.producer_binding = + std::make_unique<mojo::Binding<mojom::VirtualDevice>>( + device_entry.device.get(), std::move(virtual_device_request)); + device_entry.producer_binding->set_connection_error_handler( + base::Bind(&VirtualDeviceEnabledDeviceFactory:: + OnVirtualDeviceProducerConnectionErrorOrClose, + base::Unretained(this), device_id)); + virtual_devices_by_id_[device_id] = std::move(device_entry); +} + +void VirtualDeviceEnabledDeviceFactory::OnGetDeviceInfos( + GetDeviceInfosCallback callback, + const std::vector<media::VideoCaptureDeviceInfo>& device_infos) { + std::vector<media::VideoCaptureDeviceInfo> all_device_infos; + for (const auto& device_entry : virtual_devices_by_id_) { + all_device_infos.push_back(device_entry.second.device->device_info()); + } + all_device_infos.insert(std::end(all_device_infos), std::begin(device_infos), + std::end(device_infos)); + std::move(callback).Run(all_device_infos); +} + +void VirtualDeviceEnabledDeviceFactory:: + OnVirtualDeviceProducerConnectionErrorOrClose( + const std::string& device_id) { + virtual_devices_by_id_[device_id].device->Stop(); + virtual_devices_by_id_.erase(device_id); +} + +void VirtualDeviceEnabledDeviceFactory:: + OnVirtualDeviceConsumerConnectionErrorOrClose( + const std::string& device_id) { + virtual_devices_by_id_[device_id].device->Stop(); +} + +} // namespace video_capture
diff --git a/services/video_capture/virtual_device_enabled_device_factory.h b/services/video_capture/virtual_device_enabled_device_factory.h new file mode 100644 index 0000000..386ed3ea --- /dev/null +++ b/services/video_capture/virtual_device_enabled_device_factory.h
@@ -0,0 +1,69 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_VIDEO_CAPTURE_VIRTUAL_DEVICE_ENABLED_DEVICE_FACTORY_H_ +#define SERVICES_VIDEO_CAPTURE_VIRTUAL_DEVICE_ENABLED_DEVICE_FACTORY_H_ + +#include <map> + +#include "mojo/public/cpp/bindings/binding.h" +#include "services/service_manager/public/cpp/service_context_ref.h" +#include "services/video_capture/public/interfaces/device.mojom.h" +#include "services/video_capture/public/interfaces/device_factory.mojom.h" +#include "services/video_capture/public/interfaces/virtual_device.mojom.h" + +namespace video_capture { + +class VirtualDeviceMojoAdapter; + +// Decorator that adds support for virtual devices to a given +// mojom::DeviceFactory. +class VirtualDeviceEnabledDeviceFactory : public mojom::DeviceFactory { + public: + VirtualDeviceEnabledDeviceFactory( + std::unique_ptr<service_manager::ServiceContextRef> service_ref, + std::unique_ptr<mojom::DeviceFactory> factory); + ~VirtualDeviceEnabledDeviceFactory() override; + + // mojom::DeviceFactory implementation. + void GetDeviceInfos(GetDeviceInfosCallback callback) override; + void CreateDevice(const std::string& device_id, + mojom::DeviceRequest device_request, + CreateDeviceCallback callback) override; + void AddVirtualDevice(const media::VideoCaptureDeviceInfo& device_info, + mojom::ProducerPtr producer, + mojom::VirtualDeviceRequest virtual_device) override; + + private: + struct VirtualDeviceEntry { + VirtualDeviceEntry(); + ~VirtualDeviceEntry(); + VirtualDeviceEntry(VirtualDeviceEntry&& other); + VirtualDeviceEntry& operator=(VirtualDeviceEntry&& other); + + std::unique_ptr<VirtualDeviceMojoAdapter> device; + std::unique_ptr<mojo::Binding<mojom::VirtualDevice>> producer_binding; + std::unique_ptr<mojo::Binding<mojom::Device>> consumer_binding; + }; + + void OnGetDeviceInfos( + GetDeviceInfosCallback callback, + const std::vector<media::VideoCaptureDeviceInfo>& device_infos); + + void OnVirtualDeviceProducerConnectionErrorOrClose( + const std::string& device_id); + void OnVirtualDeviceConsumerConnectionErrorOrClose( + const std::string& device_id); + + std::map<std::string, VirtualDeviceEntry> virtual_devices_by_id_; + const std::unique_ptr<service_manager::ServiceContextRef> service_ref_; + const std::unique_ptr<mojom::DeviceFactory> device_factory_; + + base::WeakPtrFactory<VirtualDeviceEnabledDeviceFactory> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(VirtualDeviceEnabledDeviceFactory); +}; + +} // namespace video_capture + +#endif // SERVICES_VIDEO_CAPTURE_VIRTUAL_DEVICE_ENABLED_DEVICE_FACTORY_H_
diff --git a/services/video_capture/virtual_device_mojo_adapter.cc b/services/video_capture/virtual_device_mojo_adapter.cc new file mode 100644 index 0000000..6152106 --- /dev/null +++ b/services/video_capture/virtual_device_mojo_adapter.cc
@@ -0,0 +1,201 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/video_capture/virtual_device_mojo_adapter.h" + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "media/base/bind_to_current_loop.h" +#include "media/base/scoped_callback_runner.h" +#include "media/capture/video/scoped_buffer_pool_reservation.h" +#include "media/capture/video/video_capture_buffer_pool_impl.h" +#include "media/capture/video/video_capture_buffer_tracker_factory_impl.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "services/video_capture/public/interfaces/constants.mojom.h" +#include "services/video_capture/scoped_access_permission_media_to_mojo_adapter.h" + +namespace { + +// The maximum number of video frame buffers in-flight at any one time +// If all buffers are still in use by consumers when new frames are produced +// those frames get dropped. +static const int kMaxBufferCount = 3; + +void OnNewBufferHandleAcknowleged( + video_capture::mojom::VirtualDevice::RequestFrameBufferCallback callback, + int32_t buffer_id) { + std::move(callback).Run(buffer_id); +} + +} // anonymous namespace + +namespace video_capture { + +VirtualDeviceMojoAdapter::VirtualDeviceMojoAdapter( + std::unique_ptr<service_manager::ServiceContextRef> service_ref, + const media::VideoCaptureDeviceInfo& device_info, + mojom::ProducerPtr producer) + : service_ref_(std::move(service_ref)), + device_info_(device_info), + producer_(std::move(producer)), + buffer_pool_(new media::VideoCaptureBufferPoolImpl( + std::make_unique<media::VideoCaptureBufferTrackerFactoryImpl>(), + max_buffer_pool_buffer_count())) {} + +VirtualDeviceMojoAdapter::~VirtualDeviceMojoAdapter() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +int VirtualDeviceMojoAdapter::max_buffer_pool_buffer_count() { + return kMaxBufferCount; +} + +void VirtualDeviceMojoAdapter::RequestFrameBuffer( + const gfx::Size& dimension, + media::VideoPixelFormat pixel_format, + media::VideoPixelStorage pixel_storage, + RequestFrameBufferCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + int buffer_id_to_drop = media::VideoCaptureBufferPool::kInvalidId; + const int buffer_id = buffer_pool_->ReserveForProducer( + dimension, pixel_format, pixel_storage, 0 /* frame_feedback_id */, + &buffer_id_to_drop); + + // Remove dropped buffer if there is one. + if (buffer_id_to_drop != media::VideoCaptureBufferPool::kInvalidId) { + auto entry_iter = std::find(known_buffer_ids_.begin(), + known_buffer_ids_.end(), buffer_id_to_drop); + if (entry_iter != known_buffer_ids_.end()) { + known_buffer_ids_.erase(entry_iter); + producer_->OnBufferRetired(buffer_id_to_drop); + if (receiver_.is_bound()) { + receiver_->OnBufferRetired(buffer_id_to_drop); + } + } + } + + // No buffer available. + if (buffer_id == media::VideoCaptureBufferPool::kInvalidId) { + std::move(callback).Run(mojom::kInvalidBufferId); + return; + } + + if (!base::ContainsValue(known_buffer_ids_, buffer_id)) { + if (receiver_.is_bound()) { + receiver_->OnNewBufferHandle( + buffer_id, buffer_pool_->GetHandleForInterProcessTransit( + buffer_id, true /* read_only */)); + } + known_buffer_ids_.push_back(buffer_id); + + // Invoke the response back only after the producer have acked + // that it has received the newly created buffer. This is need + // because the |producer_| and the |callback| are bound to different + // message pipes, so the order for calls to |producer_| and |callback| + // is not guaranteed. + producer_->OnNewBufferHandle( + buffer_id, + buffer_pool_->GetHandleForInterProcessTransit(buffer_id, + false /* read_only */), + base::BindOnce(&OnNewBufferHandleAcknowleged, base::Passed(&callback), + buffer_id)); + return; + } + std::move(callback).Run(buffer_id); +} + +void VirtualDeviceMojoAdapter::OnFrameReadyInBuffer( + int32_t buffer_id, + ::media::mojom::VideoFrameInfoPtr frame_info) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // Unknown buffer ID. + if (!base::ContainsValue(known_buffer_ids_, buffer_id)) { + return; + } + + // Notify receiver if there is one. + if (receiver_.is_bound()) { + buffer_pool_->HoldForConsumers(buffer_id, 1 /* num_clients */); + auto access_permission = std::make_unique< + media::ScopedBufferPoolReservation<media::ConsumerReleaseTraits>>( + buffer_pool_, buffer_id); + mojom::ScopedAccessPermissionPtr access_permission_proxy; + mojo::MakeStrongBinding<mojom::ScopedAccessPermission>( + std::make_unique<ScopedAccessPermissionMediaToMojoAdapter>( + std::move(access_permission)), + mojo::MakeRequest(&access_permission_proxy)); + receiver_->OnFrameReadyInBuffer(buffer_id, 0 /* frame_feedback_id */, + std::move(access_permission_proxy), + std::move(frame_info)); + } + buffer_pool_->RelinquishProducerReservation(buffer_id); +} + +void VirtualDeviceMojoAdapter::Start( + const media::VideoCaptureParams& requested_settings, + mojom::ReceiverPtr receiver) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + receiver.set_connection_error_handler( + base::Bind(&VirtualDeviceMojoAdapter::OnReceiverConnectionErrorOrClose, + base::Unretained(this))); + receiver_ = std::move(receiver); + receiver_->OnStarted(); + + // Notify receiver of known buffers */ + for (auto buffer_id : known_buffer_ids_) { + receiver_->OnNewBufferHandle(buffer_id, + buffer_pool_->GetHandleForInterProcessTransit( + buffer_id, true /* read_only */)); + } +} + +void VirtualDeviceMojoAdapter::OnReceiverReportingUtilization( + int32_t frame_feedback_id, + double utilization) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void VirtualDeviceMojoAdapter::RequestRefreshFrame() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void VirtualDeviceMojoAdapter::MaybeSuspend() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void VirtualDeviceMojoAdapter::Resume() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void VirtualDeviceMojoAdapter::GetPhotoState(GetPhotoStateCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + std::move(callback).Run(nullptr); +} + +void VirtualDeviceMojoAdapter::SetPhotoOptions( + media::mojom::PhotoSettingsPtr settings, + SetPhotoOptionsCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void VirtualDeviceMojoAdapter::TakePhoto(TakePhotoCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void VirtualDeviceMojoAdapter::Stop() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!receiver_.is_bound()) + return; + // Unsubscribe from connection error callbacks. + receiver_.set_connection_error_handler(base::Closure()); + receiver_.reset(); +} + +void VirtualDeviceMojoAdapter::OnReceiverConnectionErrorOrClose() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + Stop(); +} + +} // namespace video_capture
diff --git a/services/video_capture/virtual_device_mojo_adapter.h b/services/video_capture/virtual_device_mojo_adapter.h new file mode 100644 index 0000000..8f2f08a --- /dev/null +++ b/services/video_capture/virtual_device_mojo_adapter.h
@@ -0,0 +1,76 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_VIDEO_CAPTURE_VIRTUAL_DEVICE_MOJO_ADAPTER_H_ +#define SERVICES_VIDEO_CAPTURE_VIRTUAL_DEVICE_MOJO_ADAPTER_H_ + +#include "base/sequence_checker.h" +#include "media/capture/video/video_capture_buffer_pool.h" +#include "media/capture/video_capture_types.h" +#include "services/service_manager/public/cpp/service_context_ref.h" +#include "services/video_capture/public/interfaces/device.mojom.h" +#include "services/video_capture/public/interfaces/producer.mojom.h" +#include "services/video_capture/public/interfaces/virtual_device.mojom.h" + +namespace video_capture { + +// Implementation of mojom::Device backed by mojom::VirtualDevice. +class VirtualDeviceMojoAdapter : public mojom::VirtualDevice, + public mojom::Device { + public: + VirtualDeviceMojoAdapter( + std::unique_ptr<service_manager::ServiceContextRef> service_ref, + const media::VideoCaptureDeviceInfo& device_info, + mojom::ProducerPtr producer); + ~VirtualDeviceMojoAdapter() override; + + // mojom::VirtualDevice implementation. + void RequestFrameBuffer(const gfx::Size& dimension, + media::VideoPixelFormat pixel_format, + media::VideoPixelStorage pixel_storage, + RequestFrameBufferCallback callback) override; + void OnFrameReadyInBuffer( + int32_t buffer_id, + ::media::mojom::VideoFrameInfoPtr frame_info) override; + + // mojom::Device implementation. + void Start(const media::VideoCaptureParams& requested_settings, + mojom::ReceiverPtr receiver) override; + void OnReceiverReportingUtilization(int32_t frame_feedback_id, + double utilization) override; + void RequestRefreshFrame() override; + void MaybeSuspend() override; + void Resume() override; + void GetPhotoState(GetPhotoStateCallback callback) override; + void SetPhotoOptions(media::mojom::PhotoSettingsPtr settings, + SetPhotoOptionsCallback callback) override; + void TakePhoto(TakePhotoCallback callback) override; + + void Stop(); + + const media::VideoCaptureDeviceInfo& device_info() const { + return device_info_; + } + + // Returns the fixed maximum number of buffers passed to the constructor + // of VideoCaptureBufferPoolImpl. + static int max_buffer_pool_buffer_count(); + + private: + void OnReceiverConnectionErrorOrClose(); + + const std::unique_ptr<service_manager::ServiceContextRef> service_ref_; + const media::VideoCaptureDeviceInfo device_info_; + mojom::ReceiverPtr receiver_; + mojom::ProducerPtr producer_; + scoped_refptr<media::VideoCaptureBufferPool> buffer_pool_; + std::vector<int> known_buffer_ids_; + SEQUENCE_CHECKER(sequence_checker_); + + DISALLOW_COPY_AND_ASSIGN(VirtualDeviceMojoAdapter); +}; + +} // namespace video_capture + +#endif // SERVICES_VIDEO_CAPTURE_VIRTUAL_DEVICE_MOJO_ADAPTER_H_
diff --git a/services/viz/privileged/interfaces/gl/BUILD.gn b/services/viz/privileged/interfaces/gl/BUILD.gn index 62691cdc..d766ad2 100644 --- a/services/viz/privileged/interfaces/gl/BUILD.gn +++ b/services/viz/privileged/interfaces/gl/BUILD.gn
@@ -12,6 +12,7 @@ ] public_deps = [ + "//components/arc/common:media", "//gpu/ipc/common:interfaces", "//media/gpu/mojo:jpeg_decoder", "//media/mojo/interfaces",
diff --git a/services/viz/privileged/interfaces/gl/gpu_service.mojom b/services/viz/privileged/interfaces/gl/gpu_service.mojom index 6d31573..b4b3d87 100644 --- a/services/viz/privileged/interfaces/gl/gpu_service.mojom +++ b/services/viz/privileged/interfaces/gl/gpu_service.mojom
@@ -4,6 +4,9 @@ module viz.mojom; +import "components/arc/common/protected_buffer_manager.mojom"; +import "components/arc/common/video_decode_accelerator.mojom"; +import "components/arc/common/video_encode_accelerator.mojom"; import "gpu/ipc/common/gpu_info.mojom"; import "gpu/ipc/common/memory_stats.mojom"; import "gpu/ipc/common/surface_handle.mojom"; @@ -25,6 +28,15 @@ // If no channel can be identified, do nothing. CloseChannel(int32 client_id); + // Create a new ARC VideoDecodeAccelerator and binds it to |vda|. + CreateArcVideoDecodeAccelerator(arc.mojom.VideoDecodeAccelerator& vda); + + // Create a new ARC VideoEncodeAccelerator and binds it to |vea|. + CreateArcVideoEncodeAccelerator(arc.mojom.VideoEncodeAccelerator& vea); + + // Create a new ARC ProtectedBufferManager and binds it to |pbm|. + CreateArcProtectedBufferManager(arc.mojom.ProtectedBufferManager& pbm); + // Creates a new JpegDecodeAccelerator and binds it to |jda|. CreateJpegDecodeAccelerator(media.mojom.GpuJpegDecodeAccelerator& jda);
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 312a09f..38f6a40f 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -5348,46 +5348,6 @@ "--bucket", "chromium-result-details", "--test-name", - "android_webview_unittests" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" - } - ], - "dimension_sets": [ - { - "device_os": "KTU84Z", - "device_type": "flo" - } - ], - "expiration": 10800, - "hard_timeout": 900, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, - "test": "android_webview_unittests" - }, - { - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", "base_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -6636,50 +6596,6 @@ ] }, "test": "vr_common_unittests" - }, - { - "args": [ - "--gs-results-bucket=chromium-result-details" - ], - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", - "webview_instrumentation_test_apk" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" - } - ], - "dimension_sets": [ - { - "device_os": "KTU84Z", - "device_type": "flo" - } - ], - "expiration": 10800, - "hard_timeout": 1800, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ], - "shards": 6 - }, - "test": "webview_instrumentation_test_apk" } ] }, @@ -9781,51 +9697,6 @@ }, { "args": [ - "--disable-browser-side-navigation", - "--gs-results-bucket=chromium-result-details" - ], - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", - "renderer_side_navigation_chrome_public_test_apk" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "name": "renderer_side_navigation_chrome_public_test_apk", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" - } - ], - "dimension_sets": [ - { - "device_os": "MMB29Q", - "device_type": "bullhead" - } - ], - "hard_timeout": 1200, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ], - "shards": 14 - }, - "test": "chrome_public_test_apk" - }, - { - "args": [ "--gs-results-bucket=chromium-result-details" ], "merge": { @@ -9867,50 +9738,6 @@ "test": "chrome_sync_shell_test_apk" }, { - "args": [ - "--disable-browser-side-navigation", - "--gs-results-bucket=chromium-result-details" - ], - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", - "renderer_side_navigation_chrome_sync_shell_test_apk" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "name": "renderer_side_navigation_chrome_sync_shell_test_apk", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" - } - ], - "dimension_sets": [ - { - "device_os": "MMB29Q", - "device_type": "bullhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, - "test": "chrome_sync_shell_test_apk" - }, - { "merge": { "args": [ "--bucket", @@ -9950,49 +9777,6 @@ "test": "components_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", - "renderer_side_navigation_components_browsertests" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "name": "renderer_side_navigation_components_browsertests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" - } - ], - "dimension_sets": [ - { - "device_os": "MMB29Q", - "device_type": "bullhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, - "test": "components_browsertests" - }, - { "merge": { "args": [ "--bucket", @@ -10033,50 +9817,6 @@ "test": "components_unittests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", - "renderer_side_navigation_components_unittests" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "name": "renderer_side_navigation_components_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" - } - ], - "dimension_sets": [ - { - "device_os": "MMB29Q", - "device_type": "bullhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ], - "shards": 2 - }, - "test": "components_unittests" - }, - { "merge": { "args": [ "--bucket", @@ -11035,50 +10775,6 @@ "test": "unit_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", - "renderer_side_navigation_unit_tests" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "name": "renderer_side_navigation_unit_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" - } - ], - "dimension_sets": [ - { - "device_os": "MMB29Q", - "device_type": "bullhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ], - "shards": 2 - }, - "test": "unit_tests" - }, - { "merge": { "args": [ "--bucket",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index beacb6e..4588121e 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -2387,17 +2387,6 @@ "test": "browser_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_browser_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 10 - }, - "test": "browser_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -2452,26 +2441,6 @@ "test": "components_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_browsertests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_unittests" - }, - { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -2552,16 +2521,6 @@ "test": "extensions_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_extensions_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "extensions_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -2610,16 +2569,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -2848,16 +2797,6 @@ "test": "unit_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_unit_tests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "unit_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true },
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 9701a5a..d6fca78 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -3624,17 +3624,6 @@ }, { "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_browser_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 5 - }, - "test": "browser_tests" - }, - { - "args": [ "--site-per-process", "--test-launcher-filter-file=../../testing/buildbot/filters/site-per-process.browser_tests.filter" ], @@ -3688,26 +3677,6 @@ "test": "components_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_browsertests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_unittests" - }, - { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -3809,16 +3778,6 @@ "test": "extensions_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_extensions_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "extensions_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -3879,16 +3838,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -3901,16 +3850,6 @@ "test": "interactive_ui_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_interactive_ui_tests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "interactive_ui_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -4104,16 +4043,6 @@ }, { "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_unit_tests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "unit_tests" - }, - { - "args": [ "--site-per-process" ], "name": "site_per_process_unit_tests", @@ -4314,17 +4243,6 @@ }, { "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_browser_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 10 - }, - "test": "browser_tests" - }, - { - "args": [ "--site-per-process", "--test-launcher-filter-file=../../testing/buildbot/filters/site-per-process.browser_tests.filter" ], @@ -4378,26 +4296,6 @@ "test": "components_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_browsertests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_unittests" - }, - { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -4499,16 +4397,6 @@ "test": "extensions_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_extensions_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "extensions_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -4569,16 +4457,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -4592,17 +4470,6 @@ "test": "interactive_ui_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_interactive_ui_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 3 - }, - "test": "interactive_ui_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -4793,16 +4660,6 @@ }, { "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_unit_tests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "unit_tests" - }, - { - "args": [ "--site_per_process" ], "name": "site_per_process_unit_tests",
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 9096448..ebea713 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -176,16 +176,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -469,17 +459,6 @@ "test": "browser_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_browser_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 10 - }, - "test": "browser_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -522,26 +501,6 @@ "test": "components_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_browsertests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_unittests" - }, - { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -554,26 +513,6 @@ "test": "content_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_content_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "content_browsertests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "content_unittests" - }, - { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_content_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -652,16 +591,6 @@ "test": "interactive_ui_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_interactive_ui_tests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "interactive_ui_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -824,16 +753,6 @@ "test": "unit_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_unit_tests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "unit_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -931,17 +850,6 @@ "test": "browser_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_browser_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 10 - }, - "test": "browser_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -984,26 +892,6 @@ "test": "components_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_browsertests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_unittests" - }, - { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -1016,26 +904,6 @@ "test": "content_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_content_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "content_browsertests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "content_unittests" - }, - { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_content_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -1114,16 +982,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -1136,16 +994,6 @@ "test": "interactive_ui_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_interactive_ui_tests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "interactive_ui_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -1308,16 +1156,6 @@ "test": "unit_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_unit_tests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "unit_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -1575,16 +1413,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -2007,16 +1835,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true },
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json index 6bd0ac5..f0f4ad5 100644 --- a/testing/buildbot/chromium.perf.fyi.json +++ b/testing/buildbot/chromium.perf.fyi.json
@@ -71,6 +71,12 @@ ], "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "id": "build34-a1", + "pool": "Chrome-perf-fyi" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": false,
diff --git a/testing/buildbot/chromium.sandbox.json b/testing/buildbot/chromium.sandbox.json index e0cac0e..0205e002 100644 --- a/testing/buildbot/chromium.sandbox.json +++ b/testing/buildbot/chromium.sandbox.json
@@ -89,17 +89,6 @@ }, { "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_browser_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 5 - }, - "test": "browser_tests" - }, - { - "args": [ "--site-per-process", "--test-launcher-filter-file=../../testing/buildbot/filters/site-per-process.browser_tests.filter" ], @@ -153,26 +142,6 @@ "test": "components_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_browsertests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_unittests" - }, - { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -192,16 +161,6 @@ }, { "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_content_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "content_browsertests" - }, - { - "args": [ "--site-per-process", "--test-launcher-filter-file=../../testing/buildbot/filters/site-per-process.content_browsertests.filter" ], @@ -219,16 +178,6 @@ }, { "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_content_unittests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "content_unittests" - }, - { - "args": [ "--site-per-process" ], "name": "site_per_process_content_unittests", @@ -274,16 +223,6 @@ "test": "extensions_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_extensions_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "extensions_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -344,16 +283,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -366,16 +295,6 @@ "test": "interactive_ui_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_interactive_ui_tests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "interactive_ui_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -569,16 +488,6 @@ }, { "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_unit_tests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "unit_tests" - }, - { - "args": [ "--site-per-process" ], "name": "site_per_process_unit_tests",
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index bbede5fd..aed9a337 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -219,16 +219,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -588,17 +578,6 @@ "test": "browser_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_browser_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 10 - }, - "test": "browser_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -653,26 +632,6 @@ "test": "components_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_browsertests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "components_unittests" - }, - { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_components_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -691,26 +650,6 @@ "test": "content_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_content_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "content_browsertests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "content_unittests" - }, - { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_content_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -759,16 +698,6 @@ "test": "extensions_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_extensions_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "extensions_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -817,16 +746,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -1062,16 +981,6 @@ "test": "unit_tests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_unit_tests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "unit_tests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -1375,16 +1284,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -1916,16 +1815,6 @@ "test": "headless_browsertests" }, { - "args": [ - "--disable-browser-side-navigation" - ], - "name": "renderer_side_navigation_headless_browsertests", - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "headless_browsertests" - }, - { "swarming": { "can_use_on_swarming_builders": true },
diff --git a/testing/buildbot/filters/mojo.fyi.mash.browser_tests.filter b/testing/buildbot/filters/mojo.fyi.mash.browser_tests.filter index cd53f7b..8b0864a 100644 --- a/testing/buildbot/filters/mojo.fyi.mash.browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.mash.browser_tests.filter
@@ -272,3 +272,6 @@ -WebViewTests/WebViewFocusTest.* -WebViewTests/WebViewSizeTest.* -WebViewTests/WebViewTest.* + +# MessagePipe closing crashes http://crbug.com/787121 +-PreferencesTest.MultiProfiles
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter index d70fa5e..cc2af1b 100644 --- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -27,15 +27,6 @@ -ChromeResourceDispatcherHostDelegateBrowserTest.ThrottlesAddedExactlyOnceToLargeSniffedDownloads -ChromeResourceDispatcherHostDelegateBrowserTest.ThrottlesAddedExactlyOnceToTinySniffedDownloads -ChromeSecurityExploitBrowserTest.CreateFilesystemURLInExtensionOrigin --ChromeServiceWorkerFetchPPAPIPrivateTest.OtherOrigin --ChromeServiceWorkerFetchPPAPIPrivateTest.OtherOriginCORS --ChromeServiceWorkerFetchPPAPIPrivateTest.OtherOriginCORSCredentials --ChromeServiceWorkerFetchPPAPIPrivateTest.OtherOriginCredentials --ChromeServiceWorkerFetchPPAPIPrivateTest.SameOrigin --ChromeServiceWorkerFetchPPAPIPrivateTest.SameOriginCORS --ChromeServiceWorkerFetchPPAPIPrivateTest.SameOriginCORSCredentials --ChromeServiceWorkerFetchPPAPIPrivateTest.SameOriginCredentials --ChromeServiceWorkerFetchPPAPITest.SameOrigin -ChromeSitePerProcessTest.LaunchExternalProtocolFromSubframe -ContentFaviconDriverTest.ReloadBypassingCache -ContentScriptApiTests/ContentScriptApiTest.CannotScriptTheNewTabPage/0 @@ -204,20 +195,6 @@ -ProfileWindowBrowserTest.GuestClearsCookies -ProxySettingsApiTest.ProxyEventsInvalidProxy -RegisterProtocolHandlerBrowserTest.CustomHandler --ResourcePrefetchPredictorBrowserTest.AlwaysRevalidate --ResourcePrefetchPredictorBrowserTest.CrossSiteNavigation --ResourcePrefetchPredictorBrowserTest.HttpToHttpsRedirect --ResourcePrefetchPredictorBrowserTest.IframeShouldBeIgnored --ResourcePrefetchPredictorBrowserTest.JavascriptAppendChild --ResourcePrefetchPredictorBrowserTest.JavascriptDocumentWrite --ResourcePrefetchPredictorBrowserTest.JavascriptInnerHtml --ResourcePrefetchPredictorBrowserTest.JavascriptRedirectsAreNotHandled --ResourcePrefetchPredictorBrowserTest.JavascriptXHR --ResourcePrefetchPredictorBrowserTest.Redirect --ResourcePrefetchPredictorBrowserTest.RedirectChain --ResourcePrefetchPredictorBrowserTest.Simple --ResourcePrefetchPredictorBrowserTest.SubresourceFcpOrder --ResourcePrefetchPredictorBrowserTest.TabIdBehavingAsExpected -ResourcePrefetchPredictorPrefetchingBrowserTest.Redirect -ResourcePrefetchPredictorPrefetchingBrowserTest.Simple -SafeBrowsingServiceTest.Prefetch @@ -230,53 +207,6 @@ -SecurityStateTabHelperTest.SHA1CertificateBlocked -SecurityStateTabHelperTest.SHA1CertificateWarning -SecurityStateTabHelperTest.UMALogsVisitsAfterWarning --ServiceWorkerAppTest.RegisterAndPostMessage --ServiceWorkerBackgroundSyncTestWithJSBindings/ServiceWorkerBackgroundSyncTest.Sync/0 --ServiceWorkerBackgroundSyncTestWithNativeBindings/ServiceWorkerBackgroundSyncTest.Sync/0 --ServiceWorkerLazyBackgroundTestWithJSBindings/ServiceWorkerLazyBackgroundTest.EventsAfterRestart/0 --ServiceWorkerLazyBackgroundTestWithJSBindings/ServiceWorkerLazyBackgroundTest.EventsToStoppedExtension/0 --ServiceWorkerLazyBackgroundTestWithJSBindings/ServiceWorkerLazyBackgroundTest.FilteredEventsAfterRestart/0 --ServiceWorkerLazyBackgroundTestWithNativeBindings/ServiceWorkerLazyBackgroundTest.EventsAfterRestart/0 --ServiceWorkerLazyBackgroundTestWithNativeBindings/ServiceWorkerLazyBackgroundTest.EventsToStoppedExtension/0 --ServiceWorkerLazyBackgroundTestWithNativeBindings/ServiceWorkerLazyBackgroundTest.FilteredEventsAfterRestart/0 --ServiceWorkerPushMessagingTestWithJSBindings/ServiceWorkerPushMessagingTest.OnPush/0 --ServiceWorkerPushMessagingTestWithNativeBindings/ServiceWorkerPushMessagingTest.OnPush/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.BackgroundPageIsWokenIfAsleep/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.BackgroundPagePostsMessageToServiceWorker/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.Events/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.EventsToStoppedWorker/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.FetchArbitraryPaths/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.FilteredEvents/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.GetBackgroundClientFailsWithNoBackgroundPage/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.LoadingBackgroundPageBypassesServiceWorker/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.NotificationAPI/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.RegisterSucceeds/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.ServiceWorkerPostsMessageToBackgroundClient/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.ServiceWorkerSuspensionOnExtensionUnload/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.SWServedBackgroundPageReceivesEvent/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.TabsCreate/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.UpdateRefreshesServiceWorker/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.WebAccessibleResourcesFetch/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.WebAccessibleResourcesIframeSrc/0 --ServiceWorkerTestWithJSBindings/ServiceWorkerTest.WorkerRefCount/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.BackgroundPageIsWokenIfAsleep/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.BackgroundPagePostsMessageToServiceWorker/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.Events/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.EventsToStoppedWorker/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.FetchArbitraryPaths/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.FilteredEvents/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.GetBackgroundClientFailsWithNoBackgroundPage/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.LoadingBackgroundPageBypassesServiceWorker/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.NotificationAPI/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.RegisterSucceeds/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.ServiceWorkerPostsMessageToBackgroundClient/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.ServiceWorkerSuspensionOnExtensionUnload/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.SWServedBackgroundPageReceivesEvent/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.TabsCreate/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.UpdateRefreshesServiceWorker/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.WebAccessibleResourcesFetch/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.WebAccessibleResourcesIframeSrc/0 --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.WorkerRefCount/0 -ShowPageActionWithoutPageActionTest/ShowPageActionWithoutPageActionTest.Test/0 -ShowPageActionWithoutPageActionTest/ShowPageActionWithoutPageActionTest.Test/1 -SiteDetailsBrowserTest.PlatformAppsNotIsolated @@ -312,6 +242,7 @@ -SSLUITestTransientAndCommitted.TestHTTPSExpiredCertGoBackUsingCommand/1 -SSLUITestTransientAndCommitted.TestHTTPSOCSPRevoked/1 -SSLUITestTransientAndCommitted.TestHTTPSOCSPRevoked/0 +-SSLUIWorkerFetchTest.TestUnsafeContentsInWorkerWithUserException/0 -SubresourceFilterBrowserTest.FailedProvisionalLoadInMainframe -SuperfishSSLUITest.NoSuperfishRecorded -SuperfishSSLUITest.SuperfishInterstitial @@ -327,22 +258,6 @@ -TaskManagerUtilityProcessBrowserTest.UtilityJSHeapMemory -TtsApiTest.NetworkSpeechEngine -V4SafeBrowsingServiceTest.Prefetch --WebNavigationApiTest.ClientRedirect --WebNavigationApiTest.Crash --WebNavigationApiTest.CrossProcess --WebNavigationApiTest.CrossProcessIframe --WebNavigationApiTest.Download --WebNavigationApiTest.History --WebNavigationApiTest.IFrame --WebNavigationApiTest.OpenTab --WebNavigationApiTest.ReferenceFragment --WebNavigationApiTest.RequestOpenTab --WebNavigationApiTest.ServerRedirectSingleProcess --WebNavigationApiTest.SimpleLoad --WebNavigationApiTest.SrcDoc --WebNavigationApiTest.TargetBlank --WebNavigationApiTest.TargetBlankIncognito --WebNavigationApiTest.UserAction -WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabsEmitsGatheringStateChange -WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabsGetStatsCallback -WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabsGetStatsPromise @@ -515,30 +430,6 @@ -PolicyTest.CertificateTransparencyEnforcementDisabledForUrls -PolicyTest.ExtensionInstallSources -PolicyTest.ForceGoogleSafeSearch --PrerenderBrowserTest.FirstContentfulPaintHiddenNoCommit --PrerenderBrowserTest.FirstContentfulPaintTimingNoCommit --PrerenderBrowserTest.FirstContentfulPaintTimingReuse --PrerenderBrowserTest.PrerenderBeforeUnload --PrerenderBrowserTest.PrerenderCancelMainFrameRedirectUnsupportedScheme --PrerenderBrowserTest.PrerenderCancelSubresourceRedirectUnsupportedScheme --PrerenderBrowserTest.PrerenderCancelSubresourceUnsupportedScheme --PrerenderBrowserTest.PrerenderCrx --PrerenderBrowserTest.PrerenderDeferredImage --PrerenderBrowserTest.PrerenderDeferredImageAfterRedirect --PrerenderBrowserTest.PrerenderDeferredSynchronousXHR --PrerenderBrowserTest.PrerenderDownloadClientRedirect --PrerenderBrowserTest.PrerenderDownloadIframe --PrerenderBrowserTest.PrerenderDownloadLocation --PrerenderBrowserTest.PrerenderLocationReplaceGWSHistograms --PrerenderBrowserTest.PrerenderNoCommitNoSwap --PrerenderBrowserTest.PrerenderNoCommitNoSwap2 --PrerenderBrowserTest.PrerenderPing --PrerenderBrowserTest.PrerenderUnload --PrerenderBrowserTest.PrerenderXhrDelete --PrerenderBrowserTest.PrerenderXhrPut --PrerenderBrowserTest.ResourcePriority --PrerenderBrowserTest.ResourcePriorityOverlappingSwap --PrerenderBrowserTestWithExtensions.WebNavigation -ProfileBrowserTest.SendHPKPReport -ProfileBrowserTest.SendHPKPReportServerHangs -ReferrerPolicyTest.ContextMenuOrigin @@ -931,3 +822,134 @@ -PredictorBrowserTest.SubframeCrossSitePrediction -PredictorBrowserTest.SubframeInitiatesPreconnects -PredictorBrowserTest.SubframeLearning + +# This feature currently hooks in using ChromeResourceDispatcherHostDelegate and +# ResourceThrottles. Need to convert PredictorResourceThrottle and +# LoadingDataCollector to gather their data from WebContentsObserver navigation +# callbacks instead. +-ResourcePrefetchPredictorBrowserTest.AlwaysRevalidate +-ResourcePrefetchPredictorBrowserTest.CrossSiteNavigation +-ResourcePrefetchPredictorBrowserTest.HttpToHttpsRedirect +-ResourcePrefetchPredictorBrowserTest.IframeShouldBeIgnored +-ResourcePrefetchPredictorBrowserTest.JavascriptAppendChild +-ResourcePrefetchPredictorBrowserTest.JavascriptDocumentWrite +-ResourcePrefetchPredictorBrowserTest.JavascriptInnerHtml +-ResourcePrefetchPredictorBrowserTest.JavascriptRedirectsAreNotHandled +-ResourcePrefetchPredictorBrowserTest.JavascriptXHR +-ResourcePrefetchPredictorBrowserTest.Redirect +-ResourcePrefetchPredictorBrowserTest.RedirectChain +-ResourcePrefetchPredictorBrowserTest.Simple +-ResourcePrefetchPredictorBrowserTest.SubresourceFcpOrder +-ResourcePrefetchPredictorBrowserTest.TabIdBehavingAsExpected + +# If prerender is completely turned down before we plan on canary, no need to +# convert. See http://crbug.com/678332 and http://crbug.com/683142 +-PrerenderBrowserTest.FirstContentfulPaintHiddenNoCommit +-PrerenderBrowserTest.FirstContentfulPaintTimingNoCommit +-PrerenderBrowserTest.FirstContentfulPaintTimingReuse +-PrerenderBrowserTest.PrerenderBeforeUnload +-PrerenderBrowserTest.PrerenderCancelMainFrameRedirectUnsupportedScheme +-PrerenderBrowserTest.PrerenderCancelSubresourceRedirectUnsupportedScheme +-PrerenderBrowserTest.PrerenderCancelSubresourceUnsupportedScheme +-PrerenderBrowserTest.PrerenderCrx +-PrerenderBrowserTest.PrerenderDeferredImage +-PrerenderBrowserTest.PrerenderDeferredImageAfterRedirect +-PrerenderBrowserTest.PrerenderDeferredSynchronousXHR +-PrerenderBrowserTest.PrerenderDownloadClientRedirect +-PrerenderBrowserTest.PrerenderDownloadIframe +-PrerenderBrowserTest.PrerenderDownloadLocation +-PrerenderBrowserTest.PrerenderLocationReplaceGWSHistograms +-PrerenderBrowserTest.PrerenderNoCommitNoSwap +-PrerenderBrowserTest.PrerenderNoCommitNoSwap2 +-PrerenderBrowserTest.PrerenderPing +-PrerenderBrowserTest.PrerenderUnload +-PrerenderBrowserTest.PrerenderXhrDelete +-PrerenderBrowserTest.PrerenderXhrPut +-PrerenderBrowserTest.ResourcePriority +-PrerenderBrowserTest.ResourcePriorityOverlappingSwap +-PrerenderBrowserTestWithExtensions.WebNavigation + +# Finish ServiceWorker networking glue rewrite. +# http://crbug.com/715640 +-ChromeServiceWorkerFetchPPAPIPrivateTest.OtherOrigin +-ChromeServiceWorkerFetchPPAPIPrivateTest.OtherOriginCORS +-ChromeServiceWorkerFetchPPAPIPrivateTest.OtherOriginCORSCredentials +-ChromeServiceWorkerFetchPPAPIPrivateTest.OtherOriginCredentials +-ChromeServiceWorkerFetchPPAPIPrivateTest.SameOrigin +-ChromeServiceWorkerFetchPPAPIPrivateTest.SameOriginCORS +-ChromeServiceWorkerFetchPPAPIPrivateTest.SameOriginCORSCredentials +-ChromeServiceWorkerFetchPPAPIPrivateTest.SameOriginCredentials +-ChromeServiceWorkerFetchPPAPITest.SameOrigin +-ServiceWorkerAppTest.RegisterAndPostMessage +-ServiceWorkerBackgroundSyncTestWithJSBindings/ServiceWorkerBackgroundSyncTest.Sync/0 +-ServiceWorkerBackgroundSyncTestWithNativeBindings/ServiceWorkerBackgroundSyncTest.Sync/0 +-ServiceWorkerLazyBackgroundTestWithJSBindings/ServiceWorkerLazyBackgroundTest.EventsAfterRestart/0 +-ServiceWorkerLazyBackgroundTestWithJSBindings/ServiceWorkerLazyBackgroundTest.EventsToStoppedExtension/0 +-ServiceWorkerLazyBackgroundTestWithJSBindings/ServiceWorkerLazyBackgroundTest.FilteredEventsAfterRestart/0 +-ServiceWorkerLazyBackgroundTestWithNativeBindings/ServiceWorkerLazyBackgroundTest.EventsAfterRestart/0 +-ServiceWorkerLazyBackgroundTestWithNativeBindings/ServiceWorkerLazyBackgroundTest.EventsToStoppedExtension/0 +-ServiceWorkerLazyBackgroundTestWithNativeBindings/ServiceWorkerLazyBackgroundTest.FilteredEventsAfterRestart/0 +-ServiceWorkerPushMessagingTestWithJSBindings/ServiceWorkerPushMessagingTest.OnPush/0 +-ServiceWorkerPushMessagingTestWithNativeBindings/ServiceWorkerPushMessagingTest.OnPush/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.BackgroundPageIsWokenIfAsleep/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.BackgroundPagePostsMessageToServiceWorker/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.Events/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.EventsToStoppedWorker/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.FetchArbitraryPaths/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.FilteredEvents/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.GetBackgroundClientFailsWithNoBackgroundPage/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.LoadingBackgroundPageBypassesServiceWorker/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.NotificationAPI/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.RegisterSucceeds/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.ServiceWorkerPostsMessageToBackgroundClient/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.ServiceWorkerSuspensionOnExtensionUnload/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.SWServedBackgroundPageReceivesEvent/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.TabsCreate/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.UpdateRefreshesServiceWorker/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.WebAccessibleResourcesFetch/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.WebAccessibleResourcesIframeSrc/0 +-ServiceWorkerTestWithJSBindings/ServiceWorkerTest.WorkerRefCount/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.BackgroundPageIsWokenIfAsleep/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.BackgroundPagePostsMessageToServiceWorker/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.Events/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.EventsToStoppedWorker/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.FetchArbitraryPaths/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.FilteredEvents/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.GetBackgroundClientFailsWithNoBackgroundPage/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.LoadingBackgroundPageBypassesServiceWorker/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.NotificationAPI/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.RegisterSucceeds/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.ServiceWorkerPostsMessageToBackgroundClient/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.ServiceWorkerSuspensionOnExtensionUnload/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.SWServedBackgroundPageReceivesEvent/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.TabsCreate/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.UpdateRefreshesServiceWorker/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.WebAccessibleResourcesFetch/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.WebAccessibleResourcesIframeSrc/0 +-ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.WorkerRefCount/0 + +# WebNavigation API seems to work, but the browser tests' harness uses a +# ResourceThrottle which doesn't work with network service. Rewrite to use +# NavigationThrottle instead. +-WebNavigationApiTest.ClientRedirect +-WebNavigationApiTest.Crash +-WebNavigationApiTest.CrossProcess +-WebNavigationApiTest.CrossProcessIframe +-WebNavigationApiTest.Download +-WebNavigationApiTest.History +-WebNavigationApiTest.IFrame +-WebNavigationApiTest.OpenTab +-WebNavigationApiTest.ReferenceFragment +-WebNavigationApiTest.RequestOpenTab +-WebNavigationApiTest.ServerRedirectSingleProcess +-WebNavigationApiTest.SimpleLoad +-WebNavigationApiTest.SrcDoc +-WebNavigationApiTest.TargetBlank +-WebNavigationApiTest.TargetBlankIncognito +-WebNavigationApiTest.UserAction + +# Stop using WebContentsObserver::DidGetResourceResponseStart, which gets +# notified from ResourceDispatcherHostDelegate. Instead use DidFinishNavigation +# for frame requests and send IPCs from the renderer for subresources. +# http://crbug.com/783981 +-ClientSideDetectionHostBrowserTest.VerifyIPAddressCollection
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter index b4964b2..dea7471 100644 --- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -20,7 +20,6 @@ -DownloadContentTest.DownloadAttributeSameSiteCookie # This started failing when the test got added in r514724. -DownloadContentTest.ForceDownloadMhtml --DragDownloadFileTest.DragDownloadFileTest_Complete # http://crbug.com/721398 -ClearSiteDataThrottleBrowserTest.CookiesIntegrationTest
diff --git a/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter index f79f822..7df8b45c 100644 --- a/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter +++ b/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter
@@ -11,8 +11,7 @@ -ScrollLatencyBrowserTest.* # Flaky timeout while waiting for scoll update http://crbug.com/786132 -WheelScrollLatchingBrowserTest.WheelScrollingRelatchWhenLatchedScrollerRemoved - +-WheelScrollLatchingBrowserTest.WheelScrollingRelatchWhenLatchedScrollerRemoved # Crash during shutdown on wrong thread http://crbug.com/785023 -ContentBrowserTestSanityTest.SingleProcess
diff --git a/testing/buildbot/filters/mus.content_browsertests.filter b/testing/buildbot/filters/mus.content_browsertests.filter index bcea9c0..c3b607fc 100644 --- a/testing/buildbot/filters/mus.content_browsertests.filter +++ b/testing/buildbot/filters/mus.content_browsertests.filter
@@ -107,6 +107,8 @@ -SnapshotBrowserTest.AsyncMultiWindowTest -SnapshotBrowserTest.SingleWindowTest -SnapshotBrowserTest.SyncMultiWindowTest +-WebRtcCaptureFromElementBrowserTest.CaptureFromCanvas2DHandlesContextLoss +-WebRtcCaptureFromElementBrowserTest.CaptureFromOpaqueCanvas2DHandlesContextLoss # TODO: these all rely on RenderWidgetHostImpl::SubmitCompositorFrame(), which # isn't hit for mus.
diff --git a/testing/buildbot/filters/viz.content_browsertests.filter b/testing/buildbot/filters/viz.content_browsertests.filter index 5d9af1a..7df8b45c 100644 --- a/testing/buildbot/filters/viz.content_browsertests.filter +++ b/testing/buildbot/filters/viz.content_browsertests.filter
@@ -11,7 +11,7 @@ -ScrollLatencyBrowserTest.* # Flaky timeout while waiting for scoll update http://crbug.com/786132 -WheelScrollLatchingBrowserTest.WheelScrollingRelatchWhenLatchedScrollerRemoved +-WheelScrollLatchingBrowserTest.WheelScrollingRelatchWhenLatchedScrollerRemoved # Crash during shutdown on wrong thread http://crbug.com/785023 -ContentBrowserTestSanityTest.SingleProcess
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn index dab495a..ed5bc63 100644 --- a/testing/libfuzzer/fuzzers/BUILD.gn +++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -516,6 +516,5 @@ "//v8:v8_libplatform", ] dict = "dicts/generated/javascript.dict" - seed_corpus = "//v8/test/mjsunit/" libfuzzer_options = [ "only_ascii=1" ] }
diff --git a/testing/libfuzzer/fuzzers/v8_fuzzer.cc b/testing/libfuzzer/fuzzers/v8_fuzzer.cc index 82995bbb..89e447c 100644 --- a/testing/libfuzzer/fuzzers/v8_fuzzer.cc +++ b/testing/libfuzzer/fuzzers/v8_fuzzer.cc
@@ -14,6 +14,8 @@ using v8::MaybeLocal; using std::ref; +using std::lock_guard; +using std::mutex; using std::chrono::time_point; using std::chrono::steady_clock; using std::chrono::seconds; @@ -25,7 +27,7 @@ // kSleepSeconds + kMaxExecutionSeconds. // TODO(metzman): Determine if having such a short timeout causes too much // indeterminism. -static const seconds kMaxExecutionSeconds(15); +static const seconds kMaxExecutionSeconds(12); // Inspired by/copied from d8 code, this allocator will return nullptr when // an allocation request is made that puts currently_allocated_ over @@ -39,7 +41,7 @@ // between runs is a good idea. Maybe we should simply prevent allocations // over a certain size regardless of previous allocations. size_t currently_allocated_; - std::mutex mtx_; + mutex mtx_; public: MockArrayBufferAllocator() @@ -56,39 +58,33 @@ } void* AllocateUninitialized(size_t length) override { - mtx_.lock(); + lock_guard<mutex> mtx_locker(mtx_); if (length + currently_allocated_ > kAllocationLimit) { - mtx_.unlock(); return nullptr; } currently_allocated_ += length; - mtx_.unlock(); return malloc(length); } void Free(void* ptr, size_t length) override { - mtx_.lock(); + lock_guard<mutex> mtx_locker(mtx_); currently_allocated_ -= length; // We need to free before we unlock, otherwise currently_allocated_ will // be innacurate. free(ptr); - mtx_.unlock(); } void Free(void* data, size_t length, AllocationMode mode) override { switch (mode) { case AllocationMode::kNormal: { - mtx_.lock(); - currently_allocated_ -= length; + // Free locks and unlocks for us. Free(data, length); - mtx_.unlock(); return; } case AllocationMode::kReservation: { - mtx_.lock(); + lock_guard<mutex> mtx_locker(mtx_); currently_allocated_ -= length; allocator_->Free(data, length, mode); - mtx_.unlock(); return; } default: @@ -97,19 +93,17 @@ } void* Reserve(size_t length) override { - mtx_.lock(); + lock_guard<mutex> mtx_locker(mtx_); if (length + currently_allocated_ > kAllocationLimit) { - mtx_.unlock(); return nullptr; } currently_allocated_ += length; - mtx_.unlock(); return allocator_->Reserve(length); } }; void terminate_execution(v8::Isolate* isolate, - std::mutex& mtx, + mutex& mtx, bool& is_running, time_point<steady_clock>& start_time) { while (true) { @@ -144,7 +138,7 @@ ref(is_running), ref(start_time)); } MockArrayBufferAllocator mock_arraybuffer_allocator; - std::mutex mtx; + mutex mtx; std::thread terminator_thread; v8::Isolate* isolate; time_point<steady_clock> start_time; @@ -193,8 +187,7 @@ ALLOW_UNUSED_LOCAL(local_script->Run(context)); - env->mtx.lock(); + lock_guard<mutex> mtx_locker(env->mtx); env->is_running = false; - env->mtx.unlock(); return 0; }
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index af6b086f..dda4897 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1941,6 +1941,25 @@ ] } ], + "NTPCaptureThumbnail": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "win" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "CaptureThumbnailDependingOnTransitionType", + "CaptureThumbnailOnNavigatingAway" + ] + } + ] + } + ], "NTPCondensedLayout": [ { "platforms": [ @@ -1948,9 +1967,9 @@ ], "experiments": [ { - "name": "CondensedLayoutWithSmallLogo", + "name": "CondensedLayoutWithLargeLogo", "params": { - "condensed_layout_logo_height": "50", + "condensed_layout_logo_height": "100", "condensed_layout_show_logo": "true", "condensed_tile_layout_for_small_screens_enabled": "true" },
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 5c4a51b..6907c0c 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -6165,8 +6165,8 @@ 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 ] -crbug.com/591099 http/tests/devtools/appcache/appcache-iframe-manifests.html [ Failure ] -crbug.com/591099 http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.html [ Failure ] +crbug.com/591099 http/tests/devtools/appcache/appcache-iframe-manifests.js [ Failure ] +crbug.com/591099 http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.js [ Failure ] crbug.com/591099 http/tests/devtools/audits2/audits2-limited-run.js [ Crash ] crbug.com/591099 http/tests/devtools/audits2/audits2-successful-run.js [ Crash ] crbug.com/591099 http/tests/devtools/console/command-line-api.js [ Pass Timeout ] @@ -6222,7 +6222,7 @@ crbug.com/591099 http/tests/devtools/tracing/timeline-layout/timeline-layout-with-invalidations.js [ Failure ] crbug.com/591099 http/tests/devtools/tracing/timeline-misc/timeline-bound-function.js [ Crash Failure ] crbug.com/591099 http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Crash ] -crbug.com/591099 http/tests/devtools/websocket/network-preserve-selection-on-frame-receive.html [ Crash ] +crbug.com/591099 http/tests/devtools/websocket/network-preserve-selection-on-frame-receive.js [ Crash ] 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 ] crbug.com/591099 http/tests/feature-policy-experimental-features/vibrate-allowed-by-container-policy.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 index d2a3e721..4f8ff47 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -1447,7 +1447,6 @@ # This test uses internal call to initiate smooth scrolling on impl-thread. crbug.com/667946 fast/compositor-wheel-scroll-latching/touchpad-scroll-impl-to-main.html [ Failure ] -Bug(none) virtual/threaded/animations/svg-attribute-composition/svg-startOffset-composition.html [ Failure ] # virtual/threaded variants of sub-directories and tests already skipped or marked as failing above. Bug(none) virtual/threaded/http/tests/devtools/ [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls index 06c6fbb..5ea2c12 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls +++ b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
@@ -3,7 +3,6 @@ crbug.com/417782 compositing/iframes/overlapped-iframe-iframe.html [ Failure ] crbug.com/417782 compositing/iframes/overlapped-nested-iframes.html [ Failure ] crbug.com/417782 compositing/layer-creation/iframe-background-attachment-fixed.html [ Failure ] -crbug.com/417782 compositing/overflow/nested-render-surfaces-with-intervening-clip.html [ Failure ] crbug.com/417782 compositing/rtl/rtl-iframe-absolute.html [ Failure ] crbug.com/417782 compositing/rtl/rtl-iframe-fixed.html [ Failure ] crbug.com/417782 compositing/rtl/rtl-iframe-relative.html [ Failure ] @@ -81,9 +80,6 @@ crbug.com/417782 printing/standards-percentage-heights.html [ Failure ] crbug.com/417782 printing/subframes-percentage-height.html [ Failure ] crbug.com/417782 printing/thead-repeats-at-top-of-each-page.html [ Failure ] -crbug.com/417782 svg/W3C-SVG-1.1/masking-path-04-b.svg [ Failure ] -crbug.com/417782 svg/custom/mask-with-default-value.svg [ Failure ] -crbug.com/417782 [ Mac ] svg/custom/masking-clipping-hidpi.svg [ Failure ] crbug.com/417782 transforms/selection-bounds-in-transformed-view.html [ Failure ] crbug.com/417782 [ Linux ] virtual/android/fast/rootscroller/nested-rootscroller-browser-controls-bounds-hidden.html [ Failure ] crbug.com/417782 [ Linux ] virtual/android/fast/rootscroller/nested-rootscroller-browser-controls-bounds-shown.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process index f394e652..a1caf968 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process +++ b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
@@ -112,16 +112,16 @@ crbug.com/623268 virtual/mojo-loading/http/tests/inspector-protocol/request-mixed-content-status-blockable.js [ Timeout ] crbug.com/623268 virtual/mojo-loading/http/tests/inspector-protocol/request-mixed-content-status-none.js [ Timeout ] crbug.com/623268 virtual/mojo-loading/http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js [ Timeout ] -crbug.com/623268 http/tests/devtools/console-cross-origin-iframe-logging.html [ Failure ] -crbug.com/623268 virtual/mojo-loading/http/tests/devtools/console-cross-origin-iframe-logging.html [ Failure ] +crbug.com/623268 http/tests/devtools/console-cross-origin-iframe-logging.js [ Failure ] +crbug.com/623268 virtual/mojo-loading/http/tests/devtools/console-cross-origin-iframe-logging.js [ Failure ] # https://crbug.com/645641 - test_runner.cc(1863) Check failed: # layout_test_runtime_flags_.have_top_loading_frame() crbug.com/645641 external/wpt/html/syntax/parsing/html5lib_tests19.html [ Crash Failure ] # http/ flaky tests w/ --site-per-process -crbug.com/678481 http/tests/devtools/appcache/appcache-iframe-manifests.html [ Timeout Pass ] -crbug.com/678481 virtual/mojo-loading/http/tests/devtools/appcache/appcache-iframe-manifests.html [ Timeout Pass ] +crbug.com/678481 http/tests/devtools/appcache/appcache-iframe-manifests.js [ Timeout Pass ] +crbug.com/678481 virtual/mojo-loading/http/tests/devtools/appcache/appcache-iframe-manifests.js [ Timeout Pass ] crbug.com/678482 http/tests/devtools/debugger/fetch-breakpoints.js [ Timeout Pass ] crbug.com/678482 virtual/mojo-loading/http/tests/devtools/debugger/fetch-breakpoints.js [ Timeout Pass ] crbug.com/678484 http/tests/devtools/startup/reattach-after-editing-styles.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests index 57ab775..5b230dd 100644 --- a/third_party/WebKit/LayoutTests/NeverFixTests +++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -297,112 +297,112 @@ # Temporary disabling of most encrypted-media WPT tests while enabling # https only. Once the switch is complete (and the WPT tests renamed so they # run using https), they can be re-enabled. -crbug.com/672605 external/wpt/encrypted-media/clearkey-check-initdata-type.html [ WontFix ] -crbug.com/672605 external/wpt/encrypted-media/clearkey-events.html [ WontFix ] -crbug.com/672605 external/wpt/encrypted-media/clearkey-generate-request-disallowed-input.html [ WontFix ] -crbug.com/672605 external/wpt/encrypted-media/clearkey-invalid-license.html [ WontFix ] -crbug.com/672605 external/wpt/encrypted-media/clearkey-keystatuses-multiple-sessions.html [ WontFix ] -crbug.com/672605 external/wpt/encrypted-media/clearkey-keystatuses.html [ WontFix ] -crbug.com/672605 external/wpt/encrypted-media/clearkey-not-callable-after-createsession.html [ WontFix ] -crbug.com/672605 external/wpt/encrypted-media/idlharness.html [ WontFix ] +crbug.com/672605 external/wpt/encrypted-media/clearkey-check-initdata-type.https.html [ WontFix ] +crbug.com/672605 external/wpt/encrypted-media/clearkey-events.https.html [ WontFix ] +crbug.com/672605 external/wpt/encrypted-media/clearkey-generate-request-disallowed-input.https.html [ WontFix ] +crbug.com/672605 external/wpt/encrypted-media/clearkey-invalid-license.https.html [ WontFix ] +crbug.com/672605 external/wpt/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html [ WontFix ] +crbug.com/672605 external/wpt/encrypted-media/clearkey-keystatuses.https.html [ WontFix ] +crbug.com/672605 external/wpt/encrypted-media/clearkey-not-callable-after-createsession.https.html [ WontFix ] +crbug.com/672605 external/wpt/encrypted-media/idlharness.https.html [ WontFix ] # Note that all the encrypted-media tests below require https too but are # disabled for other reasons also. # These tests require a DRM system that is not available with content_shell. -external/wpt/encrypted-media/drm-check-initdata-type.html [ WontFix ] -external/wpt/encrypted-media/drm-events.html [ WontFix ] -external/wpt/encrypted-media/drm-events-session-closed-event.html [ WontFix ] -external/wpt/encrypted-media/drm-expiration.html [ WontFix ] -external/wpt/encrypted-media/drm-generate-request-disallowed-input.html [ WontFix ] -external/wpt/encrypted-media/drm-invalid-license.html [ WontFix ] -external/wpt/encrypted-media/drm-keystatuses.html [ WontFix ] -external/wpt/encrypted-media/drm-keystatuses-multiple-sessions.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-onencrypted.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-destroy-persistent-license.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-persistent-license-events.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-persistent-license.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record-events.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-license.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-events.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-expired.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-multisession.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-two-videos.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-playback-temporary-waitingforkey.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-requestmediakeysystemaccess.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-reset-src-after-setmediakeys.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-playback.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-setmediakeys-at-same-time.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-setmediakeys.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-syntax-mediakeysession.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-syntax-mediakeys.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-unique-origin.html [ WontFix ] -external/wpt/encrypted-media/drm-mp4-waiting-for-a-key.html [ WontFix ] -external/wpt/encrypted-media/drm-not-callable-after-createsession.html [ WontFix ] -external/wpt/encrypted-media/drm-temporary-license-type.html [ WontFix ] +external/wpt/encrypted-media/drm-check-initdata-type.https.html [ WontFix ] +external/wpt/encrypted-media/drm-events.https.html [ WontFix ] +external/wpt/encrypted-media/drm-events-session-closed-event.https.html [ WontFix ] +external/wpt/encrypted-media/drm-expiration.https.html [ WontFix ] +external/wpt/encrypted-media/drm-generate-request-disallowed-input.https.html [ WontFix ] +external/wpt/encrypted-media/drm-invalid-license.https.html [ WontFix ] +external/wpt/encrypted-media/drm-keystatuses.https.html [ WontFix ] +external/wpt/encrypted-media/drm-keystatuses-multiple-sessions.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-onencrypted.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-persistent-license-events.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-persistent-license.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-events.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-expired.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-multisession.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-setmediakeys.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-syntax-mediakeysession.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-syntax-mediakeys.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-unique-origin.https.html [ WontFix ] +external/wpt/encrypted-media/drm-mp4-waiting-for-a-key.https.html [ WontFix ] +external/wpt/encrypted-media/drm-not-callable-after-createsession.https.html [ WontFix ] +external/wpt/encrypted-media/drm-temporary-license-type.https.html [ WontFix ] # Chromium's implementation of ClearKey doesn't support persistent licenses. -external/wpt/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license-events.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html [ WontFix ] # content_shell doesn't support MP4 files by default. -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-events.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multisession.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-two-videos.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-setmediakeys.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysession.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeys.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-unique-origin.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-update-disallowed-input.html [ WontFix ] -external/wpt/encrypted-media/clearkey-mp4-waiting-for-a-key.html [ WontFix ] -external/wpt/encrypted-media/clearkey-events-session-closed-event.html [ WontFix ] -external/wpt/encrypted-media/clearkey-update-non-ascii-input.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-events.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-setmediakeys.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-unique-origin.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-update-disallowed-input.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-events-session-closed-event.https.html [ WontFix ] +external/wpt/encrypted-media/clearkey-update-non-ascii-input.https.html [ WontFix ] # This W3C EME test fetches a file, which is not allowed. #external/wpt/encrypted-media/idlharness.html [ WontFix ]
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests index f77a785..3c74229 100644 --- a/third_party/WebKit/LayoutTests/SlowTests +++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -128,8 +128,8 @@ crbug.com/667560 virtual/mojo-loading/http/tests/devtools/startup/console/console-format-startup.html [ Slow ] crbug.com/679833 http/tests/devtools/network/network-datareceived.js [ Slow ] crbug.com/679833 virtual/mojo-loading/http/tests/devtools/network/network-datareceived.js [ Slow ] -webkit.org/b/90488 [ Release ] http/tests/devtools/compiler-source-mapping-debug.html [ Slow ] -webkit.org/b/90488 [ Release ] virtual/mojo-loading/http/tests/devtools/compiler-source-mapping-debug.html [ Slow ] +webkit.org/b/90488 [ Release ] http/tests/devtools/compiler-source-mapping-debug.js [ Slow ] +webkit.org/b/90488 [ Release ] virtual/mojo-loading/http/tests/devtools/compiler-source-mapping-debug.js [ Slow ] crbug.com/243492 http/tests/devtools/startup/injected-script-discard.html [ Slow ] crbug.com/243492 virtual/mojo-loading/http/tests/devtools/startup/injected-script-discard.html [ Slow ] crbug.com/327078 http/tests/devtools/network/long-script-content.html [ Slow ] @@ -272,8 +272,8 @@ crbug.com/480769 virtual/mojo-loading/http/tests/devtools/service-workers/service-worker-agents.js [ Slow ] crbug.com/504703 inspector-protocol/debugger/debugger-step-into-dedicated-worker.js [ Slow ] crbug.com/535478 [ Win ] virtual/threaded/http/tests/devtools/tracing/decode-resize.html [ Slow ] -crbug.com/548765 http/tests/devtools/console-fetch-logging.html [ Slow ] -crbug.com/548765 virtual/mojo-loading/http/tests/devtools/console-fetch-logging.html [ Slow ] +crbug.com/548765 http/tests/devtools/console-fetch-logging.js [ Slow ] +crbug.com/548765 virtual/mojo-loading/http/tests/devtools/console-fetch-logging.js [ Slow ] crbug.com/419993 [ Debug ] fast/css/giant-stylesheet-crash.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 329ce74..92199e9 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1066,8 +1066,8 @@ crbug.com/498539 http/tests/devtools/tracing/timeline-misc/timeline-bound-function.js [ Pass Failure ] crbug.com/667560 virtual/mojo-loading/http/tests/devtools/tracing/timeline-misc/timeline-bound-function.js [ Pass Failure ] crbug.com/498539 virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-bound-function.js [ Pass Failure ] -crbug.com/498539 [ Mac ] http/tests/devtools/sources/debugger/live-edit-no-reveal.js [ Crash Pass Timeout ] -crbug.com/667560 [ Mac ] virtual/mojo-loading/http/tests/devtools/sources/debugger/live-edit-no-reveal.js [ Crash Pass Timeout ] +crbug.com/498539 [ Mac ] http/tests/devtools/sources/debugger/live-edit-no-reveal.js [ Crash Pass Timeout Failure ] +crbug.com/667560 [ Mac ] virtual/mojo-loading/http/tests/devtools/sources/debugger/live-edit-no-reveal.js [ Crash Pass Timeout Failure ] crbug.com/498539 [ Win7 ] http/tests/devtools/sources/debugger-pause/debugger-eval-on-call-frame-inside-iframe.js [ Failure Pass ] crbug.com/667560 [ Win7 ] virtual/mojo-loading/http/tests/devtools/sources/debugger-pause/debugger-eval-on-call-frame-inside-iframe.js [ Failure Pass ] @@ -1843,8 +1843,8 @@ crbug.com/546215 [ Android ] fast/inline-block/overflow-clip.html [ Failure ] -crbug.com/548765 http/tests/devtools/console-fetch-logging.html [ Failure Pass ] -crbug.com/548765 virtual/mojo-loading/http/tests/devtools/console-fetch-logging.html [ Failure Pass ] +crbug.com/548765 http/tests/devtools/console-fetch-logging.js [ Failure Pass ] +crbug.com/548765 virtual/mojo-loading/http/tests/devtools/console-fetch-logging.js [ Failure Pass ] crbug.com/564109 [ Win ] external/wpt/css/css-fonts/font-display/font-display.html [ Failure Pass Timeout ] crbug.com/564109 [ Win ] http/tests/webfont/font-display-intervention.html [ Pass Failure Timeout ] @@ -1924,6 +1924,7 @@ crbug.com/620432 accessibility/aria-activedescendant.html [ Failure ] crbug.com/399507 virtual/threaded/http/tests/devtools/tracing/timeline-paint/layer-tree.js [ Skip ] +crbug.com/786995 virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Pass Failure ] crbug.com/636424 [ Win7 Debug ] editing/selection/modify_move/move-by-word-visually-crash-test-5.html [ Pass Timeout ] crbug.com/638618 http/tests/devtools/editor/text-editor-search-switch-editor.js [ Skip ] @@ -2035,12 +2036,10 @@ 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/animations/svg-attribute-composition/svg-startOffset-composition.html [ Failure Pass ] crbug.com/723741 virtual/threaded/http/tests/devtools/tracing/idle-callback.html [ Failure Pass Timeout ] crbug.com/723826 http/tests/security/w3c/cross-origin-objects.html [ Failure Pass ] crbug.com/723826 virtual/mojo-loading/http/tests/security/w3c/cross-origin-objects.html [ Failure Pass ] -crbug.com/724251 virtual/threaded/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html [ Failure Pass ] # Untriaged failures after https://crrev.com/c/543695/. # These need to be updated but appear not to be related to that change. @@ -2067,9 +2066,8 @@ crbug.com/751952 virtual/origin-trials-runtimeflags-disabled/http/tests/origin_trials/webexposed/budget-api-origin-trial-interfaces.html [ Pass Failure ] # ====== New tests from wpt-importer added here ====== -crbug.com/626703 external/wpt/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.html [ Timeout ] -crbug.com/626703 external/wpt/WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.html [ Timeout ] -crbug.com/626703 external/wpt/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.html [ Timeout ] +crbug.com/626703 [ Retina ] external/wpt/WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.https.html [ Timeout ] +crbug.com/626703 external/wpt/css/css-display/display-contents-dynamic-pseudo-insertion-001.html [ Failure ] crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-page/body-margin-1i.html [ Failure ] crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-page/body-margin-1j.html [ Failure ] crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-page/body-margin-1k.html [ Failure ] @@ -2119,6 +2117,7 @@ crbug.com/626703 external/wpt/css/CSS2/text/white-space-collapsing-bidi-001.xht [ Failure ] crbug.com/626703 external/wpt/css/CSS2/text/white-space-mixed-001.xht [ Failure ] crbug.com/626703 external/wpt/css/CSS2/text/white-space-mixed-003.xht [ Failure ] +crbug.com/626703 external/wpt/css/css-display/display-contents-before-after-003.html [ Failure ] crbug.com/626703 external/wpt/css/css-display/display-contents-dynamic-before-after-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-display/display-contents-dynamic-before-after-first-letter-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-fonts/alternates-order.html [ Failure ] @@ -2573,9 +2572,9 @@ crbug.com/697971 [ Mac10.12 ] fast/text/selection/flexbox-selection-nested.html [ Skip ] crbug.com/697971 [ Mac10.12 ] fast/text/selection/flexbox-selection.html [ Skip ] -crbug.com/678481 http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.html [ Timeout Failure Pass ] -crbug.com/678481 http/tests/devtools/appcache/appcache-iframe-manifests.html [ Timeout Failure Pass ] -crbug.com/678481 virtual/mojo-loading/http/tests/devtools/appcache/appcache-iframe-manifests.html [ Timeout Failure Pass ] +crbug.com/678481 http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.js [ Timeout Failure Pass ] +crbug.com/678481 http/tests/devtools/appcache/appcache-iframe-manifests.js [ Timeout Failure Pass ] +crbug.com/678481 virtual/mojo-loading/http/tests/devtools/appcache/appcache-iframe-manifests.js [ Timeout Failure Pass ] crbug.com/782858 virtual/display_list_2d_canvas/fast/canvas/canvas-filter-units-off-screen.html [ Skip ] crbug.com/782858 virtual/display_list_2d_canvas/fast/canvas/canvas-filter-units.html [ Skip ] @@ -2621,8 +2620,8 @@ crbug.com/660295 http/tests/devtools/elements/elements-panel-restore-selection-when-node-comes-later.js [ Pass Failure ] crbug.com/667560 virtual/mojo-loading/http/tests/devtools/elements/elements-panel-restore-selection-when-node-comes-later.js [ Pass Failure ] -crbug.com/735245 http/tests/devtools/application-panel/storage-view-reports-quota.html [ Pass Timeout Failure ] -crbug.com/735245 virtual/mojo-loading/http/tests/devtools/application-panel/storage-view-reports-quota.html [ Pass Timeout Failure ] +crbug.com/735245 http/tests/devtools/application-panel/storage-view-reports-quota.js [ Pass Timeout Failure ] +crbug.com/735245 virtual/mojo-loading/http/tests/devtools/application-panel/storage-view-reports-quota.js [ Pass Timeout Failure ] # [css-grid] crbug.com/659610 fast/css-grid-layout/grid-baseline.html [ Failure ] @@ -2776,6 +2775,8 @@ crbug.com/664819 http/tests/security/isolatedWorld/events.html [ Pass Failure ] crbug.com/664819 virtual/mojo-loading/http/tests/security/isolatedWorld/events.html [ Pass Failure ] +crbug.com/787084 http/tests/security/contentSecurityPolicy/report-blocked-data-uri.php [ Skip ] + crbug.com/702837 fast/text/aat-morx.html [ Skip ] crbug.com/688670 media/track/track-cue-rendering-after-controls-removed.html [ Pass Failure ] @@ -3056,8 +3057,8 @@ # Sheriff failures 2017-03-10 crbug.com/741210 [ Mac ] inspector-protocol/emulation/device-emulation-restore.js [ Failure ] -crbug.com/700374 [ Win ] virtual/mojo-loading/http/tests/devtools/workers-on-navigation.html [ Failure Pass ] -crbug.com/700374 [ Win ] http/tests/devtools/workers-on-navigation.html [ Failure Pass ] +crbug.com/700374 [ Win ] virtual/mojo-loading/http/tests/devtools/workers-on-navigation.js [ Failure Pass ] +crbug.com/700374 [ Win ] http/tests/devtools/workers-on-navigation.js [ Failure Pass ] # Sheriff failures 2017-03-21 crbug.com/703518 http/tests/devtools/tracing/worker-js-frames.js [ Failure Pass ] @@ -3565,7 +3566,6 @@ crbug.com/755405 [ Android ] external/wpt/web-animations/interfaces/Animation/playState.html [ Failure ] crbug.com/755405 [ Android ] external/wpt/web-animations/interfaces/Animation/ready.html [ Failure ] crbug.com/755405 [ Android ] external/wpt/web-animations/interfaces/AnimationEffectTiming/delay.html [ Failure ] -crbug.com/755405 [ Android ] external/wpt/web-animations/interfaces/AnimationEffectTiming/getAnimations.html [ Failure ] crbug.com/755405 [ Android ] external/wpt/web-animations/interfaces/Document/getAnimations.html [ Failure ] crbug.com/755405 [ Android ] external/wpt/web-animations/interfaces/DocumentTimeline/constructor.html [ Failure ] crbug.com/755405 [ Android ] external/wpt/web-animations/interfaces/KeyframeEffect/composite.html [ Failure ] @@ -3815,54 +3815,11 @@ crbug.com/766129 svg/wicd/test-rightsizing-b.xhtml [ Failure Pass ] -# These tests have a low level amount of flakyness on Mac and Windows and are -# failing everywhere. Disabling for now. -crbug.com/655458 crbug.com/721814 external/wpt/WebCryptoAPI/idlharness.html [ Skip ] -crbug.com/655458 crbug.com/721814 external/wpt/WebCryptoAPI/idlharness.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/failures.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/failures_AES-CBC.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/failures_AES-CTR.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/failures_AES-GCM.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/failures_AES-KW.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/failures_ECDH.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/failures_ECDSA.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/failures_HMAC.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/failures_RSA-PSS.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_AES-CBC.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_AES-CTR.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_AES-GCM.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_AES-KW.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_ECDH.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_ECDSA.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_HMAC.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_RSA-OAEP.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_RSA-PSS.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_aes-cbc.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_aes-ctr.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_failures_AES-CBC.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_failures_AES-CTR.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_failures_AES-GCM.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_failures_AES-KW.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_failures_ECDH.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_failures_ECDSA.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_failures_HMAC.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_failures_RSA-OAEP.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_failures_RSA-PSS.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_failures_RSASSA-PKCS1-v1_5.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_successes_AES-CBC.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_successes_AES-CTR.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_successes_AES-GCM.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_successes_AES-KW.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_successes_ECDH.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_successes_ECDSA.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_successes_HMAC.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_successes_RSA-PSS.https.html [ Skip ] -crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_successes_RSASSA-PKCS1-v1_5.https.html [ Skip ] +# These key generation tests are slow and sometimes time out. +crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.html [ Pass Timeout ] +crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.html [ Pass Timeout ] +crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.html [ Pass Timeout ] +crbug.com/757698 external/wpt/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html [ Pass Timeout ] # Tests occasionaly timing out (flaky) on WebKit Win7 dbg builder crbug.com/757955 [ Win7 Debug ] http/tests/devtools/sources/debugger-pause/pause-on-elements-panel.js [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites index 2981df7..4016a4e8 100644 --- a/third_party/WebKit/LayoutTests/VirtualTestSuites +++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -363,6 +363,11 @@ "args": ["--enable-features=AsmJsToWebAssembly"] }, { + "prefix": "pwa-full-code-cache", + "base": "http/tests/devtools/service-workers/", + "args": ["--enable-features=PWAFullCodeCache"] + }, + { "prefix": "service-worker-script-streaming", "base": "external/wpt/service-workers", "args": ["--enable-features=ServiceWorkerScriptStreaming"]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations index 07b8567..9c4a13e 100644 --- a/third_party/WebKit/LayoutTests/W3CImportExpectations +++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -139,12 +139,9 @@ external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ui3 [ Skip ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/values3 [ Skip ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/will-change [ Skip ] -external/wpt/css/work-in-progress [ Skip ] external/wpt/docs [ Skip ] external/wpt/dpub-aam [ Skip ] external/wpt/dpub-aria [ Skip ] -external/wpt/encrypted-media/Google [ Skip ] -external/wpt/ext-xhtml-pubid [ Skip ] external/wpt/fonts/math [ Skip ] external/wpt/html-longdesc [ Skip ] external/wpt/js [ Skip ] @@ -171,7 +168,6 @@ # files. Having unused files would be confusing. external/wpt/resources/testdriver-vendor.js [ Skip ] external/wpt/resources/testharnessreport.js [ Skip ] -external/wpt/common/vendor-prefix.js [ Skip ] # crbug.com/490939: The following tests are too large. They cause time out frequently. # [ Slow ] didn't help the following svg-in-*.html tests. @@ -422,7 +418,6 @@ external/wpt/touch-events/single-touch-manual.html [ Skip ] external/wpt/uievents/order-of-events/focus-events/focus-contained-manual.html [ Skip ] external/wpt/uievents/order-of-events/focus-events/legacy-manual.html [ Skip ] -external/wpt/uievents/order-of-events/mouse-events/click-cancel-manual.html [ Skip ] external/wpt/uievents/order-of-events/mouse-events/click-on-body-manual.html [ Skip ] external/wpt/uievents/order-of-events/mouse-events/click-on-div-manual.html [ Skip ] external/wpt/uievents/order-of-events/mouse-events/click-on-html-manual.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition-001.html similarity index 67% copy from third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html copy to third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition-001.html index d73e8102..05bdcbf 100644 --- a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition-001.html
@@ -23,13 +23,16 @@ </text> </svg> </template> -<script src="resources/interpolation-test.js"></script> +<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script> <script> 'use strict'; assertAttributeInterpolation({ property: 'startOffset', - from: '1', - to: '6' + underlying: '2', + from: '-1', + fromComposite: 'add', + to: '4', + toComposite: 'add' }, [ {at: -0.4, is: -1}, {at: 0, is: 1}, @@ -40,8 +43,11 @@ ]); assertAttributeInterpolation({ property: 'startOffset', - from: '10in', - to: '770pt' + underlying: '1in', + from: '9in', + fromComposite: 'add', + to: '698pt', + toComposite: 'add' }, [ {at: -0.4, is: '700pt'}, {at: 0, is: '720pt'}, @@ -52,23 +58,18 @@ ]); assertAttributeInterpolation({ property: 'startOffset', - from: '25%', // 25% of 1000px path length is 250px. - to: '25em' // 25 times 50px font size is 1250px. + underlying: '50', + from: '75', + fromComposite: 'add', + to: '19em', + toComposite: 'add' }, [ - {at: -0.4, is: -150}, - {at: 0, is: 250}, - {at: 0.2, is: 450}, - {at: 0.6, is: 850}, - {at: 1, is: 1250}, - {at: 1.4, is: 1650} -]); -assertAttributeInterpolation({ - property: 'startOffset', - from: '125', - to: '25ex' -}, [ + {at: -0.4, is: '-225'}, {at: 0, is: '125'}, - {at: 1, is: '25ex'}, + {at: 0.2, is: '300'}, + {at: 0.6, is: '650'}, + {at: 1, is: '1000'}, + {at: 1.4, is: '1350'} ]); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition-002.html similarity index 69% copy from third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html copy to third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition-002.html index d73e8102..4bfc861 100644 --- a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition-002.html
@@ -23,13 +23,16 @@ </text> </svg> </template> -<script src="resources/interpolation-test.js"></script> +<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script> <script> 'use strict'; assertAttributeInterpolation({ property: 'startOffset', + underlying: '2', from: '1', - to: '6' + fromComposite: 'replace', + to: '4', + toComposite: 'add' }, [ {at: -0.4, is: -1}, {at: 0, is: 1}, @@ -40,8 +43,11 @@ ]); assertAttributeInterpolation({ property: 'startOffset', + underlying: '50pt', from: '10in', - to: '770pt' + fromComposite: 'replace', + to: '720pt', + toComposite: 'add' }, [ {at: -0.4, is: '700pt'}, {at: 0, is: '720pt'}, @@ -52,23 +58,18 @@ ]); assertAttributeInterpolation({ property: 'startOffset', - from: '25%', // 25% of 1000px path length is 250px. - to: '25em' // 25 times 50px font size is 1250px. -}, [ - {at: -0.4, is: -150}, - {at: 0, is: 250}, - {at: 0.2, is: 450}, - {at: 0.6, is: 850}, - {at: 1, is: 1250}, - {at: 1.4, is: 1650} -]); -assertAttributeInterpolation({ - property: 'startOffset', + underlying: '5em', from: '125', - to: '25ex' + fromComposite: 'replace', + to: '15em', + toComposite: 'add' }, [ + {at: -0.4, is: '-225'}, {at: 0, is: '125'}, - {at: 1, is: '25ex'}, + {at: 0.2, is: '300'}, + {at: 0.6, is: '650'}, + {at: 1, is: '1000'}, + {at: 1.4, is: '1350'} ]); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition-003.html similarity index 68% copy from third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html copy to third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition-003.html index d73e8102..9a57862 100644 --- a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition-003.html
@@ -23,13 +23,15 @@ </text> </svg> </template> -<script src="resources/interpolation-test.js"></script> +<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script> <script> 'use strict'; assertAttributeInterpolation({ property: 'startOffset', - from: '1', - to: '6' + underlying: '1', + from: neutralKeyframe, + to: '6', + toComposite: 'replace' }, [ {at: -0.4, is: -1}, {at: 0, is: 1}, @@ -40,8 +42,10 @@ ]); assertAttributeInterpolation({ property: 'startOffset', - from: '10in', - to: '770pt' + underlying: '10in', + from: neutralKeyframe, + to: '770pt', + toComposite: 'replace' }, [ {at: -0.4, is: '700pt'}, {at: 0, is: '720pt'}, @@ -52,23 +56,17 @@ ]); assertAttributeInterpolation({ property: 'startOffset', - from: '25%', // 25% of 1000px path length is 250px. - to: '25em' // 25 times 50px font size is 1250px. + underlying: '125', + from: neutralKeyframe, + to: '20em', + toComposite: 'replace' }, [ - {at: -0.4, is: -150}, - {at: 0, is: 250}, - {at: 0.2, is: 450}, - {at: 0.6, is: 850}, - {at: 1, is: 1250}, - {at: 1.4, is: 1650} -]); -assertAttributeInterpolation({ - property: 'startOffset', - from: '125', - to: '25ex' -}, [ + {at: -0.4, is: '-225'}, {at: 0, is: '125'}, - {at: 1, is: '25ex'}, + {at: 0.2, is: '300'}, + {at: 0.6, is: '650'}, + {at: 1, is: '1000'}, + {at: 1.4, is: '1350'} ]); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition.html deleted file mode 100644 index 252e91d3..0000000 --- a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-startOffset-composition.html +++ /dev/null
@@ -1,165 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<script src="../../resources/ahem.js"></script> -<style> -:root { - font: 50px Ahem; -} -</style> -</head> -<body> -<svg> - <defs> - <path id="path1" d="m 0 0 h 250 v 250 h -250 z"/> - </defs> -</svg> -<template id="target-template"> -<svg width="7px" height="17px" viewBox="0 0 140 340"> - <text text-anchor="middle"> - <textPath xlink:href="#path1" startOffset="50%" class="target"> - Text on a path - </textPath> - </text> -</svg> -</template> -<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script> -<script> -'use strict'; -assertAttributeInterpolation({ - property: 'startOffset', - underlying: '2', - from: '-1', - fromComposite: 'add', - to: '4', - toComposite: 'add' -}, [ - {at: -0.4, is: -1}, - {at: 0, is: 1}, - {at: 0.2, is: 2}, - {at: 0.6, is: 4}, - {at: 1, is: 6}, - {at: 1.4, is: 8} -]); -assertAttributeInterpolation({ - property: 'startOffset', - underlying: '1in', - from: '9in', - fromComposite: 'add', - to: '698pt', - toComposite: 'add' -}, [ - {at: -0.4, is: '700pt'}, - {at: 0, is: '720pt'}, - {at: 0.2, is: '730pt'}, - {at: 0.6, is: '750pt'}, - {at: 1, is: '770pt'}, - {at: 1.4, is: '790pt'} -]); -assertAttributeInterpolation({ - property: 'startOffset', - underlying: '50', - from: '75', - fromComposite: 'add', - to: '19em', - toComposite: 'add' -}, [ - {at: -0.4, is: '-225'}, - {at: 0, is: '125'}, - {at: 0.2, is: '300'}, - {at: 0.6, is: '650'}, - {at: 1, is: '1000'}, - {at: 1.4, is: '1350'} -]); - -assertAttributeInterpolation({ - property: 'startOffset', - underlying: '2', - from: '1', - fromComposite: 'replace', - to: '4', - toComposite: 'add' -}, [ - {at: -0.4, is: -1}, - {at: 0, is: 1}, - {at: 0.2, is: 2}, - {at: 0.6, is: 4}, - {at: 1, is: 6}, - {at: 1.4, is: 8} -]); -assertAttributeInterpolation({ - property: 'startOffset', - underlying: '50pt', - from: '10in', - fromComposite: 'replace', - to: '720pt', - toComposite: 'add' -}, [ - {at: -0.4, is: '700pt'}, - {at: 0, is: '720pt'}, - {at: 0.2, is: '730pt'}, - {at: 0.6, is: '750pt'}, - {at: 1, is: '770pt'}, - {at: 1.4, is: '790pt'} -]); -assertAttributeInterpolation({ - property: 'startOffset', - underlying: '5em', - from: '125', - fromComposite: 'replace', - to: '15em', - toComposite: 'add' -}, [ - {at: -0.4, is: '-225'}, - {at: 0, is: '125'}, - {at: 0.2, is: '300'}, - {at: 0.6, is: '650'}, - {at: 1, is: '1000'}, - {at: 1.4, is: '1350'} -]); - -assertAttributeInterpolation({ - property: 'startOffset', - underlying: '1', - from: neutralKeyframe, - to: '6', - toComposite: 'replace' -}, [ - {at: -0.4, is: -1}, - {at: 0, is: 1}, - {at: 0.2, is: 2}, - {at: 0.6, is: 4}, - {at: 1, is: 6}, - {at: 1.4, is: 8} -]); -assertAttributeInterpolation({ - property: 'startOffset', - underlying: '10in', - from: neutralKeyframe, - to: '770pt', - toComposite: 'replace' -}, [ - {at: -0.4, is: '700pt'}, - {at: 0, is: '720pt'}, - {at: 0.2, is: '730pt'}, - {at: 0.6, is: '750pt'}, - {at: 1, is: '770pt'}, - {at: 1.4, is: '790pt'} -]); -assertAttributeInterpolation({ - property: 'startOffset', - underlying: '125', - from: neutralKeyframe, - to: '20em', - toComposite: 'replace' -}, [ - {at: -0.4, is: '-225'}, - {at: 0, is: '125'}, - {at: 0.2, is: '300'}, - {at: 0.6, is: '650'}, - {at: 1, is: '1000'}, - {at: 1.4, is: '1350'} -]); -</script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-001.html similarity index 65% copy from third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html copy to third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-001.html index d73e8102..0a5e000b 100644 --- a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-001.html
@@ -28,18 +28,6 @@ 'use strict'; assertAttributeInterpolation({ property: 'startOffset', - from: '1', - to: '6' -}, [ - {at: -0.4, is: -1}, - {at: 0, is: 1}, - {at: 0.2, is: 2}, - {at: 0.6, is: 4}, - {at: 1, is: 6}, - {at: 1.4, is: 8} -]); -assertAttributeInterpolation({ - property: 'startOffset', from: '10in', to: '770pt' }, [ @@ -52,18 +40,6 @@ ]); assertAttributeInterpolation({ property: 'startOffset', - from: '25%', // 25% of 1000px path length is 250px. - to: '25em' // 25 times 50px font size is 1250px. -}, [ - {at: -0.4, is: -150}, - {at: 0, is: 250}, - {at: 0.2, is: 450}, - {at: 0.6, is: 850}, - {at: 1, is: 1250}, - {at: 1.4, is: 1650} -]); -assertAttributeInterpolation({ - property: 'startOffset', from: '125', to: '25ex' }, [
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-expected.txt b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-002-expected.txt similarity index 62% rename from third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-expected.txt rename to third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-002-expected.txt index 66c3563f..84e858d 100644 --- a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-expected.txt +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-002-expected.txt
@@ -10,16 +10,6 @@ PASS Web Animations: Interpolate attribute <startOffset> from replace [1] to replace [6] at (0.6) is [4] PASS Web Animations: Interpolate attribute <startOffset> from replace [1] to replace [6] at (1) is [6] PASS Web Animations: Interpolate attribute <startOffset> from replace [1] to replace [6] at (1.4) is [8] -PASS SMIL: Interpolate attribute <startOffset> from replace [10in] to replace [770pt] at (0) is [720pt] -PASS SMIL: Interpolate attribute <startOffset> from replace [10in] to replace [770pt] at (0.2) is [730pt] -PASS SMIL: Interpolate attribute <startOffset> from replace [10in] to replace [770pt] at (0.6) is [750pt] -PASS SMIL: Interpolate attribute <startOffset> from replace [10in] to replace [770pt] at (1) is [770pt] -PASS Web Animations: Interpolate attribute <startOffset> from replace [10in] to replace [770pt] at (-0.4) is [700pt] -PASS Web Animations: Interpolate attribute <startOffset> from replace [10in] to replace [770pt] at (0) is [720pt] -PASS Web Animations: Interpolate attribute <startOffset> from replace [10in] to replace [770pt] at (0.2) is [730pt] -PASS Web Animations: Interpolate attribute <startOffset> from replace [10in] to replace [770pt] at (0.6) is [750pt] -PASS Web Animations: Interpolate attribute <startOffset> from replace [10in] to replace [770pt] at (1) is [770pt] -PASS Web Animations: Interpolate attribute <startOffset> from replace [10in] to replace [770pt] at (1.4) is [790pt] FAIL SMIL: Interpolate attribute <startOffset> from replace [25%] to replace [25em] at (0) is [250] assert_equals: expected "250 " but got "35 " FAIL SMIL: Interpolate attribute <startOffset> from replace [25%] to replace [25em] at (0.2) is [450] assert_equals: expected "450 " but got "278 " FAIL SMIL: Interpolate attribute <startOffset> from replace [25%] to replace [25em] at (0.6) is [850] assert_equals: expected "850 " but got "764 " @@ -30,9 +20,5 @@ FAIL Web Animations: Interpolate attribute <startOffset> from replace [25%] to replace [25em] at (0.6) is [850] assert_equals: expected "850 " but got "764 " PASS Web Animations: Interpolate attribute <startOffset> from replace [25%] to replace [25em] at (1) is [1250] FAIL Web Animations: Interpolate attribute <startOffset> from replace [25%] to replace [25em] at (1.4) is [1650] assert_equals: expected "1650 " but got "1736 " -PASS SMIL: Interpolate attribute <startOffset> from replace [125] to replace [25ex] at (0) is [125] -PASS SMIL: Interpolate attribute <startOffset> from replace [125] to replace [25ex] at (1) is [25ex] -PASS Web Animations: Interpolate attribute <startOffset> from replace [125] to replace [25ex] at (0) is [125] -PASS Web Animations: Interpolate attribute <startOffset> from replace [125] to replace [25ex] at (1) is [25ex] Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-002.html similarity index 73% rename from third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html rename to third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-002.html index d73e8102..6540e73 100644 --- a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation.html +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-startOffset-interpolation-002.html
@@ -40,18 +40,6 @@ ]); assertAttributeInterpolation({ property: 'startOffset', - from: '10in', - to: '770pt' -}, [ - {at: -0.4, is: '700pt'}, - {at: 0, is: '720pt'}, - {at: 0.2, is: '730pt'}, - {at: 0.6, is: '750pt'}, - {at: 1, is: '770pt'}, - {at: 1.4, is: '790pt'} -]); -assertAttributeInterpolation({ - property: 'startOffset', from: '25%', // 25% of 1000px path length is 250px. to: '25em' // 25 times 50px font size is 1250px. }, [ @@ -62,14 +50,6 @@ {at: 1, is: 1250}, {at: 1.4, is: 1650} ]); -assertAttributeInterpolation({ - property: 'startOffset', - from: '125', - to: '25ex' -}, [ - {at: 0, is: '125'}, - {at: 1, is: '25ex'}, -]); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/surface-over-composited-offscreen-expected.html b/third_party/WebKit/LayoutTests/compositing/overflow/surface-over-composited-offscreen-expected.html new file mode 100644 index 0000000..2b5cb531 --- /dev/null +++ b/third_party/WebKit/LayoutTests/compositing/overflow/surface-over-composited-offscreen-expected.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<style> + .composited-box { + position: absolute; + left: 0; + top: 1000px; + height: 300px; + width: 300px; + background-color: green; + } + + .top-box { + position: absolute; + left: 200px; + top: 1200px; + height: 300px; + width: 300px; + background-color: blue; + z-index: 1; + + } +</style> +<!-- +This test ensures that overlap testing to determine compositing requirements +works correctly for layers outside the main frame's viewport. The blue box +should appear on top of the green box. +--> +<div class="composited-box"></div> +<div class="top-box"></div> +<script> + window.scrollTo(0, 1500); +</script>
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/surface-over-composited-offscreen.html b/third_party/WebKit/LayoutTests/compositing/overflow/surface-over-composited-offscreen.html new file mode 100644 index 0000000..1b069875 --- /dev/null +++ b/third_party/WebKit/LayoutTests/compositing/overflow/surface-over-composited-offscreen.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<style> + .composited-box { + position: absolute; + left: 0; + top: 1000px; + height: 300px; + width: 300px; + will-change: transform; + background-color: green; + } + + .top-box { + position: absolute; + left: 200px; + top: 1200px; + height: 300px; + width: 300px; + background-color: blue; + z-index: 1; + + } +</style> +<!-- +This test ensures that overlap testing to determine compositing requirements +works correctly for layers outside the main frame's viewport. The blue box +should appear on top of the green box. +--> +<div class="composited-box"></div> +<div class="top-box"></div> +<script> + if ('internals' in window) { + window.addEventListener('load', () => { + // Force a compositing update so it happens while the boxes are off + // screen. + window.internals.forceCompositingUpdate(document); + + // Bring them into view, the z-index order should be correct. + window.scrollTo(0, 1500); + }); + } +</script>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/mouse/click_back_does_not_clear_editing_style.html b/third_party/WebKit/LayoutTests/editing/selection/mouse/click_back_does_not_clear_editing_style.html new file mode 100644 index 0000000..4d56465d --- /dev/null +++ b/third_party/WebKit/LayoutTests/editing/selection/mouse/click_back_does_not_clear_editing_style.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<div contenteditable id="div"></div> +<button id="button">bold</button> +<script> +const div = document.getElementById('div'); +const button = document.getElementById('button'); +button.onclick = () => document.execCommand('bold'); + +const divX = div.offsetLeft + div.offsetWidth / 2; +const divY = div.offsetTop + div.offsetHeight / 2; + +const buttonX = button.offsetLeft + button.offsetWidth / 2; +const buttonY = button.offsetTop + button.offsetHeight / 2; + +// Regression test for crbug.com/785147 +// This test requires setting selection by mouse to test code in SelectionController. +promise_test(() => { + return new Promise((resolve, reject) => { + assert_not_equals(window.chrome, undefined); + assert_not_equals(window.chrome.gpuBenchmarking, undefined); + + chrome.gpuBenchmarking.pointerActionSequence([{ + source: 'mouse', + actions: [ + // Mouse click to cursor in DIV + {name: 'pointerDown', x: divX, y: divY}, + {name: 'pointerUp'}, + // Click the button to set bold editing style and also move focus away from DIV + {name: 'pointerDown', x: buttonX, y: buttonY}, + {name: 'pointerUp'}, + // Click in DIV to set the cursor back without changing selection + {name: 'pointerDown', x: divX, y: divY}, + {name: 'pointerUp'} + ] + }], resolve); + }).then(() => { + document.execCommand('insertText', false, 'bar'); + assert_equals(div.innerHTML, '<b>bar</b>'); + }) +}, 'Mouse click without selection change should not clear editing style'); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index ca5f00f..dd7e92b 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -5463,18 +5463,6 @@ {} ] ], - "css-contain/contain-style-counters.html": [ - [ - "/css-contain/contain-style-counters.html", - [ - [ - "/css-contain/contain-style-counters-ref.html", - "==" - ] - ], - {} - ] - ], "css/CSS2/abspos/abspos-containing-block-initial-001.xht": [ [ "/css/CSS2/abspos/abspos-containing-block-initial-001.xht", @@ -31943,6 +31931,18 @@ {} ] ], + "css/css-contain/contain-style-counters.html": [ + [ + "/css/css-contain/contain-style-counters.html", + [ + [ + "/css/css-contain/contain-style-counters-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-display/display-contents-alignment-001.html": [ [ "/css/css-display/display-contents-alignment-001.html", @@ -31991,6 +31991,18 @@ {} ] ], + "css/css-display/display-contents-before-after-003.html": [ + [ + "/css/css-display/display-contents-before-after-003.html", + [ + [ + "/css/css-display/display-contents-pass-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-display/display-contents-block-001.html": [ [ "/css/css-display/display-contents-block-001.html", @@ -32195,6 +32207,18 @@ {} ] ], + "css/css-display/display-contents-dynamic-pseudo-insertion-001.html": [ + [ + "/css/css-display/display-contents-dynamic-pseudo-insertion-001.html", + [ + [ + "/css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-display/display-contents-dynamic-table-001-inline.html": [ [ "/css/css-display/display-contents-dynamic-table-001-inline.html", @@ -78123,6 +78147,18 @@ {} ] ], + "html/browsers/sandboxing/sandbox-parse-noscript.html": [ + [ + "/html/browsers/sandboxing/sandbox-parse-noscript.html", + [ + [ + "/html/browsers/sandboxing/sandbox-parse-noscript-ref.html", + "==" + ] + ], + {} + ] + ], "html/dom/elements/global-attributes/dir_auto-EN-L.html": [ [ "/html/dom/elements/global-attributes/dir_auto-EN-L.html", @@ -87383,11 +87419,6 @@ {} ] ], - "WebCryptoAPI/idlharness.https-expected.txt": [ - [ - {} - ] - ], "WebCryptoAPI/import_export/ec_importKey.js": [ [ {} @@ -89803,7 +89834,17 @@ {} ] ], - "css-contain/contain-style-counters-ref.html": [ + "credential-management/support/echoing-nester.html": [ + [ + {} + ] + ], + "credential-management/support/federatedcredential-get.html": [ + [ + {} + ] + ], + "credential-management/support/passwordcredential-get.html": [ [ {} ] @@ -95498,6 +95539,11 @@ {} ] ], + "css/css-contain/contain-style-counters-ref.html": [ + [ + {} + ] + ], "css/css-display/OWNERS": [ [ {} @@ -95523,6 +95569,11 @@ {} ] ], + "css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html": [ + [ + {} + ] + ], "css/css-display/display-contents-flex-001-ref.html": [ [ {} @@ -97148,6 +97199,11 @@ {} ] ], + "css/css-fonts/font-variant-alternates-parsing-expected.txt": [ + [ + {} + ] + ], "css/css-fonts/font-variant-caps-01-ref.html": [ [ {} @@ -123408,6 +123464,16 @@ {} ] ], + "html/browsers/sandboxing/noscript-iframe.html": [ + [ + {} + ] + ], + "html/browsers/sandboxing/sandbox-parse-noscript-ref.html": [ + [ + {} + ] + ], "html/browsers/the-window-object/.gitkeep": [ [ {} @@ -135673,32 +135739,32 @@ {} ] ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [ [ {} ] ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers": [ [ {} ] ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [ [ {} ] ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [ [ {} ] ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers": [ [ {} ] ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [ [ {} ] @@ -140383,6 +140449,11 @@ {} ] ], + "service-workers/service-worker/resource-timing.https-expected.txt": [ + [ + {} + ] + ], "service-workers/service-worker/resources/404.py": [ [ {} @@ -141318,7 +141389,7 @@ {} ] ], - "service-workers/service-worker/resources/resource-timing-iframe.html": [ + "service-workers/service-worker/resources/resource-timing-iframe.sub.html": [ [ {} ] @@ -143128,6 +143199,11 @@ {} ] ], + "web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation-expected.txt": [ + [ + {} + ] + ], "web-animations/interfaces/Animatable/animate-expected.txt": [ [ {} @@ -143153,7 +143229,7 @@ {} ] ], - "web-animations/interfaces/AnimationEffectTiming/getComputedStyle-expected.txt": [ + "web-animations/interfaces/AnimationEffectTiming/getComputedTiming-expected.txt": [ [ {} ] @@ -143183,11 +143259,6 @@ {} ] ], - "web-animations/interfaces/KeyframeEffect/getComputedTiming-expected.txt": [ - [ - {} - ] - ], "web-animations/interfaces/KeyframeEffect/idlharness-expected.txt": [ [ {} @@ -143213,7 +143284,7 @@ {} ] ], - "web-animations/interfaces/KeyframeEffect/setTarget-expected.txt": [ + "web-animations/interfaces/KeyframeEffect/target-expected.txt": [ [ {} ] @@ -144528,11 +144599,6 @@ {} ] ], - "webvtt/parsing/cue-text-parsing/tests/timestamps-expected.txt": [ - [ - {} - ] - ], "webvtt/parsing/file-parsing/README.md": [ [ {} @@ -159477,12 +159543,24 @@ {} ] ], + "credential-management/federatedcredential-framed-get.sub.https.html": [ + [ + "/credential-management/federatedcredential-framed-get.sub.https.html", + {} + ] + ], "credential-management/idl.https.html": [ [ "/credential-management/idl.https.html", {} ] ], + "credential-management/passwordcredential-framed-get.sub.https.html": [ + [ + "/credential-management/passwordcredential-framed-get.sub.https.html", + {} + ] + ], "css/css-align/content-distribution/place-content-shorthand-001.html": [ [ "/css/css-align/content-distribution/place-content-shorthand-001.html", @@ -160191,6 +160269,12 @@ {} ] ], + "css/css-fonts/font-variant-alternates-parsing.html": [ + [ + "/css/css-fonts/font-variant-alternates-parsing.html", + {} + ] + ], "css/css-fonts/test_datafont_same_origin.html": [ [ "/css/css-fonts/test_datafont_same_origin.html", @@ -168287,659 +168371,659 @@ {} ] ], - "encrypted-media/clearkey-check-initdata-type.html": [ + "encrypted-media/clearkey-check-initdata-type.https.html": [ [ - "/encrypted-media/clearkey-check-initdata-type.html", + "/encrypted-media/clearkey-check-initdata-type.https.html", {} ] ], - "encrypted-media/clearkey-events-session-closed-event.html": [ + "encrypted-media/clearkey-events-session-closed-event.https.html": [ [ - "/encrypted-media/clearkey-events-session-closed-event.html", + "/encrypted-media/clearkey-events-session-closed-event.https.html", {} ] ], - "encrypted-media/clearkey-events.html": [ + "encrypted-media/clearkey-events.https.html": [ [ - "/encrypted-media/clearkey-events.html", + "/encrypted-media/clearkey-events.https.html", {} ] ], - "encrypted-media/clearkey-generate-request-disallowed-input.html": [ + "encrypted-media/clearkey-generate-request-disallowed-input.https.html": [ [ - "/encrypted-media/clearkey-generate-request-disallowed-input.html", + "/encrypted-media/clearkey-generate-request-disallowed-input.https.html", {} ] ], - "encrypted-media/clearkey-invalid-license.html": [ + "encrypted-media/clearkey-invalid-license.https.html": [ [ - "/encrypted-media/clearkey-invalid-license.html", + "/encrypted-media/clearkey-invalid-license.https.html", {} ] ], - "encrypted-media/clearkey-keystatuses-multiple-sessions.html": [ + "encrypted-media/clearkey-keystatuses-multiple-sessions.https.html": [ [ - "/encrypted-media/clearkey-keystatuses-multiple-sessions.html", + "/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html", {} ] ], - "encrypted-media/clearkey-keystatuses.html": [ + "encrypted-media/clearkey-keystatuses.https.html": [ [ - "/encrypted-media/clearkey-keystatuses.html", + "/encrypted-media/clearkey-keystatuses.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html": [ + "encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html", + "/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-persistent-license-events.html": [ + "encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-persistent-license-events.html", + "/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-persistent-license.html": [ + "encrypted-media/clearkey-mp4-playback-persistent-license.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-persistent-license.html", + "/encrypted-media/clearkey-mp4-playback-persistent-license.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html": [ + "encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html", + "/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-persistent-usage-record.html": [ + "encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-persistent-usage-record.html", + "/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html": [ + "encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html", + "/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html": [ + "encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html", + "/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html": [ + "encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html", + "/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html", + "/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html", + "/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html", { "timeout": "long" } ] ], - "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html", + "/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-temporary-events.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-events.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-events.html", + "/encrypted-media/clearkey-mp4-playback-temporary-events.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html", + "/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html", { "timeout": "long" } ] ], - "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html", + "/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html", { "timeout": "long" } ] ], - "encrypted-media/clearkey-mp4-playback-temporary-multikey.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-multikey.html", + "/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-temporary-multisession.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-multisession.html", + "/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html", + "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html", + "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html", + "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html", + "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-temporary-two-videos.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-two-videos.html", + "/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html", { "timeout": "long" } ] ], - "encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html", + "/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html", {} ] ], - "encrypted-media/clearkey-mp4-playback-temporary.html": [ + "encrypted-media/clearkey-mp4-playback-temporary.https.html": [ [ - "/encrypted-media/clearkey-mp4-playback-temporary.html", + "/encrypted-media/clearkey-mp4-playback-temporary.https.html", {} ] ], - "encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html": [ + "encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html": [ [ - "/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html", + "/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html", { "timeout": "long" } ] ], - "encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html": [ + "encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html": [ [ - "/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html", + "/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html", {} ] ], - "encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html": [ [ - "/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html", + "/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html", {} ] ], - "encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html": [ [ - "/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html", + "/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html", {} ] ], - "encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html": [ [ - "/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html", + "/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html", {} ] ], - "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html": [ [ - "/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html", + "/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html", {} ] ], - "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html": [ [ - "/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html", + "/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html", {} ] ], - "encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html": [ [ - "/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html", + "/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html", {} ] ], - "encrypted-media/clearkey-mp4-setmediakeys.html": [ + "encrypted-media/clearkey-mp4-setmediakeys.https.html": [ [ - "/encrypted-media/clearkey-mp4-setmediakeys.html", + "/encrypted-media/clearkey-mp4-setmediakeys.https.html", {} ] ], - "encrypted-media/clearkey-mp4-syntax-mediakeys.html": [ + "encrypted-media/clearkey-mp4-syntax-mediakeys.https.html": [ [ - "/encrypted-media/clearkey-mp4-syntax-mediakeys.html", + "/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html", {} ] ], - "encrypted-media/clearkey-mp4-syntax-mediakeysession.html": [ + "encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html": [ [ - "/encrypted-media/clearkey-mp4-syntax-mediakeysession.html", + "/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html", {} ] ], - "encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html": [ + "encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html": [ [ - "/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html", + "/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html", {} ] ], - "encrypted-media/clearkey-mp4-unique-origin.html": [ + "encrypted-media/clearkey-mp4-unique-origin.https.html": [ [ - "/encrypted-media/clearkey-mp4-unique-origin.html", + "/encrypted-media/clearkey-mp4-unique-origin.https.html", {} ] ], - "encrypted-media/clearkey-mp4-update-disallowed-input.html": [ + "encrypted-media/clearkey-mp4-update-disallowed-input.https.html": [ [ - "/encrypted-media/clearkey-mp4-update-disallowed-input.html", + "/encrypted-media/clearkey-mp4-update-disallowed-input.https.html", {} ] ], - "encrypted-media/clearkey-mp4-waiting-for-a-key.html": [ + "encrypted-media/clearkey-mp4-waiting-for-a-key.https.html": [ [ - "/encrypted-media/clearkey-mp4-waiting-for-a-key.html", + "/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html", {} ] ], - "encrypted-media/clearkey-not-callable-after-createsession.html": [ + "encrypted-media/clearkey-not-callable-after-createsession.https.html": [ [ - "/encrypted-media/clearkey-not-callable-after-createsession.html", + "/encrypted-media/clearkey-not-callable-after-createsession.https.html", {} ] ], - "encrypted-media/clearkey-update-non-ascii-input.html": [ + "encrypted-media/clearkey-update-non-ascii-input.https.html": [ [ - "/encrypted-media/clearkey-update-non-ascii-input.html", + "/encrypted-media/clearkey-update-non-ascii-input.https.html", {} ] ], - "encrypted-media/drm-check-initdata-type.html": [ + "encrypted-media/drm-check-initdata-type.https.html": [ [ - "/encrypted-media/drm-check-initdata-type.html", + "/encrypted-media/drm-check-initdata-type.https.html", {} ] ], - "encrypted-media/drm-events-session-closed-event.html": [ + "encrypted-media/drm-events-session-closed-event.https.html": [ [ - "/encrypted-media/drm-events-session-closed-event.html", + "/encrypted-media/drm-events-session-closed-event.https.html", {} ] ], - "encrypted-media/drm-events.html": [ + "encrypted-media/drm-events.https.html": [ [ - "/encrypted-media/drm-events.html", + "/encrypted-media/drm-events.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-expiration.html": [ + "encrypted-media/drm-expiration.https.html": [ [ - "/encrypted-media/drm-expiration.html", + "/encrypted-media/drm-expiration.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-generate-request-disallowed-input.html": [ + "encrypted-media/drm-generate-request-disallowed-input.https.html": [ [ - "/encrypted-media/drm-generate-request-disallowed-input.html", + "/encrypted-media/drm-generate-request-disallowed-input.https.html", {} ] ], - "encrypted-media/drm-invalid-license.html": [ + "encrypted-media/drm-invalid-license.https.html": [ [ - "/encrypted-media/drm-invalid-license.html", + "/encrypted-media/drm-invalid-license.https.html", {} ] ], - "encrypted-media/drm-keystatuses-multiple-sessions.html": [ + "encrypted-media/drm-keystatuses-multiple-sessions.https.html": [ [ - "/encrypted-media/drm-keystatuses-multiple-sessions.html", + "/encrypted-media/drm-keystatuses-multiple-sessions.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-keystatuses.html": [ + "encrypted-media/drm-keystatuses.https.html": [ [ - "/encrypted-media/drm-keystatuses.html", + "/encrypted-media/drm-keystatuses.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-onencrypted.html": [ + "encrypted-media/drm-mp4-onencrypted.https.html": [ [ - "/encrypted-media/drm-mp4-onencrypted.html", + "/encrypted-media/drm-mp4-onencrypted.https.html", {} ] ], - "encrypted-media/drm-mp4-playback-destroy-persistent-license.html": [ + "encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html": [ [ - "/encrypted-media/drm-mp4-playback-destroy-persistent-license.html", + "/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-persistent-license-events.html": [ + "encrypted-media/drm-mp4-playback-persistent-license-events.https.html": [ [ - "/encrypted-media/drm-mp4-playback-persistent-license-events.html", + "/encrypted-media/drm-mp4-playback-persistent-license-events.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-persistent-license.html": [ + "encrypted-media/drm-mp4-playback-persistent-license.https.html": [ [ - "/encrypted-media/drm-mp4-playback-persistent-license.html", + "/encrypted-media/drm-mp4-playback-persistent-license.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-persistent-usage-record-events.html": [ + "encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html": [ [ - "/encrypted-media/drm-mp4-playback-persistent-usage-record-events.html", + "/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-persistent-usage-record.html": [ + "encrypted-media/drm-mp4-playback-persistent-usage-record.https.html": [ [ - "/encrypted-media/drm-mp4-playback-persistent-usage-record.html", + "/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html": [ + "encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html": [ [ - "/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html", + "/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-retrieve-persistent-license.html": [ + "encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html": [ [ - "/encrypted-media/drm-mp4-playback-retrieve-persistent-license.html", + "/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html": [ + "encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html": [ [ - "/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html", + "/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html": [ + "encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html", + "/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html": [ + "encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html", + "/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html": [ + "encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html", + "/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-events.html": [ + "encrypted-media/drm-mp4-playback-temporary-events.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-events.html", + "/encrypted-media/drm-mp4-playback-temporary-events.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-expired.html": [ + "encrypted-media/drm-mp4-playback-temporary-expired.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-expired.html", + "/encrypted-media/drm-mp4-playback-temporary-expired.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html": [ + "encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html", + "/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html": [ + "encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html", + "/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-multikey.html": [ + "encrypted-media/drm-mp4-playback-temporary-multikey.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-multikey.html", + "/encrypted-media/drm-mp4-playback-temporary-multikey.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-multisession.html": [ + "encrypted-media/drm-mp4-playback-temporary-multisession.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-multisession.html", + "/encrypted-media/drm-mp4-playback-temporary-multisession.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html": [ + "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html", + "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html": [ + "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html", + "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html": [ + "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html", + "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html": [ + "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html", + "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-two-videos.html": [ + "encrypted-media/drm-mp4-playback-temporary-two-videos.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-two-videos.html", + "/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary-waitingforkey.html": [ + "encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary-waitingforkey.html", + "/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-playback-temporary.html": [ + "encrypted-media/drm-mp4-playback-temporary.https.html": [ [ - "/encrypted-media/drm-mp4-playback-temporary.html", + "/encrypted-media/drm-mp4-playback-temporary.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-requestmediakeysystemaccess.html": [ + "encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html": [ [ - "/encrypted-media/drm-mp4-requestmediakeysystemaccess.html", + "/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html", {} ] ], - "encrypted-media/drm-mp4-reset-src-after-setmediakeys.html": [ + "encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html": [ [ - "/encrypted-media/drm-mp4-reset-src-after-setmediakeys.html", + "/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html", {} ] ], - "encrypted-media/drm-mp4-setmediakeys-again-after-playback.html": [ + "encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html": [ [ - "/encrypted-media/drm-mp4-setmediakeys-again-after-playback.html", + "/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html": [ + "encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html": [ [ - "/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html", + "/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-setmediakeys-at-same-time.html": [ + "encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html": [ [ - "/encrypted-media/drm-mp4-setmediakeys-at-same-time.html", + "/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html": [ + "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html": [ [ - "/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html", + "/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html": [ + "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html": [ [ - "/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html", + "/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html": [ + "encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html": [ [ - "/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html", + "/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-mp4-setmediakeys.html": [ + "encrypted-media/drm-mp4-setmediakeys.https.html": [ [ - "/encrypted-media/drm-mp4-setmediakeys.html", + "/encrypted-media/drm-mp4-setmediakeys.https.html", {} ] ], - "encrypted-media/drm-mp4-syntax-mediakeys.html": [ + "encrypted-media/drm-mp4-syntax-mediakeys.https.html": [ [ - "/encrypted-media/drm-mp4-syntax-mediakeys.html", + "/encrypted-media/drm-mp4-syntax-mediakeys.https.html", {} ] ], - "encrypted-media/drm-mp4-syntax-mediakeysession.html": [ + "encrypted-media/drm-mp4-syntax-mediakeysession.https.html": [ [ - "/encrypted-media/drm-mp4-syntax-mediakeysession.html", + "/encrypted-media/drm-mp4-syntax-mediakeysession.https.html", {} ] ], - "encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html": [ + "encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html": [ [ - "/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html", + "/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html", {} ] ], - "encrypted-media/drm-mp4-unique-origin.html": [ + "encrypted-media/drm-mp4-unique-origin.https.html": [ [ - "/encrypted-media/drm-mp4-unique-origin.html", + "/encrypted-media/drm-mp4-unique-origin.https.html", {} ] ], - "encrypted-media/drm-mp4-waiting-for-a-key.html": [ + "encrypted-media/drm-mp4-waiting-for-a-key.https.html": [ [ - "/encrypted-media/drm-mp4-waiting-for-a-key.html", + "/encrypted-media/drm-mp4-waiting-for-a-key.https.html", { "timeout": "long" } ] ], - "encrypted-media/drm-not-callable-after-createsession.html": [ + "encrypted-media/drm-not-callable-after-createsession.https.html": [ [ - "/encrypted-media/drm-not-callable-after-createsession.html", + "/encrypted-media/drm-not-callable-after-createsession.https.html", {} ] ], - "encrypted-media/drm-temporary-license-type.html": [ + "encrypted-media/drm-temporary-license-type.https.html": [ [ - "/encrypted-media/drm-temporary-license-type.html", + "/encrypted-media/drm-temporary-license-type.https.html", { "timeout": "long" } @@ -168951,9 +169035,9 @@ {} ] ], - "encrypted-media/idlharness.html": [ + "encrypted-media/idlharness.https.html": [ [ - "/encrypted-media/idlharness.html", + "/encrypted-media/idlharness.https.html", {} ] ], @@ -183035,39 +183119,39 @@ {} ] ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [ + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html", + "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html", {} ] ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [ + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html", + "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html", {} ] ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [ + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html", + "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html", {} ] ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [ + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html", + "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html", {} ] ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [ + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html", + "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html", {} ] ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [ + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html", + "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html", {} ] ], @@ -183083,15 +183167,15 @@ {} ] ], - "mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [ + "mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html", + "/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html", {} ] ], - "mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [ + "mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html", + "/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html", {} ] ], @@ -183101,39 +183185,39 @@ {} ] ], - "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [ + "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html", + "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html", {} ] ], - "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html": [ + "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html", + "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html", {} ] ], - "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [ + "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html", + "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html", {} ] ], - "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [ + "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html", + "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html", {} ] ], - "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html": [ + "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html", + "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html", {} ] ], - "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [ + "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html": [ [ - "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html", + "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html", {} ] ], @@ -206417,9 +206501,9 @@ {} ] ], - "web-animations/animation-model/animation-types/discrete-animation.html": [ + "web-animations/animation-model/animation-types/discrete.html": [ [ - "/web-animations/animation-model/animation-types/discrete-animation.html", + "/web-animations/animation-model/animation-types/discrete.html", {} ] ], @@ -206429,6 +206513,12 @@ {} ] ], + "web-animations/animation-model/animation-types/visibility.html": [ + [ + "/web-animations/animation-model/animation-types/visibility.html", + {} + ] + ], "web-animations/animation-model/combining-effects/effect-composition.html": [ [ "/web-animations/animation-model/combining-effects/effect-composition.html", @@ -206441,6 +206531,12 @@ {} ] ], + "web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html": [ + [ + "/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html", + {} + ] + ], "web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html": [ [ "/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html", @@ -206453,12 +206549,6 @@ {} ] ], - "web-animations/animation-model/keyframe-effects/effect-value-visibility.html": [ - [ - "/web-animations/animation-model/keyframe-effects/effect-value-visibility.html", - {} - ] - ], "web-animations/interfaces/Animatable/animate-no-browsing-context.html": [ [ "/web-animations/interfaces/Animatable/animate-no-browsing-context.html", @@ -206603,15 +206693,9 @@ {} ] ], - "web-animations/interfaces/AnimationEffectTiming/getAnimations.html": [ + "web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html": [ [ - "/web-animations/interfaces/AnimationEffectTiming/getAnimations.html", - {} - ] - ], - "web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html": [ - [ - "/web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html", + "/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html", {} ] ], @@ -206687,12 +206771,6 @@ {} ] ], - "web-animations/interfaces/KeyframeEffect/getComputedTiming.html": [ - [ - "/web-animations/interfaces/KeyframeEffect/getComputedTiming.html", - {} - ] - ], "web-animations/interfaces/KeyframeEffect/idlharness.html": [ [ "/web-animations/interfaces/KeyframeEffect/idlharness.html", @@ -206723,9 +206801,9 @@ {} ] ], - "web-animations/interfaces/KeyframeEffect/setTarget.html": [ + "web-animations/interfaces/KeyframeEffect/target.html": [ [ - "/web-animations/interfaces/KeyframeEffect/setTarget.html", + "/web-animations/interfaces/KeyframeEffect/target.html", {} ] ], @@ -223647,17 +223725,13 @@ "testharness" ], "WebCryptoAPI/idlharness-expected.txt": [ - "30f4bb482cf42bf763989902b9b93546332c3b3c", + "c57476b20323d852ad5f3d8487a26f0fbd4d918e", "support" ], "WebCryptoAPI/idlharness.html": [ "52b5381311cc0e2595d251273e054fa826de9765", "testharness" ], - "WebCryptoAPI/idlharness.https-expected.txt": [ - "b25c08025f11894649ab17de5becaf060acafd35", - "support" - ], "WebCryptoAPI/idlharness.https.html": [ "52b5381311cc0e2595d251273e054fa826de9765", "testharness" @@ -224455,7 +224529,7 @@ "testharness" ], "XMLHttpRequest/open-url-encoding-expected.txt": [ - "6c6570d2ac6bcd7fa4a4ca96a180e17627eec69a", + "14de3430e449a720beaf87466441749a61d8830d", "support" ], "XMLHttpRequest/open-url-encoding.htm": [ @@ -228754,17 +228828,29 @@ "ee1e63bbe0d74a932650c2c32ed26d7ca41e1c7d", "testharness" ], + "credential-management/federatedcredential-framed-get.sub.https.html": [ + "561636e62d50da2d14e50516c62cbaea1c5bb924", + "testharness" + ], "credential-management/idl.https.html": [ "e9a108beef51c52bbaaf2e53371aec57e69541c0", "testharness" ], - "css-contain/contain-style-counters-ref.html": [ - "295abc8d8c2490f3ff16566e49e9c77bf125461f", + "credential-management/passwordcredential-framed-get.sub.https.html": [ + "3ce3b0a2eaa10928aec1f32c9e3bcbe2af5fafba", + "testharness" + ], + "credential-management/support/echoing-nester.html": [ + "408bf741f31a9f69a2a9a50d93877f6a999cd9d9", "support" ], - "css-contain/contain-style-counters.html": [ - "056b3597f3555c803c74a8f6277a06626efd12ea", - "reftest" + "credential-management/support/federatedcredential-get.html": [ + "59b8314b8cb9044bfccf6a2a0e520a879fdf9f66", + "support" + ], + "credential-management/support/passwordcredential-get.html": [ + "cfed192579bfc57c2d266b9d4f30b669c3fccc0c", + "support" ], "css/.gitignore": [ "3f645ca3bf6a77220d48e3e07b6dc3e1653d883c", @@ -242547,7 +242633,7 @@ "visual" ], "css/README.md": [ - "17ea0b79a120fb33e736c10fa967cfd001f9b181", + "ab97108074d4c07c5333ff1148fe9a5e425484ca", "support" ], "css/build-css-testsuites.sh": [ @@ -246102,6 +246188,14 @@ "948230661efe702e443fe7e973d7c4995144588e", "testharness" ], + "css/css-contain/contain-style-counters-ref.html": [ + "295abc8d8c2490f3ff16566e49e9c77bf125461f", + "support" + ], + "css/css-contain/contain-style-counters.html": [ + "056b3597f3555c803c74a8f6277a06626efd12ea", + "reftest" + ], "css/css-display/OWNERS": [ "26cb5921a61ea01fff54a7e4b35e7929aa5a6cab", "support" @@ -246130,6 +246224,10 @@ "ab66821c508ced9656c769ff2647c7f9d57e4b15", "reftest" ], + "css/css-display/display-contents-before-after-003.html": [ + "2c15d52fdcb0ef9de97beb7bff8fdd2a733f1d67", + "reftest" + ], "css/css-display/display-contents-block-001.html": [ "c26501b3a2da59dd1615a492d580e26e401da485", "reftest" @@ -246210,6 +246308,14 @@ "4fe143c25be9ecc08e58428f0c588f72c5cb8a3f", "reftest" ], + "css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html": [ + "af3b16fc8d05be3ab16d65a2f668233668a23583", + "support" + ], + "css/css-display/display-contents-dynamic-pseudo-insertion-001.html": [ + "221fb940d34860f62541ad53bb4b3834f3552577", + "reftest" + ], "css/css-display/display-contents-dynamic-table-001-inline.html": [ "5c105a711c083e61eefc4121c707d3ca2ffda3ec", "reftest" @@ -249934,6 +250040,14 @@ "de45acb63b567c5318b014ebab07098ca8c317b6", "reftest" ], + "css/css-fonts/font-variant-alternates-parsing-expected.txt": [ + "7a592e3a2f0cabaca863e95a8a1da18db1b480b8", + "support" + ], + "css/css-fonts/font-variant-alternates-parsing.html": [ + "5a15ca070dbddff6e28995c13db825244080fc25", + "testharness" + ], "css/css-fonts/font-variant-caps-01-ref.html": [ "dfc1e1995e9841ecfa8889ad25c6ef7a6a2d992f", "support" @@ -280091,11 +280205,11 @@ "testharness" ], "css/cssom/getComputedStyle-pseudo-expected.txt": [ - "f084d668a87ac11a0631fd50eb07217999992c74", + "8778d3b4a4bf5ff7b6e80a369528a50d2b47a9a1", "support" ], "css/cssom/getComputedStyle-pseudo.html": [ - "98f4a9a445621ae328a317402bdfb62c83de6b43", + "a2033405d6852cdeb4c3b8cf628f7c1d8f7cd1aa", "testharness" ], "css/cssom/historical.html": [ @@ -288866,191 +288980,191 @@ "4cdfcbd7d8243d6cb61dbeb73535cc561cc44766", "support" ], - "encrypted-media/clearkey-check-initdata-type.html": [ + "encrypted-media/clearkey-check-initdata-type.https.html": [ "edf050cdd617f5e1b9de04c3c77b2bb92b22a74f", "testharness" ], - "encrypted-media/clearkey-events-session-closed-event.html": [ + "encrypted-media/clearkey-events-session-closed-event.https.html": [ "df3718598584c8ac59be5d4b8ef85083e1e9ddcf", "testharness" ], - "encrypted-media/clearkey-events.html": [ + "encrypted-media/clearkey-events.https.html": [ "75c9904a525c4bb1ec495445660671ad5279f0a7", "testharness" ], - "encrypted-media/clearkey-generate-request-disallowed-input.html": [ + "encrypted-media/clearkey-generate-request-disallowed-input.https.html": [ "4426b44b87b52f17c8dff8027c61e3e39ac9e321", "testharness" ], - "encrypted-media/clearkey-invalid-license.html": [ + "encrypted-media/clearkey-invalid-license.https.html": [ "4fa0b5af9fce24e3f6abd932f2352ff4deb0f90f", "testharness" ], - "encrypted-media/clearkey-keystatuses-multiple-sessions.html": [ + "encrypted-media/clearkey-keystatuses-multiple-sessions.https.html": [ "aa361d04cfd38448bde43102860cb67c92378217", "testharness" ], - "encrypted-media/clearkey-keystatuses.html": [ + "encrypted-media/clearkey-keystatuses.https.html": [ "0da720e35be9913eff72ca4686d09447a8b0baae", "testharness" ], - "encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html": [ + "encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html": [ "31f911c3795711d1ff315baa035adbf9b82063b1", "testharness" ], - "encrypted-media/clearkey-mp4-playback-persistent-license-events.html": [ + "encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html": [ "77839f9d494a4ab72d19ab6d0f8c87600af78b83", "testharness" ], - "encrypted-media/clearkey-mp4-playback-persistent-license.html": [ + "encrypted-media/clearkey-mp4-playback-persistent-license.https.html": [ "82870fec532dfca22931614b62104d82f361948d", "testharness" ], - "encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html": [ + "encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html": [ "778a2d9d48f080b497359f18f7fe5505fc1a95a6", "testharness" ], - "encrypted-media/clearkey-mp4-playback-persistent-usage-record.html": [ + "encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html": [ "0ba42cf14754d5f5a72b1bed5c4e584d98367a13", "testharness" ], - "encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html": [ + "encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html": [ "fe1e7fd17a30f52936fb533e6553f09cbd9ce954", "testharness" ], - "encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html": [ + "encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html": [ "c82925a064bcd0eadb81a6b92a7fac35e76b35d8", "testharness" ], - "encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html": [ + "encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html": [ "3db3dfc846598a30218f740201e48ca6112f4d93", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html": [ "bade72126b9a42409ef2b1901b84aef7778b2eac", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html": [ "df277e779299caa92f7b82d2f8a51eb71a77eba1", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html": [ "8a2c68dafa32348f869ffeffaa8952123f4cb539", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-events.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-events.https.html": [ "8a4fdf2f0ae55cc9b4c137ada2c2721701a34e89", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html": [ "4252b999d028092862f18663a9ab8fe654439b8c", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html": [ "3d6d572a21f7380bd69fa52360dfbde527241440", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-multikey.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html": [ "8649ac8a23f45a0c8f34a31e3df58b8da786f68e", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-multisession.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html": [ "6e12223723edeb54e41128c1c86b9ae04091b448", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html": [ "0acbe39273cd4dfffc0580ae821b4f880323ef35", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html": [ "a416bd41c485e4f0e48ad870cc4ddad40d194509", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html": [ "a1051de265005fd205ab71ccc863ab429fe1b11e", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html": [ "c2356c4d5fc4be3d6b096f1cc9ca026b9d2989d1", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-two-videos.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html": [ "03954e9c2ddc20b37d858bdcb29d4fb197fc2f9a", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html": [ + "encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html": [ "2b195d087a715ed3b5d9803dded1b9d25c135789", "testharness" ], - "encrypted-media/clearkey-mp4-playback-temporary.html": [ + "encrypted-media/clearkey-mp4-playback-temporary.https.html": [ "2d2c14ac3e4147c2ce54665ac84c102906df15bc", "testharness" ], - "encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html": [ + "encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html": [ "ccd431ebc1212c33953f273a4a1665124da3b2f1", "testharness" ], - "encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html": [ + "encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html": [ "ea428a6fd609c5f3243b0cb89171f23484475c60", "testharness" ], - "encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html": [ "09b19346bccb01a63e3b1a509f0104f99a5723a8", "testharness" ], - "encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html": [ "cba1dca366654371b3b2d046c3505d10235b9e8d", "testharness" ], - "encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html": [ "6c3e3659fe5fd7ae063371f13e6a284cdcc06019", "testharness" ], - "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html": [ "9edb8596073d8dd0a34db9398e0966f29d73b425", "testharness" ], - "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html": [ "9e177ca8da585c867cf3b9c8f08afaa914c203bc", "testharness" ], - "encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html": [ + "encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html": [ "161653f14df5c4c883922a253457cc3e711dc997", "testharness" ], - "encrypted-media/clearkey-mp4-setmediakeys.html": [ + "encrypted-media/clearkey-mp4-setmediakeys.https.html": [ "a3a30ffbe0c946b3dd3f50f46c819c94aefcb470", "testharness" ], - "encrypted-media/clearkey-mp4-syntax-mediakeys.html": [ + "encrypted-media/clearkey-mp4-syntax-mediakeys.https.html": [ "d8cd90ecb4094e6866796edb40e50a0bfecf03d2", "testharness" ], - "encrypted-media/clearkey-mp4-syntax-mediakeysession.html": [ + "encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html": [ "040914ccaba738cfc9a97f4c4a839883cde8bcef", "testharness" ], - "encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html": [ + "encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html": [ "b7115f8d8bbd2da5f4b2635f66909fd4e4252747", "testharness" ], - "encrypted-media/clearkey-mp4-unique-origin.html": [ + "encrypted-media/clearkey-mp4-unique-origin.https.html": [ "26d01bff637c6321f4d12aa8a50722f3e30b3b40", "testharness" ], - "encrypted-media/clearkey-mp4-update-disallowed-input.html": [ + "encrypted-media/clearkey-mp4-update-disallowed-input.https.html": [ "7396b7380f22845aaf66da67be5ce19a93a90259", "testharness" ], - "encrypted-media/clearkey-mp4-waiting-for-a-key.html": [ + "encrypted-media/clearkey-mp4-waiting-for-a-key.https.html": [ "349ae6a759b23051e83c7dbbf96c4938d2482429", "testharness" ], - "encrypted-media/clearkey-not-callable-after-createsession.html": [ + "encrypted-media/clearkey-not-callable-after-createsession.https.html": [ "2f0a96c7fa9927f95ff1634cb08457ef305d4e7f", "testharness" ], - "encrypted-media/clearkey-update-non-ascii-input.html": [ + "encrypted-media/clearkey-update-non-ascii-input.https.html": [ "93e7cb2f9fa4e5d0696e3f9e02e88c2adf41fbd9", "testharness" ], @@ -289098,199 +289212,199 @@ "0fb6d575a357dd5fdc4544a55cb8ef4e25f0f449", "support" ], - "encrypted-media/drm-check-initdata-type.html": [ + "encrypted-media/drm-check-initdata-type.https.html": [ "ae0f79ae94465890ded3e3a6bfd60f320b23ad44", "testharness" ], - "encrypted-media/drm-events-session-closed-event.html": [ + "encrypted-media/drm-events-session-closed-event.https.html": [ "b5061558a5860289fd81ab806179fc3bdde06d22", "testharness" ], - "encrypted-media/drm-events.html": [ + "encrypted-media/drm-events.https.html": [ "aca0d0624fc6cf16eac0c86723aa680c2fa8006c", "testharness" ], - "encrypted-media/drm-expiration.html": [ + "encrypted-media/drm-expiration.https.html": [ "d071ca11388305cd8296f1183b1c5f3e3804c468", "testharness" ], - "encrypted-media/drm-generate-request-disallowed-input.html": [ + "encrypted-media/drm-generate-request-disallowed-input.https.html": [ "4d5e1c39a7dec2ae4c2f8706d54696d456180ed4", "testharness" ], - "encrypted-media/drm-invalid-license.html": [ + "encrypted-media/drm-invalid-license.https.html": [ "74afa97cd841401cd4b8ed18ea83499f410d17bf", "testharness" ], - "encrypted-media/drm-keystatuses-multiple-sessions.html": [ + "encrypted-media/drm-keystatuses-multiple-sessions.https.html": [ "2ec2ce19b8f1f52ee33450f89cec546d4524403e", "testharness" ], - "encrypted-media/drm-keystatuses.html": [ + "encrypted-media/drm-keystatuses.https.html": [ "777476ed7189626623fe6046e67a6d9359ce5783", "testharness" ], - "encrypted-media/drm-mp4-onencrypted.html": [ + "encrypted-media/drm-mp4-onencrypted.https.html": [ "400ea20b213af0d1b5f415744ec3d48534fce7e7", "testharness" ], - "encrypted-media/drm-mp4-playback-destroy-persistent-license.html": [ + "encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html": [ "b1bd421f82ee615d7a994256363d7daf1990f74e", "testharness" ], - "encrypted-media/drm-mp4-playback-persistent-license-events.html": [ + "encrypted-media/drm-mp4-playback-persistent-license-events.https.html": [ "5f2bf9c9cc1404be0f7c948c436a60483d662600", "testharness" ], - "encrypted-media/drm-mp4-playback-persistent-license.html": [ + "encrypted-media/drm-mp4-playback-persistent-license.https.html": [ "421ab3065f65e9cd88ba318a50bbbf84beef4966", "testharness" ], - "encrypted-media/drm-mp4-playback-persistent-usage-record-events.html": [ + "encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html": [ "508a4e777bd6c050028e76b8ebfb8da36e92f613", "testharness" ], - "encrypted-media/drm-mp4-playback-persistent-usage-record.html": [ + "encrypted-media/drm-mp4-playback-persistent-usage-record.https.html": [ "bac4592aa70ea169e6424d571293dcbf10be9eda", "testharness" ], - "encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html": [ + "encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html": [ "4be63a706c6af42c22a2d8eef94d227ca7af5cbb", "testharness" ], - "encrypted-media/drm-mp4-playback-retrieve-persistent-license.html": [ + "encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html": [ "3c605d585e46f34b9cea3cda2caae72e93bb00ef", "testharness" ], - "encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html": [ + "encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html": [ "8783b5efb95e95f5547acb29fb5950ebdde498e8", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html": [ + "encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html": [ "b1825fbafaa400cd8672ca34d36e30ded98d2b9b", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html": [ + "encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html": [ "db48c1ef4d91eaec6787c6c95e2dbb9faaf41965", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html": [ + "encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html": [ "5f23926a2ed2692b3fee95ef613e02668b919106", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-events.html": [ + "encrypted-media/drm-mp4-playback-temporary-events.https.html": [ "b893677d6c12f1b05f564dbbf1c43362da9ff6e7", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-expired.html": [ + "encrypted-media/drm-mp4-playback-temporary-expired.https.html": [ "cb4a33c98fed06054e4acce8a65a0dc8e6d1b4c3", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html": [ + "encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html": [ "320fb185d71e4f76cc865c63ff99f508d994465c", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html": [ + "encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html": [ "e4616953865577bd08ba566f0487c5e7a793d291", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-multikey.html": [ + "encrypted-media/drm-mp4-playback-temporary-multikey.https.html": [ "b7fd2a7ec0adc0b5be46242af0df83fab9dda5af", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-multisession.html": [ + "encrypted-media/drm-mp4-playback-temporary-multisession.https.html": [ "15a0b2950e25edcbff1b5b2e3d5807cb91d9e531", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html": [ + "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html": [ "09ba82feb85a73a1aa275164bfacd722f893075e", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html": [ + "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html": [ "d6ba354d7c2c02775827fa1f896af5b4916a77fd", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html": [ + "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html": [ "eae1bd6fba6709856bf43e9506abf2128f79ced7", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html": [ + "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html": [ "52facbc71172a79ab84416ae249780abfa48e970", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-two-videos.html": [ + "encrypted-media/drm-mp4-playback-temporary-two-videos.https.html": [ "a8fb7e599f125c4ea3f665a9cc8be0b91a3df076", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary-waitingforkey.html": [ + "encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html": [ "82d4432235e45c61cca1fa371dcb83dfe99a3060", "testharness" ], - "encrypted-media/drm-mp4-playback-temporary.html": [ + "encrypted-media/drm-mp4-playback-temporary.https.html": [ "14db930f09d86257aea6d653805b600da772726d", "testharness" ], - "encrypted-media/drm-mp4-requestmediakeysystemaccess.html": [ + "encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html": [ "2119ef0d22c25f8f3704732c6908ed2c5ac87e03", "testharness" ], - "encrypted-media/drm-mp4-reset-src-after-setmediakeys.html": [ + "encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html": [ "f3c6f6c10c7dc7938a9c90309aecc7643de3603a", "testharness" ], - "encrypted-media/drm-mp4-setmediakeys-again-after-playback.html": [ + "encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html": [ "d0799ef8ecf2198e97af8863828cf00455ccb643", "testharness" ], - "encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html": [ + "encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html": [ "60cf1a74b1aa5eff4c817d78a6bf133588e9c9ec", "testharness" ], - "encrypted-media/drm-mp4-setmediakeys-at-same-time.html": [ + "encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html": [ "a475403fef02570be2815cc02572fc2afe7b6d55", "testharness" ], - "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html": [ + "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html": [ "0011bd6d2447f59d19844cb27c0248846dfc4a56", "testharness" ], - "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html": [ + "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html": [ "6b60d7967a71112f476700d8ce3570b40cf51f08", "testharness" ], - "encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html": [ + "encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html": [ "2681878f110de7841fba6123ceb785820b596474", "testharness" ], - "encrypted-media/drm-mp4-setmediakeys.html": [ + "encrypted-media/drm-mp4-setmediakeys.https.html": [ "c66a641651351e92d47a6e149618117eeabfaff8", "testharness" ], - "encrypted-media/drm-mp4-syntax-mediakeys.html": [ + "encrypted-media/drm-mp4-syntax-mediakeys.https.html": [ "ab9db64508f7181eef25898cfceacdc351c299ef", "testharness" ], - "encrypted-media/drm-mp4-syntax-mediakeysession.html": [ + "encrypted-media/drm-mp4-syntax-mediakeysession.https.html": [ "51fcd7900ced0c4c50ef1b1fc8f50e69db021f55", "testharness" ], - "encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html": [ + "encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html": [ "3718f25e30379509466117157f5ab7af705458a3", "testharness" ], - "encrypted-media/drm-mp4-unique-origin.html": [ + "encrypted-media/drm-mp4-unique-origin.https.html": [ "f1a76980453dfce0c9e27774c2763295c2f8eb11", "testharness" ], - "encrypted-media/drm-mp4-waiting-for-a-key.html": [ + "encrypted-media/drm-mp4-waiting-for-a-key.https.html": [ "52e710dd8e9f90e0a1a2a922bba042ea6e53a439", "testharness" ], - "encrypted-media/drm-not-callable-after-createsession.html": [ + "encrypted-media/drm-not-callable-after-createsession.https.html": [ "82c70015b32240304ab410b4a57791bb3d8c45e5", "testharness" ], - "encrypted-media/drm-temporary-license-type.html": [ + "encrypted-media/drm-temporary-license-type.https.html": [ "85124d35b37f14c143e1fcb2965f131a8f2a3391", "testharness" ], @@ -289298,7 +289412,7 @@ "d7627e2017ae8ac994a6bc8a2a00df0dd2332c59", "testharness" ], - "encrypted-media/idlharness.html": [ + "encrypted-media/idlharness.https.html": [ "69456d56a5485b04465f4f6ee4abc80388703fd9", "testharness" ], @@ -289515,7 +289629,7 @@ "support" ], "encrypted-media/scripts/unique-origin.js": [ - "781b4c4e6e48f3941e52856e3d5486b7b4a1a7a9", + "ddbdf009d11297918fe66e0b58498bd863be8333", "support" ], "encrypted-media/scripts/update-disallowed-input.js": [ @@ -293618,6 +293732,10 @@ "ba143e41121916fba5522d5e1dca29d04ab5f4ce", "support" ], + "html/browsers/sandboxing/noscript-iframe.html": [ + "cfa4043bfda350a0906cd94f3c9c9a3578e72575", + "support" + ], "html/browsers/sandboxing/sandbox-allow-same-origin.html": [ "3aa5996022d6ca80f085981190811efc490aa2e0", "testharness" @@ -293634,6 +293752,14 @@ "bbb480a9ca5139877fbab165f9356b2a67305a9c", "testharness" ], + "html/browsers/sandboxing/sandbox-parse-noscript-ref.html": [ + "4f185501effadf33e7d90e4c3990ec06ee936b43", + "support" + ], + "html/browsers/sandboxing/sandbox-parse-noscript.html": [ + "b6345b32377ff05bc7e5261b2fc14e8c875b2245", + "reftest" + ], "html/browsers/the-window-object/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -296179,7 +296305,7 @@ "testharness" ], "html/dom/reflection-tabular-expected.txt": [ - "5134550aa08accb16dd39790ce4c2c7c4380833c", + "c1016683c4e8915d11bc48c3ef4d7ff1930734ea", "support" ], "html/dom/reflection-tabular.html": [ @@ -311838,51 +311964,51 @@ "0e215b6c8f95aea079d53dca4e18e513c50ef9c0", "testharness" ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [ - "013eb078c215d37a8a52f266beaf9d3871fee401", + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html": [ + "1adabf38a9a679da7696f12d61ce50c4c75bec16", "testharness" ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [ "562977daf4fd9e09dc6153058804bc247cbe5354", "support" ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [ - "c10fe679c6cb2d69d5c6eaaa985d7d0aebf9e86a", + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [ + "41049d21e59f6b84f45096796e6b3d1e8ca25553", "testharness" ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers": [ "562977daf4fd9e09dc6153058804bc247cbe5354", "support" ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [ - "f07bd06527b7c4210c408a3593f5142f5ad47213", + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html": [ + "1d240c95fbfd0394b5458e1dae0394bdbf2bb4e1", "testharness" ], - "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [ "562977daf4fd9e09dc6153058804bc247cbe5354", "support" ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [ - "82b2035593f5408f7c3e53b640cca2f14214c606", + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html": [ + "4fb46872ee82b2d2355069dac1e56599b76e429f", "testharness" ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [ "562977daf4fd9e09dc6153058804bc247cbe5354", "support" ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [ - "0671d48855fd3fc222e13579c7b9cc10ec822898", + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [ + "2fa674993a988fa52ceffe2168536387997fa205", "testharness" ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers": [ "562977daf4fd9e09dc6153058804bc247cbe5354", "support" ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [ - "11a64084b74832bef705a46b1ef006b2e51d9bca", + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html": [ + "d6a6c64b7c530b04edd4ddf553ce5db363a5dfdd", "testharness" ], - "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ + "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [ "562977daf4fd9e09dc6153058804bc247cbe5354", "support" ], @@ -311902,40 +312028,40 @@ "562977daf4fd9e09dc6153058804bc247cbe5354", "support" ], - "mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [ - "bc56ec3ab4cc4e13527189fb43f36ebb27fa71c0", + "mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [ + "92ae912bff02681d40f206c2c9b11c1f9e8e192c", "testharness" ], - "mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [ - "ce3eb59ff993f2731c6af61806217caf7f6c3bbd", + "mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [ + "925c41353886a9abf6d96c4679635a91a74408db", "testharness" ], "mixed-content/link-prefetch-tag/meta-csp/same-host-https/top-level/no-redirect/allowed/allowed.https.html": [ "d1fea7e4b5e32b88797cdfaea1deaced699e3a80", "testharness" ], - "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [ - "baed43b2d575d296fea4d71452adea468bd02fc0", + "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html": [ + "b4c2ffb1cdc781e479582136d58b32d071efed26", "testharness" ], - "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html": [ - "8995bfa6816c2697dc449675768727abd5ecb266", + "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html": [ + "4a9452a6b58037094692565900cb3370c9f360f9", "testharness" ], - "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [ - "2b4266e2798cffa4df8085d85dc6192151125d13", + "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html": [ + "8f406983e28a48e47288eff8a120cec7ef603b67", "testharness" ], - "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [ - "34f1424d91ee6bbe1f0c6aa46e307104443f70bd", + "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html": [ + "842695f8ba053fd92766d65f27bcbc18442abbaa", "testharness" ], - "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html": [ - "62a276c360cb5540fe5decc2f388d4c667007a9b", + "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html": [ + "ee62d9adad2f7be55ed6274c6609aa03387bc8b1", "testharness" ], - "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [ - "b98e1a5a55b229fabc73ff520e93d1aae5786a84", + "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html": [ + "ced5cade402abdd4fd34b295a8c72dd674b2c6e7", "testharness" ], "mixed-content/link-prefetch-tag/no-opt-in/same-host-https/top-level/keep-scheme-redirect/allowed/allowed.https.html": [ @@ -312271,11 +312397,11 @@ "testharness" ], "mixed-content/spec.src.json": [ - "5edaa65af1b7d9f8941442dfec71e087d521c22e", + "1e46012ca5e1f0892e6c80572fa28c5358596c57", "support" ], "mixed-content/spec_json.js": [ - "212f362ad9a8828575eaca2b003a83a2276b3faa", + "f3b78849f97e307c39f81cf9cebb01b367c91b79", "support" ], "mixed-content/video-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [ @@ -329774,8 +329900,12 @@ "ee9f8140b492daf89cb715643ee40557f6ed904e", "testharness" ], + "service-workers/service-worker/resource-timing.https-expected.txt": [ + "dd950b3518f3dea3fc32c6e657ddfbeb99e5a6c1", + "support" + ], "service-workers/service-worker/resource-timing.https.html": [ - "9ca1caf0b8216eda8956be0d98eb7b5ab2d92a43", + "a835a0baeb4fcc0c44e6be28502f89308464acc5", "testharness" ], "service-workers/service-worker/resources/404.py": [ @@ -330526,8 +330656,8 @@ "c939271e717288203a5a298b95a7328100bd7c80", "support" ], - "service-workers/service-worker/resources/resource-timing-iframe.html": [ - "0fc85a13c536aad45a87fb073fdcebf371d4476d", + "service-workers/service-worker/resources/resource-timing-iframe.sub.html": [ + "c18c96a25dec48ae9d53359d4ca987ba857878a1", "support" ], "service-workers/service-worker/resources/resource-timing-worker.js": [ @@ -334227,39 +334357,43 @@ "support" ], "web-animations/README.md": [ - "d6cb0e31dc3cc6d83b5051cee38a0b8e118fd43f", + "5d6d7e4d3f727b70bd2197fb48e7a1bc04147c6a", "support" ], "web-animations/animation-model/animation-types/accumulation-per-property.html": [ - "316dd15ce99cbfb5754c236210ac9e04dfc0c7ba", + "19f8cefdfe60cf8501e7743967dc8fd4a006e4d6", "testharness" ], "web-animations/animation-model/animation-types/addition-per-property.html": [ - "24fae46b5f7b47e1d098fa446037bf9cc52e050e", + "a2abe830178357b19c6e220b14b5601b15d635f5", "testharness" ], - "web-animations/animation-model/animation-types/discrete-animation.html": [ - "5a63e9f2a369a476f56e3b792928083e83fab7ec", + "web-animations/animation-model/animation-types/discrete.html": [ + "a5fd7c9ae255d076f23b6819636f7f663589e44c", "testharness" ], "web-animations/animation-model/animation-types/interpolation-per-property.html": [ - "55100f7d505bc8cbc966ced0d1337ed78534a553", + "089b1ee060459aefe130031ddda42629edb28a7b", "testharness" ], "web-animations/animation-model/animation-types/property-list.js": [ - "6a1aafd6077aa656cfba4bba48f7ceca8344b810", + "b91b4a5d13d7aaf7cd5e953cba3d12e950110a08", "support" ], "web-animations/animation-model/animation-types/property-types.js": [ - "4b9e06fc9014110a711c590f866a149d31a9a6fa", + "ceaeb9c4a67019e68423f7cde888067c3384d756", "support" ], + "web-animations/animation-model/animation-types/visibility.html": [ + "da3370704ca9e83a1171a64320a240e3145fab2c", + "testharness" + ], "web-animations/animation-model/combining-effects/effect-composition-expected.txt": [ "100ef6fbb1b1462925d50afb9b813517cff5131b", "support" ], "web-animations/animation-model/combining-effects/effect-composition.html": [ - "8ac06085132d822e908d48de4c1109b66323f19f", + "9c043a059c26a2c1449663d4fc881e8568a53206", "testharness" ], "web-animations/animation-model/keyframe-effects/effect-value-context-expected.txt": [ @@ -334267,23 +334401,27 @@ "support" ], "web-animations/animation-model/keyframe-effects/effect-value-context.html": [ - "10d9ee521240475a1729c2facfcea8b50342614e", + "87689f24cd6bdae1a8296fcc9b96fc51455c17c9", + "testharness" + ], + "web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation-expected.txt": [ + "8122d93f30e7f51fbfd089a3404b576d2636685b", + "support" + ], + "web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html": [ + "3034db6e48e55ad5075f17f5812ee4c396606ff8", "testharness" ], "web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html": [ - "a79db70a385ad767263f285c9401b66611087e42", + "5725dc5f7d0c2b532d22add77c0f82780dd252dd", "testharness" ], "web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html": [ - "a0f0dc7d2f4833a68c6f8a5f908c498b05c6b22e", - "testharness" - ], - "web-animations/animation-model/keyframe-effects/effect-value-visibility.html": [ - "b01c7c5145c183fdca80dec4ca1966b0f72a7003", + "68f8181b4592b25195e202facf646d9035040db5", "testharness" ], "web-animations/interfaces/Animatable/animate-expected.txt": [ - "f2e65323cc15eb82b823b690c9d0c17af75f40a5", + "be0d48b5b82c87caa9f965d204937b7d2f9e20d3", "support" ], "web-animations/interfaces/Animatable/animate-no-browsing-context-expected.txt": [ @@ -334291,19 +334429,19 @@ "support" ], "web-animations/interfaces/Animatable/animate-no-browsing-context.html": [ - "3a5538db728127970721e20e3b2eaea59fac3afc", + "284d173b6875923ddd894d2ac7498cd07311c001", "testharness" ], "web-animations/interfaces/Animatable/animate.html": [ - "99868d179c69091aa63631a27d98df4ee957a746", + "b4e51f3b2fe045dfa87b0e67437b625721804bca", "testharness" ], "web-animations/interfaces/Animatable/getAnimations.html": [ - "92503fce725fcffce188df9c8e1da9d9ca281213", + "dfeebb2790874de472ebb56c7fabe81b05db77f9", "testharness" ], "web-animations/interfaces/Animation/cancel.html": [ - "a28589129c6a2665295695f786b7beb2dd887fb3", + "7fa9434d51ba76b0f097cf0f5701b49e8724caaa", "testharness" ], "web-animations/interfaces/Animation/constructor-expected.txt": [ @@ -334311,15 +334449,15 @@ "support" ], "web-animations/interfaces/Animation/constructor.html": [ - "20604949fc295efc398e297b9e4f755a116f0fbb", + "c9d4da018b279b9fb7262139f6fb12634deac858", "testharness" ], "web-animations/interfaces/Animation/effect.html": [ - "9e2551bfd9238ff99f30eabbd119a05fcf6dbeb9", + "bab0a2227994194c58e23edb3080d519ea453d1e", "testharness" ], "web-animations/interfaces/Animation/finish.html": [ - "61ab2a2d822c25f2311756baeaaa98b44c3b3a62", + "629203bd3888631c616093315f2c3f1219486131", "testharness" ], "web-animations/interfaces/Animation/finished-expected.txt": [ @@ -334327,11 +334465,11 @@ "support" ], "web-animations/interfaces/Animation/finished.html": [ - "5e3d8fa48b2737202f6bd7c2e21589e904982a6f", + "680fe7552b0cf5a246e11cd63540b343f56608bf", "testharness" ], "web-animations/interfaces/Animation/id.html": [ - "395dad4a877ef4af20649d6bcfece102a22b3059", + "2e40d20a3b221a4b99e776bdeb951c7cba173f57", "testharness" ], "web-animations/interfaces/Animation/idlharness-expected.txt": [ @@ -334343,71 +334481,67 @@ "testharness" ], "web-animations/interfaces/Animation/oncancel.html": [ - "0477d2fef7fc64bbc969b29d4ba542574c4c3706", + "03c14c90672fa8f3a4c909ceb698a1bc421208db", "testharness" ], "web-animations/interfaces/Animation/onfinish.html": [ - "43ecf628f6e7a6088ad4cc25e3a6468957049ae0", + "597362b0108c367511c26b9561158b6f32c63f54", "testharness" ], "web-animations/interfaces/Animation/pause.html": [ - "8cadcbc313fd6ed171298529c71d555cc2c43a2d", + "bdbd4d3e88a0b41f3685ba14fa049d507d7dbd59", "testharness" ], "web-animations/interfaces/Animation/play.html": [ - "0c8069de75d1c15f1d8167b433ad4c7e51f424db", + "b375f449a4c75b02d0d746e44e2ca6ff9646819b", "testharness" ], "web-animations/interfaces/Animation/playState.html": [ - "9dda649e8c668b4afbc6e683e2d853622650796a", + "69da0c5be9b5734fc45ccf0d5c855dbae8b71a8a", "testharness" ], "web-animations/interfaces/Animation/playbackRate.html": [ - "d0c73c24ed6ea6d43565ef81a3b200336a2133cd", + "a5463d070f7273e54099bc94d8a7b31b5366665d", "testharness" ], "web-animations/interfaces/Animation/ready.html": [ - "b23b76881f4d38c07710d0e59c1f6c8569de9060", + "b8c58b9d8b77ff5c10ba0f400df37e07e5bd8087", "testharness" ], "web-animations/interfaces/Animation/startTime.html": [ - "284d55c141e4a93def32393577888ffc215a8b15", + "4bafbec148bbd4b9a797fd96f482e1ed4cceabfe", "testharness" ], "web-animations/interfaces/AnimationEffectTiming/delay.html": [ - "ee2d870fae13e77e500e7067b89dbb79bd2d209a", + "17150915a06587117c3b521a212b70861afe0a04", "testharness" ], "web-animations/interfaces/AnimationEffectTiming/direction.html": [ - "87eb8b9a7b954e0eb77566eefb3034cd6235296f", + "e34557857943fb90b4f28ff52441961c8076c4d8", "testharness" ], "web-animations/interfaces/AnimationEffectTiming/duration.html": [ - "54858f64784c74a3d112e559fb765a1dbb9ba279", + "06e68349701e4dc74c79c93ce580e8f529f11594", "testharness" ], "web-animations/interfaces/AnimationEffectTiming/easing.html": [ - "a4b8b1c715795d5e66c0e32c2415a2e8fb587147", + "749c648048db7846ece84bdfe1de8bb4eeb01ff7", "testharness" ], "web-animations/interfaces/AnimationEffectTiming/endDelay.html": [ - "fde46c549f70439c80e3990ebf6897d6d6dfb76e", + "c274f5ce7947e82f8bfdbdc9638a018be0d1906c", "testharness" ], "web-animations/interfaces/AnimationEffectTiming/fill.html": [ - "adc56d3ce3595154045cb87e1cb89fe7ce2096ba", + "8d774222c824f838f846c64379b8751eeb5a57d9", "testharness" ], - "web-animations/interfaces/AnimationEffectTiming/getAnimations.html": [ - "83175d02d1a09e91189fab2ccb19f8e0f242cb2a", - "testharness" - ], - "web-animations/interfaces/AnimationEffectTiming/getComputedStyle-expected.txt": [ - "93b97ed38211b2df7a4ea4afb24376e83f6c39ce", + "web-animations/interfaces/AnimationEffectTiming/getComputedTiming-expected.txt": [ + "ed031dc998b9bbd6d9483fa69f213f5a2233e46d", "support" ], - "web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html": [ - "28819fe9fe3d38ae6d4aa2b4db4f58e8a16f0588", + "web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html": [ + "d88434cb8b9ec4e4e3821e85dca4f4f34ec4402d", "testharness" ], "web-animations/interfaces/AnimationEffectTiming/idlharness.html": [ @@ -334415,11 +334549,11 @@ "testharness" ], "web-animations/interfaces/AnimationEffectTiming/iterationStart.html": [ - "05e327706937df8319e3a8c655ee743a15902ecd", + "6a31d545493852f33b2e6a54a18ea87f16c5247a", "testharness" ], "web-animations/interfaces/AnimationEffectTiming/iterations.html": [ - "9a6eae75862dec36b7839dc68edc31891a651284", + "f04176dc8a55a7dc309b72d093b78704109258e2", "testharness" ], "web-animations/interfaces/AnimationPlaybackEvent/constructor-expected.txt": [ @@ -334427,7 +334561,7 @@ "support" ], "web-animations/interfaces/AnimationPlaybackEvent/constructor.html": [ - "1bc5f4dda96078a08a4b06ab0f6bf7b10e0acce3", + "f66a3e998c900cd169c2104b7c0e7ea51271330c", "testharness" ], "web-animations/interfaces/AnimationPlaybackEvent/idlharness.html": [ @@ -334439,15 +334573,15 @@ "support" ], "web-animations/interfaces/Document/getAnimations.html": [ - "bd39d7f28dd03ba22a32ce09226dc263180254eb", + "c07b9871f08df1183a3a33d08cc68b2d256cd493", "testharness" ], "web-animations/interfaces/Document/timeline.html": [ - "65303d138e6b9afdb5b28117ef8e1c6ba35903e3", + "ab6b19fc85e278418bd58308d6ffd5863a1dc940", "testharness" ], "web-animations/interfaces/DocumentTimeline/constructor.html": [ - "3a626b145f4eb77e816b9020f6fc67630088a00b", + "9f683dd88b148222d43736c464320bb51e9533d0", "testharness" ], "web-animations/interfaces/DocumentTimeline/idlharness.html": [ @@ -334459,15 +334593,15 @@ "support" ], "web-animations/interfaces/KeyframeEffect/composite.html": [ - "2580086b2da9b29d1645484c5ad4e59636a370e5", + "0ee4b5505a670202f0e25d483a83a10e3c8a5094", "testharness" ], "web-animations/interfaces/KeyframeEffect/constructor-expected.txt": [ - "9cc22f3feaca7e591174fb228a7aeef4555d37fd", + "dd4bc628a21326f8c407df6eae0fbd361de5b97b", "support" ], "web-animations/interfaces/KeyframeEffect/constructor.html": [ - "54a4185fd23ac4b3afe010157d4b8b766483d8f6", + "e3cb7dfa2239e29214b5a1f88cebc5d35b16ec18", "testharness" ], "web-animations/interfaces/KeyframeEffect/copy-constructor-expected.txt": [ @@ -334475,15 +334609,7 @@ "support" ], "web-animations/interfaces/KeyframeEffect/copy-constructor.html": [ - "65047bfed537a69659851a9fcdd7fb2ba5c4f790", - "testharness" - ], - "web-animations/interfaces/KeyframeEffect/getComputedTiming-expected.txt": [ - "1eefa393e34c57502712cf27837feb04767c695e", - "support" - ], - "web-animations/interfaces/KeyframeEffect/getComputedTiming.html": [ - "c9dcf7c17010e5495007e000b33aeb4dc89f92b7", + "16c69e33c1022f643a961f6f2d85c59010164e9d", "testharness" ], "web-animations/interfaces/KeyframeEffect/idlharness-expected.txt": [ @@ -334495,11 +334621,11 @@ "testharness" ], "web-animations/interfaces/KeyframeEffect/iterationComposite-expected.txt": [ - "fa0a97ae224fe540b9887552c9ed403d7828f5f8", + "d9e7a12d92d6b9fe2ed4067e45a345a7324dac5e", "support" ], "web-animations/interfaces/KeyframeEffect/iterationComposite.html": [ - "2ed50cdb27335345015d8b13c64ef86c67048757", + "8aac788873a17d840cef91ba3441451b28f40f8b", "testharness" ], "web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001-expected.txt": [ @@ -334507,7 +334633,7 @@ "support" ], "web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html": [ - "83e58d986208b6cbc51e4124a2b17269a26e0520", + "78e32ec633628ef4f236751aa159ac05b14dda2c", "testharness" ], "web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002-expected.txt": [ @@ -334515,7 +334641,7 @@ "support" ], "web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html": [ - "38b350320a08cc2a9ae4449944eea427bfbe6f9d", + "ea466d345a41c600835d278aaccf531cf3a3cc75", "testharness" ], "web-animations/interfaces/KeyframeEffect/setKeyframes-expected.txt": [ @@ -334523,23 +334649,23 @@ "support" ], "web-animations/interfaces/KeyframeEffect/setKeyframes.html": [ - "477e983fcef02361c305918d10a67f2909cfa561", + "7e4965fd6cee3406b008b093d2e2873b6eea98e9", "testharness" ], - "web-animations/interfaces/KeyframeEffect/setTarget-expected.txt": [ + "web-animations/interfaces/KeyframeEffect/target-expected.txt": [ "91c873ec0a32dddd793b479d2e0e91e59cf39ef2", "support" ], - "web-animations/interfaces/KeyframeEffect/setTarget.html": [ - "8c75e6605a134c96e261e5383414b7e15b32d121", + "web-animations/interfaces/KeyframeEffect/target.html": [ + "2e08f003caf998de2267b77416813e58a52f06e3", "testharness" ], "web-animations/resources/easing-tests.js": [ - "c255d606d00296b4c6957435773a20a9d8d0bd0b", + "77f747cef865fd5eba6ea621881706f801c812c0", "support" ], "web-animations/resources/effect-tests.js": [ - "5cdc52caac1d1db2249155e91591c983a746102e", + "b35091529e7fc13348ee95ffdf194735bfb7c151", "support" ], "web-animations/resources/keyframe-tests.js": [ @@ -334555,11 +334681,11 @@ "support" ], "web-animations/testcommon.js": [ - "d057ad66c4561ef32f83770e4948f2019da89d48", + "9556f3b9f2e52f0998519e0572154aca0568ff25", "support" ], "web-animations/timing-model/animation-effects/active-time.html": [ - "42eb1a23e89ae60ccd0a3664a9a583df1eb30d49", + "e1c65069bf437b2a18835fd7339e4a0758b86186", "testharness" ], "web-animations/timing-model/animation-effects/current-iteration-expected.txt": [ @@ -334567,7 +334693,7 @@ "support" ], "web-animations/timing-model/animation-effects/current-iteration.html": [ - "a83e4dbd359774de7e6dbea4ae0b8d28d16d62e5", + "02094259ab6ce032aaef9a1381422d6c25c8055f", "testharness" ], "web-animations/timing-model/animation-effects/local-time-expected.txt": [ @@ -334575,7 +334701,7 @@ "support" ], "web-animations/timing-model/animation-effects/local-time.html": [ - "4b24cf2374a690395398f8caed9d340667dd0a9d", + "482cd69507100d58a41a3b17a3de9198e99165c7", "testharness" ], "web-animations/timing-model/animation-effects/phases-and-states-expected.txt": [ @@ -334583,7 +334709,7 @@ "support" ], "web-animations/timing-model/animation-effects/phases-and-states.html": [ - "ce3652c8a6fdd8a6019fd665bca28ed725bacd71", + "73ef4e64d766319376fdf6bd64ef55273f97d80c", "testharness" ], "web-animations/timing-model/animation-effects/simple-iteration-progress-expected.txt": [ @@ -334591,7 +334717,7 @@ "support" ], "web-animations/timing-model/animation-effects/simple-iteration-progress.html": [ - "521524358dabafea8e78c36829f9cd7d4115400a", + "89207d5638cdf20647d3dc7300f564f6ab9eda0d", "testharness" ], "web-animations/timing-model/animations/canceling-an-animation-expected.txt": [ @@ -334599,35 +334725,35 @@ "support" ], "web-animations/timing-model/animations/canceling-an-animation.html": [ - "079bc0e0f7ea60b94999ed1b4f92c1aa2fc2c7bb", + "c4cc62ac4a9e826496eb7be12d33551861f25064", "testharness" ], "web-animations/timing-model/animations/current-time.html": [ - "b1ea8e490cbfb69fd71b91a90e7e2d9ce99f42d3", + "0c9341f917a56205e9f7e33cc809f87c5c7f831e", "testharness" ], "web-animations/timing-model/animations/finishing-an-animation.html": [ - "570ec579c6118866b888b1384e21977c9cfb0ec0", + "f662027f020312c17ec9385542583ba675c38e82", "testharness" ], "web-animations/timing-model/animations/pausing-an-animation.html": [ - "a000d8f86fa62b90ec7a60c289066aaaa1758377", + "9106dcffe7b9816cd9bda222714520f640b0afdc", "testharness" ], "web-animations/timing-model/animations/playing-an-animation.html": [ - "2b4f51977d43f9bf90c066bfcc57728ae096b6e9", + "700443f8c4a5573f0fa01932e3a6c143ccc7620f", "testharness" ], "web-animations/timing-model/animations/reversing-an-animation-expected.txt": [ - "39c6b6c585d1c2259c8da236ec094d97cb8f932c", + "a5dbf9c9ab43c46a8aa2f15da03b4647e901d540", "support" ], "web-animations/timing-model/animations/reversing-an-animation.html": [ - "2b5631893d0d0846e5e57097ce4ae54dfa8a03e3", + "01975f70399d3934db8247f3a8ddfb09afd26b78", "testharness" ], "web-animations/timing-model/animations/set-the-animation-start-time.html": [ - "84afa495b1a4c467e27b1394f6449a18c58ed98d", + "9ead33eebc9f697b71c7a7d5b22cf6302d29837b", "testharness" ], "web-animations/timing-model/animations/set-the-target-effect-of-an-animation-expected.txt": [ @@ -334635,7 +334761,7 @@ "support" ], "web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html": [ - "840be610db4bce6d6fd1c22710e494a75ee95eba", + "dec02f25748e0abdad129469469cbf0e5539941a", "testharness" ], "web-animations/timing-model/animations/set-the-timeline-of-an-animation-expected.txt": [ @@ -334643,11 +334769,11 @@ "support" ], "web-animations/timing-model/animations/set-the-timeline-of-an-animation.html": [ - "6e8e029f813046c3da69b4ff0c9d03d2a56b38a4", + "fd0c7192901ae0030268457c2dfa7554783608b3", "testharness" ], "web-animations/timing-model/animations/updating-the-finished-state.html": [ - "266f1b793aa74a59486081f3ba8f6cbb482e714b", + "74caa48024c826fcd2747d206fc2e9bebf9828be", "testharness" ], "web-animations/timing-model/time-transformations/transformed-progress-expected.txt": [ @@ -334655,15 +334781,15 @@ "support" ], "web-animations/timing-model/time-transformations/transformed-progress.html": [ - "66e2277c77e4bd7b2d8981a725fb5083a8f5e0f6", + "84bd0be22d6e250cfefd118d306b2790f67471cc", "testharness" ], "web-animations/timing-model/timelines/document-timelines.html": [ - "cfa1e9ab84cb4901068e6305f69d8987cdda69cd", + "bbe8a5565d88c5697170eba02be6858589383fdf", "testharness" ], "web-animations/timing-model/timelines/timelines.html": [ - "6f0a9efcce6d5438996b650c022d6723dbccf58b", + "e0164509c7fd07ec9deec024d5d7e370c5e0d705", "testharness" ], "web-nfc/OWNERS": [ @@ -335583,11 +335709,11 @@ "support" ], "webrtc/RTCCertificate-expected.txt": [ - "8bf66d4902ec025a7ea863623d87f08cbe1de33b", + "a75326b479a0e19e66a494d7309998f6d63059ae", "support" ], "webrtc/RTCCertificate.html": [ - "95e54d7fb8b37b9f1719137a4245cb25263336e0", + "cc1191d16707c4a5126291850414800cacb76199", "testharness" ], "webrtc/RTCConfiguration-bundlePolicy-expected.txt": [ @@ -335635,7 +335761,7 @@ "testharness" ], "webrtc/RTCDTMFSender-helper.js": [ - "0c2e8862deffeec71ac925642647bb9ee4ad70ff", + "205469a5d95d35c0cdc091afafa49ecaccac7e2d", "support" ], "webrtc/RTCDTMFSender-insertDTMF.https-expected.txt": [ @@ -337631,7 +337757,7 @@ "testharness" ], "webvtt/api/VTTCue/getCueAsHTML-expected.txt": [ - "1cdbca640a03c93f0f2ec6a8be5816e1e2fc49d2", + "29f8cdb8ffdbf0fd697f31e6af4cc9d5386f8bd7", "support" ], "webvtt/api/VTTCue/getCueAsHTML.html": [ @@ -337790,10 +337916,6 @@ "cd575cb3a8507339cfded6676279e66fa136ced1", "testharness" ], - "webvtt/parsing/cue-text-parsing/tests/timestamps-expected.txt": [ - "881e04a7bf9d3e63ab18e91416f58e8e9d0e385d", - "support" - ], "webvtt/parsing/cue-text-parsing/tests/timestamps.html": [ "5c693a298ad24030e14fb96d60dbacd8e989d6b4", "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/WebCryptoAPI/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/WebCryptoAPI/idlharness-expected.txt index 780894b..94f49e5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/WebCryptoAPI/idlharness-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/WebCryptoAPI/idlharness-expected.txt
@@ -1,21 +1,21 @@ This is a testharness.js-based test. -Found 64 tests; 33 PASS, 31 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 64 tests; 36 PASS, 28 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Crypto interface: existence and properties of interface object PASS Crypto interface object length PASS Crypto interface object name -FAIL Crypto interface: existence and properties of interface prototype object assert_equals: class string of Crypto.prototype expected "[object CryptoPrototype]" but got "[object Crypto]" +PASS Crypto interface: existence and properties of interface prototype object PASS Crypto interface: existence and properties of interface prototype object's "constructor" property FAIL Crypto interface: attribute subtle assert_true: The prototype object must have a property "subtle" expected true got false PASS Crypto interface: operation getRandomValues(ArrayBufferView) PASS Crypto must be primary interface of crypto PASS Stringification of crypto -FAIL Crypto interface: crypto must inherit property "subtle" with the proper type (0) assert_inherits: property "subtle" not found in prototype chain -PASS Crypto interface: crypto must inherit property "getRandomValues" with the proper type (1) +FAIL Crypto interface: crypto must inherit property "subtle" with the proper type assert_inherits: property "subtle" not found in prototype chain +PASS Crypto interface: crypto must inherit property "getRandomValues(ArrayBufferView)" with the proper type PASS Crypto interface: calling getRandomValues(ArrayBufferView) on crypto with too few arguments must throw TypeError PASS CryptoKey interface: existence and properties of interface object PASS CryptoKey interface object length PASS CryptoKey interface object name -FAIL CryptoKey interface: existence and properties of interface prototype object assert_equals: class string of CryptoKey.prototype expected "[object CryptoKeyPrototype]" but got "[object CryptoKey]" +PASS CryptoKey interface: existence and properties of interface prototype object PASS CryptoKey interface: existence and properties of interface prototype object's "constructor" property PASS CryptoKey interface: attribute type PASS CryptoKey interface: attribute extractable @@ -24,45 +24,45 @@ PASS SubtleCrypto interface: existence and properties of interface object PASS SubtleCrypto interface object length PASS SubtleCrypto interface object name -FAIL SubtleCrypto interface: existence and properties of interface prototype object assert_equals: class string of SubtleCrypto.prototype expected "[object SubtleCryptoPrototype]" but got "[object SubtleCrypto]" +PASS SubtleCrypto interface: existence and properties of interface prototype object PASS SubtleCrypto interface: existence and properties of interface prototype object's "constructor" property -PASS SubtleCrypto interface: operation encrypt(AlgorithmIdentifier,CryptoKey,BufferSource) -PASS SubtleCrypto interface: operation decrypt(AlgorithmIdentifier,CryptoKey,BufferSource) -PASS SubtleCrypto interface: operation sign(AlgorithmIdentifier,CryptoKey,BufferSource) -PASS SubtleCrypto interface: operation verify(AlgorithmIdentifier,CryptoKey,BufferSource,BufferSource) -PASS SubtleCrypto interface: operation digest(AlgorithmIdentifier,BufferSource) -PASS SubtleCrypto interface: operation generateKey(AlgorithmIdentifier,boolean,[object Object]) -PASS SubtleCrypto interface: operation deriveKey(AlgorithmIdentifier,CryptoKey,AlgorithmIdentifier,boolean,[object Object]) -PASS SubtleCrypto interface: operation deriveBits(AlgorithmIdentifier,CryptoKey,unsigned long) -PASS SubtleCrypto interface: operation importKey(KeyFormat,[object Object],[object Object],AlgorithmIdentifier,boolean,[object Object]) -PASS SubtleCrypto interface: operation exportKey(KeyFormat,CryptoKey) -PASS SubtleCrypto interface: operation wrapKey(KeyFormat,CryptoKey,CryptoKey,AlgorithmIdentifier) -PASS SubtleCrypto interface: operation unwrapKey(KeyFormat,BufferSource,CryptoKey,AlgorithmIdentifier,AlgorithmIdentifier,boolean,[object Object]) +PASS SubtleCrypto interface: operation encrypt(AlgorithmIdentifier, CryptoKey, BufferSource) +PASS SubtleCrypto interface: operation decrypt(AlgorithmIdentifier, CryptoKey, BufferSource) +PASS SubtleCrypto interface: operation sign(AlgorithmIdentifier, CryptoKey, BufferSource) +PASS SubtleCrypto interface: operation verify(AlgorithmIdentifier, CryptoKey, BufferSource, BufferSource) +PASS SubtleCrypto interface: operation digest(AlgorithmIdentifier, BufferSource) +PASS SubtleCrypto interface: operation generateKey(AlgorithmIdentifier, boolean, [object Object]) +PASS SubtleCrypto interface: operation deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, [object Object]) +PASS SubtleCrypto interface: operation deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long) +PASS SubtleCrypto interface: operation importKey(KeyFormat, [object Object],[object Object], AlgorithmIdentifier, boolean, [object Object]) +PASS SubtleCrypto interface: operation exportKey(KeyFormat, CryptoKey) +PASS SubtleCrypto interface: operation wrapKey(KeyFormat, CryptoKey, CryptoKey, AlgorithmIdentifier) +PASS SubtleCrypto interface: operation unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, [object Object]) FAIL SubtleCrypto must be primary interface of crypto.subtle assert_equals: wrong typeof object expected "object" but got "undefined" FAIL Stringification of crypto.subtle assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "encrypt" with the proper type (0) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling encrypt(AlgorithmIdentifier,CryptoKey,BufferSource) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "decrypt" with the proper type (1) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling decrypt(AlgorithmIdentifier,CryptoKey,BufferSource) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "sign" with the proper type (2) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling sign(AlgorithmIdentifier,CryptoKey,BufferSource) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "verify" with the proper type (3) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling verify(AlgorithmIdentifier,CryptoKey,BufferSource,BufferSource) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "digest" with the proper type (4) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling digest(AlgorithmIdentifier,BufferSource) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "generateKey" with the proper type (5) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling generateKey(AlgorithmIdentifier,boolean,[object Object]) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "deriveKey" with the proper type (6) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling deriveKey(AlgorithmIdentifier,CryptoKey,AlgorithmIdentifier,boolean,[object Object]) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "deriveBits" with the proper type (7) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling deriveBits(AlgorithmIdentifier,CryptoKey,unsigned long) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "importKey" with the proper type (8) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling importKey(KeyFormat,[object Object],[object Object],AlgorithmIdentifier,boolean,[object Object]) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "exportKey" with the proper type (9) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling exportKey(KeyFormat,CryptoKey) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "wrapKey" with the proper type (10) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling wrapKey(KeyFormat,CryptoKey,CryptoKey,AlgorithmIdentifier) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: crypto.subtle must inherit property "unwrapKey" with the proper type (11) assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL SubtleCrypto interface: calling unwrapKey(KeyFormat,BufferSource,CryptoKey,AlgorithmIdentifier,AlgorithmIdentifier,boolean,[object Object]) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "encrypt(AlgorithmIdentifier, CryptoKey, BufferSource)" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling encrypt(AlgorithmIdentifier, CryptoKey, BufferSource) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "decrypt(AlgorithmIdentifier, CryptoKey, BufferSource)" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling decrypt(AlgorithmIdentifier, CryptoKey, BufferSource) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "sign(AlgorithmIdentifier, CryptoKey, BufferSource)" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling sign(AlgorithmIdentifier, CryptoKey, BufferSource) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "verify(AlgorithmIdentifier, CryptoKey, BufferSource, BufferSource)" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling verify(AlgorithmIdentifier, CryptoKey, BufferSource, BufferSource) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "digest(AlgorithmIdentifier, BufferSource)" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling digest(AlgorithmIdentifier, BufferSource) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "generateKey(AlgorithmIdentifier, boolean, [object Object])" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling generateKey(AlgorithmIdentifier, boolean, [object Object]) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, [object Object])" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, [object Object]) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long)" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "importKey(KeyFormat, [object Object],[object Object], AlgorithmIdentifier, boolean, [object Object])" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling importKey(KeyFormat, [object Object],[object Object], AlgorithmIdentifier, boolean, [object Object]) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "exportKey(KeyFormat, CryptoKey)" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling exportKey(KeyFormat, CryptoKey) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "wrapKey(KeyFormat, CryptoKey, CryptoKey, AlgorithmIdentifier)" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling wrapKey(KeyFormat, CryptoKey, CryptoKey, AlgorithmIdentifier) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: crypto.subtle must inherit property "unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, [object Object])" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +FAIL SubtleCrypto interface: calling unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, [object Object]) on crypto.subtle with too few arguments must throw TypeError assert_equals: wrong typeof object expected "object" but got "undefined" Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/WebCryptoAPI/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/WebCryptoAPI/idlharness.https-expected.txt deleted file mode 100644 index 298b948..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/WebCryptoAPI/idlharness.https-expected.txt +++ /dev/null
@@ -1,67 +0,0 @@ -This is a testharness.js-based test. -PASS Crypto interface: existence and properties of interface object -PASS Crypto interface object length -PASS Crypto interface object name -FAIL Crypto interface: existence and properties of interface prototype object assert_equals: class string of Crypto.prototype expected "[object CryptoPrototype]" but got "[object Crypto]" -PASS Crypto interface: existence and properties of interface prototype object's "constructor" property -PASS Crypto interface: attribute subtle -PASS Crypto interface: operation getRandomValues(ArrayBufferView) -PASS Crypto must be primary interface of crypto -PASS Stringification of crypto -PASS Crypto interface: crypto must inherit property "subtle" with the proper type (0) -PASS Crypto interface: crypto must inherit property "getRandomValues" with the proper type (1) -PASS Crypto interface: calling getRandomValues(ArrayBufferView) on crypto with too few arguments must throw TypeError -PASS CryptoKey interface: existence and properties of interface object -PASS CryptoKey interface object length -PASS CryptoKey interface object name -FAIL CryptoKey interface: existence and properties of interface prototype object assert_equals: class string of CryptoKey.prototype expected "[object CryptoKeyPrototype]" but got "[object CryptoKey]" -PASS CryptoKey interface: existence and properties of interface prototype object's "constructor" property -PASS CryptoKey interface: attribute type -PASS CryptoKey interface: attribute extractable -PASS CryptoKey interface: attribute algorithm -PASS CryptoKey interface: attribute usages -PASS SubtleCrypto interface: existence and properties of interface object -PASS SubtleCrypto interface object length -PASS SubtleCrypto interface object name -FAIL SubtleCrypto interface: existence and properties of interface prototype object assert_equals: class string of SubtleCrypto.prototype expected "[object SubtleCryptoPrototype]" but got "[object SubtleCrypto]" -PASS SubtleCrypto interface: existence and properties of interface prototype object's "constructor" property -PASS SubtleCrypto interface: operation encrypt(AlgorithmIdentifier,CryptoKey,BufferSource) -PASS SubtleCrypto interface: operation decrypt(AlgorithmIdentifier,CryptoKey,BufferSource) -PASS SubtleCrypto interface: operation sign(AlgorithmIdentifier,CryptoKey,BufferSource) -PASS SubtleCrypto interface: operation verify(AlgorithmIdentifier,CryptoKey,BufferSource,BufferSource) -PASS SubtleCrypto interface: operation digest(AlgorithmIdentifier,BufferSource) -PASS SubtleCrypto interface: operation generateKey(AlgorithmIdentifier,boolean,[object Object]) -PASS SubtleCrypto interface: operation deriveKey(AlgorithmIdentifier,CryptoKey,AlgorithmIdentifier,boolean,[object Object]) -PASS SubtleCrypto interface: operation deriveBits(AlgorithmIdentifier,CryptoKey,unsigned long) -PASS SubtleCrypto interface: operation importKey(KeyFormat,[object Object],[object Object],AlgorithmIdentifier,boolean,[object Object]) -PASS SubtleCrypto interface: operation exportKey(KeyFormat,CryptoKey) -PASS SubtleCrypto interface: operation wrapKey(KeyFormat,CryptoKey,CryptoKey,AlgorithmIdentifier) -PASS SubtleCrypto interface: operation unwrapKey(KeyFormat,BufferSource,CryptoKey,AlgorithmIdentifier,AlgorithmIdentifier,boolean,[object Object]) -PASS SubtleCrypto must be primary interface of crypto.subtle -PASS Stringification of crypto.subtle -PASS SubtleCrypto interface: crypto.subtle must inherit property "encrypt" with the proper type (0) -PASS SubtleCrypto interface: calling encrypt(AlgorithmIdentifier,CryptoKey,BufferSource) on crypto.subtle with too few arguments must throw TypeError -PASS SubtleCrypto interface: crypto.subtle must inherit property "decrypt" with the proper type (1) -PASS SubtleCrypto interface: calling decrypt(AlgorithmIdentifier,CryptoKey,BufferSource) on crypto.subtle with too few arguments must throw TypeError -PASS SubtleCrypto interface: crypto.subtle must inherit property "sign" with the proper type (2) -PASS SubtleCrypto interface: calling sign(AlgorithmIdentifier,CryptoKey,BufferSource) on crypto.subtle with too few arguments must throw TypeError -PASS SubtleCrypto interface: crypto.subtle must inherit property "verify" with the proper type (3) -PASS SubtleCrypto interface: calling verify(AlgorithmIdentifier,CryptoKey,BufferSource,BufferSource) on crypto.subtle with too few arguments must throw TypeError -PASS SubtleCrypto interface: crypto.subtle must inherit property "digest" with the proper type (4) -PASS SubtleCrypto interface: calling digest(AlgorithmIdentifier,BufferSource) on crypto.subtle with too few arguments must throw TypeError -PASS SubtleCrypto interface: crypto.subtle must inherit property "generateKey" with the proper type (5) -PASS SubtleCrypto interface: calling generateKey(AlgorithmIdentifier,boolean,[object Object]) on crypto.subtle with too few arguments must throw TypeError -PASS SubtleCrypto interface: crypto.subtle must inherit property "deriveKey" with the proper type (6) -PASS SubtleCrypto interface: calling deriveKey(AlgorithmIdentifier,CryptoKey,AlgorithmIdentifier,boolean,[object Object]) on crypto.subtle with too few arguments must throw TypeError -PASS SubtleCrypto interface: crypto.subtle must inherit property "deriveBits" with the proper type (7) -PASS SubtleCrypto interface: calling deriveBits(AlgorithmIdentifier,CryptoKey,unsigned long) on crypto.subtle with too few arguments must throw TypeError -PASS SubtleCrypto interface: crypto.subtle must inherit property "importKey" with the proper type (8) -PASS SubtleCrypto interface: calling importKey(KeyFormat,[object Object],[object Object],AlgorithmIdentifier,boolean,[object Object]) on crypto.subtle with too few arguments must throw TypeError -PASS SubtleCrypto interface: crypto.subtle must inherit property "exportKey" with the proper type (9) -PASS SubtleCrypto interface: calling exportKey(KeyFormat,CryptoKey) on crypto.subtle with too few arguments must throw TypeError -PASS SubtleCrypto interface: crypto.subtle must inherit property "wrapKey" with the proper type (10) -PASS SubtleCrypto interface: calling wrapKey(KeyFormat,CryptoKey,CryptoKey,AlgorithmIdentifier) on crypto.subtle with too few arguments must throw TypeError -PASS SubtleCrypto interface: crypto.subtle must inherit property "unwrapKey" with the proper type (11) -PASS SubtleCrypto interface: calling unwrapKey(KeyFormat,BufferSource,CryptoKey,AlgorithmIdentifier,AlgorithmIdentifier,boolean,[object Object]) on crypto.subtle with too few arguments must throw TypeError -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/credential-management/federatedcredential-framed-get.sub.https.html b/third_party/WebKit/LayoutTests/external/wpt/credential-management/federatedcredential-framed-get.sub.https.html new file mode 100644 index 0000000..08688ab --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/credential-management/federatedcredential-framed-get.sub.https.html
@@ -0,0 +1,74 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +function create_iframe_test(origin, expectation) { + return function (t) { + assert_true(!!navigator.credentials, "`navigator.credentials` is supported."); + window.addEventListener("load", _ => { + var iframe = document.createElement("iframe"); + iframe.src = origin + "/credential-management/support/federatedcredential-get.html"; + window.addEventListener("message", t.step_func(e => { + if (e.source == iframe.contentWindow) { + assert_equals(e.data.status, expectation); + if (expectation == "rejected") { + assert_equals(e.data.exception, "NotAllowedError"); + } else { + assert_equals(e.data.exception, null); + } + t.done(); + } + })); + document.body.appendChild(iframe); + }); + }; +} + +function create_nested_iframe_test(outerOrigin, innerOrigin, expectation) { + return function (t) { + assert_true(!!navigator.credentials, "`navigator.credentials` is supported."); + window.addEventListener("load", _ => { + var iframe = document.createElement("iframe"); + iframe.src = outerOrigin + "/credential-management/support/echoing-nester.html?origin=" + innerOrigin + "&file=federatedcredential-get.html"; + window.addEventListener("message", t.step_func(e => { + if (e.source == iframe.contentWindow) { + assert_equals(e.data.status, expectation); + if (expectation == "rejected") { + assert_equals(e.data.exception, "NotAllowedError"); + } else { + assert_equals(e.data.exception, null); + } + t.done(); + } + })); + document.body.appendChild(iframe); + }); + }; +} + +const SAME_ORIGIN = window.origin; +const CROSS_ORIGIN = "https://{{domains[élève]}}:{{ports[https][0]}}"; + +async_test( + create_iframe_test(SAME_ORIGIN, "resolved"), + "Same-origin IFrame does not throw."); +async_test( + create_iframe_test(CROSS_ORIGIN, "rejected"), + "Cross-origin IFrame throws 'NotAllowedError'."); + +async_test( + create_nested_iframe_test(SAME_ORIGIN, SAME_ORIGIN, "resolved"), + "Same-origin IFrame in same-origin IFrame does not throw."); + +async_test( + create_nested_iframe_test(SAME_ORIGIN, CROSS_ORIGIN, "rejected"), + "Same-origin IFrame in same-origin IFrame throws 'NotAllowedError'."); + +async_test( + create_nested_iframe_test(CROSS_ORIGIN, SAME_ORIGIN, "rejected"), + "Cross-origin IFrame in same-origin IFrame throws 'NotAllowedError'."); + +async_test( + create_nested_iframe_test(CROSS_ORIGIN, CROSS_ORIGIN, "rejected"), + "Cross-origin IFrame in same-cross-origin throws 'NotAllowedError'."); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/credential-management/passwordcredential-framed-get.sub.https.html b/third_party/WebKit/LayoutTests/external/wpt/credential-management/passwordcredential-framed-get.sub.https.html new file mode 100644 index 0000000..04bb16a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/credential-management/passwordcredential-framed-get.sub.https.html
@@ -0,0 +1,74 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +function create_iframe_test(origin, expectation) { + return function (t) { + assert_true(!!navigator.credentials, "`navigator.credentials` is supported."); + window.addEventListener("load", _ => { + var iframe = document.createElement("iframe"); + iframe.src = origin + "/credential-management/support/passwordcredential-get.html"; + window.addEventListener("message", t.step_func(e => { + if (e.source == iframe.contentWindow) { + assert_equals(e.data.status, expectation); + if (expectation == "rejected") { + assert_equals(e.data.exception, "NotAllowedError"); + } else { + assert_equals(e.data.exception, null); + } + t.done(); + } + })); + document.body.appendChild(iframe); + }); + }; +} + +function create_nested_iframe_test(outerOrigin, innerOrigin, expectation) { + return function (t) { + assert_true(!!navigator.credentials, "`navigator.credentials` is supported."); + window.addEventListener("load", _ => { + var iframe = document.createElement("iframe"); + iframe.src = outerOrigin + "/credential-management/support/echoing-nester.html?origin=" + innerOrigin + "&file=passwordcredential-get.html"; + window.addEventListener("message", t.step_func(e => { + if (e.source == iframe.contentWindow) { + assert_equals(e.data.status, expectation); + if (expectation == "rejected") { + assert_equals(e.data.exception, "NotAllowedError"); + } else { + assert_equals(e.data.exception, null); + } + t.done(); + } + })); + document.body.appendChild(iframe); + }); + }; +} + +const SAME_ORIGIN = window.origin; +const CROSS_ORIGIN = "https://{{domains[élève]}}:{{ports[https][0]}}"; + +async_test( + create_iframe_test(SAME_ORIGIN, "resolved"), + "Same-origin IFrame does not throw."); +async_test( + create_iframe_test(CROSS_ORIGIN, "rejected"), + "Cross-origin IFrame throws 'NotAllowedError'."); + +async_test( + create_nested_iframe_test(SAME_ORIGIN, SAME_ORIGIN, "resolved"), + "Same-origin IFrame in same-origin IFrame does not throw."); + +async_test( + create_nested_iframe_test(SAME_ORIGIN, CROSS_ORIGIN, "rejected"), + "Same-origin IFrame in same-origin IFrame throws."); + +async_test( + create_nested_iframe_test(CROSS_ORIGIN, SAME_ORIGIN, "rejected"), + "Cross-origin IFrame in same-origin IFrame throws."); + +async_test( + create_nested_iframe_test(CROSS_ORIGIN, CROSS_ORIGIN, "rejected"), + "Cross-origin IFrame in same-cross-origin throws."); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/credential-management/support/echoing-nester.html b/third_party/WebKit/LayoutTests/external/wpt/credential-management/support/echoing-nester.html new file mode 100644 index 0000000..d4f5899d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/credential-management/support/echoing-nester.html
@@ -0,0 +1,16 @@ +<body> + <script> + window.addEventListener('message', m => { + window.parent.postMessage(m.data, '*'); + }); + + var u = new URL(window.location.href); + var origin = u.searchParams.has('origin') ? u.searchParams.get('origin') : window.origin; + var file = u.searchParams.has('file') ? u.searchParams.get('file') : 'passwordcredential-get.html'; + + var url = origin + "/credential-management/support/" + file; + var i = document.createElement('iframe'); + i.src = url; + document.body.appendChild(i); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/credential-management/support/federatedcredential-get.html b/third_party/WebKit/LayoutTests/external/wpt/credential-management/support/federatedcredential-get.html new file mode 100644 index 0000000..476f3268 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/credential-management/support/federatedcredential-get.html
@@ -0,0 +1,17 @@ +<script> + navigator.credentials.get({ 'federated': { 'providers': ['https://example.com' ] } }) + .then(c => { + window.parent.postMessage({ + "status": "resolved", + "credential": c, + "exception": null + }, "*"); + }) + .catch(omg => { + window.parent.postMessage({ + "status": "rejected", + "credential": null, + "exception": omg.name + }, "*"); + }); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/credential-management/support/passwordcredential-get.html b/third_party/WebKit/LayoutTests/external/wpt/credential-management/support/passwordcredential-get.html new file mode 100644 index 0000000..0ec584d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/credential-management/support/passwordcredential-get.html
@@ -0,0 +1,17 @@ +<script> + navigator.credentials.get({ 'password': true }) + .then(c => { + window.parent.postMessage({ + "status": "resolved", + "credential": c, + "exception": null + }, "*"); + }) + .catch(omg => { + window.parent.postMessage({ + "status": "rejected", + "credential": null, + "exception": omg.name + }, "*"); + }); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/README.md b/third_party/WebKit/LayoutTests/external/wpt/css/README.md index 668ba28..4967f8cf 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/README.md +++ b/third_party/WebKit/LayoutTests/external/wpt/css/README.md
@@ -1,12 +1,14 @@ Introduction ------------ -This directory contains all testsuites for all CSS specifications still using -the [CSS test harness][harness]. These should primarily be considered legacy; -new testsuites should almost always be put at the top level without any level -suffix. +This directory contains testsuites for CSS WG specifications, including ones +that do not strictly speaking define CSS features, e.g., +[Geometry Interfaces](https://drafts.fxtf.org/geometry/). -As the test harness relies on the largely undocumented(!) old CSS build system, +The directories should be named like the specification's shortname, but without +any level suffix. + +As the test harness relies on the largely undocumented old CSS build system, this directory has a number of test requirements specific to it: * support files for a given test must live in an adjacent `support` directory; @@ -20,21 +22,14 @@ `css` directory. -Odd Directories ---------------- - -There are a few special directories that do not map to specifications: +vendor-imports/ Directory +------------------------- vendor-imports/ is a legacy directory where third parties historically imported their tests that originate and are maintained in an external repo. Files in this directory should never be modified in this repo, but should go through the vendor's process to be imported here. -work-in-progress/ is a legacy directory that contains all the work that was -once submitted to the repo, but was not yet ready for review. As pull requests -are now used, no new files should be added here. The subdirectories here are -named by test author or contributing organization. - Importing Old Branches ----------------------
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-display/display-contents-before-after-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-display/display-contents-before-after-003.html new file mode 100644 index 0000000..772ad44 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-display/display-contents-before-after-003.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Display: Generated ::before and ::after with display:contents inside flex</title> +<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-contents"> +<link rel="match" href="display-contents-pass-ref.html"> +<style> + .flex { display: inline-flex; flex-direction: column } + .flex::before { display: contents; content: "A" } + .flex::after { display: contents; content: "S" } +</style> +<!-- The before and after pseudo elements do not generate boxes due to + display:contents, so that their generated text content constitutes a + contiguous sequence of child text runs which means they end up in the same + flex item. --> +<p>You should see the word PASS below.</p> +P<div class="flex"></div>S
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html new file mode 100644 index 0000000..9c59597 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html
@@ -0,0 +1,5 @@ +<!doctype html> +<meta charset="utf-8"> +<title>CSS Test Reference</title> +<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> +PASS
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-display/display-contents-dynamic-pseudo-insertion-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-display/display-contents-dynamic-pseudo-insertion-001.html new file mode 100644 index 0000000..f35c3cc4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-display/display-contents-dynamic-pseudo-insertion-001.html
@@ -0,0 +1,26 @@ +<!doctype html> +<meta charset="utf-8"> +<title>CSS Test: Dynamic insertion on empty display: contents element with pseudo-elements</title> +<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> +<link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-contents"> +<link rel=match href="display-contents-dynamic-pseudo-insertion-001-ref.html"> +<style> +.contents { + display: contents; + border: 10px solid red; +} +.contents::before { + content: "A"; +} +.contents::after { + content: "SS"; +} +</style> +<div class="contents"></div> +<script> +document.body.offsetTop; +let span = document.createElement('span'); +span.innerHTML = "P"; +let contents = document.querySelector('.contents'); +contents.parentNode.insertBefore(span, contents); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-variant-alternates-parsing-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-variant-alternates-parsing-expected.txt new file mode 100644 index 0000000..4ced6b7c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-variant-alternates-parsing-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL CSS Test: font-variant-alternates: historical-forms; parses case-insensitively assert_equals: historical-forms is parsed case-insensitively expected (string) "historical-forms" but got (undefined) undefined +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-variant-alternates-parsing.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-variant-alternates-parsing.html new file mode 100644 index 0000000..a02bcedf --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-variant-alternates-parsing.html
@@ -0,0 +1,18 @@ +<!doctype html> +<meta charset="utf-8"> +<title>CSS Test: font-variant-alternates: historical-forms; parses case-insensitively</title> +<link rel="author" title="Emilio Cobos Álvarez" href="emilio@crisal.io"> +<link rel="help" href="https://drafts.csswg.org/css-fonts/#font-variant-alternates-prop"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + let div = document.createElement('div'); + div.style.fontVariantAlternates = "Historical-Forms"; + assert_equals( + getComputedStyle(div).fontVariantAlternates, + "historical-forms", + "historical-forms is parsed case-insensitively" + ); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-017.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-017.html new file mode 100644 index 0000000..2c005e1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-017.html
@@ -0,0 +1,85 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment along column axis of absolute positioned items with 'definite' grid positions</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#column-align"> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos-items"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#valdef-self-position-start"> +<meta name="assert" content="Absolute positioned grid items don't participate in Baseline Alignment, so the value 'baseline' behaves like 'start'."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + justify-items: start; +} +.grid.RTL { width: 400px; } +.grid > div { position: absolute; } +.grid > :nth-child(1) { background: green; } +.grid > :nth-child(2) { background: blue; } +.grid > :nth-child(3) { background: yellow; } +.grid > :nth-child(4) { background: red; } + +.RTL { direction: rtl; } +.verticalLR { writing-mode: vertical-lr; } +.verticalRL { writing-mode: vertical-rl; } + +.firstRowFirstColumn { + grid-row: 1 / 2; + grid-column: 1 / 2; + align-self: baseline; +} +.firstRowSecondColumn { + grid-row: 1 / 2; + grid-column: 2 / 3; + align-self: baseline; +} +.secondRowFirstColumn { + grid-row: 2 / 3; + grid-column: 1 / 2; + align-self: baseline; +} +.secondRowSecondColumn { + grid-row: 2 / 3; + grid-column: 2 / 3; + align-self: baseline; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="70" data-expected-height="30" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="150" data-expected-width="60" data-expected-height="40" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div> + +<div class="grid RTL"> + <div data-offset-x="340" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="230" data-offset-y="0" data-expected-width="70" data-expected-height="30" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div> + <div data-offset-x="340" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="240" data-offset-y="150" data-expected-width="60" data-expected-height="40" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div> + +<br><br> + +<div class="grid verticalLR"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="30" data-expected-height="70" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div> + <div data-offset-x="150" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="150" data-offset-y="100" data-expected-width="40" data-expected-height="60" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div> + +<div class="grid verticalRL"> + <div data-offset-x="240" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="220" data-offset-y="100" data-expected-width="30" data-expected-height="70" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div> + <div data-offset-x="90" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="60" data-offset-y="100" data-expected-width="40" data-expected-height="60" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-017.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-017.html new file mode 100644 index 0000000..6cc1e4e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-017.html
@@ -0,0 +1,85 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment along row axis of absolute positioned items with 'definite' grid positions</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#row-align"> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos-items"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#valdef-self-position-start"> +<meta name="assert" content="Absolute positioned grid items don't participate in Baseline Alignment, so the value 'baseline' behaves like 'start'."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + align-items: start; +} +.grid.RTL { width: 400px; } +.grid > div { position: absolute; } +.grid > :nth-child(1) { background: green; } +.grid > :nth-child(2) { background: blue; } +.grid > :nth-child(3) { background: yellow; } +.grid > :nth-child(4) { background: red; } + +.RTL { direction: rtl; } +.verticalLR { writing-mode: vertical-lr; } +.verticalRL { writing-mode: vertical-rl; } + +.firstRowFirstColumn { + grid-row: 1 / 2; + grid-column: 1 / 2; + justify-self: baseline; +} +.firstRowSecondColumn { + grid-row: 1 / 2; + grid-column: 2 / 3; + justify-self: baseline; +} +.secondRowFirstColumn { + grid-row: 2 / 3; + grid-column: 1 / 2; + justify-self: baseline; +} +.secondRowSecondColumn { + grid-row: 2 / 3; + grid-column: 2 / 3; + justify-self: baseline; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="70" data-expected-height="30" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="150" data-expected-width="60" data-expected-height="40" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div> + +<div class="grid RTL"> + <div data-offset-x="340" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="230" data-offset-y="0" data-expected-width="70" data-expected-height="30" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div> + <div data-offset-x="340" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="240" data-offset-y="150" data-expected-width="60" data-expected-height="40" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div> + +<br><br> + +<div class="grid verticalLR"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="30" data-expected-height="70" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div> + <div data-offset-x="150" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="150" data-offset-y="100" data-expected-width="40" data-expected-height="60" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div> + +<div class="grid verticalRL"> + <div data-offset-x="240" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="220" data-offset-y="100" data-expected-width="30" data-expected-height="70" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div> + <div data-offset-x="90" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="60" data-offset-y="100" data-expected-width="40" data-expected-height="60" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-pseudo-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-pseudo-expected.txt index 46d7161d..4b7c2b2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-pseudo-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-pseudo-expected.txt
@@ -5,5 +5,6 @@ PASS Resolution of pseudo-element styles in display: none elements PASS Item-based blockification of pseudo-elements FAIL Item-based blockification of nonexistent pseudo-elements assert_equals: Pseudo-styles of display: flex elements should get blockified expected "block" but got "inline" +PASS display: contents on pseudo-elements Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-pseudo.html b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-pseudo.html index fa358d6d..ec7a863 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-pseudo.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-pseudo.html
@@ -38,12 +38,19 @@ #flex-no-pseudo { display: flex; } +#contents-pseudos::before, +#contents-pseudos::after { + display: contents; + content: "foo"; + position: absolute; +} </style> <div id="test"> <div id="contents"></div> <div id="none"></div> <div id="flex"></div> <div id="flex-no-pseudo"></div> + <div id="contents-pseudos"></div> </div> <script> test(function() { @@ -91,4 +98,15 @@ "Pseudo-styles of display: flex elements should get blockified"); }); }, "Item-based blockification of nonexistent pseudo-elements"); +test(function() { + var contentsPseudos = document.getElementById('contents-pseudos'); + [":before", ":after"].forEach(function(pseudo) { + assert_equals(getComputedStyle(contentsPseudos, pseudo).display, "contents", + "display: contents in " + pseudo + " should get reflected on CSSOM"); + assert_equals(getComputedStyle(contentsPseudos, pseudo).width, "auto", + pseudo + " with display: contents should have no box"); + assert_equals(getComputedStyle(contentsPseudos, pseudo).position, "absolute", + "display: contents in " + pseudo + " should reflect other non-inherited properties in CSSOM"); + }); +}, "display: contents on pseudo-elements"); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-check-initdata-type.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-check-initdata-type.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-check-initdata-type.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-check-initdata-type.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-events-session-closed-event.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-events-session-closed-event.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-events-session-closed-event.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-events-session-closed-event.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-events.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-events.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-events.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-events.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-generate-request-disallowed-input.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-generate-request-disallowed-input.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-generate-request-disallowed-input.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-generate-request-disallowed-input.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-invalid-license.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-invalid-license.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-invalid-license.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-invalid-license.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-keystatuses-multiple-sessions.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-keystatuses-multiple-sessions.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-keystatuses.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-keystatuses.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-keystatuses.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-keystatuses.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license-events.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license-events.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-license.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-events.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-events.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-events.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-events.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multisession.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multisession.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-two-videos.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-two-videos.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-playback-temporary.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-setmediakeys.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeys.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeys.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysession.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysession.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-unique-origin.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-unique-origin.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-unique-origin.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-unique-origin.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-update-disallowed-input.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-update-disallowed-input.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-update-disallowed-input.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-update-disallowed-input.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-waiting-for-a-key.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-waiting-for-a-key.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-not-callable-after-createsession.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-not-callable-after-createsession.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-not-callable-after-createsession.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-not-callable-after-createsession.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-update-non-ascii-input.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-update-non-ascii-input.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-update-non-ascii-input.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/clearkey-update-non-ascii-input.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-check-initdata-type.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-check-initdata-type.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-check-initdata-type.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-check-initdata-type.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-events-session-closed-event.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-events-session-closed-event.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-events-session-closed-event.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-events-session-closed-event.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-events.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-events.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-events.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-events.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-expiration.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-expiration.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-expiration.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-expiration.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-generate-request-disallowed-input.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-generate-request-disallowed-input.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-generate-request-disallowed-input.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-generate-request-disallowed-input.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-invalid-license.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-invalid-license.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-invalid-license.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-invalid-license.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-keystatuses-multiple-sessions.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-keystatuses-multiple-sessions.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-keystatuses-multiple-sessions.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-keystatuses-multiple-sessions.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-keystatuses.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-keystatuses.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-keystatuses.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-keystatuses.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-onencrypted.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-onencrypted.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-onencrypted.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-onencrypted.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-destroy-persistent-license.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-destroy-persistent-license.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-license-events.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-license-events.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-license-events.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-license-events.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-license.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-license.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-license.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-license.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record-events.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record-events.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-license.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-license.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-events.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-events.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-events.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-events.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-expired.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-expired.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-expired.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-expired.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multikey.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multisession.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multisession.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multisession.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-multisession.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-two-videos.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-two-videos.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-waitingforkey.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-waitingforkey.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-playback-temporary.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-requestmediakeysystemaccess.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-requestmediakeysystemaccess.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-reset-src-after-setmediakeys.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-reset-src-after-setmediakeys.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-playback.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-playback.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-at-same-time.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-at-same-time.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-setmediakeys.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeys.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeys.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeys.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeys.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeysession.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeysession.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeysession.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeysession.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-unique-origin.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-unique-origin.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-unique-origin.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-unique-origin.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-waiting-for-a-key.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-waiting-for-a-key.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-waiting-for-a-key.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-mp4-waiting-for-a-key.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-not-callable-after-createsession.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-not-callable-after-createsession.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-not-callable-after-createsession.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-not-callable-after-createsession.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-temporary-license-type.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-temporary-license-type.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-temporary-license-type.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/drm-temporary-license-type.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/idlharness.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/encrypted-media/idlharness.html rename to third_party/WebKit/LayoutTests/external/wpt/encrypted-media/idlharness.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/scripts/unique-origin.js b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/scripts/unique-origin.js index ff1122d..015ea9d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/scripts/unique-origin.js +++ b/third_party/WebKit/LayoutTests/external/wpt/encrypted-media/scripts/unique-origin.js
@@ -10,7 +10,7 @@ resolve(iframe); }; iframe.sandbox = sandbox; - iframe.src = src; + iframe.srcdoc = src; document.documentElement.appendChild(iframe); }); } @@ -25,7 +25,7 @@ } promise_test(function (test) { - var script = 'data:text/html,' + + var script = '<script>' + ' window.onmessage = function(e) {' + ' navigator.requestMediaKeySystemAccess("' + config.keysystem + '", [{' + @@ -53,7 +53,7 @@ return access.createMediaKeys(); }).then(function (mediaKeys) { // Success, so now create the iframe and try there. - return load_iframe(script, 'allow-scripts'); + return load_iframe(script, 'allow-scripts allow-secure-context'); }).then(function (iframe) { iframe.contentWindow.postMessage({}, '*'); return wait_for_message();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/sandboxing/noscript-iframe.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/sandboxing/noscript-iframe.html new file mode 100644 index 0000000..677b5fc --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/sandboxing/noscript-iframe.html
@@ -0,0 +1,3 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<noscript>PASS</noscript>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/sandboxing/sandbox-parse-noscript-ref.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/sandboxing/sandbox-parse-noscript-ref.html new file mode 100644 index 0000000..9cf92768 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/sandboxing/sandbox-parse-noscript-ref.html
@@ -0,0 +1,6 @@ +<!doctype html> +<meta charset=utf-8> +<title>noscript parsing when sandbox disables scripting</title> +<iframe srcdoc="PASS" sandbox></iframe> +<iframe srcdoc="PASS" sandbox></iframe> +<iframe srcdoc="P<b>AS</b>S" sandbox></iframe>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/sandboxing/sandbox-parse-noscript.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/sandboxing/sandbox-parse-noscript.html new file mode 100644 index 0000000..bb7ced0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/sandboxing/sandbox-parse-noscript.html
@@ -0,0 +1,7 @@ +<!doctype html> +<meta charset=utf-8> +<title>noscript parsing when sandbox disables scripting</title> +<link rel=match href=/html/browsers/sandboxing/sandbox-parse-noscript-ref.html> +<iframe srcdoc="<noscript>PASS</noscript>" sandbox></iframe> +<iframe src="noscript-iframe.html" sandbox></iframe> +<iframe srcdoc="<noscript>P<b>AS</b>S</noscript>" sandbox></iframe>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-tabular-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-tabular-expected.txt index dd3ba71..508037da 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-tabular-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-tabular-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 4894 tests; 4882 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 4894 tests; 4884 PASS, 10 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS table.title: 32 tests PASS table.lang: 32 tests PASS table.dir: 62 tests @@ -113,9 +113,7 @@ PASS td.rowSpan: 3 tests NOTRUN test PASS td.rowSpan: 4 tests -PASS td.headers: 29 tests -NOTRUN test -PASS td.headers: 2 tests +PASS td.headers: 32 tests PASS td.scope: 72 tests PASS td.abbr: 32 tests PASS td.align: 32 tests @@ -145,9 +143,7 @@ PASS th.rowSpan: 3 tests NOTRUN test PASS th.rowSpan: 4 tests -PASS th.headers: 29 tests -NOTRUN test -PASS th.headers: 2 tests +PASS th.headers: 32 tests PASS th.scope: 72 tests PASS th.abbr: 32 tests PASS th.align: 32 tests
diff --git a/third_party/WebKit/LayoutTests/external/wpt/preload/modulepreload.html b/third_party/WebKit/LayoutTests/external/wpt/preload/modulepreload.html index 5b70bc8e..6a17050 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/preload/modulepreload.html +++ b/third_party/WebKit/LayoutTests/external/wpt/preload/modulepreload.html
@@ -104,5 +104,21 @@ return attachAndWaitForError(link); }, 'link rel=modulepreload with invalid as= value'); +promise_test(function(t) { + var link = document.createElement('link'); + link.rel = 'modulepreload'; + link.href = 'resources/module1.js?integrity-match'; + link.integrity = 'sha256-ZPBZ+J9CiHzZXaBBluSeCpjzuTUkT+rSWIdXUV3AtVo=' + return attachAndWaitForLoad(link); +}, 'link rel=modulepreload with integrity match'); + +promise_test(function(t) { + var link = document.createElement('link'); + link.rel = 'modulepreload'; + link.href = 'resources/module1.js?integrity-doesnotmatch'; + link.integrity = 'sha384-doesnotmatch' + return attachAndWaitForError(link); +}, 'link rel=modulepreload with integrity mismatch'); + </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resource-timing.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resource-timing.https-expected.txt new file mode 100644 index 0000000..f127d26 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resource-timing.https-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +FAIL Controlled resource loads assert_unreached: unexpected rejection: Cannot read property 'workerStart' of undefined Reached unreachable code +PASS Non-controlled resource loads +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resource-timing.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resource-timing.https.html index c38bfc9..da898e2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resource-timing.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resource-timing.https.html
@@ -8,13 +8,25 @@ return get_host_info()['HTTPS_ORIGIN'] + base_path() + path; } -function verify(performance, resource, description) { - var entry = performance.getEntriesByName(resourceUrl(resource))[0]; +function crossOriginUrl(path) { + return get_host_info()['HTTPS_REMOTE_ORIGIN'] + base_path() + path; +} + +function verify(performance, resource, mode, description) { + var url = mode === 'cross-origin' ? crossOriginUrl(resource) + : resourceUrl(resource); + var entryList = performance.getEntries(); + var entry = performance.getEntriesByName(url)[0]; assert_greater_than(entry.workerStart, 0, description); assert_greater_than_equal(entry.workerStart, entry.startTime, description); assert_less_than_equal(entry.workerStart, entry.fetchStart, description); - assert_greater_than_equal(entry.responseStart, entry.fetchStart, description); - assert_greater_than_equal(entry.responseEnd, entry.responseStart, description); + if (mode === 'cross-origin') { + assert_equals(entry.responseStart, 0, description); + assert_greater_than_equal(entry.responseEnd, entry.fetchStart, description); + } else { + assert_greater_than_equal(entry.responseStart, entry.fetchStart, description); + assert_greater_than_equal(entry.responseEnd, entry.responseStart, description); + } assert_greater_than(entry.responseEnd, entry.fetchStart, description); assert_greater_than(entry.duration, 0, description); if (resource.indexOf('redirect.py') != -1) { @@ -27,7 +39,7 @@ async_test(function(t) { var worker_url = 'resources/resource-timing-worker.js'; - var scope = 'resources/resource-timing-iframe.html'; + var scope = 'resources/resource-timing-iframe.sub.html'; var registration; service_worker_unregister_and_register(t, worker_url, scope) @@ -40,10 +52,20 @@ }) .then(function(frame) { var performance = frame.contentWindow.performance; - verify(performance, 'resources/dummy.js', 'Generated response'); - verify(performance, 'resources/empty.js', 'Network fallback'); + verify(performance, 'resources/dummy.js', 'same-origin', + 'Generated response'); + verify(performance, 'resources/empty.js', 'same-origin', + 'Network fallback'); verify(performance, 'resources/redirect.py?Redirect=empty.js', - 'Redirect'); + 'same-origin', 'Redirect'); + verify(performance, 'resources/missing.jpg', 'same-origin', + 'Network fallback image'); + + // Test that worker start is available on cross-origin no-cors + // subresources. + verify(performance, 'resources/missing.jpg', 'cross-origin', + 'Network fallback cross-origin image'); + frame.remove(); return registration.unregister(); })
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/resource-timing-iframe.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/resource-timing-iframe.html deleted file mode 100644 index 2af679369..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/resource-timing-iframe.html +++ /dev/null
@@ -1,4 +0,0 @@ -<!DOCTYPE html> -<script src="empty.js"></script> -<script src="dummy.js"></script> -<script src="redirect.py?Redirect=empty.js"></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/resource-timing-iframe.sub.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/resource-timing-iframe.sub.html new file mode 100644 index 0000000..c9308ea --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/resource-timing-iframe.sub.html
@@ -0,0 +1,6 @@ +<!DOCTYPE html> +<script src="empty.js"></script> +<script src="dummy.js"></script> +<script src="redirect.py?Redirect=empty.js"></script> +<img src="missing.jpg"> +<img src="https://{{domains[www1]}}:{{ports[https][0]}}/service-workers/service-worker/resources/missing.jpg">
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/README.md b/third_party/WebKit/LayoutTests/external/wpt/web-animations/README.md index abc9338c..1bc3512 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/README.md +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/README.md
@@ -51,24 +51,24 @@ e.g. ```javascript - test(function(t) { + test(t => { const animation = createDiv(t).animate(null); assert_class_string(animation, 'Animation', 'Returned object is an Animation'); }, 'Element.animate() creates an Animation object'); ``` ```javascript - test(function(t) { - assert_throws({ name: 'TypeError' }, function() { + test(t => { + assert_throws({ name: 'TypeError' }, () => { createDiv(t).animate(null, -1); }); }, 'Setting a negative duration throws a TypeError'); ``` ```javascript - promise_test(function(t) { + promise_test(t => { const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); - return animation.ready.then(function() { + return animation.ready.then(() => { assert_greater_than(animation.startTime, 0, 'startTime when running'); }); }, 'startTime is resolved when running');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property.html index c4439dd..3a7201e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property.html
@@ -1,6 +1,6 @@ <!doctype html> <meta charset=utf-8> -<title>Tests for animation type of accumulation</title> +<title>Accumulation for each property</title> <link rel="help" href="https://w3c.github.io/web-animations/#animation-types"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -17,16 +17,15 @@ <script> 'use strict'; -for (var property in gCSSProperties) { +for (const property in gCSSProperties) { if (!isSupported(property)) { continue; } - var animationTypes = gCSSProperties[property].types; - var setupFunction = gCSSProperties[property].setup; - animationTypes.forEach(function(animationType) { - var typeObject; - var animationTypeString; + const setupFunction = gCSSProperties[property].setup; + for (const animationType of gCSSProperties[property].types) { + let typeObject; + let animationTypeString; if (typeof animationType === 'string') { typeObject = types[animationType]; animationTypeString = animationType; @@ -39,13 +38,13 @@ // First, test that the animation type object has 'testAccumulation'. // We use test() function here so that we can continue the remainder tests // even if this test fails. - test(function(t) { + test(t => { assert_own_property(typeObject, 'testAccumulation', animationTypeString + ' should have testAccumulation property'); assert_equals(typeof typeObject.testAccumulation, 'function', 'testAccumulation method should be a function'); - }, property + ' (type: ' + animationTypeString + - ') has testAccumulation function'); + }, `${property} (type: ${animationTypeString}) has testAccumulation` + + ' function'); if (typeObject.testAccumulation && typeof typeObject.testAccumulation === 'function') { @@ -53,6 +52,6 @@ setupFunction, animationType.options); } - }); + } } </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/addition-per-property.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/addition-per-property.html index 97f7220..c66efd3 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/addition-per-property.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/addition-per-property.html
@@ -1,6 +1,6 @@ <!doctype html> <meta charset=utf-8> -<title>Tests for animation type of addition</title> +<title>Addition for each property</title> <link rel="help" href="https://w3c.github.io/web-animations/#animation-types"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -17,16 +17,15 @@ <script> 'use strict'; -for (var property in gCSSProperties) { +for (const property in gCSSProperties) { if (!isSupported(property)) { continue; } - var animationTypes = gCSSProperties[property].types; - var setupFunction = gCSSProperties[property].setup; - animationTypes.forEach(function(animationType) { - var typeObject; - var animationTypeString; + const setupFunction = gCSSProperties[property].setup; + for (const animationType of gCSSProperties[property].types) { + let typeObject; + let animationTypeString; if (typeof animationType === 'string') { typeObject = types[animationType]; animationTypeString = animationType; @@ -39,13 +38,13 @@ // First, test that the animation type object has 'testAddition'. // We use test() function here so that we can continue the remainder tests // even if this test fails. - test(function(t) { + test(t => { assert_own_property(typeObject, 'testAddition', animationTypeString + ' should have testAddition property'); assert_equals(typeof typeObject.testAddition, 'function', 'testAddition method should be a function'); - }, property + ' (type: ' + animationTypeString + - ') has testAddition function'); + }, `${property} (type: ${animationTypeString}) has testAddition` + + ' function'); if (typeObject.testAddition && typeof typeObject.testAddition === 'function') { @@ -53,6 +52,6 @@ setupFunction, animationType.options); } - }); + } } </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/discrete-animation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/discrete.html similarity index 77% rename from third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/discrete-animation.html rename to third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/discrete.html index 2b7e6a5..add3429 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/discrete-animation.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/discrete.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Tests for discrete animation</title> -<link rel="help" href="http://w3c.github.io/web-animations/#animatable-as-string-section"> +<title>Discrete animation type</title> +<link rel="help" href="https://w3c.github.io/web-animations/#discrete-animation-type"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="../../testcommon.js"></script> @@ -10,11 +10,11 @@ <script> 'use strict'; -test(function(t) { - var div = createDiv(t); +test(t => { + const div = createDiv(t); - var anim = div.animate({ fontStyle: [ 'normal', 'italic' ] }, - { duration: 1000, fill: 'forwards' }); + const anim = div.animate({ fontStyle: [ 'normal', 'italic' ] }, + { duration: 1000, fill: 'forwards' }); assert_equals(getComputedStyle(div).fontStyle, 'normal', 'Animation produces \'from\' value at start of interval'); @@ -31,12 +31,12 @@ 'Animation produces \'to\' value during forwards fill'); }, 'Test animating discrete values'); -test(function(t) { - var div = createDiv(t); - var originalHeight = getComputedStyle(div).height; +test(t => { + const div = createDiv(t); + const originalHeight = getComputedStyle(div).height; - var anim = div.animate({ height: [ 'auto', '200px' ] }, - { duration: 1000, fill: 'forwards' }); + const anim = div.animate({ height: [ 'auto', '200px' ] }, + { duration: 1000, fill: 'forwards' }); assert_equals(getComputedStyle(div).height, originalHeight, 'Animation produces \'from\' value at start of interval'); @@ -53,15 +53,15 @@ 'Animation produces \'to\' value during forwards fill'); }, 'Test discrete animation is used when interpolation fails'); -test(function(t) { - var div = createDiv(t); - var originalHeight = getComputedStyle(div).height; +test(t => { + const div = createDiv(t); + const originalHeight = getComputedStyle(div).height; - var anim = div.animate({ height: [ 'auto', - '200px', - '300px', - 'auto', - '400px' ] }, + const anim = div.animate({ height: [ 'auto', + '200px', + '300px', + 'auto', + '400px' ] }, { duration: 1000, fill: 'forwards' }); // There are five values, so there are four pairs to try to interpolate. @@ -83,16 +83,16 @@ }, 'Test discrete animation is used only for pairs of values that cannot' + ' be interpolated'); -test(function(t) { - var div = createDiv(t); - var originalHeight = getComputedStyle(div).height; +test(t => { + const div = createDiv(t); + const originalHeight = getComputedStyle(div).height; // Easing: http://cubic-bezier.com/#.68,0,1,.01 // With this curve, we don't reach the 50% point until about 95% of // the time has expired. - var anim = div.animate({ fontStyle: [ 'normal', 'italic' ] }, - { duration: 1000, fill: 'forwards', - easing: 'cubic-bezier(0.68,0,1,0.01)' }); + const anim = div.animate({ fontStyle: [ 'normal', 'italic' ] }, + { duration: 1000, fill: 'forwards', + easing: 'cubic-bezier(0.68,0,1,0.01)' }); assert_equals(getComputedStyle(div).fontStyle, 'normal', 'Animation produces \'from\' value at start of interval'); @@ -107,15 +107,15 @@ }, 'Test the 50% switch point for discrete animation is based on the' + ' effect easing'); -test(function(t) { - var div = createDiv(t); - var originalHeight = getComputedStyle(div).height; +test(t => { + const div = createDiv(t); + const originalHeight = getComputedStyle(div).height; // Easing: http://cubic-bezier.com/#.68,0,1,.01 // With this curve, we don't reach the 50% point until about 95% of // the time has expired. - var anim = div.animate([ { fontStyle: 'normal', - easing: 'cubic-bezier(0.68,0,1,0.01)' }, + const anim = div.animate([ { fontStyle: 'normal', + easing: 'cubic-bezier(0.68,0,1,0.01)' }, { fontStyle: 'italic' } ], { duration: 1000, fill: 'forwards' });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property.html index e8e4b48f..94ce9dd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Tests for animation type of interpolation</title> +<title>Interpolation for each property</title> <link rel="help" href="https://w3c.github.io/web-animations/#animation-types"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -17,16 +17,15 @@ <script> 'use strict'; -for (var property in gCSSProperties) { +for (const property in gCSSProperties) { if (!isSupported(property)) { continue; } - var animationTypes = gCSSProperties[property].types; - var setupFunction = gCSSProperties[property].setup; - animationTypes.forEach(function(animationType) { - var typeObject; - var animationTypeString; + const setupFunction = gCSSProperties[property].setup; + for (const animationType of gCSSProperties[property].types) { + let typeObject; + let animationTypeString; if (typeof animationType === 'string') { typeObject = types[animationType]; animationTypeString = animationType; @@ -39,13 +38,13 @@ // First, test that the animation type object has 'testInterpolation'. // We use test() function() here so that we can continue the remainder tests // even if this test fails. - test(function(t) { + test(t => { assert_own_property(typeObject, 'testInterpolation', animationTypeString + ' should have testInterpolation property'); assert_equals(typeof typeObject.testInterpolation, 'function', 'testInterpolation method should be a function'); - }, property + ' (type: ' + animationTypeString + - ') has testInterpolation function'); + }, `${property} (type: ${animationTypeString}) has testInterpolation` + + ' function'); if (typeObject.testInterpolation && typeof typeObject.testInterpolation === 'function') { @@ -53,6 +52,6 @@ setupFunction, animationType.options); } - }); + } } </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/property-list.js b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/property-list.js index 4315d0f..46829c314 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/property-list.js +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/property-list.js
@@ -1,6 +1,6 @@ 'use strict'; -var gCSSProperties = { +const gCSSProperties = { 'align-content': { // https://drafts.csswg.org/css-align/#propdef-align-content types: [ @@ -146,7 +146,7 @@ // https://drafts.csswg.org/css-backgrounds-3/#border-bottom-width types: [ 'length' ], setup: t => { - var element = createElement(t); + const element = createElement(t); element.style.borderBottomStyle = 'solid'; return element; } @@ -233,7 +233,7 @@ // https://drafts.csswg.org/css-backgrounds-3/#border-left-width types: [ 'length' ], setup: t => { - var element = createElement(t); + const element = createElement(t); element.style.borderLeftStyle = 'solid'; return element; } @@ -252,7 +252,7 @@ // https://drafts.csswg.org/css-backgrounds-3/#border-right-width types: [ 'length' ], setup: t => { - var element = createElement(t); + const element = createElement(t); element.style.borderRightStyle = 'solid'; return element; } @@ -285,7 +285,7 @@ // https://drafts.csswg.org/css-backgrounds-3/#border-top-width types: [ 'length' ], setup: t => { - var element = createElement(t); + const element = createElement(t); element.style.borderTopStyle = 'solid'; return element; } @@ -402,7 +402,7 @@ // https://drafts.csswg.org/css-multicol/#propdef-column-rule-width types: [ 'length' ], setup: t => { - var element = createElement(t); + const element = createElement(t); element.style.columnRuleStyle = 'solid'; return element; } @@ -1044,7 +1044,7 @@ // https://drafts.csswg.org/css-ui-3/#propdef-outline-width types: [ 'length' ], setup: t => { - var element = createElement(t); + const element = createElement(t); element.style.outlineStyle = 'solid'; return element; } @@ -1368,7 +1368,7 @@ // https://drafts.csswg.org/css-text-decor-3/#propdef-text-shadow types: [ 'textShadowList' ], setup: t => { - var element = createElement(t); + const element = createElement(t); element.style.color = 'green'; return element; } @@ -1477,13 +1477,13 @@ const target = animation.effect.target.constructor.name === 'CSSPseudoElement' ? animation.effect.target.parentElement : animation.effect.target; - testSamples.forEach(testSample => { + for (const testSample of testSamples) { animation.currentTime = testSample.time; assert_equals(getComputedStyle(target, type)[idlName], testSample.expected, `The value should be ${testSample.expected}` + ` at ${testSample.time}ms`); - }); + } } function toOrderedArray(string) { @@ -1498,7 +1498,7 @@ const target = animation.effect.target.constructor.name === 'CSSPseudoElement' ? animation.effect.target.parentElement : animation.effect.target; - testSamples.forEach(testSample => { + for (const testSample of testSamples) { animation.currentTime = testSample.time; // Convert to array and sort the expected and actual value lists first @@ -1510,19 +1510,19 @@ assert_array_equals(computedValues, expectedValues, `The computed values should be ${expectedValues}` + ` at ${testSample.time}ms`); - }); + } } function testAnimationSampleMatrices(animation, idlName, testSamples) { - var target = animation.effect.target; - testSamples.forEach(function(testSample) { + const target = animation.effect.target; + for (const testSample of testSamples) { animation.currentTime = testSample.time; - var actual = getComputedStyle(target)[idlName]; - var expected = createMatrixFromArray(testSample.expected); + const actual = getComputedStyle(target)[idlName]; + const expected = createMatrixFromArray(testSample.expected); assert_matrix_equals(actual, expected, - 'The value should be ' + expected + - ' at ' + testSample.time + 'ms but got ' + actual); - }); + `The value should be ${expected} at` + + ` ${testSample.time}ms but got ${actual}`); + } } function createTestElement(t, setup) { @@ -1530,7 +1530,7 @@ } function isSupported(property) { - var testKeyframe = new TestKeyframe(propertyToIDL(property)); + const testKeyframe = new TestKeyframe(propertyToIDL(property)); try { // Since TestKeyframe returns 'undefined' for |property|, // the KeyframeEffect constructor will throw @@ -1541,7 +1541,7 @@ } function TestKeyframe(testProp) { - var _propAccessCount = 0; + let _propAccessCount = 0; Object.defineProperty(this, testProp, { get: function() { _propAccessCount++; }, @@ -1563,11 +1563,11 @@ return str.substr(1).toUpperCase(); }); } function calcFromPercentage(idlName, percentageValue) { - var examElem = document.createElement('div'); + const examElem = document.createElement('div'); document.body.appendChild(examElem); examElem.style[idlName] = percentageValue; - var calcValue = getComputedStyle(examElem)[idlName]; + const calcValue = getComputedStyle(examElem)[idlName]; document.body.removeChild(examElem); return calcValue;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/property-types.js b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/property-types.js index 7641bbe..eb9c8c163 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/property-types.js +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/property-types.js
@@ -1,78 +1,93 @@ +'use strict'; + const discreteType = { - testInterpolation: function(property, setup, options) { - options.forEach(function(keyframes) { - var [ from, to ] = keyframes; - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: [from, to] }, - { duration: 1000, fill: 'both' }); + testInterpolation: (property, setup, options) => { + for (const keyframes of options) { + const [ from, to ] = keyframes; + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [from, to] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 0, expected: from.toLowerCase() }, { time: 499, expected: from.toLowerCase() }, { time: 500, expected: to.toLowerCase() }, { time: 1000, expected: to.toLowerCase() }]); - }, property + ' uses discrete animation when animating between "' - + from + '" and "' + to + '" with linear easing'); + }, `${property} uses discrete animation when animating between` + + ` "${from}" and "${to}" with linear easing`); - test(function(t) { + test(t => { // Easing: http://cubic-bezier.com/#.68,0,1,.01 // With this curve, we don't reach the 50% point until about 95% of // the time has expired. - var idlName = propertyToIDL(property); - var keyframes = {}; - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: [from, to] }, - { duration: 1000, fill: 'both', - easing: 'cubic-bezier(0.68,0,1,0.01)' }); + const idlName = propertyToIDL(property); + const keyframes = {}; + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: [from, to] }, + { + duration: 1000, + fill: 'both', + easing: 'cubic-bezier(0.68,0,1,0.01)', + } + ); testAnimationSamples(animation, idlName, [{ time: 0, expected: from.toLowerCase() }, { time: 940, expected: from.toLowerCase() }, { time: 960, expected: to.toLowerCase() }]); - }, property + ' uses discrete animation when animating between "' - + from + '" and "' + to + '" with effect easing'); + }, `${property} uses discrete animation when animating between` + + ` "${from}" and "${to}" with effect easing`); - test(function(t) { + test(t => { // Easing: http://cubic-bezier.com/#.68,0,1,.01 // With this curve, we don't reach the 50% point until about 95% of // the time has expired. - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: [from, to], - easing: 'cubic-bezier(0.68,0,1,0.01)' }, - { duration: 1000, fill: 'both' }); + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: [from, to], + easing: 'cubic-bezier(0.68,0,1,0.01)', + }, + { duration: 1000, fill: 'both' } + ); testAnimationSamples(animation, idlName, [{ time: 0, expected: from.toLowerCase() }, { time: 940, expected: from.toLowerCase() }, { time: 960, expected: to.toLowerCase() }]); - }, property + ' uses discrete animation when animating between "' - + from + '" and "' + to + '" with keyframe easing'); - }); + }, `${property} uses discrete animation when animating between` + + ` "${from}" and "${to}" with keyframe easing`); + } }, - testAdditionOrAccumulation: function(property, setup, options, composite) { - options.forEach(function(keyframes) { - var [ from, to ] = keyframes; - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, options, composite) => { + for (const keyframes of options) { + const [ from, to ] = keyframes; + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.animate({ [idlName]: [from, from] }, 1000); - var animation = target.animate({ [idlName]: [to, to] }, - { duration: 1000, composite: composite }); + const animation = target.animate( + { [idlName]: [to, to] }, + { duration: 1000, composite } + ); testAnimationSamples(animation, idlName, [{ time: 0, expected: to.toLowerCase() }]); - }, property + ': "' + to + '" onto "' + from + '"'); + }, `${property}: "${to}" onto "${from}"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.animate({ [idlName]: [to, to] }, 1000); - var animation = target.animate({ [idlName]: [from, from] }, - { duration: 1000, composite: composite }); + const animation = target.animate( + { [idlName]: [from, from] }, + { duration: 1000, composite } + ); testAnimationSamples(animation, idlName, [{ time: 0, expected: from.toLowerCase() }]); - }, property + ': "' + from + '" onto "' + to + '"'); - }); + }, `${property}: "${from}" onto "${to}"`); + } }, testAddition: function(property, setup, options) { @@ -85,44 +100,48 @@ }; const lengthType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['10px', '50px'] }, - { duration: 1000, fill: 'both' }); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['10px', '50px'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: '30px' }]); - }, property + ' supports animating as a length'); + }, `${property} supports animating as a length`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['1rem', '5rem'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['1rem', '5rem'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: '30px' }]); - }, property + ' supports animating as a length of rem'); + }, `${property} supports animating as a length of rem`); }, - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '10px'; - var animation = target.animate({ [idlName]: ['10px', '50px'] }, - { duration: 1000, composite: composite}); + const animation = target.animate( + { [idlName]: ['10px', '50px'] }, + { duration: 1000, composite } + ); testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px' }]); - }, property + ': length'); + }, `${property}: length`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '1rem'; - var animation = target.animate({ [idlName]: ['1rem', '5rem'] }, - { duration: 1000, composite: composite }); + const animation = target.animate( + { [idlName]: ['1rem', '5rem'] }, + { duration: 1000, composite } + ); testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px' }]); - }, property + ': length of rem'); + }, `${property}: length of rem`); }, testAddition: function(property, setup) { @@ -135,44 +154,60 @@ }; const lengthPairType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['10px 10px', '50px 50px'] }, - { duration: 1000, fill: 'both' }); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: ['10px 10px', '50px 50px'] }, + { duration: 1000, fill: 'both' } + ); testAnimationSamples(animation, idlName, [{ time: 500, expected: '30px 30px' }]); - }, property + ' supports animating as a length pair'); + }, `${property} supports animating as a length pair`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['1rem 1rem', '5rem 5rem'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: ['1rem 1rem', '5rem 5rem'] }, + { duration: 1000, fill: 'both' } + ); testAnimationSamples(animation, idlName, [{ time: 500, expected: '30px 30px' }]); - }, property + ' supports animating as a length pair of rem'); + }, `${property} supports animating as a length pair of rem`); }, - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '10px 10px'; - var animation = target.animate({ [idlName]: ['10px 10px', '50px 50px'] }, - { duration: 1000, composite: composite }); - testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px 20px' }]); - }, property + ': length pair'); + const animation = target.animate( + { [idlName]: ['10px 10px', '50px 50px'] }, + { duration: 1000, composite } + ); + testAnimationSamples( + animation, + idlName, + [{ time: 0, expected: '20px 20px' }] + ); + }, `${property}: length pair`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '1rem 1rem'; - var animation = target.animate({ [idlName]: ['1rem 1rem', '5rem 5rem'] }, - { duration: 1000, composite: composite }); - testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px 20px' }]); - }, property + ': length pair of rem'); + const animation = target.animate( + { [idlName]: ['1rem 1rem', '5rem 5rem'] }, + { duration: 1000, composite } + ); + testAnimationSamples( + animation, + idlName, + [{ time: 0, expected: '20px 20px' }] + ); + }, `${property}: length pair of rem`); }, testAddition: function(property, setup) { @@ -185,26 +220,28 @@ }; const percentageType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['10%', '50%'] }, - { duration: 1000, fill: 'both' }); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['10%', '50%'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: '30%' }]); - }, property + ' supports animating as a percentage'); + }, `${property} supports animating as a percentage`); }, - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '60%'; - var animation = target.animate({ [idlName]: ['70%', '100%'] }, - { duration: 1000, composite: composite }); + const animation = target.animate( + { [idlName]: ['70%', '100%'] }, + { duration: 1000, composite } + ); testAnimationSamples(animation, idlName, [{ time: 0, expected: '130%' }]); - }, property + ': percentage'); + }, `${property}: percentage`); }, testAddition: function(property, setup) { @@ -217,27 +254,29 @@ }; const integerType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: [-2, 2] }, - { duration: 1000, fill: 'both' }); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [-2, 2] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: '0' }]); - }, property + ' supports animating as an integer'); + }, `${property} supports animating as an integer`); }, - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = -1; - var animation = target.animate({ [idlName]: [-2, 2] }, - { duration: 1000, composite: composite }); + const animation = target.animate( + { [idlName]: [-2, 2] }, + { duration: 1000, composite } + ); testAnimationSamples(animation, idlName, [{ time: 0, expected: '-3' }]); - }, property + ': integer'); + }, `${property}: integer`); }, testAddition: function(property, setup) { @@ -250,27 +289,29 @@ }; const positiveIntegerType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: [1, 3] }, - { duration: 1000, fill: 'both' }); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [1, 3] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [ { time: 500, expected: '2' } ]); - }, property + ' supports animating as a positive integer'); + }, `${property} supports animating as a positive integer`); }, - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 1; - var animation = target.animate({ [idlName]: [2, 5] }, - { duration: 1000, composite: composite }); + const animation = target.animate( + { [idlName]: [2, 5] }, + { duration: 1000, composite } + ); testAnimationSamples(animation, idlName, [{ time: 0, expected: '3' }]); - }, property + ': positive integer'); + }, `${property}: positive integer`); }, testAddition: function(property, setup) { @@ -283,141 +324,143 @@ }; const lengthPercentageOrCalcType = { - testInterpolation: function(property, setup) { + testInterpolation: (property, setup) => { lengthType.testInterpolation(property, setup); percentageType.testInterpolation(property, setup); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['10px', '20%'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['10px', '20%'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'calc(5px + 10%)' }]); - }, property + ' supports animating as combination units "px" and "%"'); + }, `${property} supports animating as combination units "px" and "%"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['10%', '2em'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['10%', '2em'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'calc(10px + 5%)' }]); - }, property + ' supports animating as combination units "%" and "em"'); + }, `${property} supports animating as combination units "%" and "em"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['1em', '2rem'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['1em', '2rem'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: '15px' }]); - }, property + ' supports animating as combination units "em" and "rem"'); + }, `${property} supports animating as combination units "em" and "rem"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['10px', 'calc(1em + 20%)'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: ['10px', 'calc(1em + 20%)'] }, + { duration: 1000, fill: 'both' } + ); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'calc(10px + 10%)' }]); - }, property + ' supports animating as combination units "px" and "calc"'); + }, `${property} supports animating as combination units "px" and "calc"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate( + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( { [idlName]: ['calc(10px + 10%)', 'calc(1em + 1rem + 20%)'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'calc(15px + 15%)' }]); - }, property + ' supports animating as a calc'); + }, `${property} supports animating as a calc`); }, - testAdditionOrAccumulation: function(property, setup, composite) { + testAdditionOrAccumulation: (property, setup, composite) => { lengthType.testAddition(property, setup); percentageType.testAddition(property, setup); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '10px'; - var animation = target.animate({ [idlName]: ['10%', '50%'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: ['10%', '50%'] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'calc(10px + 10%)' }]); - }, property + ': units "%" onto "px"'); + }, `${property}: units "%" onto "px"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '10%'; - var animation = target.animate({ [idlName]: ['10px', '50px'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: ['10px', '50px'] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'calc(10px + 10%)' }]); - }, property + ': units "px" onto "%"'); + }, `${property}: units "px" onto "%"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '10%'; - var animation = target.animate({ [idlName]: ['2rem', '5rem'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: ['2rem', '5rem'] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'calc(20px + 10%)' }]); - }, property + ': units "rem" onto "%"'); + }, `${property}: units "rem" onto "%"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '2rem'; - var animation = target.animate({ [idlName]: ['10%', '50%'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: ['10%', '50%'] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'calc(20px + 10%)' }]); - }, property + ': units "%" onto "rem"'); + }, `${property}: units "%" onto "rem"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '2em'; - var animation = target.animate({ [idlName]: ['2rem', '5rem'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: ['2rem', '5rem'] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: '40px' }]); - }, property + ': units "rem" onto "em"'); + }, `${property}: units "rem" onto "em"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '2rem'; - var animation = target.animate({ [idlName]: ['2em', '5em'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: ['2em', '5em'] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: '40px' }]); - }, property + ': units "em" onto "rem"'); + }, `${property}: units "em" onto "rem"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '10px'; - var animation = target.animate({ [idlName]: ['calc(2em + 20%)', + const animation = target.animate({ [idlName]: ['calc(2em + 20%)', 'calc(5rem + 50%)'] }, - { duration: 1000, composite: composite }); + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'calc(30px + 20%)' }]); - }, property + ': units "calc" onto "px"'); + }, `${property}: units "calc" onto "px"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'calc(10px + 10%)'; - var animation = target.animate({ [idlName]: ['calc(20px + 20%)', + const animation = target.animate({ [idlName]: ['calc(20px + 20%)', 'calc(2em + 3rem + 40%)'] }, - { duration: 1000, composite: composite }); + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'calc(30px + 30%)' }]); - }, property + ': calc'); + }, `${property}: calc`); }, testAddition: function(property, setup) { @@ -430,26 +473,26 @@ }; const positiveNumberType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: [1.1, 1.5] }, - { duration: 1000, fill: 'both' }); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [1.1, 1.5] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: '1.3' }]); - }, property + ' supports animating as a positive number'); + }, `${property} supports animating as a positive number`); }, - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 1.1; - var animation = target.animate({ [idlName]: [1.1, 1.5] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: [1.1, 1.5] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: '2.2' }]); - }, property + ': positive number'); + }, `${property}: positive number`); }, testAddition: function(property, setup) { @@ -463,35 +506,35 @@ // Test using float values in the range [0, 1] const opacityType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: [0.3, 0.8] }, - { duration: 1000, fill: 'both' }); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [0.3, 0.8] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: '0.55' }]); - }, property + ' supports animating as a [0, 1] number'); + }, `${property} supports animating as a [0, 1] number`); }, - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 0.3; - var animation = target.animate({ [idlName]: [0.3, 0.8] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: [0.3, 0.8] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: '0.6' }]); - }, property + ': [0, 1] number'); + }, `${property}: [0, 1] number`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 0.8; - var animation = target.animate({ [idlName]: [0.3, 0.8] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: [0.3, 0.8] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: '1' }]); - }, property + ': [0, 1] number (clamped)'); + }, `${property}: [0, 1] number (clamped)`); }, testAddition: function(property, setup) { @@ -504,51 +547,51 @@ }; const visibilityType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['visible', 'hidden'] }, - { duration: 1000, fill: 'both' }); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['visible', 'hidden'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'visible' }, { time: 999, expected: 'visible' }, { time: 1000, expected: 'hidden' }]); - }, property + ' uses visibility animation when animating ' - + 'from "visible" to "hidden"'); + }, `${property} uses visibility animation when animating` + + ' from "visible" to "hidden"'); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['hidden', 'visible'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['hidden', 'visible'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'hidden' }, { time: 1, expected: 'visible' }, { time: 1000, expected: 'visible' }]); - }, property + ' uses visibility animation when animating ' - + 'from "hidden" to "visible"'); + }, `${property} uses visibility animation when animating` + + ' from "hidden" to "visible"'); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['hidden', 'collapse'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['hidden', 'collapse'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'hidden' }, { time: 499, expected: 'hidden' }, { time: 500, expected: 'collapse' }, { time: 1000, expected: 'collapse' }]); - }, property + ' uses visibility animation when animating ' - + 'from "hidden" to "collapse"'); + }, `${property} uses visibility animation when animating` + + ' from "hidden" to "collapse"'); - test(function(t) { + test(t => { // Easing: http://cubic-bezier.com/#.68,-.55,.26,1.55 // With this curve, the value is less than 0 till about 34% // also more than 1 since about 63% - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['visible', 'hidden'] }, { duration: 1000, fill: 'both', easing: 'cubic-bezier(0.68, -0.55, 0.26, 1.55)' }); @@ -560,34 +603,34 @@ { time: 620, expected: 'visible' }, { time: 630, expected: 'hidden' }, { time: 1000, expected: 'hidden' }]); - }, property + ' uses visibility animation when animating ' - + 'from "visible" to "hidden" with easeInOutBack easing'); + }, `${property} uses visibility animation when animating` + + ' from "visible" to "hidden" with easeInOutBack easing'); }, - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'visible'; - var animation = target.animate({ [idlName]: ['visible', 'hidden'] }, - { duration: 1000, fill: 'both', - composite: composite }); + const animation = target.animate({ [idlName]: ['visible', 'hidden'] }, + { duration: 1000, fill: 'both', + composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'visible' }, { time: 1000, expected: 'visible' }]); - }, property + ': onto "visible"'); + }, `${property}: onto "visible"`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'hidden'; - var animation = target.animate({ [idlName]: ['hidden', 'visible'] }, - { duration: 1000, fill: 'both', - composite: composite }); + const animation = target.animate({ [idlName]: ['hidden', 'visible'] }, + { duration: 1000, fill: 'both', + composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'hidden' }, { time: 1000, expected: 'visible' }]); - }, property + ': onto "hidden"'); + }, `${property}: onto "hidden"`); }, testAddition: function(property, setup) { @@ -600,137 +643,153 @@ }; const colorType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['rgb(255, 0, 0)', - 'rgb(0, 0, 255)'] }, - 1000); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['rgb(255, 0, 0)', + 'rgb(0, 0, 255)'] }, + 1000); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(128, 0, 128)' }]); - }, property + ' supports animating as color of rgb()'); + }, `${property} supports animating as color of rgb()`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['#ff0000', '#0000ff'] }, - 1000); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['#ff0000', '#0000ff'] }, + 1000); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(128, 0, 128)' }]); - }, property + ' supports animating as color of #RGB'); + }, `${property} supports animating as color of #RGB`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%)', - 'hsl(240, 100%, 50%)'] }, - 1000); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%)', + 'hsl(240, 100%, 50%)'] }, + 1000); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(128, 0, 128)' }]); - }, property + ' supports animating as color of hsl()'); + }, `${property} supports animating as color of hsl()`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['#ff000066', '#0000ffcc'] }, - 1000); - // R: 255 * (0.4 * 0.5) / 0.6 = 85 - // G: 255 * (0.8 * 0.5) / 0.6 = 170 + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: ['#ff000066', '#0000ffcc'] }, + 1000 + ); + // R: 255 * (0.4 * 0.5) / 0.6 = 85 + // B: 255 * (0.8 * 0.5) / 0.6 = 170 testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgba(85, 0, 170, 0.6)' }]); - }, property + ' supports animating as color of #RGBa'); + }, `${property} supports animating as color of #RGBa`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['rgba(255, 0, 0, 0.4)', - 'rgba(0, 0, 255, 0.8)'] }, - 1000); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['rgba(255, 0, 0, 0.4)', 'rgba(0, 0, 255, 0.8)'], + }, + 1000 + ); testAnimationSamples(animation, idlName, // Same as above. [{ time: 500, expected: 'rgba(85, 0, 170, 0.6)' }]); - }, property + ' supports animating as color of rgba()'); + }, `${property} supports animating as color of rgba()`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['hsla(0, 100%, 50%, 0.4)', - 'hsla(240, 100%, 50%, 0.8)'] }, - 1000); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['hsla(0, 100%, 50%, 0.4)', 'hsla(240, 100%, 50%, 0.8)'], + }, + 1000 + ); testAnimationSamples(animation, idlName, // Same as above. [{ time: 500, expected: 'rgba(85, 0, 170, 0.6)' }]); - }, property + ' supports animating as color of hsla()'); + }, `${property} supports animating as color of hsla()`); }, - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rgb(128, 128, 128)'; - var animation = target.animate({ [idlName]: ['rgb(255, 0, 0)', - 'rgb(0, 0, 255)'] }, - { duration: 1000, composite: composite }); + const animation = target.animate( + { + [idlName]: ['rgb(255, 0, 0)', 'rgb(0, 0, 255)'], + }, + { duration: 1000, composite } + ); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'rgb(255, 128, 128)' }, // The value at 50% is interpolated // from 'rgb(128+255, 128, 128)' // to 'rgb(128, 128, 128+255)'. { time: 500, expected: 'rgb(255, 128, 255)' }]); - }, property + ' supports animating as color of rgb() with overflowed ' + - 'from and to values'); + }, `${property} supports animating as color of rgb() with overflowed ` + + ' from and to values'); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rgb(128, 128, 128)'; - var animation = target.animate({ [idlName]: ['#ff0000', '#0000ff'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: ['#ff0000', '#0000ff'] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'rgb(255, 128, 128)' }]); - }, property + ' supports animating as color of #RGB'); + }, `${property} supports animating as color of #RGB`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rgb(128, 128, 128)'; - var animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%)', - 'hsl(240, 100%, 50%)'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%)', + 'hsl(240, 100%, 50%)'] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'rgb(255, 128, 128)' }]); - }, property + ' supports animating as color of hsl()'); + }, `${property} supports animating as color of hsl()`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rgb(128, 128, 128)'; - var animation = target.animate({ [idlName]: ['#ff000066', '#0000ffcc'] }, - { duration: 1000, composite: composite }); + const animation = target.animate( + { [idlName]: ['#ff000066', '#0000ffcc'] }, + { duration: 1000, composite } + ); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'rgb(230, 128, 128)' }]); - }, property + ' supports animating as color of #RGBa'); + }, `${property} supports animating as color of #RGBa`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rgb(128, 128, 128)'; - var animation = target.animate({ [idlName]: ['rgba(255, 0, 0, 0.4)', - 'rgba(0, 0, 255, 0.8)'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: ['rgba(255, 0, 0, 0.4)', + 'rgba(0, 0, 255, 0.8)'] }, + { duration: 1000, composite }); testAnimationSamples(animation, idlName, // Same as above. [{ time: 0, expected: 'rgb(230, 128, 128)' }]); - }, property + ' supports animating as color of rgba()'); + }, `${property} supports animating as color of rgba()`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rgb(128, 128, 128)'; - var animation = target.animate({ [idlName]: ['hsla(0, 100%, 50%, 0.4)', - 'hsla(240, 100%, 50%, 0.8)'] }, - { duration: 1000, composite: composite }); + const animation = target.animate( + { + [idlName]: ['hsla(0, 100%, 50%, 0.4)', 'hsla(240, 100%, 50%, 0.8)'], + }, + { duration: 1000, composite } + ); testAnimationSamples(animation, idlName, // Same as above. [{ time: 0, expected: 'rgb(230, 128, 128)' }]); - }, property + ' supports animating as color of hsla()'); + }, `${property} supports animating as color of hsla()`); }, testAddition: function(property, setup) { @@ -743,23 +802,29 @@ }; const transformListType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['translate(200px, -200px)', - 'translate(400px, 400px)'] }, - 1000); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['translate(200px, -200px)', 'translate(400px, 400px)'], + }, + 1000 + ); testAnimationSampleMatrices(animation, idlName, [{ time: 500, expected: [ 1, 0, 0, 1, 300, 100 ] }]); - }, property + ': translate'); + }, `${property}: translate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['rotate(45deg)', - 'rotate(135deg)'] }, - 1000); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['rotate(45deg)', 'rotate(135deg)'], + }, + 1000 + ); testAnimationSampleMatrices(animation, idlName, [{ time: 500, expected: [ Math.cos(Math.PI / 2), @@ -767,35 +832,35 @@ -Math.sin(Math.PI / 2), Math.cos(Math.PI / 2), 0, 0] }]); - }, property + ': rotate'); + }, `${property}: rotate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['scale(3)', 'scale(5)'] }, - 1000); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['scale(3)', 'scale(5)'] }, + 1000); testAnimationSampleMatrices(animation, idlName, [{ time: 500, expected: [ 4, 0, 0, 4, 0, 0 ] }]); - }, property + ': scale'); + }, `${property}: scale`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['skew(30deg, 60deg)', - 'skew(60deg, 30deg)'] }, - 1000); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['skew(30deg, 60deg)', + 'skew(60deg, 30deg)'] }, + 1000); testAnimationSampleMatrices(animation, idlName, [{ time: 500, expected: [ 1, Math.tan(Math.PI / 4), Math.tan(Math.PI / 4), 1, 0, 0] }]); - }, property + ': skew'); + }, `${property}: skew`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['translateX(100px) rotate(45deg)', 'translateX(200px) rotate(135deg)'] }, 1000); @@ -806,12 +871,12 @@ -Math.sin(Math.PI / 2), Math.cos(Math.PI / 2), 150, 0 ] }]); - }, property + ': rotate and translate'); + }, `${property}: rotate and translate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['rotate(45deg) translateX(100px)', 'rotate(135deg) translateX(200px)'] }, 1000); @@ -823,12 +888,12 @@ Math.cos(Math.PI / 2), 150 * Math.cos(Math.PI / 2), 150 * Math.sin(Math.PI / 2) ] }]); - }, property + ': translate and rotate'); + }, `${property}: translate and rotate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = // matrix(0, 1, -1, 0, 0, 100) + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = // matrix(0, 1, -1, 0, 0, 100) target.animate({ [idlName]: ['rotate(90deg) translateX(100px)', // matrix(-1, 0, 0, -1, 200, 0) 'translateX(200px) rotate(180deg)'] }, @@ -840,12 +905,12 @@ -Math.sin(Math.PI * 3 / 4), Math.cos(Math.PI * 3 / 4), 100, 50 ] }]); - }, property + ': mismatch order of translate and rotate'); + }, `${property}: mismatch order of translate and rotate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = // Same matrices as above. + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = // Same matrices as above. target.animate({ [idlName]: [ 'matrix(0, 1, -1, 0, 0, 100)', 'matrix(-1, 0, 0, -1, 200, 0)' ] }, 1000); @@ -856,71 +921,75 @@ -Math.sin(Math.PI * 3 / 4), Math.cos(Math.PI * 3 / 4), 100, 50 ] }]); - }, property + ': matrix'); + }, `${property}: matrix`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'rotate3d(1, 1, 0, 0deg)', 'rotate3d(1, 1, 0, 90deg)'] }, 1000); testAnimationSampleMatrices(animation, idlName, [{ time: 500, expected: rotate3dToMatrix(1, 1, 0, Math.PI / 4) }]); - }, property + ': rotate3d'); + }, `${property}: rotate3d`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); // To calculate expected matrices easily, generate input matrices from // rotate3d. - var from = rotate3dToMatrix3d(1, 1, 0, Math.PI / 4); - var to = rotate3dToMatrix3d(1, 1, 0, Math.PI * 3 / 4); - var animation = - target.animate({ [idlName]: [ from, to ] }, 1000); + const from = rotate3dToMatrix3d(1, 1, 0, Math.PI / 4); + const to = rotate3dToMatrix3d(1, 1, 0, Math.PI * 3 / 4); + const animation = target.animate({ [idlName]: [ from, to ] }, 1000); testAnimationSampleMatrices(animation, idlName, [{ time: 500, expected: rotate3dToMatrix(1, 1, 0, Math.PI * 2 / 4) }]); - }, property + ': matrix3d'); + }, `${property}: matrix3d`); // This test aims for forcing the two mismatched transforms to be // decomposed into matrix3d before interpolation. Therefore, we not only // test the interpolation, but also test the 3D matrix decomposition. - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = - target.animate({ [idlName]: ['scale(0.3)', - // scale(0.5) translateZ(1px) - 'matrix3d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1)'] }, - 1000); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: [ + 'scale(0.3)', + // scale(0.5) translateZ(1px) + 'matrix3d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1)', + ], + }, + 1000 + ); testAnimationSampleMatrices(animation, idlName, [{ time: 500, expected: [ 0.4, 0, 0, 0, 0, 0.4, 0, 0, 0, 0, 1, 0, 0, 0, 0.5, 1] }]); - }, property + ': mismatched 3D transforms'); + }, `${property}: mismatched 3D transforms`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['rotateY(60deg)', 'none' ] }, 1000); testAnimationSampleMatrices(animation, idlName, // rotateY(30deg) == rotate3D(0, 1, 0, 30deg) [{ time: 500, expected: rotate3dToMatrix(0, 1, 0, Math.PI / 6) }]); - }, property + ': rotateY'); + }, `${property}: rotateY`); // Following tests aim for test the fallback discrete interpolation behavior // for non-invertible matrices. The non-invertible matrix that we use is the - // singuler matrix, matrix(1, 1, 0, 0, 0, 100). - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + // singular matrix, matrix(1, 1, 0, 0, 0, 100). + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0)', 'matrix( 1, 1, 0, 0, 0, 100)'] }, { duration: 1000, fill: 'both' }); @@ -930,63 +999,75 @@ { time: 499, expected: [ -1, 0, 0, -1, 200, 0 ] }, { time: 500, expected: [ 1, 1, 0, 0, 0, 100 ] }, { time: 1000, expected: [ 1, 1, 0, 0, 0, 100 ] }]); - }, property + ': non-invertible matrices'); + }, `${property}: non-invertible matrices`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = // matrix(0, -1, 1, 0, 250, 0) - target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', - // matrix(-1, -1, 0, 0, 100, 100) - 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: [ + // matrix(0, -1, 1, 0, 250, 0) + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', + // matrix(-1, -1, 0, 0, 100, 100) + 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)', + ], + }, + { duration: 1000, fill: 'both' } + ); testAnimationSampleMatrices(animation, idlName, [ { time: 0, expected: [ 0, -1, 1, 0, 250, 0 ] }, { time: 499, expected: [ 0, -1, 1, 0, 250, 0 ] }, { time: 500, expected: [ -1, -1, 0, 0, 100, 100 ] }, { time: 1000, expected: [ -1, -1, 0, 0, 100, 100 ] }]); - }, property + ': non-invertible matrices in matched transform lists'); + }, `${property}: non-invertible matrices in matched transform lists`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = // matrix(-2, 0, 0, -2, 250, 0) - target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', - // matrix(1, 1, 1, 1, 100, 100) - 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) skew(45deg)'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: [ + // matrix(-2, 0, 0, -2, 250, 0) + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', + // matrix(1, 1, 1, 1, 100, 100) + 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) skew(45deg)', + ], + }, + { duration: 1000, fill: 'both' } + ); testAnimationSampleMatrices(animation, idlName, [ { time: 0, expected: [ -2, 0, 0, -2, 250, 0 ] }, { time: 499, expected: [ -2, 0, 0, -2, 250, 0 ] }, { time: 500, expected: [ 1, 1, 1, 1, 100, 100 ] }, { time: 1000, expected: [ 1, 1, 1, 1, 100, 100 ] }]); - }, property + ': non-invertible matrices in mismatched transform lists'); + }, `${property}: non-invertible matrices in mismatched transform lists`); }, testAddition: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'translateX(100px)'; - var animation = target.animate({ [idlName]: ['translateX(-200px)', - 'translateX(500px)'] }, - { duration: 1000, fill: 'both', - composite: 'add' }); + const animation = target.animate({ [idlName]: ['translateX(-200px)', + 'translateX(500px)'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); testAnimationSampleMatrices(animation, idlName, [ { time: 0, expected: [ 1, 0, 0, 1, -100, 0 ] }, { time: 1000, expected: [ 1, 0, 0, 1, 600, 0 ] }]); - }, property + ': translate'); + }, `${property}: translate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rotate(45deg)'; - var animation = target.animate({ [idlName]: ['rotate(-90deg)', - 'rotate(90deg)'] }, - { duration: 1000, fill: 'both', - composite: 'add' }); + const animation = target.animate({ [idlName]: ['rotate(-90deg)', + 'rotate(90deg)'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: [ Math.cos(-Math.PI / 4), @@ -999,27 +1080,27 @@ -Math.sin(Math.PI * 3 / 4), Math.cos(Math.PI * 3 / 4), 0, 0] }]); - }, property + ': rotate'); + }, `${property}: rotate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'scale(2)'; - var animation = target.animate({ [idlName]: ['scale(-3)', 'scale(5)'] }, - { duration: 1000, fill: 'both', - composite: 'add' }); + const animation = target.animate({ [idlName]: ['scale(-3)', 'scale(5)'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: [ -6, 0, 0, -6, 0, 0 ] }, // scale(-3) scale(2) { time: 1000, expected: [ 10, 0, 0, 10, 0, 0 ] }]); // scale(5) scale(2) - }, property + ': scale'); + }, `${property}: scale`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); // matrix(1, tan(10deg), tan(10deg), 1) target.style[idlName] = 'skew(10deg, 10deg)'; - var animation = // matrix(1, tan(20deg), tan(-30deg), 1) + const animation = // matrix(1, tan(20deg), tan(-30deg), 1) target.animate({ [idlName]: ['skew(-30deg, 20deg)', // matrix(1, tan(-30deg), tan(20deg), 1) 'skew(20deg, -30deg)'] }, @@ -1050,14 +1131,14 @@ Math.tan(Math.PI/9) + Math.tan(Math.PI/18), 1 + Math.tan(Math.PI/18) * Math.tan(Math.PI/9), 0, 0] }]); - }, property + ': skew'); + }, `${property}: skew`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); // matrix(1, 0, 0, 1, 100, 0) target.style[idlName] = 'translateX(100px)'; - var animation = // matrix(0, 1, -1, 0, 0, 0) + const animation = // matrix(0, 1, -1, 0, 0, 0) target.animate({ [idlName]: ['rotate(90deg)', // matrix(-1, 0, 0, -1, 0, 0) 'rotate(180deg)'] }, @@ -1066,14 +1147,14 @@ testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] }, { time: 1000, expected: [ -1, 0, 0, -1, 100, 0 ] }]); - }, property + ': rotate on translate'); + }, `${property}: rotate on translate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); // matrix(0, 1, -1, 0, 0, 0) target.style[idlName] = 'rotate(90deg)'; - var animation = // matrix(1, 0, 0, 1, 100, 0) + const animation = // matrix(1, 0, 0, 1, 100, 0) target.animate({ [idlName]: ['translateX(100px)', // matrix(1, 0, 0, 1, 200, 0) 'translateX(200px)'] }, @@ -1082,13 +1163,13 @@ testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: [ 0, 1, -1, 0, 0, 100 ] }, { time: 1000, expected: [ 0, 1, -1, 0, 0, 200 ] }]); - }, property + ': translate on rotate'); + }, `${property}: translate on rotate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'matrix(0, 1, -1, 0, 0, 0)'; - var animation = // Same matrices as above. + const animation = // Same matrices as above. target.animate({ [idlName]: [ 'matrix(1, 0, 0, 1, 100, 0)', 'matrix(1, 0, 0, 1, 200, 0)' ] }, { duration: 1000, fill: 'both', composite: 'add' }); @@ -1096,13 +1177,13 @@ testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: [ 0, 1, -1, 0, 0, 100 ] }, { time: 1000, expected: [ 0, 1, -1, 0, 0, 200 ] }]); - }, property + ': matrix'); + }, `${property}: matrix`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rotate3d(1, 1, 0, 45deg)'; - var animation = + const animation = target.animate({ [idlName]: [ 'rotate3d(1, 1, 0, -90deg)', 'rotate3d(1, 1, 0, 90deg)'] }, { duration: 1000, fill: 'both', composite: 'add' }); @@ -1110,35 +1191,35 @@ testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) }, { time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]); - }, property + ': rotate3d'); + }, `${property}: rotate3d`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); // To calculate expected matrices easily, generate input matrices from // rotate3d. target.style[idlName] = rotate3dToMatrix3d(1, 1, 0, Math.PI / 4); - var from = rotate3dToMatrix3d(1, 1, 0, -Math.PI / 2); - var to = rotate3dToMatrix3d(1, 1, 0, Math.PI / 2); - var animation = + const from = rotate3dToMatrix3d(1, 1, 0, -Math.PI / 2); + const to = rotate3dToMatrix3d(1, 1, 0, Math.PI / 2); + const animation = target.animate({ [idlName]: [ from, to ] }, { duration: 1000, fill: 'both', composite: 'add' }); testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) }, { time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]); - }, property + ': matrix3d'); + }, `${property}: matrix3d`); // Following tests aim for test the addition behavior for non-invertible // matrices. Note that the addition for non-invertible matrices should be // the same, just like addition for invertible matrices. With these tests, // we can assure that addition never behaves as discrete. The non-invertible - // matrix that we use is the singuler matrix, matrix(1, 1, 0, 0, 0, 100). - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + // matrix that we use is the singular matrix, matrix(1, 1, 0, 0, 0, 100). + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'translateX(50px)'; - var animation = + const animation = target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0)', 'matrix( 1, 1, 0, 0, 0, 100)'] }, { duration: 1000, fill: 'both', composite: 'add' }); @@ -1146,13 +1227,13 @@ testAnimationSampleMatrices(animation, idlName, [ { time: 0, expected: [ -1, 0, 0, -1, 250, 0 ] }, { time: 1000, expected: [ 1, 1, 0, 0, 50, 100 ] }]); - }, property + ': non-invertible matrices'); + }, `${property}: non-invertible matrices`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'translateX(50px)'; - var animation = // matrix(0, -1, 1, 0, 200, 0) + const animation = // matrix(0, -1, 1, 0, 200, 0) target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', // matrix(-1, -1, 0, 0, 0, 100) 'matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)'] }, @@ -1161,13 +1242,13 @@ testAnimationSampleMatrices(animation, idlName, [ { time: 0, expected: [ 0, -1, 1, 0, 250, 0 ] }, { time: 1000, expected: [ -1, -1, 0, 0, 50, 100 ] }]); - }, property + ': non-invertible matrices in matched transform lists'); + }, `${property}: non-invertible matrices in matched transform lists`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'translateX(50px)'; - var animation = // matrix(-2, 0, 0, -2, 200, 0) + const animation = // matrix(-2, 0, 0, -2, 200, 0) target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0) scale(2)', // matrix(1, 1, 1, 1, 0, 100) 'matrix( 1, 1, 0, 0, 0, 100) skew(45deg)'] }, @@ -1176,28 +1257,28 @@ testAnimationSampleMatrices(animation, idlName, [ { time: 0, expected: [ -2, 0, 0, -2, 250, 0 ] }, { time: 1000, expected: [ 1, 1, 1, 1, 50, 100 ] }]); - }, property + ': non-invertible matrices in mismatched transform lists'); + }, `${property}: non-invertible matrices in mismatched transform lists`); }, testAccumulation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'translateX(100px)'; - var animation = target.animate({ [idlName]: ['translateX(-200px)', + const animation = target.animate({ [idlName]: ['translateX(-200px)', 'translateX(500px)'] }, { duration: 1000, fill: 'both', composite: 'accumulate' }); testAnimationSampleMatrices(animation, idlName, [ { time: 0, expected: [ 1, 0, 0, 1, -100, 0 ] }, { time: 1000, expected: [ 1, 0, 0, 1, 600, 0 ] }]); - }, property + ': translate'); + }, `${property}: translate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rotate(45deg)'; - var animation = target.animate({ [idlName]: ['rotate(-90deg)', + const animation = target.animate({ [idlName]: ['rotate(-90deg)', 'rotate(90deg)'] }, { duration: 1000, fill: 'both', composite: 'accumulate' }); @@ -1213,13 +1294,13 @@ -Math.sin(Math.PI * 3 / 4), Math.cos(Math.PI * 3 / 4), 0, 0] }]); - }, property + ': rotate'); + }, `${property}: rotate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'scale(2)'; - var animation = target.animate({ [idlName]: ['scale(-3)', 'scale(5)'] }, + const animation = target.animate({ [idlName]: ['scale(-3)', 'scale(5)'] }, { duration: 1000, fill: 'both', composite: 'accumulate' }); @@ -1228,14 +1309,14 @@ [{ time: 0, expected: [ -2, 0, 0, -2, 0, 0 ] }, // scale((2 - 1) + (5 - 1) + 1) { time: 1000, expected: [ 6, 0, 0, 6, 0, 0 ] }]); - }, property + ': scale'); + }, `${property}: scale`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); // matrix(1, tan(10deg), tan(10deg), 1) target.style[idlName] = 'skew(10deg, 10deg)'; - var animation = // matrix(1, tan(20deg), tan(-30deg), 1) + const animation = // matrix(1, tan(20deg), tan(-30deg), 1) target.animate({ [idlName]: ['skew(-30deg, 20deg)', // matrix(1, tan(-30deg), tan(20deg), 1) 'skew(20deg, -30deg)'] }, @@ -1248,14 +1329,14 @@ { time: 1000, expected: [ 1, Math.tan(-Math.PI/9), Math.tan(Math.PI/6), 1, 0, 0] }]); - }, property + ': skew'); + }, `${property}: skew`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); // matrix(1, 0, 0, 1, 100, 0) target.style[idlName] = 'translateX(100px)'; - var animation = // matrix(0, 1, -1, 0, 0, 0) + const animation = // matrix(0, 1, -1, 0, 0, 0) target.animate({ [idlName]: ['rotate(90deg)', // matrix(-1, 0, 0, -1, 0, 0) 'rotate(180deg)'] }, @@ -1264,14 +1345,14 @@ testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] }, { time: 1000, expected: [ -1, 0, 0, -1, 100, 0 ] }]); - }, property + ': rotate on translate'); + }, `${property}: rotate on translate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); // matrix(0, 1, -1, 0, 0, 0) target.style[idlName] = 'rotate(90deg)'; - var animation = // matrix(1, 0, 0, 1, 100, 0) + const animation = // matrix(1, 0, 0, 1, 100, 0) target.animate({ [idlName]: ['translateX(100px)', // matrix(1, 0, 0, 1, 200, 0) 'translateX(200px)'] }, @@ -1280,13 +1361,13 @@ testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] }, { time: 1000, expected: [ 0, 1, -1, 0, 200, 0 ] }]); - }, property + ': translate on rotate'); + }, `${property}: translate on rotate`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'matrix(0, 1, -1, 0, 0, 0)'; - var animation = // Same matrices as above. + const animation = // Same matrices as above. target.animate({ [idlName]: [ 'matrix(1, 0, 0, 1, 100, 0)', 'matrix(1, 0, 0, 1, 200, 0)' ] }, { duration: 1000, fill: 'both', composite: 'accumulate' }); @@ -1294,13 +1375,13 @@ testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] }, { time: 1000, expected: [ 0, 1, -1, 0, 200, 0 ] }]); - }, property + ': matrix'); + }, `${property}: matrix`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rotate3d(1, 1, 0, 45deg)'; - var animation = + const animation = target.animate({ [idlName]: [ 'rotate3d(1, 1, 0, -90deg)', 'rotate3d(1, 1, 0, 90deg)'] }, { duration: 1000, fill: 'both', composite: 'accumulate' }); @@ -1308,170 +1389,240 @@ testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) }, { time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]); - }, property + ': rotate3d'); + }, `${property}: rotate3d`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); // To calculate expected matrices easily, generate input matrices from // rotate3d. target.style[idlName] = rotate3dToMatrix3d(1, 1, 0, Math.PI / 4); - var from = rotate3dToMatrix3d(1, 1, 0, -Math.PI / 2); - var to = rotate3dToMatrix3d(1, 1, 0, Math.PI / 2); - var animation = + const from = rotate3dToMatrix3d(1, 1, 0, -Math.PI / 2); + const to = rotate3dToMatrix3d(1, 1, 0, Math.PI / 2); + const animation = target.animate({ [idlName]: [ from, to ] }, { duration: 1000, fill: 'both', composite: 'accumulate' }); testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) }, { time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]); - }, property + ': matrix3d'); + }, `${property}: matrix3d`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var matrixArray = [ 1, 0, 0, 0, + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const matrixArray = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 ]; target.style[idlName] = createMatrixFromArray(matrixArray); - var animation = + const animation = target.animate({ [idlName]: [ 'none', 'none' ] }, { duration: 1000, fill: 'both', composite: 'accumulate' }); testAnimationSampleMatrices(animation, idlName, [{ time: 0, expected: matrixArray }, { time: 1000, expected: matrixArray }]); - }, property + ': none'); + }, `${property}: none`); // Following tests aim for test the fallback discrete accumulation behavior // for non-invertible matrices. The non-invertible matrix that we use is the - // singuler matrix, matrix(1, 1, 0, 0, 0, 100). - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + // singular matrix, matrix(1, 1, 0, 0, 0, 100). + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0)', 'matrix(-1, 0, 0, -1, 200, 0)'] }, 1000); - var animation = target.animate({ [idlName]: ['matrix( 1, 1, 0, 0, 0, 100)', - 'matrix( 1, 1, 0, 0, 0, 100)'] }, - { duration: 1000, composite: 'accumulate' }); - testAnimationSampleMatrices(animation, idlName, - [{ time: 0, expected: [ 1, 1, 0, 0, 0, 100 ] }]); - }, property + ': non-invertible matrices (non-invertible onto invertible)'); + const animation = target.animate( + { + [idlName]: [ + 'matrix( 1, 1, 0, 0, 0, 100)', + 'matrix( 1, 1, 0, 0, 0, 100)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [1, 1, 0, 0, 0, 100] }, + ]); + }, `${property}: non-invertible matrices (non-invertible onto invertible)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.animate({ [idlName]: ['matrix( 1, 1, 0, 0, 0, 100)', 'matrix( 1, 1, 0, 0, 0, 100)'] }, 1000); - var animation = target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0)', - 'matrix(-1, 0, 0, -1, 200, 0)'] }, - { duration: 1000, composite: 'accumulate' }); - testAnimationSampleMatrices(animation, idlName, - [{ time: 0, expected: [ -1, 0, 0, -1, 200, 0 ] }]); - }, property + ': non-invertible matrices (invertible onto non-invertible)'); + const animation = target.animate( + { + [idlName]: [ + 'matrix(-1, 0, 0, -1, 200, 0)', + 'matrix(-1, 0, 0, -1, 200, 0)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [-1, 0, 0, -1, 200, 0] }, + ]); + }, `${property}: non-invertible matrices (invertible onto non-invertible)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - // matrix(0, -1, 1, 0, 250, 0) - target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', - 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)'] }, 1000); - var animation = // matrix(-1, -1, 0, 0, 100, 100) - target.animate({ [idlName]: ['translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)', - 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)'] }, - { duration: 1000, composite: 'accumulate' }); - testAnimationSampleMatrices(animation, idlName, - [{ time: 0, expected: [ -1, -1, 0, 0, 100, 100 ] }]); - }, property + ': non-invertible matrices in matched transform lists (non-invertible onto invertible)'); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(0, -1, 1, 0, 250, 0) + target.animate( + { + [idlName]: [ + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', + ], + }, + 1000 + ); + // matrix(-1, -1, 0, 0, 100, 100) + const animation = target.animate( + { + [idlName]: [ + 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)', + 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [-1, -1, 0, 0, 100, 100] }, + ]); + }, `${property}: non-invertible matrices in matched transform lists (non-invertible onto invertible)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - // matrix(-1, -1, 0, 0, 100, 100) - target.animate({ [idlName]: ['translate(100px) matrix(1, 1, 0, 0, 0, 100) rotate(180deg)', - 'translate(100px) matrix(1, 1, 0, 0, 0, 100) rotate(180deg)'] }, 1000); - var animation = // matrix(0, -1, 1, 0, 250, 0) - target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', - 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)'] }, - { duration: 1000, composite: 'accumulate' }); - testAnimationSampleMatrices(animation, idlName, - [{ time: 0, expected: [ 0, -1, 1, 0, 250, 0 ] }]); - }, property + ': non-invertible matrices in matched transform lists (invertible onto non-invertible)'); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(-1, -1, 0, 0, 100, 100) + target.animate( + { + [idlName]: [ + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) rotate(180deg)', + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) rotate(180deg)', + ], + }, + 1000 + ); + // matrix(0, -1, 1, 0, 250, 0) + const animation = target.animate( + { + [idlName]: [ + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [0, -1, 1, 0, 250, 0] }, + ]); + }, `${property}: non-invertible matrices in matched transform lists (invertible onto non-invertible)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - // matrix(-2, 0, 0, -2, 250, 0) - target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', - 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)'] }, 1000); - var animation = // matrix(1, 1, 1, 1, 100, 100) - target.animate({ [idlName]: ['translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)', - 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)'] }, - { duration: 1000, composite: 'accumulate' }); - testAnimationSampleMatrices(animation, idlName, - [{ time: 0, expected: [ 1, 1, 1, 1, 100, 100 ] }]); - }, property + ': non-invertible matrices in mismatched transform lists' + - ' (non-invertible onto invertible)'); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(-2, 0, 0, -2, 250, 0) + target.animate( + { + [idlName]: [ + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', + ], + }, + 1000 + ); + // matrix(1, 1, 1, 1, 100, 100) + const animation = target.animate( + { + [idlName]: [ + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)', + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [1, 1, 1, 1, 100, 100] }, + ]); + }, `${property}: non-invertible matrices in mismatched transform lists` + + ' (non-invertible onto invertible)'); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - // matrix(1, 1, 1, 1, 100, 100) - target.animate({ [idlName]: ['translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)', - 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)'] }, 1000); - var animation = // matrix(-2, 0, 0, -2, 250, 0) - target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', - 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)'] }, - { duration: 1000, composite: 'accumulate' }); - testAnimationSampleMatrices(animation, idlName, - [{ time: 0, expected: [ -2, 0, 0, -2, 250, 0 ] }]); - }, property + ': non-invertible matrices in mismatched transform lists' + - ' (invertible onto non-invertible)'); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(1, 1, 1, 1, 100, 100) + target.animate( + { + [idlName]: [ + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)', + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)', + ], + }, + 1000 + ); + // matrix(-2, 0, 0, -2, 250, 0) + const animation = target.animate( + { + [idlName]: [ + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [-2, 0, 0, -2, 250, 0] }, + ]); + }, `${property}: non-invertible matrices in mismatched transform lists` + + ' (invertible onto non-invertible)'); }, }; const filterListType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: - ['blur(10px)', 'blur(50px)'] }, - 1000); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: + ['blur(10px)', 'blur(50px)'] }, + 1000); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'blur(30px)' }]); - }, property + ': blur function' ); + }, `${property}: blur function`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['hue-rotate(0deg)', - 'hue-rotate(100deg)'] }, - 1000); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['hue-rotate(0deg)', + 'hue-rotate(100deg)'] }, + 1000); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'hue-rotate(50deg)' }]); - }, property + ': hue-rotate function with same unit(deg)' ); + }, `${property}: hue-rotate function with same unit(deg)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['hue-rotate(10deg)', - 'hue-rotate(100rad)'] }, - 1000); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['hue-rotate(10deg)', + 'hue-rotate(100rad)'] }, + 1000); // 10deg = 0.1745rad. testAnimationSamples(animation, idlName, [{ time: 500, expected: 'hue-rotate(50.0873rad)' }]); - }, property + ': hue-rotate function with different unit(deg -> rad)'); + }, `${property}: hue-rotate function with different unit(deg -> rad)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate( + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( { [idlName]: ['drop-shadow(10px 10px 10px rgba(255, 0, 0, 0.4))', 'drop-shadow(50px 50px 50px rgba(0, 0, 255, 0.8))'] }, @@ -1481,12 +1632,12 @@ animation, idlName, [{ time: 500, expected: 'drop-shadow(rgba(85, 0, 170, 0.6) 30px 30px 30px)' }]); - }, property + ': drop-shadow function' ); + }, `${property}: drop-shadow function`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate( + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( { [idlName]: ['brightness(0.1) contrast(0.1) grayscale(0.1) invert(0.1) ' + 'opacity(0.1) saturate(0.1) sepia(0.1)', @@ -1498,13 +1649,13 @@ [{ time: 500, expected: 'brightness(0.3) contrast(0.3) grayscale(0.3) ' + 'invert(0.3) opacity(0.3) saturate(0.3) sepia(0.3)' }]); - }, property + ': percentage or numeric-specifiable functions' + - '(number value)'); + }, `${property}: percentage or numeric-specifiable functions` + + ' (number value)'); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate( + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( { [idlName]: ['brightness(10%) contrast(10%) grayscale(10%) invert(10%) ' + 'opacity(10%) saturate(10%) sepia(10%)', @@ -1516,13 +1667,13 @@ [{ time: 500, expected: 'brightness(0.3) contrast(0.3) grayscale(0.3) ' + 'invert(0.3) opacity(0.3) saturate(0.3) sepia(0.3)' }]); - }, property + ': percentage or numeric-specifiable functions' + - '(percentage value)'); + }, `${property}: percentage or numeric-specifiable functions` + + ' (percentage value)'); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate( + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( { [idlName]: // To make missing filter-function-lists, specified the grayscale. ['grayscale(0)', @@ -1533,13 +1684,13 @@ [{ time: 500, expected: 'grayscale(0.5) brightness(0.5) contrast(0.5) ' + 'opacity(0.5) saturate(0.5)' }]); - }, property + ': interpolate different length of filter-function-list ' + - ' with function which lacuna value is 1'); + }, `${property}: interpolate different length of filter-function-list` + + ' with function which lacuna value is 1'); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate( + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( { [idlName]: // To make missing filter-function-lists, specified the opacity. ['opoacity(1)', @@ -1550,14 +1701,14 @@ [{ time: 500, expected: 'opacity(0.5) grayscale(0.5) invert(0.5) sepia(0.5) blur(5px)' }]); - }, property + ': interpolate different length of filter-function-list ' + - ' with function which lacuna value is 0'); + }, `${property}: interpolate different length of filter-function-list` + + ' with function which lacuna value is 0'); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style.color = "rgba(255, 0, 0, 0.4)"; - var animation = target.animate( + const animation = target.animate( { [idlName]: ['blur(0px)', 'blur(10px) drop-shadow(10px 10px 10px rgba(0, 0, 255, 0.8))'] }, @@ -1568,23 +1719,23 @@ // The lacuna value of drop-shadow's color is taken from // the color property. expected: 'blur(5px) drop-shadow(rgba(85, 0, 170, 0.6) 5px 5px 5px' }]); - }, property + ': interpolate different length of filter-function-list ' + - 'with drop-shadow function'); + }, `${property}: interpolate different length of filter-function-list` + + ' with drop-shadow function'); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['none', 'blur(10px)'] }, + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['none', 'blur(10px)'] }, 1000); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'blur(5px)' }]); - }, property + ': interpolate from none'); + }, `${property}: interpolate from none`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate( + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( { [idlName]: ['blur(0px) url(\"#f1\")', 'blur(10px) url(\"#f2\")']}, @@ -1592,103 +1743,115 @@ testAnimationSamples(animation, idlName, [{ time: 499, expected: 'blur(0px) url(\"#f1\")' }, { time: 500, expected: 'blur(10px) url(\"#f2\")' }]); - }, property + ': url function (interpoalte as discrete)'); + }, `${property}: url function (interpoalte as discrete)`); }, testAddition: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'blur(10px)'; - var animation = target.animate({ [idlName]: ['blur(20px)', - 'blur(50px)'] }, - { duration: 1000, composite: 'add' }); + const animation = target.animate({ [idlName]: ['blur(20px)', + 'blur(50px)'] }, + { duration: 1000, composite: 'add' }); testAnimationSamples(animation, idlName, [ { time: 0, expected: 'blur(10px) blur(20px)' }]); - }, property + ': blur on blur'); + }, `${property}: blur on blur`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'blur(10px)'; - var animation = target.animate({ [idlName]: ['brightness(80%)', - 'brightness(40%)'] }, - { duration: 1000, composite: 'add' }); + const animation = target.animate({ [idlName]: ['brightness(80%)', + 'brightness(40%)'] }, + { duration: 1000, composite: 'add' }); testAnimationSamples(animation, idlName, [ { time: 0, expected: 'blur(10px) brightness(0.8)' }]); - }, property + ': different filter functions'); + }, `${property}: different filter functions`); }, testAccumulation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'blur(10px) brightness(0.3)'; - var animation = target.animate({ [idlName]: ['blur(20px) brightness(0.1)', - 'blur(20px) brightness(0.1)'] }, - { duration: 1000, composite: 'accumulate' }); + const animation = target.animate( + { + [idlName]: [ + 'blur(20px) brightness(0.1)', + 'blur(20px) brightness(0.1)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); // brightness(0.1) onto brightness(0.3) means // brightness((0.1 - 1.0) + (0.3 - 1.0) + 1.0). The result of this formula // is brightness(-0.6) that means brightness(0.0). testAnimationSamples(animation, idlName, [ { time: 0, expected: 'blur(30px) brightness(0)' }]); - }, property + ': same ordered filter functions'); + }, `${property}: same ordered filter functions`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'blur(10px) brightness(1.3)'; - var animation = target.animate({ [idlName]: ['brightness(1.2) blur(20px)', - 'brightness(1.2) blur(20px)'] }, - { duration: 1000, composite: 'accumulate' }); + const animation = target.animate( + { + [idlName]: [ + 'brightness(1.2) blur(20px)', + 'brightness(1.2) blur(20px)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); // Mismatched ordered functions can't be accumulated. testAnimationSamples(animation, idlName, [ { time: 0, expected: 'brightness(1.2) blur(20px)' }]); - }, property + ': mismatched ordered filter functions'); + }, `${property}: mismatched ordered filter functions`); }, }; const textShadowListType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'none', 'rgb(100, 100, 100) 10px 10px 10px'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, // Premultiplied [{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]); - }, property + ': from none to other'); + }, `${property}: from none to other`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px', 'none' ] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, // Premultiplied [{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]); - }, property + ': from other to none'); + }, `${property}: from other to none`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px', 'rgb(100, 100, 100) 10px 10px 10px'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px' }]); - }, property + ': single shadow'); + }, `${property}: single shadow`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px, ' + 'rgb(200, 200, 200) 20px 20px 20px', 'rgb(100, 100, 100) 10px 10px 10px, ' @@ -1697,12 +1860,12 @@ testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px, ' + 'rgb(150, 150, 150) 15px 15px 15px' }]); - }, property + ': shadow list'); + }, `${property}: shadow list`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'rgb(200, 200, 200) 20px 20px 20px', 'rgb(100, 100, 100) 10px 10px 10px, ' + 'rgb(100, 100, 100) 10px 10px 10px'] }, @@ -1710,12 +1873,12 @@ testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px, ' + 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]); - }, property + ': mismatched list length (from longer to shorter)'); + }, `${property}: mismatched list length (from longer to shorter)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px, ' + 'rgb(100, 100, 100) 10px 10px 10px', 'rgb(200, 200, 200) 20px 20px 20px'] }, @@ -1723,93 +1886,93 @@ testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px, ' + 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]); - }, property + ': mismatched list length (from shorter to longer)'); + }, `${property}: mismatched list length (from shorter to longer)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style.color = 'rgb(0, 255, 0)'; - var animation = + const animation = target.animate({ [idlName]: [ 'currentcolor 0px 0px 0px', 'currentcolor 10px 10px 10px'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(0, 255, 0) 5px 5px 5px' }]); - }, property + ': with currentcolor'); + }, `${property}: with currentcolor`); }, testAddition: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rgb(0, 0, 0) 0px 0px 0px'; - var animation = + const animation = target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px', 'rgb(120, 120, 120) 10px 10px 10px'] }, { duration: 1000, composite: 'add' }); testAnimationSamples(animation, idlName, [ { time: 0, expected: 'rgb(0, 0, 0) 0px 0px 0px, ' + 'rgb(120, 120, 120) 10px 10px 10px' }]); - }, property + ': shadow'); + }, `${property}: shadow`); }, testAccumulation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rgb(120, 120, 120) 10px 10px 10px'; - var animation = + const animation = target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px', 'rgb(120, 120, 120) 10px 10px 10px'] }, { duration: 1000, composite: 'accumulate' }); testAnimationSamples(animation, idlName, [ { time: 0, expected: 'rgb(240, 240, 240) 20px 20px 20px' }]); - }, property + ': shadow'); + }, `${property}: shadow`); }, }; const boxShadowListType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'none', 'rgb(100, 100, 100) 10px 10px 10px 0px'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, // Premultiplied [{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]); - }, property + ': from none to other'); + }, `${property}: from none to other`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px 0px', 'none' ] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, // Premultiplied [{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]); - }, property + ': from other to none'); + }, `${property}: from other to none`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px 0px', 'rgb(100, 100, 100) 10px 10px 10px 0px'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px 0px' }]); - }, property + ': single shadow'); + }, `${property}: single shadow`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px 0px, ' + 'rgb(200, 200, 200) 20px 20px 20px 20px', 'rgb(100, 100, 100) 10px 10px 10px 0px, ' @@ -1818,12 +1981,12 @@ testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px 0px, ' + 'rgb(150, 150, 150) 15px 15px 15px 10px' }]); - }, property + ': shadow list'); + }, `${property}: shadow list`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'rgb(200, 200, 200) 20px 20px 20px 20px', 'rgb(100, 100, 100) 10px 10px 10px 0px, ' + 'rgb(100, 100, 100) 10px 10px 10px 0px'] }, @@ -1831,12 +1994,12 @@ testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px 10px, ' + 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]); - }, property + ': mismatched list length (from shorter to longer)'); + }, `${property}: mismatched list length (from shorter to longer)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px 0px, ' + 'rgb(100, 100, 100) 10px 10px 10px 0px', 'rgb(200, 200, 200) 20px 20px 20px 20px']}, @@ -1844,79 +2007,79 @@ testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px 10px, ' + 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]); - }, property + ': mismatched list length (from longer to shorter)'); + }, `${property}: mismatched list length (from longer to shorter)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style.color = 'rgb(0, 255, 0)'; - var animation = + const animation = target.animate({ [idlName]: [ 'currentcolor 0px 0px 0px 0px', 'currentcolor 10px 10px 10px 10px'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'rgb(0, 255, 0) 5px 5px 5px 5px' }]); - }, property + ': with currentcolor'); + }, `${property}: with currentcolor`); }, testAddition: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rgb(0, 0, 0) 0px 0px 0px 0px'; - var animation = + const animation = target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px 0px', 'rgb(120, 120, 120) 10px 10px 10px 0px'] }, { duration: 1000, composite: 'add' }); testAnimationSamples(animation, idlName, [ { time: 0, expected: 'rgb(0, 0, 0) 0px 0px 0px 0px, ' + 'rgb(120, 120, 120) 10px 10px 10px 0px' }]); - }, property + ': shadow'); + }, `${property}: shadow`); }, testAccumulation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rgb(120, 120, 120) 10px 10px 10px 10px'; - var animation = + const animation = target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px 10px', 'rgb(120, 120, 120) 10px 10px 10px 10px'] }, { duration: 1000, composite: 'accumulate' }); testAnimationSamples(animation, idlName, [ { time: 0, expected: 'rgb(240, 240, 240) 20px 20px 20px 20px' }]); - }, property + ': shadow'); + }, `${property}: shadow`); }, }; const positionType = { - testInterpolation: function(property, setup) { + testInterpolation: (property, setup) => { lengthPairType.testInterpolation(property, setup); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['10% 10%', '50% 50%'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['10% 10%', '50% 50%'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples( animation, idlName, [{ time: 500, expected: calcFromPercentage(idlName, '30% 30%') }]); - }, property + ' supports animating as a position of percent'); + }, `${property} supports animating as a position of percent`); }, - testAdditionOrAccumulation: function(property, setup, composite) { + testAdditionOrAccumulation: (property, setup, composite) => { lengthPairType.testAddition(property, setup); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '60% 60%'; - var animation = target.animate({ [idlName]: ['70% 70%', '100% 100%'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: ['70% 70%', '100% 100%'] }, + { duration: 1000, composite }); testAnimationSamples( animation, idlName, [{ time: 0, expected: calcFromPercentage(idlName, '130% 130%') }]); - }, property + ': position of percentage'); + }, `${property}: position of percentage`); }, testAddition: function(property, setup) { @@ -1929,33 +2092,33 @@ }; const rectType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: - ['rect(10px, 10px, 10px, 10px)', - 'rect(50px, 50px, 50px, 50px)'] }, - { duration: 1000, fill: 'both' }); + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: + ['rect(10px, 10px, 10px, 10px)', + 'rect(50px, 50px, 50px, 50px)'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples( animation, idlName, [{ time: 500, expected: 'rect(30px, 30px, 30px, 30px)' }]); - }, property + ' supports animating as a rect'); + }, `${property} supports animating as a rect`); }, - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'rect(100px, 100px, 100px, 100px)'; - var animation = target.animate({ [idlName]: - ['rect(10px, 10px, 10px, 10px)', - 'rect(10px, 10px, 10px, 10px)'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: + ['rect(10px, 10px, 10px, 10px)', + 'rect(10px, 10px, 10px, 10px)'] }, + { duration: 1000, composite }); testAnimationSamples( animation, idlName, [{ time: 0, expected: 'rect(110px, 110px, 110px, 110px)' }]); - }, property + ': rect'); + }, `${property}: rect`); }, testAddition: function(property, setup) { @@ -1969,33 +2132,33 @@ // stroke-dasharray: none | [ <length> | <percentage> | <number> ]* const dasharrayType = { - testInterpolation: function(property, setup) { + testInterpolation: (property, setup) => { percentageType.testInterpolation(property, setup); positiveNumberType.testInterpolation(property, setup); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: - ['8, 16, 4', - '4, 8, 12, 16'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: + ['8, 16, 4', + '4, 8, 12, 16'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples( animation, idlName, [{ time: 500, expected: '6, 12, 8, 12, 10, 6, 10, 16, 4, 8, 14, 10' }]); - }, property + ' supports animating as a dasharray (mismatched length)'); + }, `${property} supports animating as a dasharray (mismatched length)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: - ['2, 50%, 6, 10', - '6, 30%, 2, 2'] }, - { duration: 1000, fill: 'both' }); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: + ['2, 50%, 6, 10', + '6, 30%, 2, 2'] }, + { duration: 1000, fill: 'both' }); testAnimationSamples( animation, idlName, [{ time: 500, expected: '4, 40%, 4, 6' }]); - }, property + ' supports animating as a dasharray (mixed number and percentage)'); + }, `${property} supports animating as a dasharray (mixed number and percentage)`); }, @@ -2003,19 +2166,19 @@ // write this additive test case that animating value replaces underlying // values. // See https://www.w3.org/TR/SVG2/painting.html#StrokeDashing. - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = '6, 30%, 2px'; - var animation = target.animate({ [idlName]: - ['1, 2, 3, 4, 5', - '6, 7, 8, 9, 10'] }, - { duration: 1000, composite: composite }); + const animation = target.animate({ [idlName]: + ['1, 2, 3, 4, 5', + '6, 7, 8, 9, 10'] }, + { duration: 1000, composite }); testAnimationSamples( animation, idlName, [{ time: 0, expected: '1, 2, 3, 4, 5' }]); - }, property + ': dasharray'); + }, `${property}: dasharray`); }, testAddition: function(property, setup) { @@ -2028,41 +2191,42 @@ } const fontStretchType = { - testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['ultra-condensed', 'extra-condensed'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 499, expected: 'ultra-condensed' }, { time: 500, expected: 'extra-condensed' }]); - }, property + ' supports animating as a font-stretch (adjacent values)'); + }, `${property} supports animating as a font-stretch (adjacent values)`); - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['ultra-condensed', 'condensed'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, [{ time: 500, expected: 'extra-condensed' }]); - }, property + ' supports animating as a font-stretch (between value)'); + }, `${property} supports animating as a font-stretch (between value)`); }, - testAdditionOrAccumulation: function(property, setup, composite) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); target.style[idlName] = 'condensed'; - var animation = + const animation = target.animate({ [idlName]: ['expanded', 'ultra-expanded'] }, - { duration: 1000, composite: composite }); + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 0, expected: 'normal' }, { time: 250, expected: 'semi-expanded' }]); - }, property + ' uses font-stretch behavior for composite type ' + composite); + }, + `${property} uses font-stretch behavior for composite type ${composite}`); }, testAddition: function(property, setup) { @@ -2123,7 +2287,7 @@ target.style[idlName] = '"wght" 1'; const animation = target.animate({ [idlName]: ['"wght" 1.1', '"wght" 1.5'] }, - { duration: 1000, composite: composite }); + { duration: 1000, composite }); testAnimationSamples(animation, idlName, [{ time: 250, expected: '"wght" 2.2' }, { time: 750, expected: '"wght" 2.4' } ]);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-visibility.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/visibility.html similarity index 66% rename from third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-visibility.html rename to third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/visibility.html index cf951b01..f5a60b4e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-visibility.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/animation-types/visibility.html
@@ -1,7 +1,9 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Effect value computation tests for 'visibility' property</title> -<link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect"> +<title>Animation type for the 'visibility' property</title> +<!-- FIXME: The following spec link should be updated once this definition has + been moved to CSS Values & Units. --> +<link rel="help" href="https://drafts.csswg.org/css-transitions/#animtype-visibility"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="../../testcommon.js"></script> @@ -11,10 +13,10 @@ <script> 'use strict'; -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ visibility: ['hidden','visible'] }, - { duration: 100 * MS_PER_SEC, fill: 'both' }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ visibility: ['hidden','visible'] }, + { duration: 100 * MS_PER_SEC, fill: 'both' }); anim.currentTime = 0; assert_equals(getComputedStyle(div).visibility, 'hidden', @@ -30,11 +32,11 @@ }, 'Visibility clamping behavior'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ visibility: ['hidden', 'visible'] }, - { duration: 100 * MS_PER_SEC, fill: 'both', - easing: 'cubic-bezier(0.25, -0.6, 0, 0.5)' }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ visibility: ['hidden', 'visible'] }, + { duration: 100 * MS_PER_SEC, fill: 'both', + easing: 'cubic-bezier(0.25, -0.6, 0, 0.5)' }); anim.currentTime = 0; assert_equals(getComputedStyle(div).visibility, 'hidden',
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/combining-effects/effect-composition.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/combining-effects/effect-composition.html index 7604bd21..d70d9d2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/combining-effects/effect-composition.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/combining-effects/effect-composition.html
@@ -1,6 +1,6 @@ <!doctype html> <meta charset=utf-8> -<title>Test for effect composition</title> +<title>Effect composition</title> <link rel="help" href="https://w3c.github.io/web-animations/#effect-composition"> <script src=/resources/testharness.js></script> <script src=/resources/testharnessreport.js></script> @@ -9,21 +9,21 @@ <script> 'use strict'; -[ 'accumulate', 'add' ].forEach(function(composite) { - test(function(t) { - var div = createDiv(t); +for (const composite of ['accumulate', 'add']) { + test(t => { + const div = createDiv(t); div.style.marginLeft = '10px'; - var anim = + const anim = div.animate({ marginLeft: ['0px', '10px'], composite }, 100); anim.currentTime = 50; assert_equals(getComputedStyle(div).marginLeft, '15px', 'Animated margin-left style at 50%'); - }, composite + ' onto the base value'); + }, `${composite} onto the base value`); - test(function(t) { - var div = createDiv(t); - var anims = []; + test(t => { + const div = createDiv(t); + const anims = []; anims.push(div.animate({ marginLeft: ['10px', '20px'], composite: 'replace' }, 100)); @@ -31,18 +31,18 @@ composite }, 100)); - anims.forEach(function(anim) { + for (const anim of anims) { anim.currentTime = 50; - }); + } assert_equals(getComputedStyle(div).marginLeft, '20px', 'Animated style at 50%'); - }, composite + ' onto an underlying animation value'); + }, `${composite} onto an underlying animation value`); - test(function(t) { - var div = createDiv(t); + test(t => { + const div = createDiv(t); div.style.marginLeft = '10px'; - var anim = + const anim = div.animate([{ marginLeft: '10px', composite }, { marginLeft: '30px', composite: 'replace' }], 100); @@ -50,12 +50,12 @@ anim.currentTime = 50; assert_equals(getComputedStyle(div).marginLeft, '25px', 'Animated style at 50%'); - }, 'Composite when mixing ' + composite + ' and replace'); + }, `Composite when mixing ${composite} and replace`); - test(function(t) { - var div = createDiv(t); + test(t => { + const div = createDiv(t); div.style.marginLeft = '10px'; - var anim = + const anim = div.animate([{ marginLeft: '10px', composite: 'replace' }, { marginLeft: '20px' }], { duration: 100 , composite }); @@ -63,13 +63,13 @@ anim.currentTime = 50; assert_equals(getComputedStyle(div).marginLeft, '20px', 'Animated style at 50%'); - }, composite + ' specified on a keyframe overrides the composite mode of ' + - 'the effect'); + }, `${composite} specified on a keyframe overrides the composite mode of` + + ' the effect'); - test(function(t) { - var div = createDiv(t); + test(t => { + const div = createDiv(t); div.style.marginLeft = '10px'; - var anim = + const anim = div.animate([{ marginLeft: '10px', composite: 'replace' }, { marginLeft: '20px' }], 100); @@ -78,8 +78,8 @@ anim.currentTime = 50; // (10 + (10 + 20)) * 0.5 assert_equals(getComputedStyle(div).marginLeft, '20px', 'Animated style at 50%'); - }, 'unspecified composite mode on a keyframe is overriden by setting ' + - composite + ' of the effect'); -}); + }, 'unspecified composite mode on a keyframe is overriden by setting' + + ` ${composite} of the effect`); +} </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-context.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-context.html index 07fb609..4115ed64 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-context.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-context.html
@@ -1,19 +1,21 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Tests that property values respond to changes to their context</title> -<link rel="help" href="https://w3c.github.io/web-animations/#keyframes-section"> +<title>The effect value of a keyframe effect: Property values that depend on + their context (target element)</title> +<link rel="help" href="https://w3c.github.io/web-animations/#calculating-computed-keyframes"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="../../testcommon.js"></script> <body> <div id="log"></div> <script> +'use strict'; -test(function(t) { - var div = createDiv(t); +test(t => { + const div = createDiv(t); div.style.fontSize = '10px'; - var animation = div.animate([ { marginLeft: '10em' }, - { marginLeft: '20em' } ], 1000); + const animation = div.animate([ { marginLeft: '10em' }, + { marginLeft: '20em' } ], 1000); animation.currentTime = 500; assert_equals(getComputedStyle(div).marginLeft, '150px', 'Effect value before updating font-size'); @@ -22,14 +24,14 @@ 'Effect value after updating font-size'); }, 'Effect values reflect changes to font-size on element'); -test(function(t) { - var parentDiv = createDiv(t); - var div = createDiv(t); +test(t => { + const parentDiv = createDiv(t); + const div = createDiv(t); parentDiv.appendChild(div); parentDiv.style.fontSize = '10px'; - var animation = div.animate([ { marginLeft: '10em' }, - { marginLeft: '20em' } ], 1000); + const animation = div.animate([ { marginLeft: '10em' }, + { marginLeft: '20em' } ], 1000); animation.currentTime = 500; assert_equals(getComputedStyle(div).marginLeft, '150px', 'Effect value before updating font-size on parent element'); @@ -38,38 +40,38 @@ 'Effect value after updating font-size on parent element'); }, 'Effect values reflect changes to font-size on parent element'); -promise_test(function(t) { - var parentDiv = createDiv(t); - var div = createDiv(t); +promise_test(t => { + const parentDiv = createDiv(t); + const div = createDiv(t); parentDiv.appendChild(div); parentDiv.style.fontSize = '10px'; - var animation = div.animate([ { marginLeft: '10em' }, - { marginLeft: '20em' } ], 1000); + const animation = div.animate([ { marginLeft: '10em' }, + { marginLeft: '20em' } ], 1000); animation.pause(); animation.currentTime = 500; parentDiv.style.fontSize = '20px'; - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(getComputedStyle(div).marginLeft, '300px', 'Effect value after updating font-size on parent element'); }); }, 'Effect values reflect changes to font-size when computed style is not' + ' immediately flushed'); -promise_test(function(t) { - var divWith10pxFontSize = createDiv(t); +promise_test(t => { + const divWith10pxFontSize = createDiv(t); divWith10pxFontSize.style.fontSize = '10px'; - var divWith20pxFontSize = createDiv(t); + const divWith20pxFontSize = createDiv(t); divWith20pxFontSize.style.fontSize = '20px'; - var div = createDiv(t); + const div = createDiv(t); div.remove(); // Detach - var animation = div.animate([ { marginLeft: '10em' }, - { marginLeft: '20em' } ], 1000); + const animation = div.animate([ { marginLeft: '10em' }, + { marginLeft: '20em' } ], 1000); animation.pause(); - return animation.ready.then(function() { + return animation.ready.then(() => { animation.currentTime = 500; divWith10pxFontSize.appendChild(div); @@ -81,15 +83,15 @@ }); }, 'Effect values reflect changes to font-size from reparenting'); -test(function(t) { - var divA = createDiv(t); +test(t => { + const divA = createDiv(t); divA.style.fontSize = '10px'; - var divB = createDiv(t); + const divB = createDiv(t); divB.style.fontSize = '20px'; - var animation = divA.animate([ { marginLeft: '10em' }, - { marginLeft: '20em' } ], 1000); + const animation = divA.animate([ { marginLeft: '10em' }, + { marginLeft: '20em' } ], 1000); animation.currentTime = 500; assert_equals(getComputedStyle(divA).marginLeft, '150px', 'Effect value before updating target element');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation-expected.txt new file mode 100644 index 0000000..ebc51d9e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation-expected.txt
@@ -0,0 +1,35 @@ +This is a testharness.js-based test. +PASS iteration composition of discrete type animation (align-content) +FAIL iteration composition of <length> type animation assert_equals: Animated margin-left style at 0s of the third iteration expected "20px" but got "0px" +FAIL iteration composition of <percentage> type animation assert_equals: Animated width style at 0s of the third iteration expected "100px" but got "0px" +FAIL iteration composition of <color> type animation assert_equals: Animated color style at 0s of the third iteration expected "rgb(240, 240, 240)" but got "rgb(0, 0, 0)" +FAIL iteration composition of <color> type animation that green component is decreasing assert_equals: Animated color style at 0s of the third iteration expected "rgb(120, 240, 120)" but got "rgb(0, 120, 0)" +FAIL iteration composition of <number> type animation assert_equals: Animated flex-grow style at 0s of the third iteration expected "20" but got "0" +FAIL iteration composition of <shape> type animation assert_equals: Animated clip style at 0s of the third iteration expected "rect(20px, 20px, 20px, 20px)" but got "rect(0px, 0px, 0px, 0px)" +FAIL iteration composition of <calc()> value animation assert_equals: Animated calc width style at 0s of the third iteration expected "20px" but got "0px" +FAIL iteration composition of <calc()> value animation that the values can'tbe reduced assert_equals: Animated calc width style at 0s of the third iteration expected "40px" but got "0px" +FAIL iteration composition of opacity animation assert_equals: Animated opacity style at 0s of the third iteration expected "0.8" but got "0" +FAIL iteration composition of box-shadow animation assert_equals: Animated box-shadow style at 0s of the third iteration expected "rgb(240, 240, 240) 20px 20px 20px 0px" but got "rgb(0, 0, 0) 0px 0px 0px 0px" +FAIL iteration composition of filter blur animation assert_equals: Animated filter blur style at 0s of the third iteration expected "blur(20px)" but got "blur(0px)" +FAIL iteration composition of filter brightness for different unit animation assert_equals: Animated filter brightness style at 0s of the third iteration expected "brightness(2.6)" but got "brightness(1)" +PASS iteration composition of filter brightness animation +FAIL iteration composition of filter drop-shadow animation assert_equals: Animated filter drop-shadow style at 0s of the third iteration expected "drop-shadow(rgb(240, 240, 240) 20px 20px 20px)" but got "drop-shadow(rgb(0, 0, 0) 0px 0px 0px)" +FAIL iteration composition of same filter list animation assert_equals: Animated filter list at 0s of the third iteration expected "brightness(3) contrast(3)" but got "brightness(1) contrast(1)" +FAIL iteration composition of discrete filter list because of mismatch of the order assert_equals: Animated filter list at 50s of the third iteration expected "contrast(4) brightness(4)" but got "contrast(2) brightness(2)" +FAIL iteration composition of different length filter list animation assert_equals: Animated filter list at 0s of the third iteration expected "sepia(2) contrast(3)" but got "sepia(0)" +PASS iteration composition of transform(rotate) animation +PASS iteration composition of transform: [ scale(0), scale(1) ] animation +FAIL iteration composition of transform: [ scale(1), scale(2) ] animation assert_approx_equals: expected matrix(3, 0, 0, 3, 0, 0) but got matrix(1, 0, 0, 1, 0, 0): Animated transform(scale) style at 0s of the third iteration expected 3 +/- 0.0001 but got 1 +FAIL iteration composition of transform: scale(2) animation assert_approx_equals: expected matrix(2, 0, 0, 2, 0, 0) but got matrix(0, 0, 0, 0, 0, 0): Animated transform(scale) style at 0s of the third iteration expected 2 +/- 0.0001 but got 0 +FAIL iteration composition of transform list animation assert_approx_equals: expected matrix(1, 0, 0, 1, 20, 0) but got matrix(1, 0, 0, 1, 0, 0): Animated transform list at 0s of the third iteration expected 20 +/- 0.0001 but got 0 +FAIL iteration composition of transform of matrix function assert_approx_equals: expected matrix(6, 0, 0, 6, 60, 0) but got matrix(2, 0, 0, 2, 0, 0): Animated transform of matrix function at 0s of the third iteration expected 6 +/- 0.0001 but got 2 +FAIL iteration composition of transform list animation whose order is mismatched assert_approx_equals: expected matrix(6, 0, 0, 6, 60, 0) but got matrix(2, 0, 0, 2, 0, 0): Animated transform list at 0s of the third iteration expected 6 +/- 0.0001 but got 2 +FAIL iteration composition of transform list animation whose order is mismatched because of missing functions assert_approx_equals: expected matrix(3, 0, 0, 3, 40, 0) but got matrix(1, 0, 0, 1, 0, 0): Animated transform list at 0s of the third iteration expected 3 +/- 0.0001 but got 1 +FAIL iteration composition of transform from none to translate assert_approx_equals: expected matrix(1, 0, 0, 1, 20, 0) but got matrix(1, 0, 0, 1, 0, 0): Animated transform list at 0s of the third iteration expected 20 +/- 0.0001 but got 0 +FAIL iteration composition of transform of matrix3d function assert_approx_equals: expected matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1) but got matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 30, 1): Animated transform of matrix3d function at 0s of the third iteration expected 130 +/- 0.0001 but got 30 +FAIL iteration composition of transform of rotate3d function assert_equals: dimension of the matrix: Animated transform of rotate3d function at 0s of the third iteration expected 16 but got 6 +FAIL iteration composition starts with non-zero value animation assert_equals: Animated margin-left style at 0s of the third iteration expected "50px" but got "10px" +FAIL iteration composition with negative final value animation assert_equals: Animated margin-left style at 0s of the third iteration expected "-10px" but got "10px" +FAIL duration changes with an iteration composition operation of accumulate assert_equals: Animated style at 50s of the third iteration expected "25px" but got "5px" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html new file mode 100644 index 0000000..29da85e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html
@@ -0,0 +1,819 @@ +<!doctype html> +<meta charset=utf-8> +<title>The effect value of a keyframe effect: Applying the iteration composite + operation</title> +<link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect"> +<link rel="help" href="https://w3c.github.io/web-animations/#effect-accumulation-section"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="../../testcommon.js"></script> +<div id="log"></div> +<script> +'use strict'; + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ alignContent: ['flex-start', 'flex-end'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).alignContent, 'flex-end', + 'Animated align-content style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).alignContent, 'flex-start', + 'Animated align-content style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).alignContent, 'flex-end', + 'Animated align-content style at 50s of the third iteration'); +}, 'iteration composition of discrete type animation (align-content)'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ marginLeft: ['0px', '10px'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).marginLeft, '5px', + 'Animated margin-left style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).marginLeft, '20px', + 'Animated margin-left style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).marginLeft, '25px', + 'Animated margin-left style at 50s of the third iteration'); +}, 'iteration composition of <length> type animation'); + +test(t => { + const parent = createDiv(t); + parent.style.width = '100px'; + const div = createDiv(t); + parent.appendChild(div); + + const anim = + div.animate({ width: ['0%', '50%'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).width, '25px', + 'Animated width style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).width, '100px', + 'Animated width style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).width, '125px', + 'Animated width style at 50s of the third iteration'); +}, 'iteration composition of <percentage> type animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ color: ['rgb(0, 0, 0)', 'rgb(120, 120, 120)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).color, 'rgb(60, 60, 60)', + 'Animated color style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).color, 'rgb(240, 240, 240)', + 'Animated color style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).color, 'rgb(255, 255, 255)', + 'Animated color style at 50s of the third iteration'); +}, 'iteration composition of <color> type animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ color: ['rgb(0, 120, 0)', 'rgb(60, 60, 60)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).color, 'rgb(30, 90, 30)', + 'Animated color style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).color, 'rgb(120, 240, 120)', + 'Animated color style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + // The green color is (240 + 180) / 2 = 210 + assert_equals(getComputedStyle(div).color, 'rgb(150, 210, 150)', + 'Animated color style at 50s of the third iteration'); +}, 'iteration composition of <color> type animation that green component is ' + + 'decreasing'); + + test(t => { + const div = createDiv(t); + const anim = + div.animate({ flexGrow: [0, 10] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).flexGrow, '5', + 'Animated flex-grow style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).flexGrow, '20', + 'Animated flex-grow style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).flexGrow, '25', + 'Animated flex-grow style at 50s of the third iteration'); +}, 'iteration composition of <number> type animation'); + +test(t => { + const div = createDiv(t); + div.style.position = 'absolute'; + const anim = + div.animate({ clip: ['rect(0px, 0px, 0px, 0px)', + 'rect(10px, 10px, 10px, 10px)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).clip, 'rect(5px, 5px, 5px, 5px)', + 'Animated clip style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).clip, 'rect(20px, 20px, 20px, 20px)', + 'Animated clip style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).clip, 'rect(25px, 25px, 25px, 25px)', + 'Animated clip style at 50s of the third iteration'); +}, 'iteration composition of <shape> type animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ width: ['calc(0vw + 0px)', 'calc(0vw + 10px)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).width, '5px', + 'Animated calc width style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).width, '20px', + 'Animated calc width style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).width, '25px', + 'Animated calc width style at 50s of the third iteration'); +}, 'iteration composition of <calc()> value animation'); + +test(t => { + const parent = createDiv(t); + parent.style.width = '100px'; + const div = createDiv(t); + parent.appendChild(div); + + const anim = + div.animate({ width: ['calc(0% + 0px)', 'calc(10% + 10px)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).width, '10px', + // 100px * 5% + 5px + 'Animated calc width style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).width, + '40px', // 100px * (10% + 10%) + (10px + 10px) + 'Animated calc width style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).width, + '50px', // (40px + 60px) / 2 + 'Animated calc width style at 50s of the third iteration'); +}, 'iteration composition of <calc()> value animation that the values can\'t' + + 'be reduced'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ opacity: [0, 0.4] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).opacity, '0.2', + 'Animated opacity style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).opacity, '0.8', + 'Animated opacity style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).opacity, '1', // (0.8 + 1.2) * 0.5 + 'Animated opacity style at 50s of the third iteration'); +}, 'iteration composition of opacity animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ boxShadow: ['rgb(0, 0, 0) 0px 0px 0px 0px', + 'rgb(120, 120, 120) 10px 10px 10px 0px'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).boxShadow, + 'rgb(60, 60, 60) 5px 5px 5px 0px', + 'Animated box-shadow style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).boxShadow, + 'rgb(240, 240, 240) 20px 20px 20px 0px', + 'Animated box-shadow style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).boxShadow, + 'rgb(255, 255, 255) 25px 25px 25px 0px', + 'Animated box-shadow style at 50s of the third iteration'); +}, 'iteration composition of box-shadow animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ filter: ['blur(0px)', 'blur(10px)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, 'blur(5px)', + 'Animated filter blur style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).filter, 'blur(20px)', + 'Animated filter blur style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, 'blur(25px)', + 'Animated filter blur style at 50s of the third iteration'); +}, 'iteration composition of filter blur animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ filter: ['brightness(1)', + 'brightness(180%)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + 'brightness(1.4)', + 'Animated filter brightness style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).filter, + 'brightness(2.6)', // brightness(1) + brightness(0.8) + brightness(0.8) + 'Animated filter brightness style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + 'brightness(3)', // (brightness(2.6) + brightness(3.4)) * 0.5 + 'Animated filter brightness style at 50s of the third iteration'); +}, 'iteration composition of filter brightness for different unit animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ filter: ['brightness(0)', + 'brightness(1)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + 'brightness(0.5)', + 'Animated filter brightness style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).filter, + 'brightness(0)', // brightness(1) is an identity element, not accumulated. + 'Animated filter brightness style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + 'brightness(0.5)', // brightness(1) is an identity element, not accumulated. + 'Animated filter brightness style at 50s of the third iteration'); +}, 'iteration composition of filter brightness animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ filter: ['drop-shadow(rgb(0, 0, 0) 0px 0px 0px)', + 'drop-shadow(rgb(120, 120, 120) 10px 10px 10px)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + 'drop-shadow(rgb(60, 60, 60) 5px 5px 5px)', + 'Animated filter drop-shadow style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).filter, + 'drop-shadow(rgb(240, 240, 240) 20px 20px 20px)', + 'Animated filter drop-shadow style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + 'drop-shadow(rgb(255, 255, 255) 25px 25px 25px)', + 'Animated filter drop-shadow style at 50s of the third iteration'); +}, 'iteration composition of filter drop-shadow animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ filter: ['brightness(1) contrast(1)', + 'brightness(2) contrast(2)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + 'brightness(1.5) contrast(1.5)', + 'Animated filter list at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).filter, + 'brightness(3) contrast(3)', + 'Animated filter list at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + 'brightness(3.5) contrast(3.5)', + 'Animated filter list at 50s of the third iteration'); +}, 'iteration composition of same filter list animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ filter: ['brightness(1) contrast(1)', + 'contrast(2) brightness(2)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + 'contrast(2) brightness(2)', // discrete + 'Animated filter list at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).filter, + // We can't accumulate 'contrast(2) brightness(2)' onto + // the first list 'brightness(1) contrast(1)' because of + // mismatch of the order. + 'brightness(1) contrast(1)', + 'Animated filter list at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + // We *can* accumulate 'contrast(2) brightness(2)' onto + // the same list 'contrast(2) brightness(2)' here. + 'contrast(4) brightness(4)', // discrete + 'Animated filter list at 50s of the third iteration'); +}, 'iteration composition of discrete filter list because of mismatch ' + + 'of the order'); + + test(t => { + const div = createDiv(t); + const anim = + div.animate({ filter: ['sepia(0)', + 'sepia(1) contrast(2)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + 'sepia(0.5) contrast(1.5)', + 'Animated filter list at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).filter, + 'sepia(2) contrast(3)', + 'Animated filter list at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).filter, + 'sepia(2.5) contrast(3.5)', + 'Animated filter list at 50s of the third iteration'); +}, 'iteration composition of different length filter list animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ transform: ['rotate(0deg)', 'rotate(180deg)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(0, 1, -1, 0, 0, 0)', // rotate(90deg) + 'Animated transform(rotate) style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(1, 0, 0, 1, 0, 0)', // rotate(360deg) + 'Animated transform(rotate) style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(0, 1, -1, 0, 0, 0)', // rotate(450deg) + 'Animated transform(rotate) style at 50s of the third iteration'); +}, 'iteration composition of transform(rotate) animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ transform: ['scale(0)', 'scale(1)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5) + 'Animated transform(scale) style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(0, 0, 0, 0, 0, 0)', // scale(0); scale(1) is an identity element, + // not accumulated. + 'Animated transform(scale) style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5); scale(1) an identity + // element, not accumulated. + 'Animated transform(scale) style at 50s of the third iteration'); +}, 'iteration composition of transform: [ scale(0), scale(1) ] animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ transform: ['scale(1)', 'scale(2)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(1.5, 0, 0, 1.5, 0, 0)', // scale(1.5) + 'Animated transform(scale) style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(3, 0, 0, 3, 0, 0)', // scale(1 + (2 -1) + (2 -1)) + 'Animated transform(scale) style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(3.5, 0, 0, 3.5, 0, 0)', // (scale(3) + scale(4)) * 0.5 + 'Animated transform(scale) style at 50s of the third iteration'); +}, 'iteration composition of transform: [ scale(1), scale(2) ] animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ transform: ['scale(0)', 'scale(2)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(1, 0, 0, 1, 0, 0)', // scale(1) + 'Animated transform(scale) style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(2, 0, 0, 2, 0, 0)', // (scale(0) + scale(2-1)*2) + 'Animated transform(scale) style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(3, 0, 0, 3, 0, 0)', // (scale(2) + scale(4)) * 0.5 + 'Animated transform(scale) style at 50s of the third iteration'); +}, 'iteration composition of transform: scale(2) animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ transform: ['rotate(0deg) translateX(0px)', + 'rotate(180deg) translateX(10px)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(0, 1, -1, 0, 0, 5)', // rotate(90deg) translateX(5px) + 'Animated transform list at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(1, 0, 0, 1, 20, 0)', // rotate(360deg) translateX(20px) + 'Animated transform list at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(0, 1, -1, 0, 0, 25)', // rotate(450deg) translateX(25px) + 'Animated transform list at 50s of the third iteration'); +}, 'iteration composition of transform list animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ transform: ['matrix(2, 0, 0, 2, 0, 0)', + 'matrix(3, 0, 0, 3, 30, 0)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(2.5, 0, 0, 2.5, 15, 0)', + 'Animated transform of matrix function at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_matrix_equals(getComputedStyle(div).transform, + // scale(2) + (scale(3-1)*2) + translateX(30px)*2 + 'matrix(6, 0, 0, 6, 60, 0)', + 'Animated transform of matrix function at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + // from: matrix(6, 0, 0, 6, 60, 0) + // to: matrix(7, 0, 0, 7, 90, 0) + // = scale(3) + (scale(3-1)*2) + translateX(30px)*3 + 'matrix(6.5, 0, 0, 6.5, 75, 0)', + 'Animated transform of matrix function at 50s of the third iteration'); +}, 'iteration composition of transform of matrix function'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ transform: ['translateX(0px) scale(2)', + 'scale(3) translateX(10px)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + // Interpolate between matrix(2, 0, 0, 2, 0, 0) = translateX(0px) scale(2) + // and matrix(3, 0, 0, 3, 30, 0) = scale(3) translateX(10px) + 'matrix(2.5, 0, 0, 2.5, 15, 0)', + 'Animated transform list at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_matrix_equals(getComputedStyle(div).transform, + // 'from' and 'to' value are mismatched, so accumulate + // matrix(2, 0, 0, 2, 0, 0) onto matrix(3, 0, 0, 3, 30, 0) * 2 + // = scale(2) + (scale(3-1)*2) + translateX(30px)*2 + 'matrix(6, 0, 0, 6, 60, 0)', + 'Animated transform list at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + // Interpolate between matrix(6, 0, 0, 6, 60, 0) + // and matrix(7, 0, 0, 7, 210, 0) = scale(7) translate(30px) + 'matrix(6.5, 0, 0, 6.5, 135, 0)', + 'Animated transform list at 50s of the third iteration'); +}, 'iteration composition of transform list animation whose order is' + + ' mismatched'); + +test(t => { + const div = createDiv(t); + // Even if each transform list does not have functions which exist in + // other pair of the list, we don't fill any missing functions at all. + const anim = + div.animate({ transform: ['translateX(0px)', + 'scale(2) translateX(10px)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + // Interpolate between matrix(1, 0, 0, 1, 0, 0) = translateX(0px) + // and matrix(2, 0, 0, 2, 20, 0) = scale(2) translateX(10px) + 'matrix(1.5, 0, 0, 1.5, 10, 0)', + 'Animated transform list at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_matrix_equals(getComputedStyle(div).transform, + // 'from' and 'to' value are mismatched, so accumulate + // matrix(1, 0, 0, 1, 0, 0) onto matrix(2, 0, 0, 2, 20, 0) * 2 + // = scale(1) + (scale(2-1)*2) + translateX(20px)*2 + 'matrix(3, 0, 0, 3, 40, 0)', + 'Animated transform list at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + // Interpolate between matrix(3, 0, 0, 3, 40, 0) + // and matrix(4, 0, 0, 4, 120, 0) = + // scale(2 + (2-1)*2) translate(10px * 3) + 'matrix(3.5, 0, 0, 3.5, 80, 0)', + 'Animated transform list at 50s of the third iteration'); +}, 'iteration composition of transform list animation whose order is' + + ' mismatched because of missing functions'); + + test(t => { + const div = createDiv(t); + const anim = + div.animate({ transform: ['none', + 'translateX(10px)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + // translateX(none) -> translateX(10px) @ 50% + 'matrix(1, 0, 0, 1, 5, 0)', + 'Animated transform list at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_matrix_equals(getComputedStyle(div).transform, + // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 0% + 'matrix(1, 0, 0, 1, 20, 0)', + 'Animated transform list at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 50% + 'matrix(1, 0, 0, 1, 25, 0)', + 'Animated transform list at 50s of the third iteration'); +}, 'iteration composition of transform from none to translate'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ transform: ['matrix3d(1, 0, 0, 0, ' + + '0, 1, 0, 0, ' + + '0, 0, 1, 0, ' + + '0, 0, 30, 1)', + 'matrix3d(1, 0, 0, 0, ' + + '0, 1, 0, 0, ' + + '0, 0, 1, 0, ' + + '0, 0, 50, 1)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 40, 1)', + 'Animated transform of matrix3d function at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_matrix_equals(getComputedStyle(div).transform, + // translateZ(30px) + (translateZ(50px)*2) + 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)', + 'Animated transform of matrix3d function at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + // from: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1) + // to: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 150, 1) + 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 140, 1)', + 'Animated transform of matrix3d function at 50s of the third iteration'); +}, 'iteration composition of transform of matrix3d function'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ transform: ['rotate3d(1, 1, 0, 0deg)', + 'rotate3d(1, 1, 0, 90deg)'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = 0; + assert_matrix_equals(getComputedStyle(div).transform, + 'matrix(1, 0, 0, 1, 0, 0)', // Actually not rotated at all. + 'Animated transform of rotate3d function at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_matrix_equals(getComputedStyle(div).transform, + rotate3dToMatrix3d(1, 1, 0, Math.PI), // 180deg + 'Animated transform of rotate3d function at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_matrix_equals(getComputedStyle(div).transform, + rotate3dToMatrix3d(1, 1, 0, 225 * Math.PI / 180), //((270 + 180) * 0.5)deg + 'Animated transform of rotate3d function at 50s of the third iteration'); +}, 'iteration composition of transform of rotate3d function'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ marginLeft: ['10px', '20px'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).marginLeft, '15px', + 'Animated margin-left style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).marginLeft, '50px', // 10px + 20px + 20px + 'Animated margin-left style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).marginLeft, '55px', // (50px + 60px) * 0.5 + 'Animated margin-left style at 50s of the third iteration'); +}, 'iteration composition starts with non-zero value animation'); + +test(t => { + const div = createDiv(t); + const anim = + div.animate({ marginLeft: ['10px', '-10px'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).marginLeft, + '0px', + 'Animated margin-left style at 50s of the first iteration'); + anim.currentTime = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).marginLeft, + '-10px', // 10px + -10px + -10px + 'Animated margin-left style at 0s of the third iteration'); + anim.currentTime += anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).marginLeft, + '-20px', // (-10px + -30px) * 0.5 + 'Animated margin-left style at 50s of the third iteration'); +}, 'iteration composition with negative final value animation'); + +test(t => { + const div = createDiv(t); + const anim = div.animate({ marginLeft: ['0px', '10px'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); + anim.pause(); + + anim.currentTime = + anim.effect.timing.duration * 2 + anim.effect.timing.duration / 2; + assert_equals(getComputedStyle(div).marginLeft, '25px', + 'Animated style at 50s of the third iteration'); + + // double its duration. + anim.effect.timing.duration = anim.effect.timing.duration * 2; + assert_equals(getComputedStyle(div).marginLeft, '12.5px', + 'Animated style at 25s of the first iteration'); + + // half of original. + anim.effect.timing.duration = anim.effect.timing.duration / 4; + assert_equals(getComputedStyle(div).marginLeft, '50px', + 'Animated style at 50s of the fourth iteration'); +}, 'duration changes with an iteration composition operation of accumulate'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html index 99b4f3d..011b76f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Effect value computation tests when keyframes overlap</title> +<title>The effect value of a keyframe effect: Overlapping keyframes</title> <link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -11,16 +11,16 @@ <script> 'use strict'; -test(function(t) { - var div = createDiv(t); - var anim = div.animate([ { offset: 0, opacity: 0 }, - { offset: 0, opacity: 0.1 }, - { offset: 0, opacity: 0.2 }, - { offset: 1, opacity: 0.8 }, - { offset: 1, opacity: 0.9 }, - { offset: 1, opacity: 1 } ], - { duration: 1000, - easing: 'cubic-bezier(0.5, -0.5, 0.5, 1.5)' }); +test(t => { + const div = createDiv(t); + const anim = div.animate([ { offset: 0, opacity: 0 }, + { offset: 0, opacity: 0.1 }, + { offset: 0, opacity: 0.2 }, + { offset: 1, opacity: 0.8 }, + { offset: 1, opacity: 0.9 }, + { offset: 1, opacity: 1 } ], + { duration: 1000, + easing: 'cubic-bezier(0.5, -0.5, 0.5, 1.5)' }); assert_equals(getComputedStyle(div).opacity, '0.2', 'When progress is zero the last keyframe with offset 0 should' + ' be used'); @@ -47,13 +47,13 @@ }, 'Overlapping keyframes at 0 and 1 use the appropriate value when the' + ' progress is outside the range [0, 1]'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate([ { offset: 0, opacity: 0 }, - { offset: 0.5, opacity: 0.3 }, - { offset: 0.5, opacity: 0.5 }, - { offset: 0.5, opacity: 0.7 }, - { offset: 1, opacity: 1 } ], 1000); +test(t => { + const div = createDiv(t); + const anim = div.animate([ { offset: 0, opacity: 0 }, + { offset: 0.5, opacity: 0.3 }, + { offset: 0.5, opacity: 0.5 }, + { offset: 0.5, opacity: 0.7 }, + { offset: 1, opacity: 1 } ], 1000); anim.currentTime = 250; assert_equals(getComputedStyle(div).opacity, '0.15', 'Before the overlap point, the first keyframe from the'
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html index 87efd42..1f7065c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Tests for calculation of the transformed distance when computing an effect value</title> +<title>The effect value of a keyframe effect: Calculating the transformed + distance between keyframes</title> <link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -13,8 +14,8 @@ // Test that applying easing to keyframes is applied as expected -gEasingTests.forEach(params => { - test(function(t) { +for (const params of gEasingTests) { + test(t => { const target = createDiv(t); const anim = target.animate([ { width: '0px' }, // We put the easing on the second keyframe @@ -25,7 +26,7 @@ { duration: 2000, fill: 'forwards' }); - [ 0, 999, 1000, 1100, 1500, 2000 ].forEach(sampleTime => { + for (const sampleTime of [0, 999, 1000, 1100, 1500, 2000]) { anim.currentTime = sampleTime; const portion = (sampleTime - 1000) / 1000; @@ -37,18 +38,18 @@ 0.01, 'The width should be approximately ' + `${expectedWidth} at ${sampleTime}ms`); - }); + } }, `A ${params.desc} on a keyframe affects the resulting style`); -}); +} // Test that a linear-equivalent cubic-bezier easing applied to a keyframe does // not alter (including clamping) the result. -gEasingTests.forEach(params => { +for (const params of gEasingTests) { const linearEquivalentEasings = [ 'cubic-bezier(0, 0, 0, 0)', 'cubic-bezier(1, 1, 1, 1)' ]; - test(function(t) { - linearEquivalentEasings.forEach(linearEquivalentEasing => { + test(t => { + for (const linearEquivalentEasing of linearEquivalentEasings) { const timing = { duration: 1000, fill: 'forwards', easing: params.easing }; @@ -65,7 +66,7 @@ { width: '100px' } ], timing); - [ 0, 250, 500, 750, 1000 ].forEach(sampleTime => { + for (const sampleTime of [0, 250, 500, 750, 1000]) { linearAnim.currentTime = sampleTime; equivalentAnim.currentTime = sampleTime; @@ -73,11 +74,11 @@ getComputedStyle(equivalentTarget).width, `The 'width' of the animated elements should be equal ` + `at ${sampleTime}ms`); - }); - }); + } + } }, 'Linear-equivalent cubic-bezier keyframe easing applied to an effect ' + `with a ${params.desc} does not alter the result`); -}); +} </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt index 14da79c..36647164 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt
@@ -79,13 +79,13 @@ PASS Element.animate() does not accept empty property-indexed keyframe with an invalid easing PASS Element.animate() does not accept empty property-indexed keyframe with an invalid easings array PASS Element.animate() does not accept a keyframe sequence with an invalid easing value -FAIL Element.animate() does not accept property-indexed keyframes with an invalid composite value assert_throws: function "function () { +FAIL Element.animate() does not accept property-indexed keyframes with an invalid composite value assert_throws: function "() => { div.animate(subtest.input, 2000); }" did not throw -FAIL Element.animate() does not accept property-indexed keyframes with an invalid composite value as one of the array values assert_throws: function "function () { +FAIL Element.animate() does not accept property-indexed keyframes with an invalid composite value as one of the array values assert_throws: function "() => { div.animate(subtest.input, 2000); }" did not throw -FAIL Element.animate() does not accept keyframes with an invalid composite value assert_throws: function "function () { +FAIL Element.animate() does not accept keyframes with an invalid composite value assert_throws: function "() => { div.animate(subtest.input, 2000); }" did not throw PASS Element.animate() does not accept invalid easing: ''
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-no-browsing-context.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-no-browsing-context.html index 1037195..e4fd70a4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-no-browsing-context.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-no-browsing-context.html
@@ -1,6 +1,6 @@ <!doctype html> <meta charset=utf-8> -<title>Animatable.animate tests in combination with elements in documents +<title>Animatable.animate in combination with elements in documents without a browsing context</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animatable-animate"> <script src="/resources/testharness.js"></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate.html index a07103c..5464711 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Animatable.animate tests</title> +<title>Animatable.animate</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animatable-animate"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -16,16 +16,16 @@ // Tests on Element -test(function(t) { - var div = createDiv(t); - var anim = div.animate(null); +test(t => { + const div = createDiv(t); + const anim = div.animate(null); assert_class_string(anim, 'Animation', 'Returned object is an Animation'); }, 'Element.animate() creates an Animation object'); -test(function(t) { - var iframe = window.frames[0]; - var div = createDiv(t, iframe.document); - var anim = Element.prototype.animate.call(div, null); +test(t => { + const iframe = window.frames[0]; + const div = createDiv(t, iframe.document); + const anim = Element.prototype.animate.call(div, null); assert_equals(Object.getPrototypeOf(anim), iframe.Animation.prototype, 'The prototype of the created Animation is that defined on' + ' the relevant global for the target element'); @@ -35,17 +35,17 @@ }, 'Element.animate() creates an Animation object in the relevant realm of' + ' the target element'); -test(function(t) { - var div = createDiv(t); - var anim = Element.prototype.animate.call(div, null); +test(t => { + const div = createDiv(t); + const anim = Element.prototype.animate.call(div, null); assert_class_string(anim.effect, 'KeyframeEffect', 'Returned Animation has a KeyframeEffect'); }, 'Element.animate() creates an Animation object with a KeyframeEffect'); -test(function(t) { - var iframe = window.frames[0]; - var div = createDiv(t, iframe.document); - var anim = Element.prototype.animate.call(div, null); +test(t => { + const iframe = window.frames[0]; + const div = createDiv(t, iframe.document); + const anim = Element.prototype.animate.call(div, null); assert_equals(Object.getPrototypeOf(anim.effect), iframe.KeyframeEffect.prototype, 'The prototype of the created KeyframeEffect is that defined on' @@ -57,10 +57,10 @@ }, 'Element.animate() creates an Animation object with a KeyframeEffect' + ' that is created in the relevant realm of the target element'); -test(function(t) { - var iframe = window.frames[0]; - var div = createDiv(t, iframe.document); - var anim = div.animate(null); +test(t => { + const iframe = window.frames[0]; + const div = createDiv(t, iframe.document); + const anim = div.animate(null); assert_equals(Object.getPrototypeOf(anim.effect.timing), iframe.AnimationEffectTiming.prototype, 'The prototype of the created AnimationEffectTiming is that' @@ -73,91 +73,91 @@ + ' whose AnimationEffectTiming object is created in the relevant realm' + ' of the target element'); -gEmptyKeyframeListTests.forEach(function(subTest) { - test(function(t) { - var div = createDiv(t); - var anim = div.animate(subTest, 2000); +for (const subtest of gEmptyKeyframeListTests) { + test(t => { + const div = createDiv(t); + const anim = div.animate(subtest, 2000); assert_not_equals(anim, null); }, 'Element.animate() accepts empty keyframe lists ' + - `(input: ${JSON.stringify(subTest)})`); -}); + `(input: ${JSON.stringify(subtest)})`); +} -gKeyframesTests.forEach(function(subtest) { - test(function(t) { - var div = createDiv(t); - var anim = div.animate(subtest.input, 2000); +for (const subtest of gKeyframesTests) { + test(t => { + const div = createDiv(t); + const anim = div.animate(subtest.input, 2000); assert_frame_lists_equal(anim.effect.getKeyframes(), subtest.output); - }, 'Element.animate() accepts ' + subtest.desc); -}); + }, `Element.animate() accepts ${subtest.desc}`); +} -gInvalidKeyframesTests.forEach(function(subtest) { - test(function(t) { - var div = createDiv(t); - assert_throws(new TypeError, function() { +for (const subtest of gInvalidKeyframesTests) { + test(t => { + const div = createDiv(t); + assert_throws(new TypeError, () => { div.animate(subtest.input, 2000); }); - }, 'Element.animate() does not accept ' + subtest.desc); -}); + }, `Element.animate() does not accept ${subtest.desc}`); +} -gInvalidEasings.forEach(invalidEasing => { - test(function(t) { - var div = createDiv(t); +for (const invalidEasing of gInvalidEasings) { + test(t => { + const div = createDiv(t); assert_throws(new TypeError, () => { div.animate({ easing: invalidEasing }, 2000); }); }, `Element.animate() does not accept invalid easing: '${invalidEasing}'`); -}); +} -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); assert_equals(anim.effect.timing.duration, 2000); // Also check that unspecified parameters receive their default values assert_equals(anim.effect.timing.fill, 'auto'); }, 'Element.animate() accepts a double as an options argument'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { duration: Infinity, fill: 'forwards' }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { duration: Infinity, fill: 'forwards' }); assert_equals(anim.effect.timing.duration, Infinity); assert_equals(anim.effect.timing.fill, 'forwards'); // Also check that unspecified parameters receive their default values assert_equals(anim.effect.timing.direction, 'normal'); }, 'Element.animate() accepts a KeyframeAnimationOptions argument'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }); assert_equals(anim.effect.timing.duration, 'auto'); }, 'Element.animate() accepts an absent options argument'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); assert_equals(anim.id, ''); }, 'Element.animate() correctly sets the id attribute when no id is specified'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, { id: 'test' }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, { id: 'test' }); assert_equals(anim.id, 'test'); }, 'Element.animate() correctly sets the id attribute'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); assert_equals(anim.timeline, document.timeline); }, 'Element.animate() correctly sets the Animation\'s timeline'); -async_test(function(t) { - var iframe = document.createElement('iframe'); +async_test(t => { + const iframe = document.createElement('iframe'); iframe.width = 10; iframe.height = 10; - iframe.addEventListener('load', t.step_func(function() { - var div = createDiv(t, iframe.contentDocument); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); + iframe.addEventListener('load', t.step_func(() => { + const div = createDiv(t, iframe.contentDocument); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); assert_equals(anim.timeline, iframe.contentDocument.timeline); iframe.remove(); t.done(); @@ -167,23 +167,23 @@ }, 'Element.animate() correctly sets the Animation\'s timeline when ' + 'triggered on an element in a different document'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); assert_equals(anim.playState, 'pending'); }, 'Element.animate() calls play on the Animation'); // Tests on CSSPseudoElement -test(function(t) { - var pseudoTarget = createPseudo(t, 'before'); - var anim = pseudoTarget.animate(null); +test(t => { + const pseudoTarget = createPseudo(t, 'before'); + const anim = pseudoTarget.animate(null); assert_class_string(anim, 'Animation', 'The returned object is an Animation'); }, 'CSSPseudoElement.animate() creates an Animation object'); -test(function(t) { - var pseudoTarget = createPseudo(t, 'before'); - var anim = pseudoTarget.animate(null); +test(t => { + const pseudoTarget = createPseudo(t, 'before'); + const anim = pseudoTarget.animate(null); assert_equals(anim.effect.target, pseudoTarget, 'The returned Animation targets to the correct object'); }, 'CSSPseudoElement.animate() creates an Animation object targeting ' +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/getAnimations.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/getAnimations.html index 49551a8..ec50df3f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/getAnimations.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/getAnimations.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Animatable.getAnimations tests</title> +<title>Animatable.getAnimations</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animatable-getanimations"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -9,62 +9,148 @@ <script> 'use strict'; -test(function(t) { - var div = createDiv(t); +test(t => { + const div = createDiv(t); assert_array_equals(div.getAnimations(), []); -}, 'Test getAnimations on element with no animations'); +}, 'Returns an empty array for an element with no animations'); -test(function(t) { - var div = createDiv(t); - var animationA = div.animate(null, 100 * MS_PER_SEC); - var animationB = div.animate(null, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animationA = div.animate(null, 100 * MS_PER_SEC); + const animationB = div.animate(null, 100 * MS_PER_SEC); assert_array_equals(div.getAnimations(), [animationA, animationB]); -}, 'Test getAnimations on element with two animations'); +}, 'Returns both animations for an element with two animations'); -test(function(t) { - var divA = createDiv(t); - var divB = createDiv(t); - var animationA = divA.animate(null, 100 * MS_PER_SEC); - var animationB = divB.animate(null, 100 * MS_PER_SEC); +test(t => { + const divA = createDiv(t); + const divB = createDiv(t); + const animationA = divA.animate(null, 100 * MS_PER_SEC); + const animationB = divB.animate(null, 100 * MS_PER_SEC); assert_array_equals(divA.getAnimations(), [animationA], 'divA'); assert_array_equals(divB.getAnimations(), [animationB], 'divB'); -}, 'Test getAnimations on separate elements with separate animations'); +}, 'Returns only the animations specific to each sibling element'); -test(function(t) { - var divParent = createDiv(t); - var divChild = createDiv(t); +test(t => { + const divParent = createDiv(t); + const divChild = createDiv(t); divParent.appendChild(divChild); - var animationParent = divParent.animate(null, 100 * MS_PER_SEC); - var animationChild = divChild.animate(null, 100 * MS_PER_SEC); - assert_array_equals(divParent.getAnimations(), [animationParent], 'divParent'); + const animationParent = divParent.animate(null, 100 * MS_PER_SEC); + const animationChild = divChild.animate(null, 100 * MS_PER_SEC); + assert_array_equals(divParent.getAnimations(), [animationParent], + 'divParent'); assert_array_equals(divChild.getAnimations(), [animationChild], 'divChild'); -}, 'Test getAnimations on parent and child elements with separate animations'); +}, 'Returns only the animations specific to each parent/child element'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate(null, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate(null, 100 * MS_PER_SEC); animation.finish(); assert_array_equals(div.getAnimations(), []); -}, 'Test getAnimations on element with finished fill none animation'); +}, 'Does not return finished animations that do not fill forwards'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate(null, { +test(t => { + const div = createDiv(t); + const animation = div.animate(null, { duration: 100 * MS_PER_SEC, fill: 'forwards', }); animation.finish(); assert_array_equals(div.getAnimations(), [animation]); -}, 'Test getAnimations on element with finished fill forwards animation'); +}, 'Returns finished animations that fill forwards'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate(null, { +test(t => { + const div = createDiv(t); + const animation = div.animate(null, { duration: 100 * MS_PER_SEC, delay: 100 * MS_PER_SEC, }); assert_array_equals(div.getAnimations(), [animation]); -}, 'Test getAnimations on element with delayed animation'); +}, 'Returns animations in their delay phase'); + +test(t => { + const div = createDiv(t); + const animation = div.animate(null, 100 * MS_PER_SEC); + + animation.finish(); + assert_array_equals(div.getAnimations(), [], + 'Animation should not be returned when it is finished'); + + animation.effect.timing.duration += 100 * MS_PER_SEC; + assert_array_equals(div.getAnimations(), [animation], + 'Animation should be returned after extending the' + + ' duration'); + + animation.effect.timing.duration = 0; + assert_array_equals(div.getAnimations(), [], + 'Animation should not be returned after setting the' + + ' duration to zero'); +}, 'Returns animations based on dynamic changes to individual' + + ' animations\' duration'); + +test(t => { + const div = createDiv(t); + const animation = div.animate(null, 100 * MS_PER_SEC); + + animation.effect.timing.endDelay = -200 * MS_PER_SEC; + assert_array_equals(div.getAnimations(), [], + 'Animation should not be returned after setting a' + + ' negative end delay such that the end time is less' + + ' than the current time'); + + animation.effect.timing.endDelay = 100 * MS_PER_SEC; + assert_array_equals(div.getAnimations(), [animation], + 'Animation should be returned after setting a positive' + + ' end delay such that the end time is more than the' + + ' current time'); +}, 'Returns animations based on dynamic changes to individual' + + ' animations\' end delay'); + +test(t => { + const div = createDiv(t); + const animation = div.animate(null, 100 * MS_PER_SEC); + + animation.finish(); + assert_array_equals(div.getAnimations(), [], + 'Animation should not be returned when it is finished'); + + animation.effect.timing.iterations = 10; + assert_array_equals(div.getAnimations(), [animation], + 'Animation should be returned after inreasing the' + + ' number of iterations'); + + animation.effect.timing.iterations = 0; + assert_array_equals(div.getAnimations(), [], + 'Animations should not be returned after setting the' + + ' iteration count to zero'); + + animation.effect.timing.iterations = Infinity; + assert_array_equals(div.getAnimations(), [animation], + 'Animation should be returned after inreasing the' + + ' number of iterations to infinity'); +}, 'Returns animations based on dynamic changes to individual' + + ' animations\' iteration count'); + +test(t => { + const div = createDiv(t); + const animation = div.animate(null, + { duration: 100 * MS_PER_SEC, + delay: 50 * MS_PER_SEC, + endDelay: -50 * MS_PER_SEC }); + + assert_array_equals(div.getAnimations(), [animation], + 'Animation should be returned at during delay phase'); + + animation.currentTime = 50 * MS_PER_SEC; + assert_array_equals(div.getAnimations(), [animation], + 'Animation should be returned after seeking to the start' + + ' of the active interval'); + + animation.currentTime = 100 * MS_PER_SEC; + assert_array_equals(div.getAnimations(), [], + 'Animation should not be returned after seeking to the' + + ' clipped end of the active interval'); +}, 'Returns animations based on dynamic changes to individual' + + ' animations\' current time'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/cancel.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/cancel.html index f8f174a..a342b2e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/cancel.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/cancel.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Animation.cancel()</title> +<title>Animation.cancel</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-cancel"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -10,11 +10,13 @@ <script> 'use strict'; -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({transform: ['translate(100px)', 'translate(100px)']}, - 100 * MS_PER_SEC); - return animation.ready.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate( + { transform: ['translate(100px)', 'translate(100px)'] }, + 100 * MS_PER_SEC + ); + return animation.ready.then(() => { assert_not_equals(getComputedStyle(div).transform, 'none', 'transform style is animated before cancelling'); animation.cancel(); @@ -23,10 +25,10 @@ }); }, 'Animated style is cleared after calling Animation.cancel()'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({marginLeft: ['100px', '200px']}, - 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate({ marginLeft: ['100px', '200px'] }, + 100 * MS_PER_SEC); animation.effect.timing.easing = 'linear'; animation.cancel(); assert_equals(getComputedStyle(div).marginLeft, '0px', @@ -38,11 +40,11 @@ + ' seeked'); }, 'After cancelling an animation, it can still be seeked'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({marginLeft:['100px', '200px']}, - 100 * MS_PER_SEC); - return animation.ready.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({ marginLeft:['100px', '200px'] }, + 100 * MS_PER_SEC); + return animation.ready.then(() => { animation.cancel(); assert_equals(getComputedStyle(div).marginLeft, '0px', 'margin-left style is not animated after cancelling'); @@ -50,7 +52,7 @@ assert_equals(getComputedStyle(div).marginLeft, '100px', 'margin-left style is animated after re-starting animation'); return animation.ready; - }).then(function() { + }).then(() => { assert_equals(animation.playState, 'running', 'Animation succeeds in running after being re-started'); });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/constructor.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/constructor.html index 4f76194..6b7978cd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/constructor.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/constructor.html
@@ -1,8 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Animation constructor tests</title> -<link rel="help" href="http://w3c.github.io/web-animations/#dom-animation-animation"> -<link rel="author" title="Hiroyuki Ikezoe" href="mailto:hiikezoe@mozilla-japan.org"> +<title>Animation constructor</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-animation"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="../../testcommon.js"></script> @@ -10,9 +9,9 @@ <div id="log"></div> <div id="target"></div> <script> -"use strict"; +'use strict'; -var gTarget = document.getElementById("target"); +const gTarget = document.getElementById('target'); function createEffect() { return new KeyframeEffectReadOnly(gTarget, { opacity: [0, 1] }); @@ -22,94 +21,94 @@ return null; } -var gTestArguments = [ +const gTestArguments = [ { createEffect: createNull, timeline: null, expectedTimeline: null, - expectedTimelineDescription: "null", - description: "with null effect and null timeline" + expectedTimelineDescription: 'null', + description: 'with null effect and null timeline' }, { createEffect: createNull, timeline: document.timeline, expectedTimeline: document.timeline, - expectedTimelineDescription: "document.timeline", - description: "with null effect and non-null timeline" + expectedTimelineDescription: 'document.timeline', + description: 'with null effect and non-null timeline' }, { createEffect: createNull, expectedTimeline: document.timeline, - expectedTimelineDescription: "document.timeline", - description: "with null effect and no timeline parameter" + expectedTimelineDescription: 'document.timeline', + description: 'with null effect and no timeline parameter' }, { createEffect: createEffect, timeline: null, expectedTimeline: null, - expectedTimelineDescription: "null", - description: "with non-null effect and null timeline" + expectedTimelineDescription: 'null', + description: 'with non-null effect and null timeline' }, { createEffect: createEffect, timeline: document.timeline, expectedTimeline: document.timeline, - expectedTimelineDescription: "document.timeline", - description: "with non-null effect and non-null timeline" + expectedTimelineDescription: 'document.timeline', + description: 'with non-null effect and non-null timeline' }, { createEffect: createEffect, expectedTimeline: document.timeline, - expectedTimelineDescription: "document.timeline", - description: "with non-null effect and no timeline parameter" + expectedTimelineDescription: 'document.timeline', + description: 'with non-null effect and no timeline parameter' }, ]; -gTestArguments.forEach(function(args) { - test(function(t) { - var effect = args.createEffect(); - var animation = new Animation(effect, args.timeline); +for (const args of gTestArguments) { + test(t => { + const effect = args.createEffect(); + const animation = new Animation(effect, args.timeline); assert_not_equals(animation, null, - "An animation sohuld be created"); + 'An animation sohuld be created'); assert_equals(animation.effect, effect, - "Animation returns the same effect passed to " + - "the Constructor"); + 'Animation returns the same effect passed to ' + + 'the Constructor'); assert_equals(animation.timeline, args.expectedTimeline, - "Animation timeline should be " + args.expectedTimelineDescription); - assert_equals(animation.playState, "idle", - "Animation.playState should be initially 'idle'"); - }, "Animation can be constructed " + args.description); -}); + 'Animation timeline should be ' + args.expectedTimelineDescription); + assert_equals(animation.playState, 'idle', + 'Animation.playState should be initially \'idle\''); + }, 'Animation can be constructed ' + args.description); +} -test(function(t) { - var effect = new KeyframeEffectReadOnly(null, - { left: ["10px", "20px"] }, - { duration: 10000, - fill: "forwards" }); - var anim = new Animation(effect, document.timeline); +test(t => { + const effect = new KeyframeEffectReadOnly(null, + { left: ['10px', '20px'] }, + { duration: 10000, + fill: 'forwards' }); + const anim = new Animation(effect, document.timeline); anim.pause(); assert_equals(effect.getComputedTiming().progress, 0.0); anim.currentTime += 5000; assert_equals(effect.getComputedTiming().progress, 0.5); anim.finish(); assert_equals(effect.getComputedTiming().progress, 1.0); -}, "Animation constructed by an effect with null target runs normally"); +}, 'Animation constructed by an effect with null target runs normally'); -async_test(function(t) { - var iframe = document.createElement('iframe'); +async_test(t => { + const iframe = document.createElement('iframe'); - iframe.addEventListener('load', t.step_func(function() { - var div = createDiv(t, iframe.contentDocument); - var effect = new KeyframeEffectReadOnly(div, null, 10000); - var anim = new Animation(effect); + iframe.addEventListener('load', t.step_func(() => { + const div = createDiv(t, iframe.contentDocument); + const effect = new KeyframeEffectReadOnly(div, null, 10000); + const anim = new Animation(effect); assert_equals(anim.timeline, document.timeline); iframe.remove(); t.done(); })); document.body.appendChild(iframe); -}, "Animation constructed with a keyframe that target element is in iframe"); +}, 'Animation constructed with a keyframe that target element is in iframe'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/effect.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/effect.html index 3c9c4f0..339028e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/effect.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/effect.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Animation.effect tests</title> +<title>Animation.effect</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-effect"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -8,22 +8,22 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; -test(function(t) { - var anim = new Animation(); - assert_equals(anim.effect, null, "initial effect is null"); +test(t => { + const anim = new Animation(); + assert_equals(anim.effect, null, 'initial effect is null'); - var newEffect = new KeyframeEffectReadOnly(createDiv(t), null); + const newEffect = new KeyframeEffectReadOnly(createDiv(t), null); anim.effect = newEffect; - assert_equals(anim.effect, newEffect, "new effect is set"); -}, "effect is set correctly."); + assert_equals(anim.effect, newEffect, 'new effect is set'); +}, 'effect is set correctly.'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({ left: ['100px', '100px'] }, - { fill: 'forwards' }); - var effect = animation.effect; +test(t => { + const div = createDiv(t); + const animation = div.animate({ left: ['100px', '100px'] }, + { fill: 'forwards' }); + const effect = animation.effect; assert_equals(getComputedStyle(div).left, '100px', 'animation is initially having an effect');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finish.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finish.html index 9b9c4c7..c413d04 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finish.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finish.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Animation.finish()</title> +<title>Animation.finish</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-finish"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -10,32 +10,32 @@ <script> 'use strict'; -var gKeyFrames = { 'marginLeft': ['100px', '200px'] }; +const gKeyFrames = { 'marginLeft': ['100px', '200px'] }; -test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); animation.playbackRate = 0; - assert_throws({name: 'InvalidStateError'}, function() { + assert_throws({name: 'InvalidStateError'}, () => { animation.finish(); }); }, 'Test exceptions when finishing non-running animation'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, - {duration : 100 * MS_PER_SEC, - iterations : Infinity}); +test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, + { duration : 100 * MS_PER_SEC, + iterations : Infinity }); - assert_throws({name: 'InvalidStateError'}, function() { + assert_throws({name: 'InvalidStateError'}, () => { animation.finish(); }); }, 'Test exceptions when finishing infinite animation'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); animation.finish(); assert_equals(animation.currentTime, 100 * MS_PER_SEC, @@ -43,9 +43,9 @@ 'of the active duration'); }, 'Test finishing of animation'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); // 1s past effect end animation.currentTime = animation.effect.getComputedTiming().endTime + 1 * MS_PER_SEC; @@ -56,11 +56,11 @@ 'end of the active duration'); }, 'Test finishing of animation with a current time past the effect end'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); animation.currentTime = 100 * MS_PER_SEC; - return animation.finished.then(function() { + return animation.finished.then(() => { animation.playbackRate = -1; animation.finish(); @@ -70,11 +70,11 @@ }); }, 'Test finishing of reversed animation'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); animation.currentTime = 100 * MS_PER_SEC; - return animation.finished.then(function() { + return animation.finished.then(() => { animation.playbackRate = -1; animation.currentTime = -1000; animation.finish(); @@ -85,11 +85,11 @@ }); }, 'Test finishing of reversed animation with a current time less than zero'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); animation.pause(); - return animation.ready.then(function() { + return animation.ready.then(() => { animation.finish(); assert_equals(animation.playState, 'finished', @@ -102,9 +102,9 @@ }); }, 'Test finish() while paused'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); animation.pause(); // Update playbackRate so we can test that the calculated startTime // respects it @@ -121,9 +121,9 @@ 'be set after calling finish()'); }, 'Test finish() while pause-pending with positive playbackRate'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); animation.pause(); animation.playbackRate = -2; animation.finish(); @@ -136,9 +136,9 @@ 'set after calling finish()'); }, 'Test finish() while pause-pending with negative playbackRate'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); animation.playbackRate = 0.5; animation.finish(); @@ -155,10 +155,10 @@ // - In that case even after calling finish() we should still be pending but // the current time should be updated -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); - return animation.ready.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); + return animation.ready.then(() => { animation.pause(); animation.play(); // We are now in the unusual situation of being play-pending whilst having @@ -172,13 +172,13 @@ }); }, 'Test finish() during aborted pause'); -promise_test(function(t) { - var div = createDiv(t); +promise_test(t => { + const div = createDiv(t); div.style.marginLeft = '10px'; - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); - return animation.ready.then(function() { + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); + return animation.ready.then(() => { animation.finish(); - var marginLeft = parseFloat(getComputedStyle(div).marginLeft); + const marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, 10, 'The computed style should be reset when finish() is ' + @@ -186,34 +186,34 @@ }); }, 'Test resetting of computed style'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); - var resolvedFinished = false; - animation.finished.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC); + let resolvedFinished = false; + animation.finished.then(() => { resolvedFinished = true; }); - return animation.ready.then(function() { + return animation.ready.then(() => { animation.finish(); - }).then(function() { + }).then(() => { assert_true(resolvedFinished, 'Animation.finished should be resolved soon after ' + 'Animation.finish()'); }); }, 'Test finish() resolves finished promise synchronously'); -promise_test(function(t) { - var effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC); - var animation = new Animation(effect, document.timeline); - var resolvedFinished = false; - animation.finished.then(function() { +promise_test(t => { + const effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC); + const animation = new Animation(effect, document.timeline); + let resolvedFinished = false; + animation.finished.then(() => { resolvedFinished = true; }); - return animation.ready.then(function() { + return animation.ready.then(() => { animation.finish(); - }).then(function() { + }).then(() => { assert_true(resolvedFinished, 'Animation.finished should be resolved soon after ' + 'Animation.finish()'); @@ -221,20 +221,20 @@ }, 'Test finish() resolves finished promise synchronously with an animation ' + 'without a target'); -promise_test(function(t) { - var effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC); - var animation = new Animation(effect, document.timeline); +promise_test(t => { + const effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC); + const animation = new Animation(effect, document.timeline); animation.play(); - var resolvedFinished = false; - animation.finished.then(function() { + let resolvedFinished = false; + animation.finished.then(() => { resolvedFinished = true; }); - return animation.ready.then(function() { + return animation.ready.then(() => { animation.currentTime = animation.effect.getComputedTiming().endTime - 1; return waitForAnimationFrames(2); - }).then(function() { + }).then(() => { assert_true(resolvedFinished, 'Animation.finished should be resolved soon after ' + 'Animation finishes normally');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished.html index 006b54a0a..7d0aa387 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished.html
@@ -8,13 +8,13 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var previousFinishedPromise = animation.finished; - return animation.ready.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + const previousFinishedPromise = animation.finished; + return animation.ready.then(() => { assert_equals(animation.finished, previousFinishedPromise, 'Finished promise is the same object when playing starts'); animation.pause(); @@ -27,18 +27,18 @@ animation.currentTime = 100 * MS_PER_SEC; return animation.finished; - }).then(function() { + }).then(() => { assert_equals(animation.finished, previousFinishedPromise, 'Finished promise is the same object when playing completes'); }); }, 'Test pausing then playing does not change the finished promise'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var previousFinishedPromise = animation.finished; +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + let previousFinishedPromise = animation.finished; animation.finish(); - return animation.finished.then(function() { + return animation.finished.then(() => { assert_equals(animation.finished, previousFinishedPromise, 'Finished promise is the same object when playing completes'); animation.play(); @@ -53,12 +53,12 @@ }); }, 'Test restarting a finished animation'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var previousFinishedPromise; +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + let previousFinishedPromise; animation.finish(); - return animation.finished.then(function() { + return animation.finished.then(() => { previousFinishedPromise = animation.finished; animation.playbackRate = -1; assert_not_equals(animation.finished, previousFinishedPromise, @@ -66,7 +66,7 @@ 'finished promise'); animation.currentTime = 0; return animation.finished; - }).then(function() { + }).then(() => { previousFinishedPromise = animation.finished; animation.play(); assert_not_equals(animation.finished, previousFinishedPromise, @@ -75,12 +75,12 @@ }); }, 'Test restarting a reversed finished animation'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var previousFinishedPromise = animation.finished; +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + const previousFinishedPromise = animation.finished; animation.finish(); - return animation.finished.then(function() { + return animation.finished.then(() => { animation.currentTime = 100 * MS_PER_SEC + 1000; assert_equals(animation.finished, previousFinishedPromise, 'Finished promise is unchanged jumping past end of ' + @@ -88,71 +88,71 @@ }); }, 'Test redundant finishing of animation'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); // Setup callback to run if finished promise is resolved - var finishPromiseResolved = false; - animation.finished.then(function() { + let finishPromiseResolved = false; + animation.finished.then(() => { finishPromiseResolved = true; }); - return animation.ready.then(function() { + return animation.ready.then(() => { // Jump to mid-way in interval and pause animation.currentTime = 100 * MS_PER_SEC / 2; animation.pause(); return animation.ready; - }).then(function() { + }).then(() => { // Jump to the end // (But don't use finish() since that should unpause as well) animation.currentTime = 100 * MS_PER_SEC; return waitForAnimationFrames(2); - }).then(function() { + }).then(() => { assert_false(finishPromiseResolved, 'Finished promise should not resolve when paused'); }); }, 'Finished promise does not resolve when paused'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); // Setup callback to run if finished promise is resolved - var finishPromiseResolved = false; - animation.finished.then(function() { + let finishPromiseResolved = false; + animation.finished.then(() => { finishPromiseResolved = true; }); - return animation.ready.then(function() { + return animation.ready.then(() => { // Jump to mid-way in interval and pause animation.currentTime = 100 * MS_PER_SEC / 2; animation.pause(); // Jump to the end animation.currentTime = 100 * MS_PER_SEC; return waitForAnimationFrames(2); - }).then(function() { + }).then(() => { assert_false(finishPromiseResolved, 'Finished promise should not resolve when pause-pending'); }); }, 'Finished promise does not resolve when pause-pending'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.finish(); - return animation.finished.then(function(resolvedAnimation) { + return animation.finished.then(resolvedAnimation => { assert_equals(resolvedAnimation, animation, 'Object identity of animation passed to Promise callback' + ' matches the animation object owning the Promise'); }); }, 'The finished promise is fulfilled with its Animation'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var previousFinishedPromise = animation.finished; +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + const previousFinishedPromise = animation.finished; // Set up listeners on finished promise - var retPromise = animation.finished.then(function() { + const retPromise = animation.finished.then(() => { assert_unreached('finished promise was fulfilled'); - }).catch(function(err) { + }).catch(err => { assert_equals(err.name, 'AbortError', 'finished promise is rejected with AbortError'); assert_not_equals(animation.finished, previousFinishedPromise, @@ -166,12 +166,12 @@ }, 'finished promise is rejected when an animation is cancelled by calling ' + 'cancel()'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var previousFinishedPromise = animation.finished; +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + const previousFinishedPromise = animation.finished; animation.finish(); - return animation.finished.then(function() { + return animation.finished.then(() => { animation.cancel(); assert_not_equals(animation.finished, previousFinishedPromise, 'A new finished promise should be created when' @@ -179,20 +179,20 @@ }); }, 'cancelling an already-finished animation replaces the finished promise'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.cancel(); // The spec says we still create a new finished promise and reject the old // one even if we're already idle. That behavior might change, but for now // test that we do that. - var retPromise = animation.finished.catch(function(err) { + const retPromise = animation.finished.catch(err => { assert_equals(err.name, 'AbortError', 'finished promise is rejected with AbortError'); }); // Redundant call to cancel(); - var previousFinishedPromise = animation.finished; + const previousFinishedPromise = animation.finished; animation.cancel(); assert_not_equals(animation.finished, previousFinishedPromise, 'A redundant call to cancel() should still generate a new' @@ -200,15 +200,15 @@ return retPromise; }, 'cancelling an idle animation still replaces the finished promise'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); const HALF_DUR = 100 * MS_PER_SEC / 2; const QUARTER_DUR = 100 * MS_PER_SEC / 4; - var gotNextFrame = false; - var currentTimeBeforeShortening; + let gotNextFrame = false; + let currentTimeBeforeShortening; animation.currentTime = HALF_DUR; - return animation.ready.then(function() { + return animation.ready.then(() => { currentTimeBeforeShortening = animation.currentTime; animation.effect.timing.duration = QUARTER_DUR; // Below we use gotNextFrame to check that shortening of the animation @@ -216,17 +216,17 @@ // getting resolved on the next animation frame. This relies on the fact // that the promises are resolved as a micro-task before the next frame // happens. - waitForAnimationFrames(1).then(function() { + waitForAnimationFrames(1).then(() => { gotNextFrame = true; }); return animation.finished; - }).then(function() { + }).then(() => { assert_false(gotNextFrame, 'shortening of the animation duration should ' + 'resolve the finished promise'); assert_equals(animation.currentTime, currentTimeBeforeShortening, 'currentTime should be unchanged when duration shortened'); - var previousFinishedPromise = animation.finished; + const previousFinishedPromise = animation.finished; animation.effect.timing.duration = 100 * MS_PER_SEC; assert_not_equals(animation.finished, previousFinishedPromise, 'Finished promise should change after lengthening the ' + @@ -234,16 +234,16 @@ }); }, 'Test finished promise changes for animation duration changes'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var retPromise = animation.ready.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + const retPromise = animation.ready.then(() => { animation.playbackRate = 0; animation.currentTime = 100 * MS_PER_SEC + 1000; return waitForAnimationFrames(2); }); - animation.finished.then(t.step_func(function() { + animation.finished.then(t.step_func(() => { assert_unreached('finished promise should not resolve when playbackRate ' + 'is zero'); })); @@ -251,21 +251,21 @@ return retPromise; }, 'Test finished promise changes when playbackRate == 0'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - return animation.ready.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + return animation.ready.then(() => { animation.playbackRate = -1; return animation.finished; }); }, 'Test finished promise resolves when reaching to the natural boundary.'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var previousFinishedPromise = animation.finished; +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + const previousFinishedPromise = animation.finished; animation.finish(); - return animation.finished.then(function() { + return animation.finished.then(() => { animation.currentTime = 0; assert_not_equals(animation.finished, previousFinishedPromise, 'Finished promise should change once a prior ' + @@ -275,10 +275,10 @@ }, 'Test finished promise changes when a prior finished promise resolved ' + 'and the animation falls out finished state'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var previousFinishedPromise = animation.finished; +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + const previousFinishedPromise = animation.finished; animation.currentTime = 100 * MS_PER_SEC; animation.currentTime = 100 * MS_PER_SEC / 2; assert_equals(animation.finished, previousFinishedPromise, @@ -287,10 +287,10 @@ }, 'Test no new finished promise generated when finished state ' + 'is checked asynchronously'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var previousFinishedPromise = animation.finished; +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + const previousFinishedPromise = animation.finished; animation.finish(); animation.currentTime = 100 * MS_PER_SEC / 2; assert_not_equals(animation.finished, previousFinishedPromise, @@ -299,17 +299,17 @@ }, 'Test new finished promise generated when finished state ' + 'is checked synchronously'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var resolvedFinished = false; - animation.finished.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + let resolvedFinished = false; + animation.finished.then(() => { resolvedFinished = true; }); - return animation.ready.then(function() { + return animation.ready.then(() => { animation.finish(); animation.currentTime = 100 * MS_PER_SEC / 2; - }).then(function() { + }).then(() => { assert_true(resolvedFinished, 'Animation.finished should be resolved even if ' + 'the finished state is changed soon'); @@ -318,18 +318,18 @@ }, 'Test synchronous finished promise resolved even if finished state ' + 'is changed soon'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var resolvedFinished = false; - animation.finished.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + let resolvedFinished = false; + animation.finished.then(() => { resolvedFinished = true; }); - return animation.ready.then(function() { + return animation.ready.then(() => { animation.currentTime = 100 * MS_PER_SEC; animation.finish(); - }).then(function() { + }).then(() => { assert_true(resolvedFinished, 'Animation.finished should be resolved soon after finish() is ' + 'called even if there are other asynchronous promises just before it'); @@ -337,26 +337,26 @@ }, 'Test synchronous finished promise resolved even if asynchronous ' + 'finished promise happens just before synchronous promise'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - animation.finished.then(t.step_func(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + animation.finished.then(t.step_func(() => { assert_unreached('Animation.finished should not be resolved'); })); - return animation.ready.then(function() { + return animation.ready.then(() => { animation.currentTime = 100 * MS_PER_SEC; animation.currentTime = 100 * MS_PER_SEC / 2; }); }, 'Test finished promise is not resolved when the animation ' + 'falls out finished state immediately'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - return animation.ready.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + return animation.ready.then(() => { animation.currentTime = 100 * MS_PER_SEC; - animation.finished.then(t.step_func(function() { + animation.finished.then(t.step_func(() => { assert_unreached('Animation.finished should not be resolved'); })); animation.currentTime = 0; @@ -366,24 +366,24 @@ 'falls out finished state even though the current finished ' + 'promise is generated soon after animation state became finished'); -promise_test(function(t) { - var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); - var ready = false; +promise_test(t => { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); + let ready = false; animation.ready.then( - t.step_func(function() { + t.step_func(() => { ready = true; }), t.unreached_func('Ready promise must not be rejected') ); - var testSuccess = animation.finished.then( - t.step_func(function() { + const testSuccess = animation.finished.then( + t.step_func(() => { assert_true(ready, 'Ready promise has resolved'); }), t.unreached_func('Finished promise must not be rejected') ); - var timeout = waitForAnimationFrames(3).then(function() { + const timeout = waitForAnimationFrames(3).then(() => { return Promise.reject('Finished promise did not arrive in time'); }); @@ -391,24 +391,24 @@ return Promise.race([timeout, testSuccess]); }, 'Finished promise should be resolved after the ready promise is resolved'); -promise_test(function(t) { - var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); - var caught = false; +promise_test(t => { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); + let caught = false; animation.ready.then( t.unreached_func('Ready promise must not be resolved'), - t.step_func(function() { + t.step_func(() => { caught = true; }) ); - var testSuccess = animation.finished.then( + const testSuccess = animation.finished.then( t.unreached_func('Finished promise must not be resolved'), - t.step_func(function() { + t.step_func(() => { assert_true(caught, 'Ready promise has been rejected'); }) ); - var timeout = waitForAnimationFrames(3).then(function() { + const timeout = waitForAnimationFrames(3).then(() => { return Promise.reject('Finished promise was not rejected in time'); });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/id.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/id.html index 2fadd56..b41076a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/id.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/id.html
@@ -8,17 +8,17 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); assert_equals(animation.id, '', 'id for Animation is initially empty'); }, 'Animation.id initial value'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.id = 'anim'; assert_equals(animation.id, 'anim', 'animation.id reflects the value set');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/oncancel.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/oncancel.html index b8d9ced61..5f29dab 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/oncancel.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/oncancel.html
@@ -8,17 +8,17 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; -async_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var finishedTimelineTime; - animation.finished.then().catch(function() { +async_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + let finishedTimelineTime; + animation.finished.then().catch(() => { finishedTimelineTime = animation.timeline.currentTime; }); - animation.oncancel = t.step_func_done(function(event) { + animation.oncancel = t.step_func_done(event => { assert_equals(event.currentTime, null, 'event.currentTime should be null'); assert_equals(event.timelineTime, finishedTimelineTime,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/onfinish.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/onfinish.html index 50e5bed..0313385 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/onfinish.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/onfinish.html
@@ -8,17 +8,17 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; -async_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - var finishedTimelineTime; - animation.finished.then(function() { +async_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + let finishedTimelineTime; + animation.finished.then(() => { finishedTimelineTime = animation.timeline.currentTime; }); - animation.onfinish = t.step_func_done(function(event) { + animation.onfinish = t.step_func_done(event => { assert_equals(event.currentTime, 0, 'event.currentTime should be zero'); assert_equals(event.timelineTime, finishedTimelineTime, @@ -30,16 +30,16 @@ }, 'onfinish event is fired when the currentTime < 0 and ' + 'the playbackRate < 0'); -async_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +async_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); - var finishedTimelineTime; - animation.finished.then(function() { + let finishedTimelineTime; + animation.finished.then(() => { finishedTimelineTime = animation.timeline.currentTime; }); - animation.onfinish = t.step_func_done(function(event) { + animation.onfinish = t.step_func_done(event => { assert_equals(event.currentTime, 100 * MS_PER_SEC, 'event.currentTime should be the effect end'); assert_equals(event.timelineTime, finishedTimelineTime, @@ -51,16 +51,16 @@ }, 'onfinish event is fired when the currentTime > 0 and ' + 'the playbackRate > 0'); -async_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +async_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); - var finishedTimelineTime; - animation.finished.then(function() { + let finishedTimelineTime; + animation.finished.then(() => { finishedTimelineTime = animation.timeline.currentTime; }); - animation.onfinish = t.step_func_done(function(event) { + animation.onfinish = t.step_func_done(event => { assert_equals(event.currentTime, 100 * MS_PER_SEC, 'event.currentTime should be the effect end'); assert_equals(event.timelineTime, finishedTimelineTime, @@ -71,45 +71,45 @@ animation.finish(); }, 'onfinish event is fired when animation.finish() is called'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); - animation.onfinish = function(event) { + animation.onfinish = event => { assert_unreached('onfinish event should not be fired'); }; animation.currentTime = 100 * MS_PER_SEC / 2; animation.pause(); - return animation.ready.then(function() { + return animation.ready.then(() => { animation.currentTime = 100 * MS_PER_SEC; return waitForAnimationFrames(2); }); }, 'onfinish event is not fired when paused'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - animation.onfinish = function(event) { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + animation.onfinish = event => { assert_unreached('onfinish event should not be fired'); }; - return animation.ready.then(function() { + return animation.ready.then(() => { animation.playbackRate = 0; animation.currentTime = 100 * MS_PER_SEC; return waitForAnimationFrames(2); }); }, 'onfinish event is not fired when the playbackRate is zero'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); - animation.onfinish = function(event) { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); + animation.onfinish = event => { assert_unreached('onfinish event should not be fired'); }; - return animation.ready.then(function() { + return animation.ready.then(() => { animation.currentTime = 100 * MS_PER_SEC; animation.currentTime = 100 * MS_PER_SEC / 2; return waitForAnimationFrames(2);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/pause.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/pause.html index bcfaf4a..3be8bc3 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/pause.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/pause.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Animation.pause()</title> +<title>Animation.pause</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-pause"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -8,30 +8,30 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 1000 * MS_PER_SEC); - var previousCurrentTime = animation.currentTime; +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 1000 * MS_PER_SEC); + let previousCurrentTime = animation.currentTime; - return animation.ready.then(waitForAnimationFrames(1)).then(function() { + return animation.ready.then(waitForAnimationFrames(1)).then(() => { assert_true(animation.currentTime >= previousCurrentTime, 'currentTime is initially increasing'); animation.pause(); return animation.ready; - }).then(function() { + }).then(() => { previousCurrentTime = animation.currentTime; return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_equals(animation.currentTime, previousCurrentTime, 'currentTime does not increase after calling pause()'); }); }, 'pause() a running animation'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 1000 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 1000 * MS_PER_SEC); // Go to idle state then pause animation.cancel(); @@ -42,7 +42,7 @@ assert_equals(animation.playState, 'pending', 'initially pause-pending'); // Check it still resolves as expected - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(animation.playState, 'paused', 'resolves to paused state asynchronously'); assert_equals(animation.currentTime, 0, @@ -50,9 +50,9 @@ }); }, 'pause() from idle'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 1000 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 1000 * MS_PER_SEC); animation.cancel(); animation.playbackRate = -1; animation.pause(); @@ -60,35 +60,35 @@ assert_equals(animation.currentTime, 1000 * MS_PER_SEC, 'currentTime is set to the effect end'); - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(animation.currentTime, 1000 * MS_PER_SEC, 'keeps the initially set currentTime'); }); }, 'pause() from idle with a negative playbackRate'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, {duration: 1000 * MS_PER_SEC, +test(t => { + const div = createDiv(t); + const animation = div.animate({}, {duration: 1000 * MS_PER_SEC, iterations: Infinity}); animation.cancel(); animation.playbackRate = -1; assert_throws('InvalidStateError', - function () { animation.pause(); }, + () => { animation.pause(); }, 'Expect InvalidStateError exception on calling pause() ' + 'from idle with a negative playbackRate and ' + 'infinite-duration animation'); }, 'pause() from idle with a negative playbackRate and endless effect'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 1000 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 1000 * MS_PER_SEC); return animation.ready - .then(function(animation) { + .then(animation => { animation.finish(); animation.pause(); return animation.ready; - }).then(function(animation) { + }).then(animation => { assert_equals(animation.currentTime, 1000 * MS_PER_SEC, 'currentTime after pausing finished animation'); });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/play.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/play.html index 767d8df..d3e0122 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/play.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/play.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Animation.play()</title> +<title>Animation.play</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-play"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -10,19 +10,19 @@ <script> 'use strict'; -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({ transform: ['none', 'translate(10px)']}, - { duration : 100 * MS_PER_SEC, - iterations : Infinity}); - return animation.ready.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({ transform: ['none', 'translate(10px)']}, + { duration: 100 * MS_PER_SEC, + iterations: Infinity }); + return animation.ready.then(() => { // Seek to a time outside the active range so that play() will have to // snap back to the start animation.currentTime = -5 * MS_PER_SEC; animation.playbackRate = -1; assert_throws('InvalidStateError', - function () { animation.play(); }, + () => { animation.play(); }, 'Expected InvalidStateError exception on calling play() ' + 'with a negative playbackRate and infinite-duration ' + 'animation');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/playState.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/playState.html index 15af526c..cf6ce66 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/playState.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/playState.html
@@ -10,38 +10,38 @@ <script> 'use strict'; -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); assert_equals(animation.playState, 'pending'); - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(animation.playState, 'running'); }); }, 'Animation.playState reports \'pending\'->\'running\' when initially ' + 'played'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.pause(); assert_equals(animation.playState, 'pending'); - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(animation.playState, 'paused'); }); }, 'Animation.playState reports \'pending\'->\'paused\' when pausing'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.cancel(); assert_equals(animation.playState, 'idle'); }, 'Animation.playState is \'idle\' when canceled.'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.cancel(); animation.currentTime = 50 * MS_PER_SEC; assert_equals(animation.playState, 'paused',
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/playbackRate.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/playbackRate.html index c923df6..4f9bed1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/playbackRate.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/playbackRate.html
@@ -8,16 +8,16 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; function assert_playbackrate(animation, previousAnimationCurrentTime, previousTimelineCurrentTime, description) { - var accuracy = 0.001; /* accuracy of DOMHighResTimeStamp */ - var animationCurrentTimeDifference = + const accuracy = 0.001; /* accuracy of DOMHighResTimeStamp */ + const animationCurrentTimeDifference = animation.currentTime - previousAnimationCurrentTime; - var timelineCurrentTimeDifference = + const timelineCurrentTimeDifference = animation.timeline.currentTime - previousTimelineCurrentTime; assert_approx_equals(animationCurrentTimeDifference, @@ -26,10 +26,10 @@ description); } -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate(null, 100 * MS_PER_SEC); - return animation.ready.then(function() { +promise_test(t => { + const div = createDiv(t); + const animation = div.animate(null, 100 * MS_PER_SEC); + return animation.ready.then(() => { animation.currentTime = 7 * MS_PER_SEC; // ms animation.playbackRate = 0.5; @@ -43,17 +43,17 @@ }); }, 'Test the initial effect of setting playbackRate on currentTime'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate(null, 100 * MS_PER_SEC); animation.playbackRate = 2; - var previousTimelineCurrentTime; - var previousAnimationCurrentTime; - return animation.ready.then(function() { + let previousTimelineCurrentTime; + let previousAnimationCurrentTime; + return animation.ready.then(() => { previousAnimationCurrentTime = animation.currentTime; previousTimelineCurrentTime = animation.timeline.currentTime; return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_playbackrate(animation, previousAnimationCurrentTime, previousTimelineCurrentTime, @@ -61,18 +61,18 @@ }); }, 'Test the effect of setting playbackRate on currentTime'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate(null, 100 * MS_PER_SEC); animation.playbackRate = 2; - var previousTimelineCurrentTime; - var previousAnimationCurrentTime; - return animation.ready.then(function() { + let previousTimelineCurrentTime; + let previousAnimationCurrentTime; + return animation.ready.then(() => { previousAnimationCurrentTime = animation.currentTime; previousTimelineCurrentTime = animation.timeline.currentTime; animation.playbackRate = 1; return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_equals(animation.playbackRate, 1, 'sanity check: animation.playbackRate is still 1.'); assert_playbackrate(animation,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/ready.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/ready.html index b61a3c49..eb8713d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/ready.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/ready.html
@@ -8,15 +8,15 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate(null, 100 * MS_PER_SEC); - var originalReadyPromise = animation.ready; - var pauseReadyPromise; +promise_test(t => { + const div = createDiv(t); + const animation = div.animate(null, 100 * MS_PER_SEC); + const originalReadyPromise = animation.ready; + let pauseReadyPromise; - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(animation.ready, originalReadyPromise, 'Ready promise is the same object when playing completes'); animation.pause(); @@ -26,19 +26,19 @@ // Wait for the promise to fulfill since if we abort the pause the ready // promise object is reused. return animation.ready; - }).then(function() { + }).then(() => { animation.play(); assert_not_equals(animation.ready, pauseReadyPromise, 'A new ready promise is created when playing'); }); }, 'A new ready promise is created when play()/pause() is called'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate(null, 100 * MS_PER_SEC); - return animation.ready.then(function() { - var promiseBeforeCallingPlay = animation.ready; + return animation.ready.then(() => { + const promiseBeforeCallingPlay = animation.ready; animation.play(); assert_equals(animation.ready, promiseBeforeCallingPlay, 'Ready promise has same object identity after redundant call' @@ -46,11 +46,11 @@ }); }, 'Redundant calls to play() do not generate new ready promise objects'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate(null, 100 * MS_PER_SEC); - return animation.ready.then(function(resolvedAnimation) { + return animation.ready.then(resolvedAnimation => { assert_equals(resolvedAnimation, animation, 'Object identity of Animation passed to Promise callback' + ' matches the Animation object owning the Promise');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/startTime.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/startTime.html index 6dfd7cf..fab8534f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/startTime.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/startTime.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Animation.startTime tests</title> +<title>Animation.startTime</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-starttime"> <script src="/resources/testharness.js"></script> @@ -11,41 +11,41 @@ <script> 'use strict'; -test(function(t) { - var animation = new Animation(new KeyframeEffect(createDiv(t), null), - document.timeline); +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null), + document.timeline); assert_equals(animation.startTime, null, 'startTime is unresolved'); }, 'startTime of a newly created (idle) animation is unresolved'); -test(function(t) { - var animation = new Animation(new KeyframeEffect(createDiv(t), null), - document.timeline); +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null), + document.timeline); animation.play(); assert_equals(animation.startTime, null, 'startTime is unresolved'); }, 'startTime of a play-pending animation is unresolved'); -test(function(t) { - var animation = new Animation(new KeyframeEffect(createDiv(t), null), - document.timeline); +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null), + document.timeline); animation.pause(); assert_equals(animation.startTime, null, 'startTime is unresolved'); }, 'startTime of a pause-pending animation is unresolved'); -test(function(t) { - var animation = createDiv(t).animate(null); +test(t => { + const animation = createDiv(t).animate(null); assert_equals(animation.startTime, null, 'startTime is unresolved'); }, 'startTime of a play-pending animation created using Element.animate' + ' shortcut is unresolved'); -promise_test(function(t) { - var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); - return animation.ready.then(function() { +promise_test(t => { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); + return animation.ready.then(() => { assert_greater_than(animation.startTime, 0, 'startTime when running'); }); }, 'startTime is resolved when running'); -test(function(t) { - var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); +test(t => { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); animation.cancel(); assert_equals(animation.startTime, null); assert_equals(animation.currentTime, null);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/delay.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/delay.html index 1b34f7db..80149458 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/delay.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/delay.html
@@ -1,8 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>delay tests</title> +<title>AnimationEffectTiming.delay</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-delay"> -<link rel="author" title="Daisuke Akatsuka" href="mailto:daisuke@mozilla-japan.org"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="../../testcommon.js"></script> @@ -11,69 +10,69 @@ <script> 'use strict'; -test(function(t) { - var anim = createDiv(t).animate(null); +test(t => { + const anim = createDiv(t).animate(null); assert_equals(anim.effect.timing.delay, 0); -}, 'Test default value'); +}, 'Has the default value 0'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 100); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 100); anim.effect.timing.delay = 100; assert_equals(anim.effect.timing.delay, 100, 'set delay 100'); assert_equals(anim.effect.getComputedTiming().delay, 100, 'getComputedTiming() after set delay 100'); -}, 'set delay 100'); +}, 'Can be set to a positive number'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 100); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 100); anim.effect.timing.delay = -100; assert_equals(anim.effect.timing.delay, -100, 'set delay -100'); assert_equals(anim.effect.getComputedTiming().delay, -100, 'getComputedTiming() after set delay -100'); -}, 'set delay -100'); +}, 'Can be set to a negative number'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 100); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 100); anim.effect.timing.delay = 100; assert_equals(anim.effect.getComputedTiming().progress, null); assert_equals(anim.effect.getComputedTiming().currentIteration, null); -}, 'Test adding a positive delay to an animation without a backwards fill ' + - 'makes it no longer active'); +}, 'Can set a positive delay on an animation without a backwards fill to' + + ' make it no longer active'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { fill: 'both', - duration: 100 }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { fill: 'both', + duration: 100 }); anim.effect.timing.delay = -50; assert_equals(anim.effect.getComputedTiming().progress, 0.5); -}, 'Test seeking an animation by setting a negative delay'); +}, 'Can set a negative delay to seek into the active interval'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { fill: 'both', - duration: 100 }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { fill: 'both', + duration: 100 }); anim.effect.timing.delay = -100; assert_equals(anim.effect.getComputedTiming().progress, 1); assert_equals(anim.effect.getComputedTiming().currentIteration, 0); -}, 'Test finishing an animation using a large negative delay'); +}, 'Can set a large negative delay to finishing an animation'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate(null); +test(t => { + const div = createDiv(t); + const anim = div.animate(null); for (let invalid of [NaN, Infinity]) { - assert_throws({ name: 'TypeError' }, function() { + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.delay = invalid; - }, 'setting ' + invalid); - assert_throws({ name: 'TypeError' }, function() { + }, `setting ${invalid}`); + assert_throws({ name: 'TypeError' }, () => { div.animate({}, { delay: invalid }); - }, 'animate() with ' + invalid); + }, `animate() with ${invalid}`); } -}, 'Setting invalid values should throw TypeError'); +}, 'Throws when setting invalid values'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/direction.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/direction.html index 957181202..2fb300292 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/direction.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/direction.html
@@ -1,8 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>direction tests</title> +<title>AnimationEffectTiming.direction</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-direction"> -<link rel="author" title="Ryo Kato" href="mailto:foobar094@gmail.com"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="../../testcommon.js"></script> @@ -11,22 +10,99 @@ <script> 'use strict'; -test(function(t) { - var anim = createDiv(t).animate(null); +test(t => { + const anim = createDiv(t).animate(null); assert_equals(anim.effect.timing.direction, 'normal'); -}, 'Test default value'); +}, 'Has the default value \'normal\''); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - var directions = ['normal', 'reverse', 'alternate', 'alternate-reverse']; - directions.forEach(function(direction) { + const directions = ['normal', 'reverse', 'alternate', 'alternate-reverse']; + for (const direction of directions) { anim.effect.timing.direction = direction; assert_equals(anim.effect.timing.direction, direction, - 'set direction to ' + direction); - }); -}, 'set direction to a valid keyword'); + `set direction to ${direction}`); + } +}, 'Can be set to each of the possible keywords'); + +test(t => { + const div = createDiv(t); + const anim = div.animate(null, { duration: 10000, direction: 'normal' }); + anim.currentTime = 7000; + assert_times_equal(anim.effect.getComputedTiming().progress, 0.7, + 'progress before updating direction'); + + anim.effect.timing.direction = 'reverse'; + + assert_times_equal(anim.effect.getComputedTiming().progress, 0.3, + 'progress after updating direction'); +}, 'Can be changed from \'normal\' to \'reverse\' while in progress'); + +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { duration: 10000, + direction: 'normal' }); + assert_equals(anim.effect.getComputedTiming().progress, 0, + 'progress before updating direction'); + + anim.effect.timing.direction = 'reverse'; + + assert_equals(anim.effect.getComputedTiming().progress, 1, + 'progress after updating direction'); +}, 'Can be changed from \'normal\' to \'reverse\' while at start of active' + + ' interval'); + +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { fill: 'backwards', + duration: 10000, + delay: 10000, + direction: 'normal' }); + assert_equals(anim.effect.getComputedTiming().progress, 0, + 'progress before updating direction'); + + anim.effect.timing.direction = 'reverse'; + + assert_equals(anim.effect.getComputedTiming().progress, 1, + 'progress after updating direction'); +}, 'Can be changed from \'normal\' to \'reverse\' while filling backwards'); + +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { iterations: 2, + duration: 10000, + direction: 'normal' }); + anim.currentTime = 17000; + assert_times_equal(anim.effect.getComputedTiming().progress, 0.7, + 'progress before updating direction'); + + anim.effect.timing.direction = 'alternate'; + + assert_times_equal(anim.effect.getComputedTiming().progress, 0.3, + 'progress after updating direction'); +}, 'Can be changed from \'normal\' to \'alternate\' while in progress'); + +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { iterations: 2, + duration: 10000, + direction: 'alternate' }); + anim.currentTime = 17000; + assert_times_equal(anim.effect.getComputedTiming().progress, 0.3, + 'progress before updating direction'); + + anim.effect.timing.direction = 'alternate-reverse'; + + assert_times_equal(anim.effect.getComputedTiming().progress, 0.7, + 'progress after updating direction'); +}, 'Can be changed from \'alternate\' to \'alternate-reverse\' while in' + + ' progress'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/duration.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/duration.html index c8154d53..98ddd68 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/duration.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/duration.html
@@ -1,8 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>duration tests</title> -<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationeffecttiming-duration"> -<link rel="author" title="Ryo Motozawa" href="mailto:motozawa@mozilla-japan.org"> +<title>AnimationEffectTiming.duration</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-duration"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="../../testcommon.js"></script> @@ -11,148 +10,150 @@ <script> 'use strict'; -test(function(t) { - var anim = createDiv(t).animate(null); +test(t => { + const anim = createDiv(t).animate(null); assert_equals(anim.effect.timing.duration, 'auto'); -}, 'Test default value'); +}, 'Has the default value \'auto\''); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); anim.effect.timing.duration = 123.45; assert_times_equal(anim.effect.timing.duration, 123.45, 'set duration 123.45'); assert_times_equal(anim.effect.getComputedTiming().duration, 123.45, 'getComputedTiming() after set duration 123.45'); -}, 'set duration 123.45'); +}, 'Can be set to a double value'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); anim.effect.timing.duration = 'auto'; assert_equals(anim.effect.timing.duration, 'auto', 'set duration \'auto\''); assert_equals(anim.effect.getComputedTiming().duration, 0, 'getComputedTiming() after set duration \'auto\''); -}, 'set duration auto'); +}, 'Can be set to the string \'auto\''); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, { duration: 'auto' }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, { duration: 'auto' }); assert_equals(anim.effect.timing.duration, 'auto', 'set duration \'auto\''); assert_equals(anim.effect.getComputedTiming().duration, 0, 'getComputedTiming() after set duration \'auto\''); -}, 'set auto duration in animate as object'); +}, 'Can be set to \'auto\' using a dictionary object'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); anim.effect.timing.duration = Infinity; assert_equals(anim.effect.timing.duration, Infinity, 'set duration Infinity'); assert_equals(anim.effect.getComputedTiming().duration, Infinity, 'getComputedTiming() after set duration Infinity'); -}, 'set duration Infinity'); +}, 'Can be set to Infinity'); -test(function(t) { - var div = createDiv(t); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + assert_throws({ name: 'TypeError' }, () => { div.animate({ opacity: [ 0, 1 ] }, -1); }); -}, 'set negative duration in animate using a duration parameter'); +}, 'animate() throws when passed a negative number'); -test(function(t) { - var div = createDiv(t); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + assert_throws({ name: 'TypeError' }, () => { div.animate({ opacity: [ 0, 1 ] }, -Infinity); }); -}, 'set negative Infinity duration in animate using a duration parameter'); +}, 'animate() throws when passed negative Infinity'); -test(function(t) { - var div = createDiv(t); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + assert_throws({ name: 'TypeError' }, () => { div.animate({ opacity: [ 0, 1 ] }, NaN); }); -}, 'set NaN duration in animate using a duration parameter'); +}, 'animate() throws when passed a NaN value'); -test(function(t) { - var div = createDiv(t); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + assert_throws({ name: 'TypeError' }, () => { div.animate({ opacity: [ 0, 1 ] }, { duration: -1 }); }); -}, 'set negative duration in animate using an options object'); +}, 'animate() throws when passed a negative number using a dictionary object'); -test(function(t) { - var div = createDiv(t); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + assert_throws({ name: 'TypeError' }, () => { div.animate({ opacity: [ 0, 1 ] }, { duration: -Infinity }); }); -}, 'set negative Infinity duration in animate using an options object'); +}, 'animate() throws when passed negative Infinity using a dictionary object'); -test(function(t) { - var div = createDiv(t); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + assert_throws({ name: 'TypeError' }, () => { div.animate({ opacity: [ 0, 1 ] }, { duration: NaN }); }); -}, 'set NaN duration in animate using an options object'); +}, 'animate() throws when passed a NaN value using a dictionary object'); -test(function(t) { - var div = createDiv(t); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + assert_throws({ name: 'TypeError' }, () => { div.animate({ opacity: [ 0, 1 ] }, { duration: 'abc' }); }); -}, 'set abc string duration in animate using an options object'); +}, 'animate() throws when passed a string other than \'auto\' using a' + + ' dictionary object'); -test(function(t) { - var div = createDiv(t); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + assert_throws({ name: 'TypeError' }, () => { div.animate({ opacity: [ 0, 1 ] }, { duration: '100' }); }); -}, 'set 100 string duration in animate using an options object'); +}, 'animate() throws when passed a string containing a number using a' + + ' dictionary object'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.duration = -1; }); -}, 'set negative duration'); +}, 'Throws when setting a negative number'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.duration = -Infinity; }); -}, 'set negative Infinity duration'); +}, 'Throws when setting negative infinity'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.duration = NaN; }); -}, 'set NaN duration'); +}, 'Throws when setting a NaN value'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.duration = 'abc'; }); -}, 'set duration abc'); +}, 'Throws when setting a string other than \'auto\''); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.duration = '100'; }); -}, 'set duration string 100'); +}, 'Throws when setting a string containing a number'); -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); - return anim.ready.then(function() { - var originalStartTime = anim.startTime; - var originalCurrentTime = anim.currentTime; +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); + return anim.ready.then(() => { + const originalStartTime = anim.startTime; + const originalCurrentTime = anim.currentTime; assert_equals(anim.effect.getComputedTiming().duration, 100 * MS_PER_SEC, 'Initial duration should be as set on KeyframeEffect'); @@ -168,5 +169,22 @@ }); }, 'Extending an effect\'s duration does not change the start or current time'); +test(t => { + const div = createDiv(t); + const anim = div.animate(null, { duration: 100000, fill: 'both' }); + anim.finish(); + assert_equals(anim.effect.getComputedTiming().progress, 1, + 'progress when animation is finished'); + anim.effect.timing.duration *= 2; + assert_times_equal(anim.effect.getComputedTiming().progress, 0.5, + 'progress after doubling the duration'); + anim.effect.timing.duration = 0; + assert_equals(anim.effect.getComputedTiming().progress, 1, + 'progress after setting duration to zero'); + anim.effect.timing.duration = 'auto'; + assert_equals(anim.effect.getComputedTiming().progress, 1, + 'progress after setting duration to \'auto\''); +}, 'Can be updated while the animation is in progress'); + </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/easing.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/easing.html index 11173fc..28f8a537 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/easing.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/easing.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>easing tests</title> +<title>AnimationEffectTiming.easing</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-easing"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -11,68 +11,68 @@ <script> 'use strict'; -test(function(t) { - var anim = createDiv(t).animate(null); +test(t => { + const anim = createDiv(t).animate(null); assert_equals(anim.effect.timing.easing, 'linear'); -}, 'Test default value'); +}, 'Has the default value \'linear\''); function assert_progress(animation, currentTime, easingFunction) { animation.currentTime = currentTime; - var portion = currentTime / animation.effect.timing.duration; + const portion = currentTime / animation.effect.timing.duration; assert_approx_equals(animation.effect.getComputedTiming().progress, easingFunction(portion), 0.01, - 'The progress of the animation should be approximately ' + - easingFunction(portion) + ' at ' + currentTime + 'ms'); + 'The progress of the animation should be approximately' + + ` ${easingFunction(portion)} at ${currentTime}ms`); } -gEasingTests.forEach(function(options) { - test(function(t) { - var target = createDiv(t); - var anim = target.animate([ { opacity: 0 }, { opacity: 1 } ], - { duration: 1000 * MS_PER_SEC, - fill: 'forwards' }); +for (const options of gEasingTests) { + test(t => { + const target = createDiv(t); + const anim = target.animate([ { opacity: 0 }, { opacity: 1 } ], + { duration: 1000 * MS_PER_SEC, + fill: 'forwards' }); anim.effect.timing.easing = options.easing; assert_equals(anim.effect.timing.easing, options.serialization || options.easing); - var easing = options.easingFunction; + const easing = options.easingFunction; assert_progress(anim, 0, easing); assert_progress(anim, 250 * MS_PER_SEC, easing); assert_progress(anim, 500 * MS_PER_SEC, easing); assert_progress(anim, 750 * MS_PER_SEC, easing); assert_progress(anim, 1000 * MS_PER_SEC, easing); }, options.desc); -}); +} -gInvalidEasings.forEach(function(invalidEasing) { - test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC); +for (const invalidEasing of gInvalidEasings) { + test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC); assert_throws({ name: 'TypeError' }, - function() { + () => { anim.effect.timing.easing = invalidEasing; }); - }, 'Invalid effect easing value test: \'' + invalidEasing + '\''); -}); + }, `Throws on invalid easing: '${invalidEasing}'`); +} -gRoundtripEasings.forEach(easing => { - test(function(t) { +for (const easing of gRoundtripEasings) { + test(t => { const anim = createDiv(t).animate(null); anim.effect.timing.easing = easing; assert_equals(anim.effect.timing.easing, easing); }, `Canonical easing '${easing}' is returned as set`); -}); +} -test(function(t) { - var delay = 1000 * MS_PER_SEC; +test(t => { + const delay = 1000 * MS_PER_SEC; - var target = createDiv(t); - var anim = target.animate([ { opacity: 0 }, { opacity: 1 } ], - { duration: 1000 * MS_PER_SEC, - fill: 'both', - delay: delay, - easing: 'steps(2, start)' }); + const target = createDiv(t); + const anim = target.animate([ { opacity: 0 }, { opacity: 1 } ], + { duration: 1000 * MS_PER_SEC, + fill: 'both', + delay: delay, + easing: 'steps(2, start)' }); anim.effect.timing.easing = 'steps(2, end)'; assert_equals(anim.effect.getComputedTiming().progress, 0, @@ -90,7 +90,7 @@ anim.effect.timing.easing = 'steps(2, end)'; assert_equals(anim.effect.getComputedTiming().progress, 1, 'easing replace to steps(2, end) again at after phase'); -}, 'Change the easing while the animation is running'); +}, 'Allows the easing to be changed while the animation is in progress'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/endDelay.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/endDelay.html index c6c2e88..7b4ceca0 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/endDelay.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/endDelay.html
@@ -1,8 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>endDelay tests</title> -<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationeffecttiming-enddelay"> -<link rel="author" title="Ryo Motozawa" href="mailto:motozawa@mozilla-japan.org"> +<title>AnimationEffectTiming.endDelay</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-enddelay"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="../../testcommon.js"></script> @@ -11,79 +10,80 @@ <script> 'use strict'; -test(function(t) { - var anim = createDiv(t).animate(null); +test(t => { + const anim = createDiv(t).animate(null); assert_equals(anim.effect.timing.endDelay, 0); -}, 'Test default value'); +}, 'Has the default value 0'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); anim.effect.timing.endDelay = 123.45; assert_times_equal(anim.effect.timing.endDelay, 123.45, 'set endDelay 123.45'); assert_times_equal(anim.effect.getComputedTiming().endDelay, 123.45, 'getComputedTiming() after set endDelay 123.45'); -}, 'set endDelay 123.45'); +}, 'Can be set to a positive number'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); anim.effect.timing.endDelay = -1000; assert_equals(anim.effect.timing.endDelay, -1000, 'set endDelay -1000'); assert_equals(anim.effect.getComputedTiming().endDelay, -1000, 'getComputedTiming() after set endDelay -1000'); -}, 'set endDelay -1000'); +}, 'Can be set to a negative number'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - assert_throws({name: "TypeError"}, function() { +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.endDelay = Infinity; }, 'we can not assign Infinity to timing.endDelay'); -}, 'set endDelay Infinity'); +}, 'Throws when setting infinity'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - assert_throws({name: "TypeError"}, function() { +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.endDelay = -Infinity; }, 'we can not assign negative Infinity to timing.endDelay'); -}, 'set endDelay negative Infinity'); +}, 'Throws when setting negative infinity'); -async_test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { duration: 100000, endDelay: 50000 }); - anim.onfinish = t.step_func(function(event) { - assert_unreached('onfinish event should not be fired'); +async_test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { duration: 100000, endDelay: 50000 }); + anim.onfinish = t.step_func(event => { + assert_unreached('finish event should not be fired'); }); - anim.ready.then(function() { + anim.ready.then(() => { anim.currentTime = 100000; return waitForAnimationFrames(2); - }).then(t.step_func(function() { + }).then(t.step_func(() => { t.done(); })); -}, 'onfinish event is not fired duration endDelay'); +}, 'finish event is not fired at the end of the active interval when the' + + ' endDelay has not expired'); -async_test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { duration: 100000, endDelay: 30000 }); - anim.ready.then(function() { +async_test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { duration: 100000, endDelay: 30000 }); + anim.ready.then(() => { anim.currentTime = 110000; // during endDelay - anim.onfinish = t.step_func(function(event) { + anim.onfinish = t.step_func(event => { assert_unreached('onfinish event should not be fired during endDelay'); }); return waitForAnimationFrames(2); - }).then(t.step_func(function() { - anim.onfinish = t.step_func(function(event) { + }).then(t.step_func(() => { + anim.onfinish = t.step_func(event => { t.done(); }); anim.currentTime = 130000; // after endTime })); -}, 'onfinish event is fired currentTime is after endTime'); +}, 'finish event is fired after the endDelay has expired'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/fill.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/fill.html index 89f6a46..5686b58 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/fill.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/fill.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>fill tests</title> +<title>AnimationEffectTiming.fill</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-fill"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -10,20 +10,21 @@ <script> 'use strict'; -test(function(t) { - var anim = createDiv(t).animate(null); +test(t => { + const anim = createDiv(t).animate(null); assert_equals(anim.effect.timing.fill, 'auto'); -}, 'Test default value'); +}, 'Has the default value \'auto\''); -["none", "forwards", "backwards", "both", ].forEach(function(fill){ - test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 100); +for (const fill of ['none', 'forwards', 'backwards', 'both']) { + test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 100); anim.effect.timing.fill = fill; assert_equals(anim.effect.timing.fill, fill, 'set fill ' + fill); - assert_equals(anim.effect.getComputedTiming().fill, fill, 'getComputedTiming() after set fill ' + fill); - }, 'set fill ' + fill); -}); + assert_equals(anim.effect.getComputedTiming().fill, fill, + 'getComputedTiming() after set fill ' + fill); + }, `Can set fill to ${fill}`); +} </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getAnimations.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getAnimations.html deleted file mode 100644 index d96192c9..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getAnimations.html +++ /dev/null
@@ -1,91 +0,0 @@ -<!DOCTYPE html> -<meta charset=utf-8> -<title>Element.getAnimations tests</title> -<link rel="help" href="http://w3c.github.io/web-animations/#animationeffecttiming"> -<link rel="author" title="Ryo Motozawa" href="mailto:motozawa@mozilla-japan.org"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="../../testcommon.js"></script> -<body> -<div id="log"></div> -<script> -'use strict'; - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - anim.finish(); - assert_equals(div.getAnimations().length, 0, 'animation finished'); - anim.effect.timing.duration += 100000; - assert_equals(div.getAnimations()[0], anim, 'set duration 102000'); - anim.effect.timing.duration = 0; - assert_equals(div.getAnimations().length, 0, 'set duration 0'); - anim.effect.timing.duration = 'auto'; - assert_equals(div.getAnimations().length, 0, 'set duration \'auto\''); -}, 'when duration is changed'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - - anim.effect.timing.endDelay = -3000; - assert_equals(div.getAnimations().length, 0, - 'set negative endDelay so as endTime is less than currentTime'); - anim.effect.timing.endDelay = 1000; - assert_equals(div.getAnimations()[0], anim, - 'set positive endDelay so as endTime is more than currentTime'); - - anim.effect.timing.duration = 1000; - anim.currentTime = 1500; - assert_equals(div.getAnimations().length, 0, - 'set currentTime less than endTime'); - anim.effect.timing.endDelay = -500; - anim.currentTime = 400; - assert_equals(div.getAnimations()[0], anim, - 'set currentTime less than endTime when endDelay is negative value'); - anim.currentTime = 500; - assert_equals(div.getAnimations().length, 0, - 'set currentTime same as endTime when endDelay is negative value'); - anim.currentTime = 1000; - assert_equals(div.getAnimations().length, 0, - 'set currentTime same as duration when endDelay is negative value'); -}, 'when endDelay is changed'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - anim.finish(); - assert_equals(div.getAnimations().length, 0, 'animation finished'); - anim.effect.timing.iterations = 10; - assert_equals(div.getAnimations()[0], anim, 'set iterations 10'); - anim.effect.timing.iterations = 0; - assert_equals(div.getAnimations().length, 0, 'set iterations 0'); - anim.effect.timing.iterations = Infinity; - assert_equals(div.getAnimations().length, 1, 'set iterations Infinity'); -}, 'when iterations is changed'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { duration: 1000, delay: 500, endDelay: -500 }); - assert_equals(div.getAnimations()[0], anim, 'when currentTime 0'); - anim.currentTime = 500; - assert_equals(div.getAnimations()[0], anim, 'set currentTime 500'); - anim.currentTime = 1000; - assert_equals(div.getAnimations().length, 0, 'set currentTime 1000'); -}, 'when currentTime changed in duration:1000, delay: 500, endDelay: -500'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { duration: 1000, delay: -500, endDelay: -500 }); - assert_equals(div.getAnimations().length, 0, 'when currentTime 0'); - anim.currentTime = 500; - assert_equals(div.getAnimations().length, 0, 'set currentTime 500'); - anim.currentTime = 1000; - assert_equals(div.getAnimations().length, 0, 'set currentTime 1000'); -}, 'when currentTime changed in duration:1000, delay: -500, endDelay: -500'); - - -</script> -</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedStyle-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedStyle-expected.txt deleted file mode 100644 index 8f6f6605..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedStyle-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ -This is a testharness.js-based test. -PASS changed duration immediately updates its computed styles -PASS changed iterations immediately updates its computed styles -PASS change currentTime when fill is none and endDelay is positive -PASS change currentTime when fill forwards and endDelay is positive -PASS change currentTime when fill none and endDelay is negative -FAIL change currentTime when fill forwards and endDelay is negative assert_equals: set currentTime after endTime expected "0" but got "0.5" -PASS change direction from "normal" to "reverse" -PASS change direction from "normal" to "alternate" -PASS change direction from "normal" to "alternate-reverse" -PASS change direction from "normal" to "reverse" when currentTime is 0 -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html deleted file mode 100644 index cfc233f0..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html +++ /dev/null
@@ -1,172 +0,0 @@ -<!DOCTYPE html> -<meta charset=utf-8> -<title>getComputedStyle tests</title> -<link rel="help" href="http://w3c.github.io/web-animations/#animationeffecttiming"> -<link rel="author" title="Ryo Motozawa" href="mailto:motozawa@mozilla-japan.org"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="../../testcommon.js"></script> -<body> -<div id="log"></div> -<script> -'use strict'; - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 100000); - anim.finish(); - assert_equals(getComputedStyle(div).opacity, '1', 'animation finished'); - anim.effect.timing.duration *= 2; - assert_equals(getComputedStyle(div).opacity, '0.5', 'set double duration'); - anim.effect.timing.duration = 0; - assert_equals(getComputedStyle(div).opacity, '1', 'set duration 0'); - anim.effect.timing.duration = 'auto'; - assert_equals(getComputedStyle(div).opacity, '1', 'set duration \'auto\''); -}, 'changed duration immediately updates its computed styles'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 100000); - anim.finish(); - assert_equals(getComputedStyle(div).opacity, '1', 'animation finished'); - anim.effect.timing.iterations = 2; - assert_equals(getComputedStyle(div).opacity, '0', 'set 2 iterations'); - anim.effect.timing.iterations = 0; - assert_equals(getComputedStyle(div).opacity, '1', 'set iterations 0'); - anim.effect.timing.iterations = Infinity; - assert_equals(getComputedStyle(div).opacity, '0', 'set iterations Infinity'); -}, 'changed iterations immediately updates its computed styles'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 1, 0 ] }, - { duration: 10000, endDelay: 1000, fill: 'none' }); - - anim.currentTime = 9000; - assert_equals(getComputedStyle(div).opacity, '0.1', - 'set currentTime during duration'); - - anim.currentTime = 10900; - assert_equals(getComputedStyle(div).opacity, '1', - 'set currentTime during endDelay'); - - anim.currentTime = 11100; - assert_equals(getComputedStyle(div).opacity, '1', - 'set currentTime after endDelay'); -}, 'change currentTime when fill is none and endDelay is positive'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 1, 0 ] }, - { duration: 10000, - endDelay: 1000, - fill: 'forwards' }); - anim.currentTime = 5000; - assert_equals(getComputedStyle(div).opacity, '0.5', - 'set currentTime during duration'); - - anim.currentTime = 9999; - assert_equals(getComputedStyle(div).opacity, '0.0001', - 'set currentTime just a little before duration'); - - anim.currentTime = 10900; - assert_equals(getComputedStyle(div).opacity, '0', - 'set currentTime during endDelay'); - - anim.currentTime = 11100; - assert_equals(getComputedStyle(div).opacity, '0', - 'set currentTime after endDelay'); -}, 'change currentTime when fill forwards and endDelay is positive'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 1, 0 ] }, - { duration: 10000, endDelay: -5000, fill: 'none' }); - - anim.currentTime = 1000; - assert_equals(getComputedStyle(div).opacity, '0.9', - 'set currentTime before endTime'); - - anim.currentTime = 10000; - assert_equals(getComputedStyle(div).opacity, '1', - 'set currentTime after endTime'); -}, 'change currentTime when fill none and endDelay is negative'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 1, 0 ] }, - { duration: 10000, - endDelay: -5000, - fill: 'forwards' }); - - anim.currentTime = 1000; - assert_equals(getComputedStyle(div).opacity, '0.9', - 'set currentTime before endTime'); - - anim.currentTime = 5000; - assert_equals(getComputedStyle(div).opacity, '0.5', - 'set currentTime same as endTime'); - - anim.currentTime = 10000; - assert_equals(getComputedStyle(div).opacity, '0', - 'set currentTime after endTime'); -}, 'change currentTime when fill forwards and endDelay is negative'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { duration: 10000, - direction: 'normal' }); - - anim.currentTime = 7000; - anim.effect.timing.direction = 'reverse'; - - assert_equals(getComputedStyle(div).opacity, '0.3', - 'change direction from "normal" to "reverse"'); -}, 'change direction from "normal" to "reverse"'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { iterations: 2, - duration: 10000, - direction: 'normal' }); - - anim.currentTime = 17000; - anim.effect.timing.direction = 'alternate'; - - assert_equals(getComputedStyle(div).opacity, '0.3', - 'change direction from "normal" to "alternate"'); - }, 'change direction from "normal" to "alternate"'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { iterations: 2, - duration: 10000, - direction: 'normal' }); - - anim.currentTime = 17000; - anim.effect.timing.direction = 'alternate-reverse'; - - assert_equals(getComputedStyle(div).opacity, '0.7', - 'change direction from "normal" to "alternate-reverse"'); -}, 'change direction from "normal" to "alternate-reverse"'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { fill: 'backwards', - duration: 10000, - direction: 'normal' }); - - // test for a flip of value at the currentTime = 0 - anim.effect.timing.direction = 'reverse'; - - assert_equals(getComputedStyle(div).opacity, '1', - 'change direction from "normal" to "reverse" ' + - 'at the starting point'); -}, 'change direction from "normal" to "reverse" when currentTime is 0'); - -</script> -</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/getComputedTiming-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedTiming-expected.txt similarity index 69% rename from third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/getComputedTiming-expected.txt rename to third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedTiming-expected.txt index cff0f6da..e6c52da 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/getComputedTiming-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedTiming-expected.txt
@@ -1,14 +1,14 @@ This is a testharness.js-based test. -PASS values of getComputedTiming() when a KeyframeEffectReadOnly is constructed without any KeyframeEffectOptions object -PASS values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by an empty KeyframeEffectOptions object -PASS values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by a normal KeyframeEffectOptions object -PASS values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by a double value -PASS values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by +Infinity -PASS values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by an Infinity duration -PASS values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by an auto duration -PASS values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by an Infinity iterations -PASS values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by an auto fill -PASS values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by a forwards fill +PASS values of getComputedTiming() when a KeyframeEffect is constructed without any KeyframeEffectOptions object +PASS values of getComputedTiming() when a KeyframeEffect is constructed by an empty KeyframeEffectOptions object +PASS values of getComputedTiming() when a KeyframeEffect is constructed by a normal KeyframeEffectOptions object +PASS values of getComputedTiming() when a KeyframeEffect is constructed by a double value +PASS values of getComputedTiming() when a KeyframeEffect is constructed by +Infinity +PASS values of getComputedTiming() when a KeyframeEffect is constructed by an Infinity duration +PASS values of getComputedTiming() when a KeyframeEffect is constructed by an auto duration +PASS values of getComputedTiming() when a KeyframeEffect is constructed by an Infinity iterations +PASS values of getComputedTiming() when a KeyframeEffect is constructed by an auto fill +PASS values of getComputedTiming() when a KeyframeEffect is constructed by a forwards fill PASS getComputedTiming().activeDuration for an empty KeyframeEffectOptions object PASS getComputedTiming().activeDuration for a non-zero duration and default iteration count PASS getComputedTiming().activeDuration for a non-zero duration and integral iteration count
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html new file mode 100644 index 0000000..ee0a5e2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html
@@ -0,0 +1,201 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>AnimationEffectTiming.getComputedTiming</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffectreadonly-getcomputedtiming"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +'use strict'; + +test(t => { + const effect = new KeyframeEffect(null, null); + + const ct = effect.getComputedTiming(); + assert_equals(ct.delay, 0, 'computed delay'); + assert_equals(ct.fill, 'none', 'computed fill'); + assert_equals(ct.iterations, 1.0, 'computed iterations'); + assert_equals(ct.duration, 0, 'computed duration'); + assert_equals(ct.direction, 'normal', 'computed direction'); +}, 'values of getComputedTiming() when a KeyframeEffect is ' + + 'constructed without any KeyframeEffectOptions object'); + +const gGetComputedTimingTests = [ + { desc: 'an empty KeyframeEffectOptions object', + input: { }, + expected: { } }, + { desc: 'a normal KeyframeEffectOptions object', + input: { delay: 1000, + fill: 'auto', + iterations: 5.5, + duration: 'auto', + direction: 'alternate' }, + expected: { delay: 1000, + fill: 'none', + iterations: 5.5, + duration: 0, + direction: 'alternate' } }, + { desc: 'a double value', + input: 3000, + timing: { duration: 3000 }, + expected: { delay: 0, + fill: 'none', + iterations: 1, + duration: 3000, + direction: 'normal' } }, + { desc: '+Infinity', + input: Infinity, + expected: { duration: Infinity } }, + { desc: 'an Infinity duration', + input: { duration: Infinity }, + expected: { duration: Infinity } }, + { desc: 'an auto duration', + input: { duration: 'auto' }, + expected: { duration: 0 } }, + { desc: 'an Infinity iterations', + input: { iterations: Infinity }, + expected: { iterations: Infinity } }, + { desc: 'an auto fill', + input: { fill: 'auto' }, + expected: { fill: 'none' } }, + { desc: 'a forwards fill', + input: { fill: 'forwards' }, + expected: { fill: 'forwards' } } +]; + +for (const stest of gGetComputedTimingTests) { + test(t => { + const effect = new KeyframeEffect(null, null, stest.input); + + // Helper function to provide default expected values when the test does + // not supply them. + const expected = (field, defaultValue) => { + return field in stest.expected ? stest.expected[field] : defaultValue; + }; + + const ct = effect.getComputedTiming(); + assert_equals(ct.delay, expected('delay', 0), + 'computed delay'); + assert_equals(ct.fill, expected('fill', 'none'), + 'computed fill'); + assert_equals(ct.iterations, expected('iterations', 1), + 'computed iterations'); + assert_equals(ct.duration, expected('duration', 0), + 'computed duration'); + assert_equals(ct.direction, expected('direction', 'normal'), + 'computed direction'); + + }, 'values of getComputedTiming() when a KeyframeEffect is' + + ` constructed by ${stest.desc}`); +} + +const gActiveDurationTests = [ + { desc: 'an empty KeyframeEffectOptions object', + input: { }, + expected: 0 }, + { desc: 'a non-zero duration and default iteration count', + input: { duration: 1000 }, + expected: 1000 }, + { desc: 'a non-zero duration and integral iteration count', + input: { duration: 1000, iterations: 7 }, + expected: 7000 }, + { desc: 'a non-zero duration and fractional iteration count', + input: { duration: 1000, iterations: 2.5 }, + expected: 2500 }, + { desc: 'an non-zero duration and infinite iteration count', + input: { duration: 1000, iterations: Infinity }, + expected: Infinity }, + { desc: 'an non-zero duration and zero iteration count', + input: { duration: 1000, iterations: 0 }, + expected: 0 }, + { desc: 'a zero duration and default iteration count', + input: { duration: 0 }, + expected: 0 }, + { desc: 'a zero duration and fractional iteration count', + input: { duration: 0, iterations: 2.5 }, + expected: 0 }, + { desc: 'a zero duration and infinite iteration count', + input: { duration: 0, iterations: Infinity }, + expected: 0 }, + { desc: 'a zero duration and zero iteration count', + input: { duration: 0, iterations: 0 }, + expected: 0 }, + { desc: 'an infinite duration and default iteration count', + input: { duration: Infinity }, + expected: Infinity }, + { desc: 'an infinite duration and zero iteration count', + input: { duration: Infinity, iterations: 0 }, + expected: 0 }, + { desc: 'an infinite duration and fractional iteration count', + input: { duration: Infinity, iterations: 2.5 }, + expected: Infinity }, + { desc: 'an infinite duration and infinite iteration count', + input: { duration: Infinity, iterations: Infinity }, + expected: Infinity }, +]; + +for (const stest of gActiveDurationTests) { + test(t => { + const effect = new KeyframeEffect(null, null, stest.input); + + assert_equals(effect.getComputedTiming().activeDuration, + stest.expected); + + }, `getComputedTiming().activeDuration for ${stest.desc}`); +} + +const gEndTimeTests = [ + { desc: 'an empty KeyframeEffectOptions object', + input: { }, + expected: 0 }, + { desc: 'a non-zero duration and default iteration count', + input: { duration: 1000 }, + expected: 1000 }, + { desc: 'a non-zero duration and non-default iteration count', + input: { duration: 1000, iterations: 2.5 }, + expected: 2500 }, + { desc: 'a non-zero duration and non-zero delay', + input: { duration: 1000, delay: 1500 }, + expected: 2500 }, + { desc: 'a non-zero duration, non-zero delay and non-default iteration', + input: { duration: 1000, delay: 1500, iterations: 2 }, + expected: 3500 }, + { desc: 'an infinite iteration count', + input: { duration: 1000, iterations: Infinity }, + expected: Infinity }, + { desc: 'an infinite duration', + input: { duration: Infinity, iterations: 10 }, + expected: Infinity }, + { desc: 'an infinite duration and delay', + input: { duration: Infinity, iterations: 10, delay: 1000 }, + expected: Infinity }, + { desc: 'an infinite duration and negative delay', + input: { duration: Infinity, iterations: 10, delay: -1000 }, + expected: Infinity }, + { desc: 'an non-zero duration and negative delay', + input: { duration: 1000, iterations: 2, delay: -1000 }, + expected: 1000 }, + { desc: 'an non-zero duration and negative delay greater than active ' + + 'duration', + input: { duration: 1000, iterations: 2, delay: -3000 }, + expected: 0 }, + { desc: 'a zero duration and negative delay', + input: { duration: 0, iterations: 2, delay: -1000 }, + expected: 0 } +]; + +for (const stest of gEndTimeTests) { + test(t => { + const effect = new KeyframeEffect(null, null, stest.input); + + assert_equals(effect.getComputedTiming().endTime, + stest.expected); + + }, `getComputedTiming().endTime for ${stest.desc}`); +} + +done(); +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterationStart.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterationStart.html index ed2d0e09..8ba01a92 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterationStart.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterationStart.html
@@ -1,8 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>iterationStart tests</title> +<title>AnimationEffectTiming.iterationStart</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-iterationstart"> -<link rel="author" title="Daisuke Akatsuka" href="mailto:daisuke@mozilla-japan.org"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="../../testcommon.js"></script> @@ -11,66 +10,63 @@ <script> 'use strict'; -test(function(t) { - var anim = createDiv(t).animate(null); +test(t => { + const anim = createDiv(t).animate(null); assert_equals(anim.effect.timing.iterationStart, 0); -}, 'Test default value'); +}, 'Has the default value 0'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { iterationStart: 0.2, - iterations: 1, - fill: 'both', - duration: 100, - delay: 1 }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { iterationStart: 0.2, + iterations: 1, + fill: 'both', + duration: 100, + delay: 1 }); anim.effect.timing.iterationStart = 2.5; assert_times_equal(anim.effect.getComputedTiming().progress, 0.5); assert_equals(anim.effect.getComputedTiming().currentIteration, 2); -}, 'Test that changing the iterationStart affects computed timing ' + - 'when backwards-filling'); +}, 'Changing the value updates computed timing when backwards-filling'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { iterationStart: 0.2, - iterations: 1, - fill: 'both', - duration: 100, - delay: 0 }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { iterationStart: 0.2, + iterations: 1, + fill: 'both', + duration: 100, + delay: 0 }); anim.effect.timing.iterationStart = 2.5; assert_times_equal(anim.effect.getComputedTiming().progress, 0.5); assert_equals(anim.effect.getComputedTiming().currentIteration, 2); -}, 'Test that changing the iterationStart affects computed timing ' + - 'during the active phase'); +}, 'Changing the value updates computed timing during the active phase'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, - { iterationStart: 0.2, - iterations: 1, - fill: 'both', - duration: 100, - delay: 0 }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, + { iterationStart: 0.2, + iterations: 1, + fill: 'both', + duration: 100, + delay: 0 }); anim.finish(); anim.effect.timing.iterationStart = 2.5; assert_times_equal(anim.effect.getComputedTiming().progress, 0.5); assert_equals(anim.effect.getComputedTiming().currentIteration, 3); -}, 'Test that changing the iterationStart affects computed timing ' + - 'when forwards-filling'); +}, 'Changing the value updates computed timing when forwards-filling'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate(null); +test(t => { + const div = createDiv(t); + const anim = div.animate(null); for (let invalid of [-1, NaN, Infinity]) { - assert_throws({ name: 'TypeError' }, function() { + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.iterationStart = invalid; - }, 'setting ' + invalid); - assert_throws({ name: 'TypeError' }, function() { + }, `setting ${invalid}`); + assert_throws({ name: 'TypeError' }, () => { div.animate({}, { iterationStart: invalid }); - }, 'animate() with ' + invalid); + }, `animate() with ${invalid}`); } -}, 'Using invalid values should throw TypeError'); +}, 'Throws when setting invalid values'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterations.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterations.html index 8dfe1695..b8192e07 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterations.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterations.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>iterations tests</title> +<title>AnimationEffectTiming.iterations</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-iterations"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -10,52 +10,85 @@ <script> 'use strict'; -test(function(t) { - var anim = createDiv(t).animate(null); +test(t => { + const anim = createDiv(t).animate(null); assert_equals(anim.effect.timing.iterations, 1); -}, 'Test default value'); +}, 'Has the default value 1'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); anim.effect.timing.iterations = 2; assert_equals(anim.effect.timing.iterations, 2, 'set duration 2'); assert_equals(anim.effect.getComputedTiming().iterations, 2, 'getComputedTiming() after set iterations 2'); -}, 'set iterations 2'); +}, 'Can be set to a double value'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); anim.effect.timing.iterations = Infinity; assert_equals(anim.effect.timing.iterations, Infinity, 'set duration Infinity'); assert_equals(anim.effect.getComputedTiming().iterations, Infinity, 'getComputedTiming() after set iterations Infinity'); -}, 'set iterations Infinity'); +}, 'Can be set to infinity'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.iterations = -1; }); -}, 'set negative iterations'); +}, 'Throws when setting a negative number'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.iterations = -Infinity; }); -}, 'set negative infinity iterations '); +}, 'Throws when setting negative infinity'); -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, 2000); - assert_throws({ name: 'TypeError' }, function() { +test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, 2000); + assert_throws({ name: 'TypeError' }, () => { anim.effect.timing.iterations = NaN; }); -}, 'set NaN iterations'); +}, 'Throws when setting a NaN value'); + +test(t => { + const div = createDiv(t); + const anim = div.animate(null, { duration: 100000, fill: 'both' }); + + anim.finish(); + + assert_equals(anim.effect.getComputedTiming().progress, 1, + 'progress when animation is finished'); + assert_equals(anim.effect.getComputedTiming().currentIteration, 0, + 'current iteration when animation is finished'); + + anim.effect.timing.iterations = 2; + + assert_times_equal(anim.effect.getComputedTiming().progress, 0, + 'progress after adding an iteration'); + assert_times_equal(anim.effect.getComputedTiming().currentIteration, 1, + 'current iteration after adding an iteration'); + + anim.effect.timing.iterations = 0; + + assert_equals(anim.effect.getComputedTiming().progress, 0, + 'progress after setting iterations to zero'); + assert_equals(anim.effect.getComputedTiming().currentIteration, 0, + 'current iteration after setting iterations to zero'); + + anim.effect.timing.iterations = Infinity; + + assert_equals(anim.effect.getComputedTiming().progress, 0, + 'progress after setting iterations to Infinity'); + assert_equals(anim.effect.getComputedTiming().currentIteration, 1, + 'current iteration after setting iterations to Infinity'); +}, 'Can be updated while the animation is in progress'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationPlaybackEvent/constructor.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationPlaybackEvent/constructor.html index ca6dc6ee..41cf603 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationPlaybackEvent/constructor.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationPlaybackEvent/constructor.html
@@ -9,14 +9,14 @@ <script> 'use strict'; -test(function(t) { +test(t => { const evt = new AnimationPlaybackEvent('finish'); assert_equals(evt.type, 'finish'); assert_equals(evt.currentTime, null); assert_equals(evt.timelineTime, null); }, 'Event created without an event parameter has null time values'); -test(function(t) { +test(t => { const evt = new AnimationPlaybackEvent('cancel', { currentTime: -100,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations.html index e87751c..9533bee 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>document.getAnimations tests</title> +<title>Document.getAnimations</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-document-getanimations"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -9,20 +9,20 @@ <div id="log"></div> <div id="target"></div> <script> -"use strict"; +'use strict'; -var gKeyFrames = { 'marginLeft': ['100px', '200px'] }; +const gKeyFrames = { 'marginLeft': ['100px', '200px'] }; -test(function(t) { +test(t => { assert_equals(document.getAnimations().length, 0, 'getAnimations returns an empty sequence for a document ' + 'with no animations'); }, 'Test document.getAnimations for non-animated content'); -test(function(t) { - var div = createDiv(t); - var anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC); - var anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC); + const anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC); assert_equals(document.getAnimations().length, 2, 'getAnimation returns running animations'); @@ -32,18 +32,18 @@ 'getAnimation only returns running animations'); }, 'Test document.getAnimations for script-generated animations') -test(function(t) { - var div = createDiv(t); - var anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC); - var anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC); + const anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC); assert_array_equals(document.getAnimations(), [ anim1, anim2 ], 'getAnimations() returns running animations'); }, 'Test the order of document.getAnimations with script generated animations') -test(function(t) { - var effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC); - var anim = new Animation(effect, document.timeline); +test(t => { + const effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC); + const anim = new Animation(effect, document.timeline); anim.play(); assert_equals(document.getAnimations().length, 0,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/timeline.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/timeline.html index b8a5303..a0d7c9f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/timeline.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/timeline.html
@@ -10,7 +10,7 @@ <script> 'use strict'; -test(function() { +test(() => { assert_equals(document.timeline, document.timeline, 'Document.timeline returns the same object every time'); const iframe = document.getElementById('iframe');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/DocumentTimeline/constructor.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/DocumentTimeline/constructor.html index 8968ff4..47d353c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/DocumentTimeline/constructor.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/DocumentTimeline/constructor.html
@@ -8,30 +8,30 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; -test(function(t) { - var timeline = new DocumentTimeline(); +test(t => { + const timeline = new DocumentTimeline(); assert_times_equal(timeline.currentTime, document.timeline.currentTime); }, 'An origin time of zero is used when none is supplied'); -test(function(t) { - var timeline = new DocumentTimeline({ originTime: 0 }); +test(t => { + const timeline = new DocumentTimeline({ originTime: 0 }); assert_times_equal(timeline.currentTime, document.timeline.currentTime); }, 'A zero origin time produces a document timeline with a current time ' + 'identical to the default document timeline'); -test(function(t) { - var timeline = new DocumentTimeline({ originTime: 10 * MS_PER_SEC }); +test(t => { + const timeline = new DocumentTimeline({ originTime: 10 * MS_PER_SEC }); assert_times_equal(timeline.currentTime, (document.timeline.currentTime - 10 * MS_PER_SEC)); }, 'A positive origin time makes the document timeline\'s current time lag ' + 'behind the default document timeline'); -test(function(t) { - var timeline = new DocumentTimeline({ originTime: -10 * MS_PER_SEC }); +test(t => { + const timeline = new DocumentTimeline({ originTime: -10 * MS_PER_SEC }); assert_times_equal(timeline.currentTime, (document.timeline.currentTime + 10 * MS_PER_SEC));
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/composite.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/composite.html index 1825b71..6447dd2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/composite.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/composite.html
@@ -1,6 +1,6 @@ <!doctype html> <meta charset=utf-8> -<title>KeyframeEffect.composite tests</title> +<title>KeyframeEffect.composite</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-keyframeeffect-composite"> <script src="/resources/testharness.js"></script> @@ -11,34 +11,34 @@ <script> 'use strict'; -test(function(t) { - var anim = createDiv(t).animate(null); +test(t => { + const anim = createDiv(t).animate(null); assert_equals(anim.effect.composite, 'replace', 'The default value should be replace'); }, 'Default value'); -test(function(t) { - var anim = createDiv(t).animate(null); +test(t => { + const anim = createDiv(t).animate(null); anim.effect.composite = 'add'; assert_equals(anim.effect.composite, 'add', 'The effect composite value should be replaced'); }, 'Change composite value'); -test(function(t) { - var anim = createDiv(t).animate({ left: '10px' }); +test(t => { + const anim = createDiv(t).animate({ left: '10px' }); anim.effect.composite = 'add'; - var keyframes = anim.effect.getKeyframes(); + const keyframes = anim.effect.getKeyframes(); assert_equals(keyframes[0].composite, undefined, 'unspecified keyframe composite value should be absent even ' + 'if effect composite is set'); }, 'Unspecified keyframe composite value when setting effect composite'); -test(function(t) { - var anim = createDiv(t).animate({ left: '10px', composite: 'replace' }); +test(t => { + const anim = createDiv(t).animate({ left: '10px', composite: 'replace' }); anim.effect.composite = 'add'; - var keyframes = anim.effect.getKeyframes(); + const keyframes = anim.effect.getKeyframes(); assert_equals(keyframes[0].composite, 'replace', 'specified keyframe composite value should not be overridden ' + 'by setting effect composite');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor-expected.txt index f8143d1e..009bba2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor-expected.txt
@@ -136,13 +136,13 @@ PASS KeyframeEffectReadOnly constructor throws with empty property-indexed keyframe with an invalid easing PASS KeyframeEffectReadOnly constructor throws with empty property-indexed keyframe with an invalid easings array PASS KeyframeEffectReadOnly constructor throws with a keyframe sequence with an invalid easing value -FAIL KeyframeEffectReadOnly constructor throws with property-indexed keyframes with an invalid composite value assert_throws: function "function () { +FAIL KeyframeEffectReadOnly constructor throws with property-indexed keyframes with an invalid composite value assert_throws: function "() => { new KeyframeEffectReadOnly(target, subtest.input); }" did not throw -FAIL KeyframeEffectReadOnly constructor throws with property-indexed keyframes with an invalid composite value as one of the array values assert_throws: function "function () { +FAIL KeyframeEffectReadOnly constructor throws with property-indexed keyframes with an invalid composite value as one of the array values assert_throws: function "() => { new KeyframeEffectReadOnly(target, subtest.input); }" did not throw -FAIL KeyframeEffectReadOnly constructor throws with keyframes with an invalid composite value assert_throws: function "function () { +FAIL KeyframeEffectReadOnly constructor throws with keyframes with an invalid composite value assert_throws: function "() => { new KeyframeEffectReadOnly(target, subtest.input); }" did not throw FAIL A KeyframeEffectReadOnly constructed without any KeyframeEffectOptions object assert_equals: default composite expected (string) "replace" but got (undefined) undefined @@ -172,7 +172,7 @@ PASS Invalid KeyframeEffectReadOnly option by a variable easing PASS Invalid KeyframeEffectReadOnly option by a multi-value easing FAIL A KeyframeEffectReadOnly constructed with null target assert_equals: Effect created with null target has correct target expected (object) null but got (undefined) undefined -FAIL KeyframeEffect constructor propagates exceptions generated by accessing the options object assert_throws: function "function () { +FAIL KeyframeEffect constructor propagates exceptions generated by accessing the options object assert_throws: function "() => { new KeyframeEffect(target, { get left() { throw test_error }}) }" did not throw Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor.html index 711b4ed7..41cc396 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor.html
@@ -19,16 +19,16 @@ const target = document.getElementById('target'); -test(function(t) { - gEmptyKeyframeListTests.forEach(function(frames) { +test(t => { + for (const frames of gEmptyKeyframeListTests) { assert_equals(new KeyframeEffectReadOnly(target, frames) .getKeyframes().length, - 0, 'number of frames for ' + JSON.stringify(frames)); - }); + 0, `number of frames for ${JSON.stringify(frames)}`); + } }, 'A KeyframeEffectReadOnly can be constructed with no frames'); -test(function(t) { - gEasingParsingTests.forEach(function(subtest) { +test(t => { + for (const subtest of gEasingParsingTests) { const easing = subtest[0]; const expected = subtest[1]; const effect = new KeyframeEffectReadOnly(target, { @@ -36,98 +36,96 @@ }, { easing: easing }); assert_equals(effect.timing.easing, expected, `resulting easing for '${easing}'`); - }); + } }, 'easing values are parsed correctly when passed to the ' + 'KeyframeEffectReadOnly constructor in KeyframeEffectOptions'); -test(function(t) { - gInvalidEasings.forEach(invalidEasing => { +test(t => { + for (const invalidEasing of gInvalidEasings) { assert_throws(new TypeError, () => { new KeyframeEffectReadOnly(target, null, { easing: invalidEasing }); }, `TypeError is thrown for easing '${invalidEasing}'`); - }); + } }, 'Invalid easing values are correctly rejected when passed to the ' + 'KeyframeEffectReadOnly constructor in KeyframeEffectOptions'); -test(function(t) { - const getKeyframe = function(composite) { - return { left: [ '10px', '20px' ], composite: composite }; - }; - gGoodKeyframeCompositeValueTests.forEach(function(composite) { +test(t => { + const getKeyframe = + composite => ({ left: [ '10px', '20px' ], composite: composite }); + for (const composite of gGoodKeyframeCompositeValueTests) { const effect = new KeyframeEffectReadOnly(target, getKeyframe(composite)); assert_equals(effect.getKeyframes()[0].composite, composite, `resulting composite for '${composite}'`); - }); - gBadCompositeValueTests.forEach(function(composite) { - assert_throws(new TypeError, function() { + } + for (const composite of gBadCompositeValueTests) { + assert_throws(new TypeError, () => { new KeyframeEffectReadOnly(target, getKeyframe(composite)); }); - }); + } }, 'composite values are parsed correctly when passed to the ' + 'KeyframeEffectReadOnly constructor in property-indexed keyframes'); -test(function(t) { - const getKeyframes = function(composite) { - return [ +test(t => { + const getKeyframes = composite => + [ { offset: 0, left: '10px', composite: composite }, { offset: 1, left: '20px' } ]; - }; - gGoodKeyframeCompositeValueTests.forEach(function(composite) { + for (const composite of gGoodKeyframeCompositeValueTests) { const effect = new KeyframeEffectReadOnly(target, getKeyframes(composite)); assert_equals(effect.getKeyframes()[0].composite, composite, `resulting composite for '${composite}'`); - }); - gBadCompositeValueTests.forEach(function(composite) { - assert_throws(new TypeError, function() { + } + for (const composite of gBadCompositeValueTests) { + assert_throws(new TypeError, () => { new KeyframeEffectReadOnly(target, getKeyframes(composite)); }); - }); + } }, 'composite values are parsed correctly when passed to the ' + 'KeyframeEffectReadOnly constructor in regular keyframes'); -test(function(t) { - gGoodOptionsCompositeValueTests.forEach(function(composite) { +test(t => { + for (const composite of gGoodOptionsCompositeValueTests) { const effect = new KeyframeEffectReadOnly(target, { left: ['10px', '20px'] }, { composite: composite }); assert_equals(effect.getKeyframes()[0].composite, undefined, `resulting composite for '${composite}'`); - }); - gBadCompositeValueTests.forEach(function(composite) { - assert_throws(new TypeError, function() { + } + for (const composite of gBadCompositeValueTests) { + assert_throws(new TypeError, () => { new KeyframeEffectReadOnly(target, { left: ['10px', '20px'] }, { composite: composite }); }); - }); + } }, 'composite value is absent if the composite operation specified on the ' + 'keyframe effect is being used'); -gKeyframesTests.forEach(function(subtest) { - test(function(t) { +for (const subtest of gKeyframesTests) { + test(t => { const effect = new KeyframeEffectReadOnly(target, subtest.input); assert_frame_lists_equal(effect.getKeyframes(), subtest.output); }, `A KeyframeEffectReadOnly can be constructed with ${subtest.desc}`); - test(function(t) { + test(t => { const effect = new KeyframeEffectReadOnly(target, subtest.input); const secondEffect = new KeyframeEffectReadOnly(target, effect.getKeyframes()); assert_frame_lists_equal(secondEffect.getKeyframes(), effect.getKeyframes()); }, `A KeyframeEffectReadOnly constructed with ${subtest.desc} roundtrips`); -}); +} -gInvalidKeyframesTests.forEach(function(subtest) { - test(function(t) { - assert_throws(new TypeError, function() { +for (const subtest of gInvalidKeyframesTests) { + test(t => { + assert_throws(new TypeError, () => { new KeyframeEffectReadOnly(target, subtest.input); }); }, `KeyframeEffectReadOnly constructor throws with ${subtest.desc}`); -}); +} -test(function(t) { +test(t => { const effect = new KeyframeEffectReadOnly(target, { left: ['10px', '20px'] }); @@ -147,8 +145,8 @@ }, 'A KeyframeEffectReadOnly constructed without any ' + 'KeyframeEffectOptions object'); -gKeyframeEffectOptionTests.forEach(function(subtest) { - test(function(t) { +for (const subtest of gKeyframeEffectOptionTests) { + test(t => { const effect = new KeyframeEffectReadOnly(target, { left: ['10px', '20px'] }, subtest.input); @@ -172,19 +170,19 @@ 'timing direction'); }, `A KeyframeEffectReadOnly constructed by ${subtest.desc}`); -}); +} -gInvalidKeyframeEffectOptionTests.forEach(function(subtest) { - test(function(t) { - assert_throws(new TypeError, function() { +for (const subtest of gInvalidKeyframeEffectOptionTests) { + test(t => { + assert_throws(new TypeError, () => { new KeyframeEffectReadOnly(target, { left: ['10px', '20px'] }, subtest.input); }); }, `Invalid KeyframeEffectReadOnly option by ${subtest.desc}`); -}); +} -test(function(t) { +test(t => { const effect = new KeyframeEffectReadOnly(null, { left: ['10px', '20px'] }, { duration: 100 * MS_PER_SEC, @@ -193,10 +191,10 @@ 'Effect created with null target has correct target'); }, 'A KeyframeEffectReadOnly constructed with null target'); -test(function(t) { +test(t => { const test_error = { name: 'test' }; - assert_throws(test_error, function() { + assert_throws(test_error, () => { new KeyframeEffect(target, { get left() { throw test_error }}) }); }, 'KeyframeEffect constructor propagates exceptions generated by accessing'
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/copy-constructor.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/copy-constructor.html index a6b4132..f6bb45a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/copy-constructor.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/copy-constructor.html
@@ -13,13 +13,13 @@ <script> 'use strict'; -test(function(t) { +test(t => { const effect = new KeyframeEffectReadOnly(createDiv(t), null); const copiedEffect = new KeyframeEffectReadOnly(effect); assert_equals(copiedEffect.target, effect.target, 'same target'); }, 'Copied KeyframeEffectReadOnly has the same target'); -test(function(t) { +test(t => { const effect = new KeyframeEffectReadOnly(null, [ { marginLeft: '0px' }, @@ -52,7 +52,7 @@ } }, 'Copied KeyframeEffectReadOnly has the same keyframes'); -test(function(t) { +test(t => { const effect = new KeyframeEffectReadOnly(null, null, { iterationComposite: 'accumulate' }); @@ -64,7 +64,7 @@ 'same compositeOperation'); }, 'Copied KeyframeEffectReadOnly has the same KeyframeEffectOptions'); -test(function(t) { +test(t => { const effect = new KeyframeEffectReadOnly(null, null, { duration: 100 * MS_PER_SEC, delay: -1 * MS_PER_SEC, @@ -90,7 +90,7 @@ assert_equals(timingA.easing, timingB.easing, 'same easing'); }, 'Copied KeyframeEffectReadOnly has the same timing content'); -test(function(t) { +test(t => { const effect = new KeyframeEffectReadOnly(createDiv(t), null); assert_equals(effect.constructor.name, 'KeyframeEffectReadOnly'); assert_equals(effect.timing.constructor.name,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/getComputedTiming.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/getComputedTiming.html deleted file mode 100644 index 4d79927..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/getComputedTiming.html +++ /dev/null
@@ -1,212 +0,0 @@ -<!DOCTYPE html> -<meta charset=utf-8> -<title>KeyframeEffectReadOnly getComputedTiming() tests</title> -<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffectreadonly-getcomputedtiming"> -<link rel="author" title="Boris Chiou" href="mailto:boris.chiou@gmail.com"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="../../testcommon.js"></script> -<body> -<div id="log"></div> -<div id="target"></div> -<script> -"use strict"; - -var target = document.getElementById("target"); - -test(function(t) { - var effect = new KeyframeEffectReadOnly(target, - { left: ["10px", "20px"] }); - - var ct = effect.getComputedTiming(); - assert_equals(ct.delay, 0, "computed delay"); - assert_equals(ct.fill, "none", "computed fill"); - assert_equals(ct.iterations, 1.0, "computed iterations"); - assert_equals(ct.duration, 0, "computed duration"); - assert_equals(ct.direction, "normal", "computed direction"); -}, "values of getComputedTiming() when a KeyframeEffectReadOnly is " + - "constructed without any KeyframeEffectOptions object"); - -var gGetComputedTimingTests = [ - { desc: "an empty KeyframeEffectOptions object", - input: { }, - expected: { } }, - { desc: "a normal KeyframeEffectOptions object", - input: { delay: 1000, - fill: "auto", - iterations: 5.5, - duration: "auto", - direction: "alternate" }, - expected: { delay: 1000, - fill: "none", - iterations: 5.5, - duration: 0, - direction: "alternate" } }, - { desc: "a double value", - input: 3000, - timing: { duration: 3000 }, - expected: { delay: 0, - fill: "none", - iterations: 1, - duration: 3000, - direction: "normal" } }, - { desc: "+Infinity", - input: Infinity, - expected: { duration: Infinity } }, - { desc: "an Infinity duration", - input: { duration: Infinity }, - expected: { duration: Infinity } }, - { desc: "an auto duration", - input: { duration: "auto" }, - expected: { duration: 0 } }, - { desc: "an Infinity iterations", - input: { iterations: Infinity }, - expected: { iterations: Infinity } }, - { desc: "an auto fill", - input: { fill: "auto" }, - expected: { fill: "none" } }, - { desc: "a forwards fill", - input: { fill: "forwards" }, - expected: { fill: "forwards" } } -]; - -gGetComputedTimingTests.forEach(function(stest) { - test(function(t) { - var effect = new KeyframeEffectReadOnly(target, - { left: ["10px", "20px"] }, - stest.input); - - // Helper function to provide default expected values when the test does - // not supply them. - var expected = function(field, defaultValue) { - return field in stest.expected ? stest.expected[field] : defaultValue; - }; - - var ct = effect.getComputedTiming(); - assert_equals(ct.delay, expected("delay", 0), - "computed delay"); - assert_equals(ct.fill, expected("fill", "none"), - "computed fill"); - assert_equals(ct.iterations, expected("iterations", 1), - "computed iterations"); - assert_equals(ct.duration, expected("duration", 0), - "computed duration"); - assert_equals(ct.direction, expected("direction", "normal"), - "computed direction"); - - }, "values of getComputedTiming() when a KeyframeEffectReadOnly is " + - "constructed by " + stest.desc); -}); - -var gActiveDurationTests = [ - { desc: "an empty KeyframeEffectOptions object", - input: { }, - expected: 0 }, - { desc: "a non-zero duration and default iteration count", - input: { duration: 1000 }, - expected: 1000 }, - { desc: "a non-zero duration and integral iteration count", - input: { duration: 1000, iterations: 7 }, - expected: 7000 }, - { desc: "a non-zero duration and fractional iteration count", - input: { duration: 1000, iterations: 2.5 }, - expected: 2500 }, - { desc: "an non-zero duration and infinite iteration count", - input: { duration: 1000, iterations: Infinity }, - expected: Infinity }, - { desc: "an non-zero duration and zero iteration count", - input: { duration: 1000, iterations: 0 }, - expected: 0 }, - { desc: "a zero duration and default iteration count", - input: { duration: 0 }, - expected: 0 }, - { desc: "a zero duration and fractional iteration count", - input: { duration: 0, iterations: 2.5 }, - expected: 0 }, - { desc: "a zero duration and infinite iteration count", - input: { duration: 0, iterations: Infinity }, - expected: 0 }, - { desc: "a zero duration and zero iteration count", - input: { duration: 0, iterations: 0 }, - expected: 0 }, - { desc: "an infinite duration and default iteration count", - input: { duration: Infinity }, - expected: Infinity }, - { desc: "an infinite duration and zero iteration count", - input: { duration: Infinity, iterations: 0 }, - expected: 0 }, - { desc: "an infinite duration and fractional iteration count", - input: { duration: Infinity, iterations: 2.5 }, - expected: Infinity }, - { desc: "an infinite duration and infinite iteration count", - input: { duration: Infinity, iterations: Infinity }, - expected: Infinity }, -]; - -gActiveDurationTests.forEach(function(stest) { - test(function(t) { - var effect = new KeyframeEffectReadOnly(target, - { left: ["10px", "20px"] }, - stest.input); - - assert_equals(effect.getComputedTiming().activeDuration, - stest.expected); - - }, "getComputedTiming().activeDuration for " + stest.desc); -}); - -var gEndTimeTests = [ - { desc: "an empty KeyframeEffectOptions object", - input: { }, - expected: 0 }, - { desc: "a non-zero duration and default iteration count", - input: { duration: 1000 }, - expected: 1000 }, - { desc: "a non-zero duration and non-default iteration count", - input: { duration: 1000, iterations: 2.5 }, - expected: 2500 }, - { desc: "a non-zero duration and non-zero delay", - input: { duration: 1000, delay: 1500 }, - expected: 2500 }, - { desc: "a non-zero duration, non-zero delay and non-default iteration", - input: { duration: 1000, delay: 1500, iterations: 2 }, - expected: 3500 }, - { desc: "an infinite iteration count", - input: { duration: 1000, iterations: Infinity }, - expected: Infinity }, - { desc: "an infinite duration", - input: { duration: Infinity, iterations: 10 }, - expected: Infinity }, - { desc: "an infinite duration and delay", - input: { duration: Infinity, iterations: 10, delay: 1000 }, - expected: Infinity }, - { desc: "an infinite duration and negative delay", - input: { duration: Infinity, iterations: 10, delay: -1000 }, - expected: Infinity }, - { desc: "an non-zero duration and negative delay", - input: { duration: 1000, iterations: 2, delay: -1000 }, - expected: 1000 }, - { desc: "an non-zero duration and negative delay greater than active " + - "duration", - input: { duration: 1000, iterations: 2, delay: -3000 }, - expected: 0 }, - { desc: "a zero duration and negative delay", - input: { duration: 0, iterations: 2, delay: -1000 }, - expected: 0 } -]; - -gEndTimeTests.forEach(function(stest) { - test(function(t) { - var effect = new KeyframeEffectReadOnly(target, - { left: ["10px", "20px"] }, - stest.input); - - assert_equals(effect.getComputedTiming().endTime, - stest.expected); - - }, "getComputedTiming().endTime for " + stest.desc); -}); - -done(); -</script> -</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite-expected.txt index 35cd047..5319aef 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite-expected.txt
@@ -1,36 +1,4 @@ This is a testharness.js-based test. -PASS iterationComposite of discrete type animation (align-content) -FAIL iterationComposite of <length> type animation assert_equals: Animated margin-left style at 0s of the third iteration expected "20px" but got "0px" -FAIL iterationComposite of <percentage> type animation assert_equals: Animated width style at 0s of the third iteration expected "100px" but got "0px" -FAIL iterationComposite of <color> type animation assert_equals: Animated color style at 0s of the third iteration expected "rgb(240, 240, 240)" but got "rgb(0, 0, 0)" -FAIL iterationComposite of <color> type animation that green component is decreasing assert_equals: Animated color style at 0s of the third iteration expected "rgb(120, 240, 120)" but got "rgb(0, 120, 0)" -FAIL iterationComposite of <number> type animation assert_equals: Animated flex-grow style at 0s of the third iteration expected "20" but got "0" -FAIL iterationComposite of <shape> type animation assert_equals: Animated clip style at 0s of the third iteration expected "rect(20px, 20px, 20px, 20px)" but got "rect(0px, 0px, 0px, 0px)" -FAIL iterationComposite of <calc()> value animation assert_equals: Animated calc width style at 0s of the third iteration expected "20px" but got "0px" -FAIL iterationComposite of <calc()> value animation that the values can'tbe reduced assert_equals: Animated calc width style at 0s of the third iteration expected "40px" but got "0px" -FAIL iterationComposite of opacity animation assert_equals: Animated opacity style at 0s of the third iteration expected "0.8" but got "0" -FAIL iterationComposite of box-shadow animation assert_equals: Animated box-shadow style at 0s of the third iteration expected "rgb(240, 240, 240) 20px 20px 20px 0px" but got "rgb(0, 0, 0) 0px 0px 0px 0px" -FAIL iterationComposite of filter blur animation assert_equals: Animated filter blur style at 0s of the third iteration expected "blur(20px)" but got "blur(0px)" -FAIL iterationComposite of filter brightness for different unit animation assert_equals: Animated filter brightness style at 0s of the third iteration expected "brightness(2.6)" but got "brightness(1)" -PASS iterationComposite of filter brightness animation -FAIL iterationComposite of filter drop-shadow animation assert_equals: Animated filter drop-shadow style at 0s of the third iteration expected "drop-shadow(rgb(240, 240, 240) 20px 20px 20px)" but got "drop-shadow(rgb(0, 0, 0) 0px 0px 0px)" -FAIL iterationComposite of same filter list animation assert_equals: Animated filter list at 0s of the third iteration expected "brightness(3) contrast(3)" but got "brightness(1) contrast(1)" -FAIL iterationComposite of discrete filter list because of mismatch of the order assert_equals: Animated filter list at 50s of the third iteration expected "contrast(4) brightness(4)" but got "contrast(2) brightness(2)" -FAIL iterationComposite of different length filter list animation assert_equals: Animated filter list at 0s of the third iteration expected "sepia(2) contrast(3)" but got "sepia(0)" -PASS iterationComposite of transform(rotate) animation -PASS iterationComposite of transform: [ scale(0), scale(1) ] animation -FAIL iterationComposite of transform: [ scale(1), scale(2) ] animation assert_approx_equals: expected matrix(3, 0, 0, 3, 0, 0) but got matrix(1, 0, 0, 1, 0, 0): Animated transform(scale) style at 0s of the third iteration expected 3 +/- 0.0001 but got 1 -FAIL iterationComposite of transform: scale(2) animation assert_approx_equals: expected matrix(2, 0, 0, 2, 0, 0) but got matrix(0, 0, 0, 0, 0, 0): Animated transform(scale) style at 0s of the third iteration expected 2 +/- 0.0001 but got 0 -FAIL iterationComposite of transform list animation assert_approx_equals: expected matrix(1, 0, 0, 1, 20, 0) but got matrix(1, 0, 0, 1, 0, 0): Animated transform list at 0s of the third iteration expected 20 +/- 0.0001 but got 0 -FAIL iterationComposite of transform of matrix function assert_approx_equals: expected matrix(6, 0, 0, 6, 60, 0) but got matrix(2, 0, 0, 2, 0, 0): Animated transform of matrix function at 0s of the third iteration expected 6 +/- 0.0001 but got 2 -FAIL iterationComposite of transform list animation whose order is mismatched assert_approx_equals: expected matrix(6, 0, 0, 6, 60, 0) but got matrix(2, 0, 0, 2, 0, 0): Animated transform list at 0s of the third iteration expected 6 +/- 0.0001 but got 2 -FAIL iterationComposite of transform list animation whose order is mismatched because of missing functions assert_approx_equals: expected matrix(3, 0, 0, 3, 40, 0) but got matrix(1, 0, 0, 1, 0, 0): Animated transform list at 0s of the third iteration expected 3 +/- 0.0001 but got 1 -FAIL iterationComposite of transform from none to translate assert_approx_equals: expected matrix(1, 0, 0, 1, 20, 0) but got matrix(1, 0, 0, 1, 0, 0): Animated transform list at 0s of the third iteration expected 20 +/- 0.0001 but got 0 -FAIL iterationComposite of transform of matrix3d function assert_approx_equals: expected matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1) but got matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 30, 1): Animated transform of matrix3d function at 0s of the third iteration expected 130 +/- 0.0001 but got 30 -FAIL iterationComposite of transform of rotate3d function assert_equals: dimension of the matrix: Animated transform of rotate3d function at 0s of the third iteration expected 16 but got 6 -FAIL iterationComposite starts with non-zero value animation assert_equals: Animated margin-left style at 0s of the third iteration expected "50px" but got "10px" -FAIL iterationComposite with negative final value animation assert_equals: Animated margin-left style at 0s of the third iteration expected "-10px" but got "10px" -FAIL interationComposite changes assert_equals: Animated style at 50s of the third iteration expected "25px" but got "5px" -FAIL duration changes with iterationComposite(accumulate) assert_equals: Animated style at 50s of the third iteration expected "25px" but got "5px" +FAIL iterationComposite can be updated while an animation is in progress assert_equals: Animated style at 50s of the third iteration expected "25px" but got "5px" Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite.html index 7719fa9..cab51d0 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite.html
@@ -1,7 +1,7 @@ <!doctype html> <meta charset=utf-8> -<title>KeyframeEffect.iterationComposite tests</title> -<link rel="help" href="https://w3c.github.io/web-animations/#effect-accumulation-section"> +<title>KeyframeEffect.iterationComposite</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-keyframeeffect-iterationcomposite"> <script src=/resources/testharness.js></script> <script src=/resources/testharnessreport.js></script> <script src="../../testcommon.js"></script> @@ -9,792 +9,13 @@ <script> 'use strict'; -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ alignContent: ['flex-start', 'flex-end'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).alignContent, 'flex-end', - 'Animated align-content style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).alignContent, 'flex-start', - 'Animated align-content style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).alignContent, 'flex-end', - 'Animated align-content style at 50s of the third iteration'); -}, 'iterationComposite of discrete type animation (align-content)'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ marginLeft: ['0px', '10px'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).marginLeft, '5px', - 'Animated margin-left style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).marginLeft, '20px', - 'Animated margin-left style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).marginLeft, '25px', - 'Animated margin-left style at 50s of the third iteration'); -}, 'iterationComposite of <length> type animation'); - -test(function(t) { - var parent = createDiv(t); - parent.style.width = '100px'; - var div = createDiv(t); - parent.appendChild(div); - - var anim = - div.animate({ width: ['0%', '50%'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).width, '25px', - 'Animated width style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).width, '100px', - 'Animated width style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).width, '125px', - 'Animated width style at 50s of the third iteration'); -}, 'iterationComposite of <percentage> type animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ color: ['rgb(0, 0, 0)', 'rgb(120, 120, 120)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).color, 'rgb(60, 60, 60)', - 'Animated color style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).color, 'rgb(240, 240, 240)', - 'Animated color style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).color, 'rgb(255, 255, 255)', - 'Animated color style at 50s of the third iteration'); -}, 'iterationComposite of <color> type animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ color: ['rgb(0, 120, 0)', 'rgb(60, 60, 60)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).color, 'rgb(30, 90, 30)', - 'Animated color style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).color, 'rgb(120, 240, 120)', - 'Animated color style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - // The green color is (240 + 180) / 2 = 210 - assert_equals(getComputedStyle(div).color, 'rgb(150, 210, 150)', - 'Animated color style at 50s of the third iteration'); -}, 'iterationComposite of <color> type animation that green component is ' + - 'decreasing'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ flexGrow: [0, 10] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).flexGrow, '5', - 'Animated flex-grow style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).flexGrow, '20', - 'Animated flex-grow style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).flexGrow, '25', - 'Animated flex-grow style at 50s of the third iteration'); -}, 'iterationComposite of <number> type animation'); - -test(function(t) { - var div = createDiv(t); - div.style.position = 'absolute'; - var anim = - div.animate({ clip: ['rect(0px, 0px, 0px, 0px)', - 'rect(10px, 10px, 10px, 10px)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).clip, 'rect(5px, 5px, 5px, 5px)', - 'Animated clip style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).clip, 'rect(20px, 20px, 20px, 20px)', - 'Animated clip style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).clip, 'rect(25px, 25px, 25px, 25px)', - 'Animated clip style at 50s of the third iteration'); -}, 'iterationComposite of <shape> type animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ width: ['calc(0vw + 0px)', 'calc(0vw + 10px)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).width, '5px', - 'Animated calc width style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).width, '20px', - 'Animated calc width style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).width, '25px', - 'Animated calc width style at 50s of the third iteration'); -}, 'iterationComposite of <calc()> value animation'); - -test(function(t) { - var parent = createDiv(t); - parent.style.width = '100px'; - var div = createDiv(t); - parent.appendChild(div); - - var anim = - div.animate({ width: ['calc(0% + 0px)', 'calc(10% + 10px)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).width, '10px', - // 100px * 5% + 5px - 'Animated calc width style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).width, - '40px', // 100px * (10% + 10%) + (10px + 10px) - 'Animated calc width style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).width, - '50px', // (40px + 60px) / 2 - 'Animated calc width style at 50s of the third iteration'); -}, 'iterationComposite of <calc()> value animation that the values can\'t' + - 'be reduced'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ opacity: [0, 0.4] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).opacity, '0.2', - 'Animated opacity style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).opacity, '0.8', - 'Animated opacity style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).opacity, '1', // (0.8 + 1.2) * 0.5 - 'Animated opacity style at 50s of the third iteration'); -}, 'iterationComposite of opacity animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ boxShadow: ['rgb(0, 0, 0) 0px 0px 0px 0px', - 'rgb(120, 120, 120) 10px 10px 10px 0px'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).boxShadow, - 'rgb(60, 60, 60) 5px 5px 5px 0px', - 'Animated box-shadow style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).boxShadow, - 'rgb(240, 240, 240) 20px 20px 20px 0px', - 'Animated box-shadow style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).boxShadow, - 'rgb(255, 255, 255) 25px 25px 25px 0px', - 'Animated box-shadow style at 50s of the third iteration'); -}, 'iterationComposite of box-shadow animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ filter: ['blur(0px)', 'blur(10px)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, 'blur(5px)', - 'Animated filter blur style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).filter, 'blur(20px)', - 'Animated filter blur style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, 'blur(25px)', - 'Animated filter blur style at 50s of the third iteration'); -}, 'iterationComposite of filter blur animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ filter: ['brightness(1)', - 'brightness(180%)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - 'brightness(1.4)', - 'Animated filter brightness style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).filter, - 'brightness(2.6)', // brightness(1) + brightness(0.8) + brightness(0.8) - 'Animated filter brightness style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - 'brightness(3)', // (brightness(2.6) + brightness(3.4)) * 0.5 - 'Animated filter brightness style at 50s of the third iteration'); -}, 'iterationComposite of filter brightness for different unit animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ filter: ['brightness(0)', - 'brightness(1)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - 'brightness(0.5)', - 'Animated filter brightness style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).filter, - 'brightness(0)', // brightness(1) is an identity element, not accumulated. - 'Animated filter brightness style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - 'brightness(0.5)', // brightness(1) is an identity element, not accumulated. - 'Animated filter brightness style at 50s of the third iteration'); -}, 'iterationComposite of filter brightness animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ filter: ['drop-shadow(rgb(0, 0, 0) 0px 0px 0px)', - 'drop-shadow(rgb(120, 120, 120) 10px 10px 10px)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - 'drop-shadow(rgb(60, 60, 60) 5px 5px 5px)', - 'Animated filter drop-shadow style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).filter, - 'drop-shadow(rgb(240, 240, 240) 20px 20px 20px)', - 'Animated filter drop-shadow style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - 'drop-shadow(rgb(255, 255, 255) 25px 25px 25px)', - 'Animated filter drop-shadow style at 50s of the third iteration'); -}, 'iterationComposite of filter drop-shadow animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ filter: ['brightness(1) contrast(1)', - 'brightness(2) contrast(2)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - 'brightness(1.5) contrast(1.5)', - 'Animated filter list at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).filter, - 'brightness(3) contrast(3)', - 'Animated filter list at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - 'brightness(3.5) contrast(3.5)', - 'Animated filter list at 50s of the third iteration'); -}, 'iterationComposite of same filter list animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ filter: ['brightness(1) contrast(1)', - 'contrast(2) brightness(2)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - 'contrast(2) brightness(2)', // discrete - 'Animated filter list at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).filter, - // We can't accumulate 'contrast(2) brightness(2)' onto - // the first list 'brightness(1) contrast(1)' because of - // mismatch of the order. - 'brightness(1) contrast(1)', - 'Animated filter list at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - // We *can* accumulate 'contrast(2) brightness(2)' onto - // the same list 'contrast(2) brightness(2)' here. - 'contrast(4) brightness(4)', // discrete - 'Animated filter list at 50s of the third iteration'); -}, 'iterationComposite of discrete filter list because of mismatch ' + - 'of the order'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ filter: ['sepia(0)', - 'sepia(1) contrast(2)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - 'sepia(0.5) contrast(1.5)', - 'Animated filter list at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).filter, - 'sepia(2) contrast(3)', - 'Animated filter list at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).filter, - 'sepia(2.5) contrast(3.5)', - 'Animated filter list at 50s of the third iteration'); -}, 'iterationComposite of different length filter list animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ transform: ['rotate(0deg)', 'rotate(180deg)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(0, 1, -1, 0, 0, 0)', // rotate(90deg) - 'Animated transform(rotate) style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(1, 0, 0, 1, 0, 0)', // rotate(360deg) - 'Animated transform(rotate) style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(0, 1, -1, 0, 0, 0)', // rotate(450deg) - 'Animated transform(rotate) style at 50s of the third iteration'); -}, 'iterationComposite of transform(rotate) animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ transform: ['scale(0)', 'scale(1)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5) - 'Animated transform(scale) style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(0, 0, 0, 0, 0, 0)', // scale(0); scale(1) is an identity element, - // not accumulated. - 'Animated transform(scale) style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5); scale(1) an identity - // element, not accumulated. - 'Animated transform(scale) style at 50s of the third iteration'); -}, 'iterationComposite of transform: [ scale(0), scale(1) ] animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ transform: ['scale(1)', 'scale(2)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(1.5, 0, 0, 1.5, 0, 0)', // scale(1.5) - 'Animated transform(scale) style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(3, 0, 0, 3, 0, 0)', // scale(1 + (2 -1) + (2 -1)) - 'Animated transform(scale) style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(3.5, 0, 0, 3.5, 0, 0)', // (scale(3) + scale(4)) * 0.5 - 'Animated transform(scale) style at 50s of the third iteration'); -}, 'iterationComposite of transform: [ scale(1), scale(2) ] animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ transform: ['scale(0)', 'scale(2)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(1, 0, 0, 1, 0, 0)', // scale(1) - 'Animated transform(scale) style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(2, 0, 0, 2, 0, 0)', // (scale(0) + scale(2-1)*2) - 'Animated transform(scale) style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(3, 0, 0, 3, 0, 0)', // (scale(2) + scale(4)) * 0.5 - 'Animated transform(scale) style at 50s of the third iteration'); -}, 'iterationComposite of transform: scale(2) animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ transform: ['rotate(0deg) translateX(0px)', - 'rotate(180deg) translateX(10px)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(0, 1, -1, 0, 0, 5)', // rotate(90deg) translateX(5px) - 'Animated transform list at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(1, 0, 0, 1, 20, 0)', // rotate(360deg) translateX(20px) - 'Animated transform list at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(0, 1, -1, 0, 0, 25)', // rotate(450deg) translateX(25px) - 'Animated transform list at 50s of the third iteration'); -}, 'iterationComposite of transform list animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ transform: ['matrix(2, 0, 0, 2, 0, 0)', - 'matrix(3, 0, 0, 3, 30, 0)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(2.5, 0, 0, 2.5, 15, 0)', - 'Animated transform of matrix function at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_matrix_equals(getComputedStyle(div).transform, - // scale(2) + (scale(3-1)*2) + translateX(30px)*2 - 'matrix(6, 0, 0, 6, 60, 0)', - 'Animated transform of matrix function at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - // from: matrix(6, 0, 0, 6, 60, 0) - // to: matrix(7, 0, 0, 7, 90, 0) - // = scale(3) + (scale(3-1)*2) + translateX(30px)*3 - 'matrix(6.5, 0, 0, 6.5, 75, 0)', - 'Animated transform of matrix function at 50s of the third iteration'); -}, 'iterationComposite of transform of matrix function'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ transform: ['translateX(0px) scale(2)', - 'scale(3) translateX(10px)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - // Interpolate between matrix(2, 0, 0, 2, 0, 0) = translateX(0px) scale(2) - // and matrix(3, 0, 0, 3, 30, 0) = scale(3) translateX(10px) - 'matrix(2.5, 0, 0, 2.5, 15, 0)', - 'Animated transform list at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_matrix_equals(getComputedStyle(div).transform, - // 'from' and 'to' value are mismatched, so accumulate - // matrix(2, 0, 0, 2, 0, 0) onto matrix(3, 0, 0, 3, 30, 0) * 2 - // = scale(2) + (scale(3-1)*2) + translateX(30px)*2 - 'matrix(6, 0, 0, 6, 60, 0)', - 'Animated transform list at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - // Interpolate between matrix(6, 0, 0, 6, 60, 0) - // and matrix(7, 0, 0, 7, 210, 0) = scale(7) translate(30px) - 'matrix(6.5, 0, 0, 6.5, 135, 0)', - 'Animated transform list at 50s of the third iteration'); -}, 'iterationComposite of transform list animation whose order is mismatched'); - -test(function(t) { - var div = createDiv(t); - // Even if each transform list does not have functions which exist in - // other pair of the list, we don't fill any missing functions at all. - var anim = - div.animate({ transform: ['translateX(0px)', - 'scale(2) translateX(10px)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - // Interpolate between matrix(1, 0, 0, 1, 0, 0) = translateX(0px) - // and matrix(2, 0, 0, 2, 20, 0) = scale(2) translateX(10px) - 'matrix(1.5, 0, 0, 1.5, 10, 0)', - 'Animated transform list at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_matrix_equals(getComputedStyle(div).transform, - // 'from' and 'to' value are mismatched, so accumulate - // matrix(1, 0, 0, 1, 0, 0) onto matrix(2, 0, 0, 2, 20, 0) * 2 - // = scale(1) + (scale(2-1)*2) + translateX(20px)*2 - 'matrix(3, 0, 0, 3, 40, 0)', - 'Animated transform list at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - // Interpolate between matrix(3, 0, 0, 3, 40, 0) - // and matrix(4, 0, 0, 4, 120, 0) = - // scale(2 + (2-1)*2) translate(10px * 3) - 'matrix(3.5, 0, 0, 3.5, 80, 0)', - 'Animated transform list at 50s of the third iteration'); -}, 'iterationComposite of transform list animation whose order is mismatched ' + - 'because of missing functions'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ transform: ['none', - 'translateX(10px)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - // translateX(none) -> translateX(10px) @ 50% - 'matrix(1, 0, 0, 1, 5, 0)', - 'Animated transform list at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_matrix_equals(getComputedStyle(div).transform, - // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 0% - 'matrix(1, 0, 0, 1, 20, 0)', - 'Animated transform list at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 50% - 'matrix(1, 0, 0, 1, 25, 0)', - 'Animated transform list at 50s of the third iteration'); -}, 'iterationComposite of transform from none to translate'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ transform: ['matrix3d(1, 0, 0, 0, ' + - '0, 1, 0, 0, ' + - '0, 0, 1, 0, ' + - '0, 0, 30, 1)', - 'matrix3d(1, 0, 0, 0, ' + - '0, 1, 0, 0, ' + - '0, 0, 1, 0, ' + - '0, 0, 50, 1)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 40, 1)', - 'Animated transform of matrix3d function at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_matrix_equals(getComputedStyle(div).transform, - // translateZ(30px) + (translateZ(50px)*2) - 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)', - 'Animated transform of matrix3d function at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - // from: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1) - // to: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 150, 1) - 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 140, 1)', - 'Animated transform of matrix3d function at 50s of the third iteration'); -}, 'iterationComposite of transform of matrix3d function'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ transform: ['rotate3d(1, 1, 0, 0deg)', - 'rotate3d(1, 1, 0, 90deg)'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = 0; - assert_matrix_equals(getComputedStyle(div).transform, - 'matrix(1, 0, 0, 1, 0, 0)', // Actually not rotated at all. - 'Animated transform of rotate3d function at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_matrix_equals(getComputedStyle(div).transform, - rotate3dToMatrix3d(1, 1, 0, Math.PI), // 180deg - 'Animated transform of rotate3d function at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_matrix_equals(getComputedStyle(div).transform, - rotate3dToMatrix3d(1, 1, 0, 225 * Math.PI / 180), //((270 + 180) * 0.5)deg - 'Animated transform of rotate3d function at 50s of the third iteration'); -}, 'iterationComposite of transform of rotate3d function'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ marginLeft: ['10px', '20px'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).marginLeft, '15px', - 'Animated margin-left style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).marginLeft, '50px', // 10px + 20px + 20px - 'Animated margin-left style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).marginLeft, '55px', // (50px + 60px) * 0.5 - 'Animated margin-left style at 50s of the third iteration'); -}, 'iterationComposite starts with non-zero value animation'); - -test(function(t) { - var div = createDiv(t); - var anim = - div.animate({ marginLeft: ['10px', '-10px'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).marginLeft, - '0px', - 'Animated margin-left style at 50s of the first iteration'); - anim.currentTime = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).marginLeft, - '-10px', // 10px + -10px + -10px - 'Animated margin-left style at 0s of the third iteration'); - anim.currentTime += anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).marginLeft, - '-20px', // (-10px + -30px) * 0.5 - 'Animated margin-left style at 50s of the third iteration'); -}, 'iterationComposite with negative final value animation'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ marginLeft: ['0px', '10px'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); +test(t => { + const div = createDiv(t); + const anim = div.animate({ marginLeft: ['0px', '10px'] }, + { duration: 100 * MS_PER_SEC, + easing: 'linear', + iterations: 10, + iterationComposite: 'accumulate' }); anim.pause(); anim.currentTime = @@ -809,31 +30,6 @@ anim.effect.iterationComposite = 'accumulate'; assert_equals(getComputedStyle(div).marginLeft, '25px', 'Animated style at 50s of the third iteration'); -}, 'interationComposite changes'); - -test(function(t) { - var div = createDiv(t); - var anim = div.animate({ marginLeft: ['0px', '10px'] }, - { duration: 100 * MS_PER_SEC, - easing: 'linear', - iterations: 10, - iterationComposite: 'accumulate' }); - anim.pause(); - - anim.currentTime = - anim.effect.timing.duration * 2 + anim.effect.timing.duration / 2; - assert_equals(getComputedStyle(div).marginLeft, '25px', - 'Animated style at 50s of the third iteration'); - - // double its duration. - anim.effect.timing.duration = anim.effect.timing.duration * 2; - assert_equals(getComputedStyle(div).marginLeft, '12.5px', - 'Animated style at 25s of the first iteration'); - - // half of original. - anim.effect.timing.duration = anim.effect.timing.duration / 4; - assert_equals(getComputedStyle(div).marginLeft, '50px', - 'Animated style at 50s of the fourth iteration'); -}, 'duration changes with iterationComposite(accumulate)'); +}, 'iterationComposite can be updated while an animation is in progress'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html index b20f5193..b1de5bda 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Tests for processing a keyframes argument (property access)</title> +<title>Processing a keyframes argument (property access)</title> <link rel="help" href="https://w3c.github.io/web-animations/#processing-a-keyframes-argument"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -201,7 +201,7 @@ { offset: null, computedOffset: 0.5, easing: 'linear', left: '300px' }, { offset: null, computedOffset: 1, easing: 'linear', left: '200px' }, ]); -}, "'easing' and 'offset' are ignored on iterable objects"); +}, '\'easing\' and \'offset\' are ignored on iterable objects'); test(() => { const effect = new KeyframeEffect(null, createIterable([
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html index c44de91..13715bc6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Tests for processing a keyframes argument (easing)</title> +<title>Processing a keyframes argument (easing)</title> <link rel="help" href="https://w3c.github.io/web-animations/#processing-a-keyframes-argument"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/setKeyframes.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/setKeyframes.html index 079e896..1ea4090b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/setKeyframes.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/setKeyframes.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>KeyframeEffect setKeyframes() tests</title> +<title>KeyframeEffect.setKeyframes</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-keyframeeffect-setkeyframes"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -13,31 +13,31 @@ <script> 'use strict'; -var target = document.getElementById('target'); +const target = document.getElementById('target'); -test(function(t) { - gEmptyKeyframeListTests.forEach(function(frame) { - var effect = new KeyframeEffect(target, {}); +test(t => { + for (const frame of gEmptyKeyframeListTests) { + const effect = new KeyframeEffect(target, {}); effect.setKeyframes(frame); assert_frame_lists_equal(effect.getKeyframes(), []); - }); + } }, 'Keyframes can be replaced with an empty keyframe'); -gKeyframesTests.forEach(function(subtest) { - test(function(t) { - var effect = new KeyframeEffect(target, {}); +for (const subtest of gKeyframesTests) { + test(t => { + const effect = new KeyframeEffect(target, {}); effect.setKeyframes(subtest.input); assert_frame_lists_equal(effect.getKeyframes(), subtest.output); - }, 'Keyframes can be replaced with ' + subtest.desc); -}); + }, `Keyframes can be replaced with ${subtest.desc}`); +} -gInvalidKeyframesTests.forEach(function(subtest) { - test(function(t) { - var effect = new KeyframeEffect(target, {}); - assert_throws(new TypeError, function() { +for (const subtest of gInvalidKeyframesTests) { + test(t => { + const effect = new KeyframeEffect(target, {}); + assert_throws(new TypeError, () => { effect.setKeyframes(subtest.input); }); - }, 'KeyframeEffect constructor throws with ' + subtest.desc); -}); + }, `KeyframeEffect constructor throws with ${subtest.desc}`); +} </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/setTarget-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/target-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/setTarget-expected.txt rename to third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/target-expected.txt
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/setTarget.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/target.html similarity index 79% rename from third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/setTarget.html rename to third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/target.html index 49ef8402..a00c96c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/setTarget.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/target.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Writable effect.target tests</title> +<title>KeyframeEffect.target</title> <link rel="help" href="https://w3c.github.io/web-animations/#dom-keyframeeffect-target"> <script src="/resources/testharness.js"></script> @@ -9,16 +9,16 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; -var gKeyFrames = { 'marginLeft': ['0px', '100px'] }; +const gKeyFrames = { 'marginLeft': ['0px', '100px'] }; -test(function(t) { - var div = createDiv(t); - var effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC); effect.target = div; - var anim = new Animation(effect, document.timeline); + const anim = new Animation(effect, document.timeline); anim.play(); anim.currentTime = 50 * MS_PER_SEC; @@ -26,11 +26,11 @@ 'Value at 50% progress'); }, 'Test setting target before constructing the associated animation'); -test(function(t) { - var div = createDiv(t); +test(t => { + const div = createDiv(t); div.style.marginLeft = '10px'; - var effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC); - var anim = new Animation(effect, document.timeline); + const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC); + const anim = new Animation(effect, document.timeline); anim.play(); anim.currentTime = 50 * MS_PER_SEC; @@ -41,10 +41,10 @@ 'Value at 50% progress after setting new target'); }, 'Test setting target from null to a valid target'); -test(function(t) { - var div = createDiv(t); +test(t => { + const div = createDiv(t); div.style.marginLeft = '10px'; - var anim = div.animate(gKeyFrames, 100 * MS_PER_SEC); + const anim = div.animate(gKeyFrames, 100 * MS_PER_SEC); anim.currentTime = 50 * MS_PER_SEC; assert_equals(getComputedStyle(div).marginLeft, '50px', @@ -55,12 +55,12 @@ 'Value after clearing the target') }, 'Test setting target from a valid target to null'); -test(function(t) { - var a = createDiv(t); - var b = createDiv(t); +test(t => { + const a = createDiv(t); + const b = createDiv(t); a.style.marginLeft = '10px'; b.style.marginLeft = '20px'; - var anim = a.animate(gKeyFrames, 100 * MS_PER_SEC); + const anim = a.animate(gKeyFrames, 100 * MS_PER_SEC); anim.currentTime = 50 * MS_PER_SEC; assert_equals(getComputedStyle(a).marginLeft, '50px',
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/easing-tests.js b/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/easing-tests.js index f2d7a3ee..fc43385 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/easing-tests.js +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/easing-tests.js
@@ -1,4 +1,6 @@ -var gEasingTests = [ +'use strict'; + +const gEasingTests = [ { desc: 'step-start function', easing: 'step-start',
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/effect-tests.js b/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/effect-tests.js index 4a0c66e..f3f7fc2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/effect-tests.js +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/effect-tests.js
@@ -1,3 +1,5 @@ +'use strict'; + // Common utility methods for testing animation effects // Tests the |property| member of |animation's| target effect's computed timing
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/testcommon.js b/third_party/WebKit/LayoutTests/external/wpt/web-animations/testcommon.js index 008d424d..e2062b4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/testcommon.js +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/testcommon.js
@@ -10,19 +10,19 @@ 'use strict'; -var MS_PER_SEC = 1000; +const MS_PER_SEC = 1000; // The recommended minimum precision to use for time values[1]. // // [1] https://w3c.github.io/web-animations/#precision-of-time-values -var TIME_PRECISION = 0.0005; // ms +const TIME_PRECISION = 0.0005; // ms // Allow implementations to substitute an alternative method for comparing // times based on their precision requirements. if (!window.assert_times_equal) { - window.assert_times_equal = function(actual, expected, description) { + window.assert_times_equal = (actual, expected, description) => { assert_approx_equals(actual, expected, TIME_PRECISION, description); - } + }; } // creates div element, appends it to the document body and @@ -38,9 +38,9 @@ if (!doc) { doc = document; } - var element = doc.createElement(tagName || 'div'); + const element = doc.createElement(tagName || 'div'); doc.body.appendChild(element); - test.add_cleanup(function() { + test.add_cleanup(() => { element.remove(); }); return element; @@ -61,16 +61,16 @@ if (!doc) { doc = document; } - var extraStyle = doc.createElement('style'); + const extraStyle = doc.createElement('style'); doc.head.appendChild(extraStyle); if (rules) { - var sheet = extraStyle.sheet; - for (var selector in rules) { - sheet.insertRule(selector + '{' + rules[selector] + '}', + const sheet = extraStyle.sheet; + for (const selector in rules) { + sheet.insertRule(`${selector}{${rules[selector]}}`, sheet.cssRules.length); } } - test.add_cleanup(function() { + test.add_cleanup(() => { extraStyle.remove(); }); } @@ -78,37 +78,37 @@ // Create a pseudo element function createPseudo(test, type) { createStyle(test, { '@keyframes anim': '', - ['.pseudo::' + type]: 'animation: anim 10s; ' + + [`.pseudo::${type}`]: 'animation: anim 10s; ' + 'content: \'\';' }); - var div = createDiv(test); + const div = createDiv(test); div.classList.add('pseudo'); - var anims = document.getAnimations(); + const anims = document.getAnimations(); assert_true(anims.length >= 1); - var anim = anims[anims.length - 1]; + const anim = anims[anims.length - 1]; assert_equals(anim.effect.target.parentElement, div); - assert_equals(anim.effect.target.type, '::' + type); + assert_equals(anim.effect.target.type, `::${type}`); anim.cancel(); return anim.effect.target; } // Cubic bezier with control points (0, 0), (x1, y1), (x2, y2), and (1, 1). function cubicBezier(x1, y1, x2, y2) { - function xForT(t) { - var omt = 1-t; + const xForT = t => { + const omt = 1-t; return 3 * omt * omt * t * x1 + 3 * omt * t * t * x2 + t * t * t; - } + }; - function yForT(t) { - var omt = 1-t; + const yForT = t => { + const omt = 1-t; return 3 * omt * omt * t * y1 + 3 * omt * t * t * y2 + t * t * t; - } + }; - function tForX(x) { + const tForX = x => { // Binary subdivision. - var mint = 0, maxt = 1; - for (var i = 0; i < 30; ++i) { - var guesst = (mint + maxt) / 2; - var guessx = xForT(guesst); + let mint = 0, maxt = 1; + for (let i = 0; i < 30; ++i) { + const guesst = (mint + maxt) / 2; + const guessx = xForT(guesst); if (x < guessx) { maxt = guesst; } else { @@ -116,9 +116,9 @@ } } return (mint + maxt) / 2; - } + }; - return function bezierClosure(x) { + return x => { if (x == 0) { return 0; } @@ -126,31 +126,29 @@ return 1; } return yForT(tForX(x)); - } + }; } function stepEnd(nsteps) { - return function stepEndClosure(x) { - return Math.floor(x * nsteps) / nsteps; - } + return x => Math.floor(x * nsteps) / nsteps; } function stepStart(nsteps) { - return function stepStartClosure(x) { - var result = Math.floor(x * nsteps + 1.0) / nsteps; + return x => { + const result = Math.floor(x * nsteps + 1.0) / nsteps; return (result > 1.0) ? 1.0 : result; - } + }; } function framesTiming(nframes) { - return function framesClosure(x) { - var result = Math.floor(x * nframes) / (nframes - 1); + return x => { + const result = Math.floor(x * nframes) / (nframes - 1); return (result > 1.0 && x <= 1.0) ? 1.0 : result; - } + }; } function waitForAnimationFrames(frameCount) { - return new Promise(function(resolve, reject) { + return new Promise(resolve => { function handleFrame() { if (--frameCount <= 0) { resolve(); @@ -166,8 +164,8 @@ // as recorded using document.timeline.currentTime (i.e. frame time not // wall-clock time). function waitForAnimationFramesWithDelay(minDelay) { - var startTime = document.timeline.currentTime; - return new Promise(function(resolve) { + const startTime = document.timeline.currentTime; + return new Promise(resolve => { (function handleFrame() { if (document.timeline.currentTime - startTime >= minDelay) { resolve(); @@ -180,8 +178,7 @@ // Returns 'matrix()' or 'matrix3d()' function string generated from an array. function createMatrixFromArray(array) { - return (array.length == 16 ? 'matrix3d' : 'matrix') + - '(' + array.join() + ')'; + return (array.length == 16 ? 'matrix3d' : 'matrix') + `(${array.join()})`; } // Returns 'matrix3d()' function string equivalent to @@ -193,11 +190,11 @@ // Returns an array of the 4x4 matrix equivalent to 'rotate3d(x, y, z, radian)'. // https://www.w3.org/TR/css-transforms-1/#Rotate3dDefined function rotate3dToMatrix(x, y, z, radian) { - var sc = Math.sin(radian / 2) * Math.cos(radian / 2); - var sq = Math.sin(radian / 2) * Math.sin(radian / 2); + const sc = Math.sin(radian / 2) * Math.cos(radian / 2); + const sq = Math.sin(radian / 2) * Math.sin(radian / 2); // Normalize the vector. - var length = Math.sqrt(x*x + y*y + z*z); + const length = Math.sqrt(x*x + y*y + z*z); x /= length; y /= length; z /= length; @@ -224,21 +221,21 @@ // Compare matrix string like 'matrix(1, 0, 0, 1, 100, 0)' with tolerances. function assert_matrix_equals(actual, expected, description) { - var matrixRegExp = /^matrix(?:3d)*\((.+)\)/; + const matrixRegExp = /^matrix(?:3d)*\((.+)\)/; assert_regexp_match(actual, matrixRegExp, 'Actual value is not a matrix') assert_regexp_match(expected, matrixRegExp, 'Expected value is not a matrix'); - var actualMatrixArray = + const actualMatrixArray = actual.match(matrixRegExp)[1].split(',').map(Number); - var expectedMatrixArray = + const expectedMatrixArray = expected.match(matrixRegExp)[1].split(',').map(Number); assert_equals(actualMatrixArray.length, expectedMatrixArray.length, - 'dimension of the matrix: ' + description); - for (var i = 0; i < actualMatrixArray.length; i++) { + `dimension of the matrix: ${description}`); + for (let i = 0; i < actualMatrixArray.length; i++) { assert_approx_equals(actualMatrixArray[i], expectedMatrixArray[i], 0.0001, - 'expected ' + expected + ' but got ' + actual + ": " + description); + `expected ${expected} but got ${actual}: ${description}`); } }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/active-time.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/active-time.html index bdaad08..c5d91fc 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/active-time.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/active-time.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Active time tests</title> +<title>Active time</title> <link rel="help" href="https://w3c.github.io/web-animations/#calculating-the-active-time"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -10,110 +10,109 @@ <script> 'use strict'; -test(function(t) { - var tests = [ { fill: 'none', progress: null }, - { fill: 'backwards', progress: 0 }, - { fill: 'forwards', progress: null }, - { fill: 'both', progress: 0 } ]; - tests.forEach(function(test) { - var anim = createDiv(t).animate(null, { delay: 1, fill: test.fill }); +test(t => { + const tests = [ { fill: 'none', progress: null }, + { fill: 'backwards', progress: 0 }, + { fill: 'forwards', progress: null }, + { fill: 'both', progress: 0 } ]; + for (const test of tests) { + const anim = createDiv(t).animate(null, { delay: 1, fill: test.fill }); assert_equals(anim.effect.getComputedTiming().progress, test.progress, - 'Progress in before phase when using \'' + test.fill - + '\' fill'); - }); + `Progress in before phase when using '${test.fill}' fill`); + } }, 'Active time in before phase'); -test(function(t) { - var anim = createDiv(t).animate(null, 1000); +test(t => { + const anim = createDiv(t).animate(null, 1000); anim.currentTime = 500; assert_times_equal(anim.effect.getComputedTiming().progress, 0.5); }, 'Active time in active phase and no start delay is the local time'); -test(function(t) { - var anim = createDiv(t).animate(null, { duration: 1000, delay: 500 }); +test(t => { + const anim = createDiv(t).animate(null, { duration: 1000, delay: 500 }); anim.currentTime = 1000; assert_times_equal(anim.effect.getComputedTiming().progress, 0.5); }, 'Active time in active phase and positive start delay is the local time' + ' minus the start delay'); -test(function(t) { - var anim = createDiv(t).animate(null, { duration: 1000, delay: -500 }); +test(t => { + const anim = createDiv(t).animate(null, { duration: 1000, delay: -500 }); assert_times_equal(anim.effect.getComputedTiming().progress, 0.5); }, 'Active time in active phase and negative start delay is the local time' + ' minus the start delay'); -test(function(t) { - var anim = createDiv(t).animate(null); +test(t => { + const anim = createDiv(t).animate(null); assert_equals(anim.effect.getComputedTiming().progress, null); }, 'Active time in after phase with no fill is unresolved'); -test(function(t) { - var anim = createDiv(t).animate(null, { fill: 'backwards' }); +test(t => { + const anim = createDiv(t).animate(null, { fill: 'backwards' }); assert_equals(anim.effect.getComputedTiming().progress, null); }, 'Active time in after phase with backwards-only fill is unresolved'); -test(function(t) { - var anim = createDiv(t).animate(null, { duration: 1000, - iterations: 2.3, - delay: 500, // Should have no effect - fill: 'forwards' }); +test(t => { + const anim = createDiv(t).animate(null, { duration: 1000, + iterations: 2.3, + delay: 500, // Should have no effect + fill: 'forwards' }); anim.finish(); assert_equals(anim.effect.getComputedTiming().currentIteration, 2); assert_times_equal(anim.effect.getComputedTiming().progress, 0.3); }, 'Active time in after phase with forwards fill is the active duration'); -test(function(t) { - var anim = createDiv(t).animate(null, { duration: 0, - iterations: Infinity, - fill: 'forwards' }); +test(t => { + const anim = createDiv(t).animate(null, { duration: 0, + iterations: Infinity, + fill: 'forwards' }); anim.finish(); assert_equals(anim.effect.getComputedTiming().currentIteration, Infinity); assert_equals(anim.effect.getComputedTiming().progress, 1); }, 'Active time in after phase with forwards fill, zero-duration, and ' + ' infinite iteration count is the active duration'); -test(function(t) { - var anim = createDiv(t).animate(null, { duration: 1000, - iterations: 2.3, - delay: 500, - endDelay: 4000, - fill: 'forwards' }); +test(t => { + const anim = createDiv(t).animate(null, { duration: 1000, + iterations: 2.3, + delay: 500, + endDelay: 4000, + fill: 'forwards' }); anim.finish(); assert_equals(anim.effect.getComputedTiming().currentIteration, 2); assert_times_equal(anim.effect.getComputedTiming().progress, 0.3); }, 'Active time in after phase with forwards fill and positive end delay' + ' is the active duration'); -test(function(t) { - var anim = createDiv(t).animate(null, { duration: 1000, - iterations: 2.3, - delay: 500, - endDelay: -800, - fill: 'forwards' }); +test(t => { + const anim = createDiv(t).animate(null, { duration: 1000, + iterations: 2.3, + delay: 500, + endDelay: -800, + fill: 'forwards' }); anim.finish(); assert_equals(anim.effect.getComputedTiming().currentIteration, 1); assert_times_equal(anim.effect.getComputedTiming().progress, 0.5); }, 'Active time in after phase with forwards fill and negative end delay' + ' is the active duration + end delay'); -test(function(t) { - var anim = createDiv(t).animate(null, { duration: 1000, - iterations: 2.3, - delay: 500, - endDelay: -2500, - fill: 'forwards' }); +test(t => { + const anim = createDiv(t).animate(null, { duration: 1000, + iterations: 2.3, + delay: 500, + endDelay: -2500, + fill: 'forwards' }); anim.finish(); assert_equals(anim.effect.getComputedTiming().currentIteration, 0); assert_equals(anim.effect.getComputedTiming().progress, 0); }, 'Active time in after phase with forwards fill and negative end delay' + ' greater in magnitude than the active duration is zero'); -test(function(t) { - var anim = createDiv(t).animate(null, { duration: 1000, - iterations: 2.3, - delay: 500, - endDelay: -4000, - fill: 'forwards' }); +test(t => { + const anim = createDiv(t).animate(null, { duration: 1000, + iterations: 2.3, + delay: 500, + endDelay: -4000, + fill: 'forwards' }); anim.finish(); assert_equals(anim.effect.getComputedTiming().currentIteration, 0); assert_equals(anim.effect.getComputedTiming().progress, 0); @@ -121,20 +120,20 @@ + ' greater in magnitude than the sum of the active duration and start delay' + ' is zero'); -test(function(t) { - var anim = createDiv(t).animate(null, { duration: 1000, - iterations: 2.3, - delay: 500, - fill: 'both' }); +test(t => { + const anim = createDiv(t).animate(null, { duration: 1000, + iterations: 2.3, + delay: 500, + fill: 'both' }); anim.finish(); assert_equals(anim.effect.getComputedTiming().currentIteration, 2); assert_times_equal(anim.effect.getComputedTiming().progress, 0.3); }, 'Active time in after phase with \'both\' fill is the active duration'); -test(function(t) { +test(t => { // Create an effect with a non-zero duration so we ensure we're not just // testing the after-phase behavior. - var effect = new KeyframeEffect(null, null, 1); + const effect = new KeyframeEffect(null, null, 1); assert_equals(effect.getComputedTiming().progress, null); }, 'Active time when the local time is unresolved, is unresolved');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/current-iteration.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/current-iteration.html index df08d43..0ac920d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/current-iteration.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/current-iteration.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Current iteration tests</title> +<title>Current iteration</title> <link rel="help" href="https://w3c.github.io/web-animations/#current-iteration"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -38,11 +38,11 @@ } } -async_test(function(t) { - var div = createDiv(t); - var anim = div.animate({ opacity: [ 0, 1 ] }, { delay: 1 }); +async_test(t => { + const div = createDiv(t); + const anim = div.animate({ opacity: [ 0, 1 ] }, { delay: 1 }); assert_equals(anim.effect.getComputedTiming().currentIteration, null); - anim.finished.then(t.step_func(function() { + anim.finished.then(t.step_func(() => { assert_equals(anim.effect.getComputedTiming().currentIteration, null); t.done(); }));
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/local-time.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/local-time.html index 91c1ed4..54455a1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/local-time.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/local-time.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>AnimationEffect local time tests</title> +<title>Local time</title> <link rel="help" href="https://w3c.github.io/web-animations/#local-time"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -9,16 +9,19 @@ <script> 'use strict'; -test(function(t) { - var anim = createDiv(t).animate(null, 10 * MS_PER_SEC); - for (var seconds of [-1, 0, 5, 10, 20]) { +test(t => { + const anim = createDiv(t).animate(null, 10 * MS_PER_SEC); + for (const seconds of [-1, 0, 5, 10, 20]) { anim.currentTime = seconds * MS_PER_SEC; - assert_equals(anim.effect.getComputedTiming().localTime, seconds * MS_PER_SEC); + assert_equals( + anim.effect.getComputedTiming().localTime, + seconds * MS_PER_SEC + ); } }, 'Local time is current time for animation effects associated with an animation'); -test(function(t) { - var effect = new KeyframeEffect(createDiv(t), null, 10 * MS_PER_SEC); +test(t => { + const effect = new KeyframeEffect(createDiv(t), null, 10 * MS_PER_SEC); assert_equals(effect.getComputedTiming().localTime, null); }, 'Local time is unresolved for animation effects not associated with an animation');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html index 5dc32066..b3e8f7852 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html
@@ -1,6 +1,6 @@ <!doctype html> <meta charset=utf-8> -<title>Tests for phases and states</title> +<title>Phases and states</title> <link rel="help" href="https://w3c.github.io/web-animations/#animation-effect-phases-and-states"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -25,7 +25,7 @@ animation.effect.timing.fill = 'none'; assert_not_equals(animation.effect.getComputedTiming().progress, null, 'Animation effect is in active phase when current time' - + ' is ' + currentTime + 'ms'); + + ` is ${currentTime}ms`); } else { // The easiest way to distinguish between the 'before' phase and the 'after' // phase is to toggle the fill mode. For example, if the progress is null @@ -33,157 +33,146 @@ // 'backwards' then we are in the before phase. animation.effect.timing.fill = 'none'; assert_equals(animation.effect.getComputedTiming().progress, null, - 'Animation effect is in ' + phase + ' phase when current time' - + ' is ' + currentTime + 'ms' + `Animation effect is in ${phase} phase when current time` + + ` is ${currentTime}ms` + ' (progress is null with \'none\' fill mode)'); animation.effect.timing.fill = phase === 'before' ? 'backwards' : 'forwards'; assert_not_equals(animation.effect.getComputedTiming().progress, null, - 'Animation effect is in ' + phase + ' phase when current' - + ' time is ' + currentTime + 'ms' + `Animation effect is in ${phase} phase when current time` + + ` is ${currentTime}ms` + ' (progress is non-null with appropriate fill mode)'); } } -test(function(t) { - var animation = createDiv(t).animate(null, 1); +test(t => { + const animation = createDiv(t).animate(null, 1); - [ { currentTime: -1, phase: 'before' }, - { currentTime: 0, phase: 'active' }, - { currentTime: 1, phase: 'after' } ] - .forEach(function(test) { + for (const test of [{ currentTime: -1, phase: 'before' }, + { currentTime: 0, phase: 'active' }, + { currentTime: 1, phase: 'after' }]) { assert_phase_at_time(animation, test.phase, test.currentTime); - }); + } }, 'Phase calculation for a simple animation effect'); -test(function(t) { - var animation = createDiv(t).animate(null, { duration: 1, delay: 1 }); +test(t => { + const animation = createDiv(t).animate(null, { duration: 1, delay: 1 }); - [ { currentTime: 0, phase: 'before' }, - { currentTime: 1, phase: 'active' }, - { currentTime: 2, phase: 'after' } ] - .forEach(function(test) { + for (const test of [{ currentTime: 0, phase: 'before' }, + { currentTime: 1, phase: 'active' }, + { currentTime: 2, phase: 'after' }]) { assert_phase_at_time(animation, test.phase, test.currentTime); - }); + } }, 'Phase calculation for an animation effect with a positive start delay'); -test(function(t) { - var animation = createDiv(t).animate(null, { duration: 1, delay: -1 }); +test(t => { + const animation = createDiv(t).animate(null, { duration: 1, delay: -1 }); - [ { currentTime: -2, phase: 'before' }, - { currentTime: -1, phase: 'before' }, - { currentTime: 0, phase: 'after' } ] - .forEach(function(test) { + for (const test of [{ currentTime: -2, phase: 'before' }, + { currentTime: -1, phase: 'before' }, + { currentTime: 0, phase: 'after' }]) { assert_phase_at_time(animation, test.phase, test.currentTime); - }); + } }, 'Phase calculation for an animation effect with a negative start delay'); -test(function(t) { - var animation = createDiv(t).animate(null, { duration: 1, endDelay: 1 }); +test(t => { + const animation = createDiv(t).animate(null, { duration: 1, endDelay: 1 }); - [ { currentTime: -1, phase: 'before' }, - { currentTime: 0, phase: 'active' }, - { currentTime: 1, phase: 'after' }, - { currentTime: 2, phase: 'after' } ] - .forEach(function(test) { + for (const test of [{ currentTime: -1, phase: 'before' }, + { currentTime: 0, phase: 'active' }, + { currentTime: 1, phase: 'after' }, + { currentTime: 2, phase: 'after' }]) { assert_phase_at_time(animation, test.phase, test.currentTime); - }); + } }, 'Phase calculation for an animation effect with a positive end delay'); -test(function(t) { - var animation = createDiv(t).animate(null, { duration: 2, endDelay: -1 }); +test(t => { + const animation = createDiv(t).animate(null, { duration: 2, endDelay: -1 }); - [ { currentTime: -1, phase: 'before' }, - { currentTime: 0, phase: 'active' }, - { currentTime: 0.9, phase: 'active' }, - { currentTime: 1, phase: 'after' } ] - .forEach(function(test) { + for (const test of [{ currentTime: -1, phase: 'before' }, + { currentTime: 0, phase: 'active' }, + { currentTime: 0.9, phase: 'active' }, + { currentTime: 1, phase: 'after' }]) { assert_phase_at_time(animation, test.phase, test.currentTime); - }); + } }, 'Phase calculation for an animation effect with a negative end delay lesser' + ' in magnitude than the active duration'); -test(function(t) { - var animation = createDiv(t).animate(null, { duration: 1, endDelay: -1 }); +test(t => { + const animation = createDiv(t).animate(null, { duration: 1, endDelay: -1 }); - [ { currentTime: -1, phase: 'before' }, - { currentTime: 0, phase: 'after' }, - { currentTime: 1, phase: 'after' } ] - .forEach(function(test) { + for (const test of [{ currentTime: -1, phase: 'before' }, + { currentTime: 0, phase: 'after' }, + { currentTime: 1, phase: 'after' }]) { assert_phase_at_time(animation, test.phase, test.currentTime); - }); + } }, 'Phase calculation for an animation effect with a negative end delay equal' + ' in magnitude to the active duration'); -test(function(t) { - var animation = createDiv(t).animate(null, { duration: 1, endDelay: -2 }); +test(t => { + const animation = createDiv(t).animate(null, { duration: 1, endDelay: -2 }); - [ { currentTime: -2, phase: 'before' }, - { currentTime: -1, phase: 'before' }, - { currentTime: 0, phase: 'after' } ] - .forEach(function(test) { + for (const test of [{ currentTime: -2, phase: 'before' }, + { currentTime: -1, phase: 'before' }, + { currentTime: 0, phase: 'after' }]) { assert_phase_at_time(animation, test.phase, test.currentTime); - }); + } }, 'Phase calculation for an animation effect with a negative end delay' + ' greater in magnitude than the active duration'); -test(function(t) { - var animation = createDiv(t).animate(null, { duration: 2, - delay: 1, - endDelay: -1 }); +test(t => { + const animation = createDiv(t).animate(null, { duration: 2, + delay: 1, + endDelay: -1 }); - [ { currentTime: 0, phase: 'before' }, - { currentTime: 1, phase: 'active' }, - { currentTime: 2, phase: 'after' } ] - .forEach(function(test) { + for (const test of [{ currentTime: 0, phase: 'before' }, + { currentTime: 1, phase: 'active' }, + { currentTime: 2, phase: 'after' }]) { assert_phase_at_time(animation, test.phase, test.currentTime); - }); + } }, 'Phase calculation for an animation effect with a positive start delay' + ' and a negative end delay lesser in magnitude than the active duration'); -test(function(t) { - var animation = createDiv(t).animate(null, { duration: 1, - delay: -1, - endDelay: -1 }); +test(t => { + const animation = createDiv(t).animate(null, { duration: 1, + delay: -1, + endDelay: -1 }); - [ { currentTime: -2, phase: 'before' }, - { currentTime: -1, phase: 'before' }, - { currentTime: 0, phase: 'after' } ] - .forEach(function(test) { + for (const test of [{ currentTime: -2, phase: 'before' }, + { currentTime: -1, phase: 'before' }, + { currentTime: 0, phase: 'after' }]) { assert_phase_at_time(animation, test.phase, test.currentTime); - }); + } }, 'Phase calculation for an animation effect with a negative start delay' + ' and a negative end delay equal in magnitude to the active duration'); -test(function(t) { - var animation = createDiv(t).animate(null, { duration: 1, - delay: -1, - endDelay: -2 }); +test(t => { + const animation = createDiv(t).animate(null, { duration: 1, + delay: -1, + endDelay: -2 }); - [ { currentTime: -3, phase: 'before' }, - { currentTime: -2, phase: 'before' }, - { currentTime: -1, phase: 'before' }, - { currentTime: 0, phase: 'after' } ] - .forEach(function(test) { + for (const test of [{ currentTime: -3, phase: 'before' }, + { currentTime: -2, phase: 'before' }, + { currentTime: -1, phase: 'before' }, + { currentTime: 0, phase: 'after' }]) { assert_phase_at_time(animation, test.phase, test.currentTime); - }); + } }, 'Phase calculation for an animation effect with a negative start delay' + ' and a negative end delay equal greater in magnitude than the active' + ' duration'); -test(function(t) { - var animation = createDiv(t).animate(null, 1); +test(t => { + const animation = createDiv(t).animate(null, 1); animation.playbackRate = -1; - [ { currentTime: -1, phase: 'before' }, - { currentTime: 0, phase: 'before' }, - { currentTime: 1, phase: 'active' }, - { currentTime: 2, phase: 'after' } ] - .forEach(function(test) { + for (const test of [{ currentTime: -1, phase: 'before' }, + { currentTime: 0, phase: 'before' }, + { currentTime: 1, phase: 'active' }, + { currentTime: 2, phase: 'after' }]) { assert_phase_at_time(animation, test.phase, test.currentTime); - }); + } }, 'Phase calculation for a simple animation effect with negative playback' + ' rate');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/simple-iteration-progress.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/simple-iteration-progress.html index e4253a0b..22331f43 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/simple-iteration-progress.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/simple-iteration-progress.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Simple iteration progress tests</title> +<title>Simple iteration progress</title> <link rel="help" href="https://w3c.github.io/web-animations/#simple-iteration-progress"> <script src="/resources/testharness.js"></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/canceling-an-animation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/canceling-an-animation.html index 5aa7de2b..e4cafc0 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/canceling-an-animation.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/canceling-an-animation.html
@@ -9,9 +9,9 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; -promise_test(function(t) { +promise_test(t => { const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); const retPromise = animation.ready.then(() => { assert_unreached('ready promise was fulfilled'); @@ -26,12 +26,12 @@ }, 'A play-pending ready promise should be rejected when the animation is' + ' canceled'); -promise_test(function(t) { +promise_test(t => { const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); return animation.ready.then(() => { animation.pause(); // Set up listeners on pause-pending ready promise - var retPromise = animation.ready.then(function() { + const retPromise = animation.ready.then(() => { assert_unreached('ready promise was fulfilled'); }).catch(err => { assert_equals(err.name, 'AbortError', @@ -43,15 +43,15 @@ }, 'A pause-pending ready promise should be rejected when the animation is' + ' canceled'); -promise_test(function(t) { +promise_test(t => { const animation = createDiv(t).animate(null); animation.cancel(); - return animation.ready.then(function(p) { + return animation.ready.then(p => { assert_equals(p, animation); }); }, 'When an animation is canceled, it should create a resolved Promise'); -test(function(t) { +test(t => { const animation = createDiv(t).animate(null); const promise = animation.ready; animation.cancel();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/current-time.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/current-time.html index 7500175..680d8ad9 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/current-time.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/current-time.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Tests for current time</title> +<title>Current time</title> <link rel="help" href="https://w3c.github.io/web-animations/#current-time"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -10,8 +10,8 @@ <script> 'use strict'; -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); @@ -21,12 +21,12 @@ 'state'); }, 'The current time returns the hold time when set'); -promise_test(function(t) { - var animation = +promise_test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(animation.currentTime, null); }); }, 'The current time is unresolved when there is no associated timeline ' + @@ -35,8 +35,8 @@ // FIXME: Test that the current time is unresolved when we have an inactive // timeline if we find a way of creating an inactive timeline! -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); @@ -45,30 +45,29 @@ }, 'The current time is unresolved when the start time is unresolved ' + '(and no hold time is set)'); -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); animation.playbackRate = 2; animation.startTime = document.timeline.currentTime - 25 * MS_PER_SEC; - var timelineTime = document.timeline.currentTime; - var startTime = animation.startTime; - var playbackRate = animation.playbackRate; + const timelineTime = document.timeline.currentTime; + const startTime = animation.startTime; + const playbackRate = animation.playbackRate; assert_times_equal(animation.currentTime, (timelineTime - startTime) * playbackRate, 'Animation has a unresolved start time'); }, 'The current time is calculated from the timeline time, start time and ' + 'playback rate'); -promise_test(function(t) { - var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); animation.playbackRate = 0; - return animation.ready.then(function() { - return waitForAnimationFrames(1); - }).then(function() { + return animation.ready.then(() => waitForAnimationFrames(1)) + .then(() => { assert_times_equal(animation.currentTime, 0); }); }, 'The current time does not progress if playback rate is 0');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/finishing-an-animation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/finishing-an-animation.html index 4890bd1b..566fb3c1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/finishing-an-animation.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/finishing-an-animation.html
@@ -11,7 +11,7 @@ <script> 'use strict'; -promise_test(function(t) { +promise_test(t => { const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); const promise = animation.ready; let readyResolved = false;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/pausing-an-animation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/pausing-an-animation.html index 9a4da2e..bb75dcc 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/pausing-an-animation.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/pausing-an-animation.html
@@ -2,7 +2,7 @@ <meta charset=utf-8> <title>Pausing an animation</title> <link rel="help" - href="https://w3c.github.io/web-animations/#finishing-an-animation-section"> + href="https://w3c.github.io/web-animations/#pausing-an-animation-section"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="../../testcommon.js"></script> @@ -11,7 +11,7 @@ <script> 'use strict'; -promise_test(function(t) { +promise_test(t => { const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); const promise = animation.ready; animation.pause();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/playing-an-animation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/playing-an-animation.html index 1cf109d..43e9a6b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/playing-an-animation.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/playing-an-animation.html
@@ -11,24 +11,24 @@ <script> 'use strict'; -test(function(t) { - var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); +test(t => { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); animation.currentTime = 1 * MS_PER_SEC; assert_times_equal(animation.currentTime, 1 * MS_PER_SEC); animation.play(); assert_times_equal(animation.currentTime, 1 * MS_PER_SEC); }, 'Playing a running animation leaves the current time unchanged'); -test(function(t) { - var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); +test(t => { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); animation.finish(); assert_times_equal(animation.currentTime, 100 * MS_PER_SEC); animation.play(); assert_times_equal(animation.currentTime, 0); }, 'Playing a finished animation seeks back to the start'); -test(function(t) { - var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); +test(t => { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); animation.playbackRate = -1; animation.currentTime = 0; assert_times_equal(animation.currentTime, 0); @@ -36,7 +36,7 @@ assert_times_equal(animation.currentTime, 100 * MS_PER_SEC); }, 'Playing a finished and reversed animation seeks to end'); -test(function(t) { +test(t => { const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); animation.cancel(); const promise = animation.ready; @@ -45,7 +45,7 @@ }, 'The ready promise should be replaced if the animation is not already' + ' pending'); -promise_test(function(t) { +promise_test(t => { const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); const promise = animation.ready; return promise.then(p => {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/reversing-an-animation-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/reversing-an-animation-expected.txt index b8b660f7..59488bb 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/reversing-an-animation-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/reversing-an-animation-expected.txt
@@ -13,6 +13,6 @@ PASS Reversing animation when playbackRate = 0 and currentTime < 0 and the target effect end is positive infinity should NOT throw an exception PASS Reversing an animation when playbackRate < 0 and currentTime < 0 and the target effect end is positive infinity should make it play from the start PASS Reversing when when playbackRate == 0 should preserve the current time and playback rate -FAIL Reversing an animation without an active timeline throws an InvalidStateError assert_throws: function "function () { animation.reverse(); }" did not throw +FAIL Reversing an animation without an active timeline throws an InvalidStateError assert_throws: function "() => { animation.reverse(); }" did not throw Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/reversing-an-animation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/reversing-an-animation.html index 42093c9c..5c96a6f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/reversing-an-animation.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/reversing-an-animation.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Reversing an animation</title> +<title>Reverse an animation</title> <link rel="help" href="https://w3c.github.io/web-animations/#reverse-an-animation"> <script src="/resources/testharness.js"></script> @@ -9,45 +9,45 @@ <body> <div id="log"></div> <script> -"use strict"; +'use strict'; -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, {duration: 100 * MS_PER_SEC, - iterations: Infinity}); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, { duration: 100 * MS_PER_SEC, + iterations: Infinity }); // Wait a frame because if currentTime is still 0 when we call // reverse(), it will throw (per spec). - return animation.ready.then(waitForAnimationFrames(1)).then(function() { + return animation.ready.then(waitForAnimationFrames(1)).then(() => { assert_greater_than_equal(animation.currentTime, 0, 'currentTime expected to be greater than 0, one frame after starting'); animation.currentTime = 50 * MS_PER_SEC; - var previousPlaybackRate = animation.playbackRate; + const previousPlaybackRate = animation.playbackRate; animation.reverse(); assert_equals(animation.playbackRate, -previousPlaybackRate, 'playbackRate should be inverted'); }); }, 'Reversing an animation inverts the playback rate'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, {duration: 100 * MS_PER_SEC, - iterations: Infinity}); +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, { duration: 100 * MS_PER_SEC, + iterations: Infinity }); animation.currentTime = 50 * MS_PER_SEC; animation.pause(); - return animation.ready.then(function() { + return animation.ready.then(() => { animation.reverse(); return animation.ready; - }).then(function() { + }).then(() => { assert_equals(animation.playState, 'running', 'Animation.playState should be "running" after reverse()'); }); }, 'Reversing an animation plays a pausing animation'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.currentTime = 50 * MS_PER_SEC; animation.reverse(); @@ -56,10 +56,10 @@ 'the animation duration'); }, 'Reversing an animation maintains the same current time'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, { duration: 200 * MS_PER_SEC, - delay: -100 * MS_PER_SEC }); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, { duration: 200 * MS_PER_SEC, + delay: -100 * MS_PER_SEC }); assert_equals(animation.playState, 'pending', 'The playState is pending before we call reverse'); @@ -69,11 +69,11 @@ 'The playState is still pending after calling reverse'); }, 'Reversing an animation does not cause it to leave the pending state'); -promise_test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, { duration: 200 * MS_PER_SEC, - delay: -100 * MS_PER_SEC }); - var readyResolved = false; +promise_test(t => { + const div = createDiv(t); + const animation = div.animate({}, { duration: 200 * MS_PER_SEC, + delay: -100 * MS_PER_SEC }); + let readyResolved = false; animation.ready.then(() => { readyResolved = true; }); animation.reverse(); @@ -84,9 +84,9 @@ }); }, 'Reversing an animation does not cause it to resolve the ready promise'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.currentTime = 200 * MS_PER_SEC; animation.reverse(); @@ -96,9 +96,9 @@ }, 'Reversing an animation when playbackRate > 0 and currentTime > ' + 'effect end should make it play from the end'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.currentTime = -200 * MS_PER_SEC; animation.reverse(); @@ -109,9 +109,9 @@ }, 'Reversing an animation when playbackRate > 0 and currentTime < 0 ' + 'should make it play from the end'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.playbackRate = -1; animation.currentTime = -200 * MS_PER_SEC; animation.reverse(); @@ -122,9 +122,9 @@ }, 'Reversing an animation when playbackRate < 0 and currentTime < 0 ' + 'should make it play from the start'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.playbackRate = -1; animation.currentTime = 200 * MS_PER_SEC; animation.reverse(); @@ -135,23 +135,23 @@ }, 'Reversing an animation when playbackRate < 0 and currentTime > effect ' + 'end should make it play from the start'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, {duration: 100 * MS_PER_SEC, - iterations: Infinity}); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, { duration: 100 * MS_PER_SEC, + iterations: Infinity }); animation.currentTime = -200 * MS_PER_SEC; assert_throws('InvalidStateError', - function () { animation.reverse(); }, + () => { animation.reverse(); }, 'reverse() should throw InvalidStateError ' + 'if the playbackRate > 0 and the currentTime < 0 ' + 'and the target effect is positive infinity'); }, 'Reversing an animation when playbackRate > 0 and currentTime < 0 ' + 'and the target effect end is positive infinity should throw an exception'); -test(function(t) { - var animation = createDiv(t).animate({}, { duration: 100 * MS_PER_SEC, - iterations: Infinity }); +test(t => { + const animation = createDiv(t).animate({}, { duration: 100 * MS_PER_SEC, + iterations: Infinity }); animation.currentTime = -200 * MS_PER_SEC; try { animation.reverse(); } catch(e) { } @@ -159,10 +159,10 @@ assert_equals(animation.playbackRate, 1, 'playbackRate remains unchanged'); }, 'When reversing throws an exception, the playback rate remains unchanged'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, {duration: 100 * MS_PER_SEC, - iterations: Infinity}); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, { duration: 100 * MS_PER_SEC, + iterations: Infinity }); animation.currentTime = -200 * MS_PER_SEC; animation.playbackRate = 0; @@ -175,10 +175,10 @@ 'and the target effect end is positive infinity should NOT throw an ' + 'exception'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, {duration: 100 * MS_PER_SEC, - iterations: Infinity}); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, { duration: 100 * MS_PER_SEC, + iterations: Infinity }); animation.playbackRate = -1; animation.currentTime = -200 * MS_PER_SEC; animation.reverse(); @@ -191,9 +191,9 @@ 'and the target effect end is positive infinity should make it play ' + 'from the start'); -test(function(t) { - var div = createDiv(t); - var animation = div.animate({}, 100 * MS_PER_SEC); +test(t => { + const div = createDiv(t); + const animation = div.animate({}, 100 * MS_PER_SEC); animation.playbackRate = 0; animation.currentTime = 50 * MS_PER_SEC; animation.reverse(); @@ -206,12 +206,12 @@ }, 'Reversing when when playbackRate == 0 should preserve the current ' + 'time and playback rate'); -test(function(t) { - var div = createDiv(t); - var animation = +test(t => { + const div = createDiv(t); + const animation = new Animation(new KeyframeEffect(div, null, 100 * MS_PER_SEC), null); - assert_throws('InvalidStateError', function() { animation.reverse(); }); + assert_throws('InvalidStateError', () => { animation.reverse(); }); }, 'Reversing an animation without an active timeline throws an ' + 'InvalidStateError');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-animation-start-time.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-animation-start-time.html index 8b74c92a..48071c0 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-animation-start-time.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-animation-start-time.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Setting the start time tests</title> +<title>Set the animation start time</title> <link rel="help" href="https://w3c.github.io/web-animations/#set-the-animation-start-time"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -10,12 +10,11 @@ <script> 'use strict'; -test(function(t) -{ +test(t => { // It should only be possible to set *either* the start time or the current // time for an animation that does not have an active timeline. - var animation = + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); @@ -41,12 +40,11 @@ }, 'Setting the start time of an animation without an active timeline'); -test(function(t) -{ +test(t => { // Setting an unresolved start time on an animation without an active // timeline should not clear the current time. - var animation = + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); @@ -66,9 +64,8 @@ }, 'Setting an unresolved start time an animation without an active timeline' + ' does not clear the current time'); -test(function(t) -{ - var animation = + test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); @@ -93,9 +90,8 @@ + ' start time'); }, 'Setting the start time clears the hold time'); -test(function(t) -{ - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); @@ -115,14 +111,13 @@ + ' start time'); }, 'Setting an unresolved start time sets the hold time'); -promise_test(function(t) -{ - var animation = +promise_test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); - var readyPromiseCallbackCalled = false; - animation.ready.then(function() { readyPromiseCallbackCalled = true; } ); + let readyPromiseCallbackCalled = false; + animation.ready.then(() => { readyPromiseCallbackCalled = true; } ); // Put the animation in the play-pending state animation.play(); @@ -139,20 +134,19 @@ // If we schedule another microtask then it should run immediately after // the ready promise resolution microtask. - return Promise.resolve().then(function() { + return Promise.resolve().then(() => { assert_true(readyPromiseCallbackCalled, 'Ready promise callback called after setting startTime'); }); }, 'Setting the start time resolves a pending ready promise'); -promise_test(function(t) -{ - var animation = +promise_test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); - var readyPromiseCallbackCalled = false; - animation.ready.then(function() { readyPromiseCallbackCalled = true; } ); + let readyPromiseCallbackCalled = false; + animation.ready.then(() => { readyPromiseCallbackCalled = true; } ); // Put the animation in the pause-pending state animation.startTime = document.timeline.currentTime; @@ -168,15 +162,14 @@ assert_false(readyPromiseCallbackCalled, 'Ready promise callback is not called synchronously'); - return Promise.resolve().then(function() { + return Promise.resolve().then(() => { assert_true(readyPromiseCallbackCalled, 'Ready promise callback called after setting startTime'); }); }, 'Setting the start time resolves a pending pause task'); -promise_test(function(t) -{ - var animation = +promise_test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); @@ -195,8 +188,8 @@ // Furthermore, that time should persist if we have correctly updated // the hold time - var finishedCurrentTime = animation.currentTime; - return waitForAnimationFrames(1).then(function() { + const finishedCurrentTime = animation.currentTime; + return waitForAnimationFrames(1).then(() => { assert_equals(animation.currentTime, finishedCurrentTime, 'Current time does not change after seeking past the effect' + ' end time by setting the current time');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html index 4c51f01..8f835cc 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Setting the target effect tests</title> +<title>Setting the target effect</title> <link rel='help' href='https://w3c.github.io/web-animations/#setting-the-target-effect'> <script src='/resources/testharness.js'></script> <script src='/resources/testharnessreport.js'></script> @@ -10,14 +10,14 @@ <script> 'use strict'; -promise_test(function(t) { - var anim = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] }, - 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] }, + 100 * MS_PER_SEC); assert_equals(anim.playState, 'pending'); - var retPromise = anim.ready.then(function() { + const retPromise = anim.ready.then(() => { assert_unreached('ready promise is fulfilled'); - }).catch(function(err) { + }).catch(err => { assert_equals(err.name, 'AbortError', 'ready promise is rejected with AbortError'); }); @@ -29,8 +29,8 @@ }, 'If new effect is null and old effect is not null, we reset the pending ' + 'tasks and ready promise is rejected'); -promise_test(function(t) { - var anim = new Animation(); +promise_test(t => { + const anim = new Animation(); anim.pause(); assert_equals(anim.playState, 'pending'); @@ -39,14 +39,14 @@ 100 * MS_PER_SEC); assert_equals(anim.playState, 'pending'); - return anim.ready.then(function() { + return anim.ready.then(() => { assert_equals(anim.playState, 'paused'); }); }, 'If animation has a pending pause task, reschedule that task to run ' + 'as soon as animation is ready.'); -promise_test(function(t) { - var anim = new Animation(); +promise_test(t => { + const anim = new Animation(); anim.play(); assert_equals(anim.playState, 'pending'); @@ -55,18 +55,18 @@ 100 * MS_PER_SEC); assert_equals(anim.playState, 'pending'); - return anim.ready.then(function() { + return anim.ready.then(() => { assert_equals(anim.playState, 'running'); }); }, 'If animation has a pending play task, reschedule that task to run ' + 'as soon as animation is ready to play new effect.'); -promise_test(function(t) { - var animA = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] }, - 100 * MS_PER_SEC); - var animB = new Animation(); +promise_test(t => { + const animA = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] }, + 100 * MS_PER_SEC); + const animB = new Animation(); - return animA.ready.then(function() { + return animA.ready.then(() => { animB.effect = animA.effect; assert_equals(animA.effect, null); assert_equals(animA.playState, 'finished'); @@ -74,11 +74,11 @@ }, 'When setting the effect of an animation to the effect of an existing ' + 'animation, the existing animation\'s target effect should be set to null.'); -test(function(t) { - var animA = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] }, - 100 * MS_PER_SEC); - var animB = new Animation(); - var effect = animA.effect; +test(t => { + const animA = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] }, + 100 * MS_PER_SEC); + const animB = new Animation(); + const effect = animA.effect; animA.currentTime = 50 * MS_PER_SEC; animB.currentTime = 20 * MS_PER_SEC; assert_equals(effect.getComputedTiming().progress, 0.5,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-timeline-of-an-animation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-timeline-of-an-animation.html index c540fe2..63662fd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-timeline-of-an-animation.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/set-the-timeline-of-an-animation.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Setting the timeline tests</title> +<title>Setting the timeline</title> <link rel="help" href="https://w3c.github.io/web-animations/#setting-the-timeline"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -16,8 +16,8 @@ // // --------------------------------------------------------------------- -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); animation.currentTime = 50 * MS_PER_SEC; @@ -29,8 +29,8 @@ assert_times_equal(animation.currentTime, 50 * MS_PER_SEC); }, 'After setting timeline on paused animation it is still paused'); -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); animation.currentTime = 200 * MS_PER_SEC; @@ -43,8 +43,8 @@ }, 'After setting timeline on animation paused outside active interval' + ' it is still paused'); -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); assert_equals(animation.playState, 'idle'); @@ -55,8 +55,8 @@ }, 'After setting timeline on an idle animation without a start time' + ' it is still idle'); -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); animation.startTime = document.timeline.currentTime; @@ -68,8 +68,8 @@ }, 'After setting timeline on an idle animation with a start time' + ' it is running'); -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); animation.startTime = document.timeline.currentTime - 200 * MS_PER_SEC; @@ -81,8 +81,8 @@ }, 'After setting timeline on an idle animation with a sufficiently ancient' + ' start time it is finished'); -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); animation.play(); @@ -93,8 +93,8 @@ assert_equals(animation.playState, 'pending'); }, 'After setting timeline on a play-pending animation it is still pending'); -promise_test(function(t) { - var animation = +promise_test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); animation.play(); @@ -102,14 +102,14 @@ animation.timeline = document.timeline; - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(animation.playState, 'running'); }); }, 'After setting timeline on a play-pending animation it begins playing' + ' after pending'); -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); animation.startTime = document.timeline.currentTime; @@ -122,8 +122,8 @@ assert_equals(animation.playState, 'pending'); }, 'After setting timeline on a pause-pending animation it is still pending'); -promise_test(function(t) { - var animation = +promise_test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); animation.startTime = document.timeline.currentTime; @@ -133,7 +133,7 @@ animation.timeline = document.timeline; - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(animation.playState, 'paused'); }); }, 'After setting timeline on a pause-pending animation it becomes paused' @@ -145,8 +145,8 @@ // // --------------------------------------------------------------------- -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); animation.currentTime = 50 * MS_PER_SEC; @@ -158,11 +158,11 @@ assert_times_equal(animation.currentTime, 50 * MS_PER_SEC); }, 'After clearing timeline on paused animation it is still paused'); -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); - var initialStartTime = document.timeline.currentTime - 200 * MS_PER_SEC; + const initialStartTime = document.timeline.currentTime - 200 * MS_PER_SEC; animation.startTime = initialStartTime; assert_equals(animation.playState, 'finished'); @@ -172,11 +172,11 @@ assert_times_equal(animation.startTime, initialStartTime); }, 'After clearing timeline on finished animation it is idle'); -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); - var initialStartTime = document.timeline.currentTime - 50 * MS_PER_SEC; + const initialStartTime = document.timeline.currentTime - 50 * MS_PER_SEC; animation.startTime = initialStartTime; assert_equals(animation.playState, 'running'); @@ -186,8 +186,8 @@ assert_times_equal(animation.startTime, initialStartTime); }, 'After clearing timeline on running animation it is idle'); -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); assert_equals(animation.playState, 'idle'); @@ -198,8 +198,8 @@ assert_equals(animation.startTime, null); }, 'After clearing timeline on idle animation it is still idle'); -test(function(t) { - var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); +test(t => { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); assert_equals(animation.playState, 'pending'); animation.timeline = null; @@ -207,22 +207,22 @@ assert_equals(animation.playState, 'pending'); }, 'After clearing timeline on play-pending animation it is still pending'); -promise_test(function(t) { - var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); assert_equals(animation.playState, 'pending'); animation.timeline = null; animation.timeline = document.timeline; assert_equals(animation.playState, 'pending'); - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(animation.playState, 'running'); }); }, 'After clearing and re-setting timeline on play-pending animation it' + ' begins to play'); -test(function(t) { - var animation = +test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); animation.startTime = document.timeline.currentTime; @@ -234,8 +234,8 @@ assert_equals(animation.playState, 'pending'); }, 'After clearing timeline on a pause-pending animation it is still pending'); -promise_test(function(t) { - var animation = +promise_test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); animation.startTime = document.timeline.currentTime; @@ -246,17 +246,17 @@ animation.timeline = document.timeline; assert_equals(animation.playState, 'pending'); - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(animation.playState, 'paused'); }); }, 'After clearing and re-setting timeline on a pause-pending animation it' + ' becomes paused'); -promise_test(function(t) { - var animation = +promise_test(t => { + const animation = new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), document.timeline); - var initialStartTime = document.timeline.currentTime - 50 * MS_PER_SEC; + const initialStartTime = document.timeline.currentTime - 50 * MS_PER_SEC; animation.startTime = initialStartTime; animation.pause(); animation.play(); @@ -265,7 +265,7 @@ animation.timeline = document.timeline; assert_equals(animation.playState, 'pending'); - return animation.ready.then(function() { + return animation.ready.then(() => { assert_equals(animation.playState, 'running'); assert_times_equal(animation.startTime, initialStartTime); });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html index 7b9efed..c77c4d7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Tests for updating the finished state of an animation</title> +<title>Updating the finished state</title> <link rel="help" href="https://w3c.github.io/web-animations/#updating-the-finished-state"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -20,29 +20,29 @@ // (Also the start time is resolved and there is pending task) // Did seek = false -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); // Here and in the following tests we wait until ready resolves as // otherwise we don't have a resolved start time. We test the case // where the start time is unresolved in a subsequent test. - return anim.ready.then(function() { + return anim.ready.then(() => { // Seek to 1ms before the target end and then wait 1ms anim.currentTime = 100 * MS_PER_SEC - 1; return waitForAnimationFramesWithDelay(1); - }).then(function() { + }).then(() => { assert_equals(anim.currentTime, 100 * MS_PER_SEC, 'Hold time is set to target end clamping current time'); }); }, 'Updating the finished state when playing past end'); // Did seek = true -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); - return anim.ready.then(function() { +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); + return anim.ready.then(() => { anim.currentTime = 200 * MS_PER_SEC; return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_equals(anim.currentTime, 200 * MS_PER_SEC, 'Hold time is set so current time should NOT change'); }); @@ -59,12 +59,12 @@ // (on the subsequent tick the hold time will be set to the same value anyway). // Did seek = true -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); - return anim.ready.then(function() { +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); + return anim.ready.then(() => { anim.currentTime = 100 * MS_PER_SEC; return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_equals(anim.currentTime, 100 * MS_PER_SEC, 'Hold time is set so current time should NOT change'); }); @@ -75,29 +75,29 @@ // (Also the start time is resolved and there is pending task) // Did seek = false -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.playbackRate = -1; anim.play(); // Make sure animation is not initially finished - return anim.ready.then(function() { + return anim.ready.then(() => { // Seek to 1ms before 0 and then wait 1ms anim.currentTime = 1; return waitForAnimationFramesWithDelay(1); - }).then(function() { + }).then(() => { assert_equals(anim.currentTime, 0 * MS_PER_SEC, 'Hold time is set to zero clamping current time'); }); }, 'Updating the finished state when playing in reverse past zero'); // Did seek = true -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.playbackRate = -1; anim.play(); - return anim.ready.then(function() { + return anim.ready.then(() => { anim.currentTime = -100 * MS_PER_SEC; return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_equals(anim.currentTime, -100 * MS_PER_SEC, 'Hold time is set so current time should NOT change'); }); @@ -107,14 +107,14 @@ // it doesn't really matter. // Did seek = true -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.playbackRate = -1; anim.play(); - return anim.ready.then(function() { + return anim.ready.then(() => { anim.currentTime = 0; return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_equals(anim.currentTime, 0 * MS_PER_SEC, 'Hold time is set so current time should NOT change'); }); @@ -126,30 +126,30 @@ // (Also the start time is resolved and there is pending task) // Did seek = false; playback rate > 0 -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); // We want to test that the hold time is cleared so first we need to // put the animation in a state where the hold time is set. anim.finish(); - return anim.ready.then(function() { + return anim.ready.then(() => { assert_equals(anim.currentTime, 100 * MS_PER_SEC, 'Hold time is initially set'); // Then extend the duration so that the hold time is cleared and on // the next tick the current time will increase. anim.effect.timing.duration *= 2; return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_greater_than(anim.currentTime, 100 * MS_PER_SEC, 'Hold time is not set so current time should increase'); }); }, 'Updating the finished state when playing before end'); // Did seek = true; playback rate > 0 -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.finish(); - return anim.ready.then(function() { + return anim.ready.then(() => { anim.currentTime = 50 * MS_PER_SEC; // When did seek = true, updating the finished state: (i) updates // the animation's start time and (ii) clears the hold time. @@ -157,7 +157,7 @@ // updated and then increases. assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated'); return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_greater_than(anim.currentTime, 50 * MS_PER_SEC, 'Hold time is not set so current time should increase'); }); @@ -177,14 +177,14 @@ // will set did seek = true). // Did seek = true; playback rate < 0 -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.playbackRate = -1; - return anim.ready.then(function() { + return anim.ready.then(() => { anim.currentTime = 50 * MS_PER_SEC; assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated'); return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_less_than(anim.currentTime, 50 * MS_PER_SEC, 'Hold time is not set so current time should decrease'); }); @@ -193,13 +193,13 @@ // CASE 4: playback rate == 0 // current time < 0 -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.playbackRate = 0; - return anim.ready.then(function() { + return anim.ready.then(() => { anim.currentTime = -100 * MS_PER_SEC; return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_equals(anim.currentTime, -100 * MS_PER_SEC, 'Hold time should not be cleared so current time should' + ' NOT change'); @@ -208,13 +208,13 @@ + ' current time is less than zero'); // current time < target end -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.playbackRate = 0; - return anim.ready.then(function() { + return anim.ready.then(() => { anim.currentTime = 50 * MS_PER_SEC; return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Hold time should not be cleared so current time should' + ' NOT change'); @@ -223,13 +223,13 @@ + ' current time is less than end'); // current time > target end -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.playbackRate = 0; - return anim.ready.then(function() { + return anim.ready.then(() => { anim.currentTime = 200 * MS_PER_SEC; return waitForAnimationFrames(1); - }).then(function() { + }).then(() => { assert_equals(anim.currentTime, 200 * MS_PER_SEC, 'Hold time should not be cleared so current time should' + ' NOT change'); @@ -239,8 +239,8 @@ // CASE 5: current time unresolved -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.cancel(); // Trigger a change that will cause the "update the finished state" // procedure to run. @@ -251,7 +251,7 @@ // change to timing, but just in case an implementation defers that, let's // wait a frame and check that the hold time / start time has still not been // updated. - return waitForAnimationFrames(1).then(function() { + return waitForAnimationFrames(1).then(() => { assert_equals(anim.currentTime, null, 'The animation hold time / start time should not be updated'); }); @@ -259,8 +259,8 @@ // CASE 6: has a pending task -test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.cancel(); anim.currentTime = 75 * MS_PER_SEC; anim.play(); @@ -278,8 +278,8 @@ // CASE 7: start time unresolved // Did seek = false -promise_test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +promise_test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.cancel(); // Make it so that only the start time is unresolved (to avoid overlapping // with the test case where current time is unresolved) @@ -287,7 +287,7 @@ // Trigger a change that will cause the "update the finished state" // procedure to run (did seek = false). anim.effect.timing.duration = 200 * MS_PER_SEC; - return waitForAnimationFrames(1).then(function() { + return waitForAnimationFrames(1).then(() => { assert_equals(anim.currentTime, 150 * MS_PER_SEC, 'The animation hold time should not be updated'); assert_equals(anim.startTime, null, @@ -297,8 +297,8 @@ + ' did seek = false'); // Did seek = true -test(function(t) { - var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); +test(t => { + const anim = createDiv(t).animate(null, 100 * MS_PER_SEC); anim.cancel(); anim.currentTime = 150 * MS_PER_SEC; // Trigger a change that will cause the "update the finished state" @@ -318,14 +318,14 @@ // -------------------------------------------------------------------- function waitForFinishEventAndPromise(animation) { - var eventPromise = new Promise(function(resolve) { - animation.onfinish = function() { resolve(); } + const eventPromise = new Promise(resolve => { + animation.onfinish = resolve; }); return Promise.all([eventPromise, animation.finished]); } -promise_test(function(t) { - var animation = createDiv(t).animate(null, 1); +promise_test(t => { + const animation = createDiv(t).animate(null, 1); animation.onfinish = t.unreached_func('Seeking to finish should not fire finish event'); animation.finished.then( @@ -337,27 +337,27 @@ }, 'Finish notification steps don\'t run when the animation seeks to finish' + ' and then seeks back again'); -promise_test(function(t) { - var animation = createDiv(t).animate(null, 1); - return animation.ready.then(function() { +promise_test(t => { + const animation = createDiv(t).animate(null, 1); + return animation.ready.then(() => { return waitForFinishEventAndPromise(animation); }); }, 'Finish notification steps run when the animation completes normally'); -promise_test(function(t) { - var animation = createDiv(t).animate(null, 1); - return animation.ready.then(function() { +promise_test(t => { + const animation = createDiv(t).animate(null, 1); + return animation.ready.then(() => { animation.currentTime = 10; return waitForFinishEventAndPromise(animation); }); }, 'Finish notification steps run when the animation seeks past finish'); -promise_test(function(t) { - var animation = createDiv(t).animate(null, 1); - return animation.ready.then(function() { +promise_test(t => { + const animation = createDiv(t).animate(null, 1); + return animation.ready.then(() => { // Register for notifications now since once we seek away from being // finished the 'finished' promise will be replaced. - var finishNotificationSteps = waitForFinishEventAndPromise(animation); + const finishNotificationSteps = waitForFinishEventAndPromise(animation); animation.finish(); animation.currentTime = 0; animation.pause(); @@ -366,41 +366,41 @@ }, 'Finish notification steps run when the animation completes with .finish(),' + ' even if we then seek away'); -promise_test(function(t) { - var animation = createDiv(t).animate(null, 1); - var initialFinishedPromise = animation.finished; +promise_test(t => { + const animation = createDiv(t).animate(null, 1); + const initialFinishedPromise = animation.finished; - return animation.finished.then(function(target) { + return animation.finished.then(target => { animation.currentTime = 0; assert_not_equals(initialFinishedPromise, animation.finished); }); }, 'Animation finished promise is replaced after seeking back to start'); -promise_test(function(t) { - var animation = createDiv(t).animate(null, 1); - var initialFinishedPromise = animation.finished; +promise_test(t => { + const animation = createDiv(t).animate(null, 1); + const initialFinishedPromise = animation.finished; - return animation.finished.then(function(target) { + return animation.finished.then(target => { animation.play(); assert_not_equals(initialFinishedPromise, animation.finished); }); }, 'Animation finished promise is replaced after replaying from start'); -async_test(function(t) { - var animation = createDiv(t).animate(null, 1); - animation.onfinish = function(event) { +async_test(t => { + const animation = createDiv(t).animate(null, 1); + animation.onfinish = event => { animation.currentTime = 0; - animation.onfinish = function(event) { + animation.onfinish = event => { t.done(); }; }; }, 'Animation finish event is fired again after seeking back to start'); -async_test(function(t) { - var animation = createDiv(t).animate(null, 1); - animation.onfinish = function(event) { +async_test(t => { + const animation = createDiv(t).animate(null, 1); + animation.onfinish = event => { animation.play(); - animation.onfinish = function(event) { + animation.onfinish = event => { t.done(); }; };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/time-transformations/transformed-progress.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/time-transformations/transformed-progress.html index 6ca27cf..946babf2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/time-transformations/transformed-progress.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/time-transformations/transformed-progress.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> -<title>Tests for the transformed progress</title> +<title>Transformed progress</title> <link rel="help" href="https://w3c.github.io/web-animations/#calculating-the-transformed-progress"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -12,14 +12,14 @@ <script> 'use strict'; -gEasingTests.forEach(params => { - test(function(t) { +for (const params of gEasingTests) { + test(t => { const target = createDiv(t); const anim = target.animate(null, { duration: 1000, fill: 'forwards', easing: params.easing }); - [ 0, 250, 500, 750, 1000 ].forEach(sampleTime => { + for (const sampleTime of [0, 250, 500, 750, 1000]) { anim.currentTime = sampleTime; const portion = sampleTime / anim.effect.getComputedTiming().duration; const expectedProgress = params.easingFunction(portion); @@ -27,15 +27,15 @@ expectedProgress, 0.01, 'The progress should be approximately ' + - expectedProgress + ` at ${sampleTime}ms`); - }); - }, 'Transformed progress for ' + params.desc); -}); + `${expectedProgress} at ${sampleTime}ms`); + } + }, `Transformed progress for ${params.desc}`); +} // Additional tests for various boundary conditions of step timing functions and // frames timing functions. -var gStepAndFramesTimingFunctionTests = [ +const gStepAndFramesTimingFunctionTests = [ { description: 'Test bounds point of step-start easing', effect: { @@ -291,18 +291,18 @@ } ]; -gStepAndFramesTimingFunctionTests.forEach(function(options) { - test(function(t) { - var target = createDiv(t); - var animation = target.animate(null, options.effect); - options.conditions.forEach(function(condition) { +for (const options of gStepAndFramesTimingFunctionTests) { + test(t => { + const target = createDiv(t); + const animation = target.animate(null, options.effect); + for (const condition of options.conditions) { animation.currentTime = condition.currentTime; assert_equals(animation.effect.getComputedTiming().progress, condition.progress, - 'Progress at ' + animation.currentTime + 'ms'); - }); + `Progress at ${animation.currentTime}ms`); + } }, options.description); -}); +} </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/timelines/document-timelines.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/timelines/document-timelines.html index 7b863888..545ec2c9 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/timelines/document-timelines.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/timelines/document-timelines.html
@@ -9,7 +9,7 @@ <script> 'use strict'; -async_test(function(t) { +async_test(t => { assert_true(document.timeline.currentTime > 0, 'The current time is initially is positive'); // document.timeline.currentTime should be set even before document @@ -25,8 +25,8 @@ // We can't just compare document.timeline.currentTime to // window.performance.now() because currentTime is only updated on a sample // so we use requestAnimationFrame instead. - window.requestAnimationFrame(function(rafTime) { - t.step(function() { + window.requestAnimationFrame(rafTime => { + t.step(() => { assert_equals(document.timeline.currentTime, rafTime, 'The current time matches requestAnimationFrame time'); });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/timelines/timelines.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/timelines/timelines.html index 290c71b..0f7db3f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/timelines/timelines.html +++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/timelines/timelines.html
@@ -9,7 +9,7 @@ <script> 'use strict'; -promise_test(function(t) { +promise_test(t => { const valueAtStart = document.timeline.currentTime; const timeAtStart = window.performance.now(); while (window.performance.now() - timeAtStart < 50) { @@ -17,13 +17,13 @@ } assert_equals(document.timeline.currentTime, valueAtStart, 'Timeline time does not change within an animation frame'); - return waitForAnimationFrames(1).then(function() { + return waitForAnimationFrames(1).then(() => { assert_greater_than(document.timeline.currentTime, valueAtStart, 'Timeline time increases between animation frames'); }); }, 'Timeline time increases once per animation frame'); -async_test(function(t) { +async_test(t => { const iframe = document.createElement('iframe'); iframe.width = 10; iframe.height = 10; @@ -49,20 +49,20 @@ document.body.appendChild(iframe); }, 'Timeline time increases once per animation frame in an iframe'); -async_test(function(t) { +async_test(t => { const startTime = document.timeline.currentTime; let firstRafTime; - requestAnimationFrame(function() { - t.step(function() { + requestAnimationFrame(() => { + t.step(() => { assert_greater_than_equal(document.timeline.currentTime, startTime, 'Timeline time should have progressed'); firstRafTime = document.timeline.currentTime; }); }); - requestAnimationFrame(function() { - t.step(function() { + requestAnimationFrame(() => { + t.step(() => { assert_equals(document.timeline.currentTime, firstRafTime, 'Timeline time should be the same'); });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCCertificate-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCCertificate-expected.txt index 2fe7663..883749d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCCertificate-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCCertificate-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. PASS Constructing RTCPeerConnection with expired certificate should reject with InvalidAccessError PASS Calling setConfiguration with different set of certs should reject with InvalidModificationError -FAIL RTCCertificate should have at least one fingerprint assert_true: Expect fingerprint.algorithm to be string of algorithm identifier expected true got false +PASS RTCCertificate should have at least one fingerprint PASS RTCPeerConnection({ certificates }) should generate offer SDP with fingerprint of provided certificate FAIL RTCPeerConnection({ certificates }) should generate offer SDP with fingerprint of all provided certificates assert_true: Expect fingerprint line to be found in SDP expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCCertificate.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCCertificate.html index f5eccab..e5f1749 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCCertificate.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCCertificate.html
@@ -172,8 +172,9 @@ assert_equals(typeof fingerprint, 'object', 'Expect fingerprint to be an object (dictionary)'); - // Can only do simple test as the allowed values may be extended - assert_true(/^[a-zA-Z\-]+$/.test(fingerprint.algorithm), + // https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml + const algorithms = ['md2', 'md5', 'sha-1', 'sha-224', 'sha-256', 'sha-384', 'sha-512']; + assert_in_array(fingerprint.algorithm, algorithms, 'Expect fingerprint.algorithm to be string of algorithm identifier'); assert_true(/^([0-9a-f]{2}\:)+[0-9a-f]{2}$/.test(fingerprint.value),
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCDTMFSender-helper.js b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCDTMFSender-helper.js index b66c4ae..97bb6f934 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCDTMFSender-helper.js +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCDTMFSender-helper.js
@@ -76,8 +76,8 @@ const now = Date.now(); const duration = now - lastEventTime; - assert_approx_equals(duration, expectedDuration, 150, - `Expect tonechange event for "${tone}" to be fired approximately after ${expectedDuration} seconds`); + assert_approx_equals(duration, expectedDuration, 250, + `Expect tonechange event for "${tone}" to be fired approximately after ${expectedDuration} milliseconds`); lastEventTime = now;
diff --git a/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null-expected.txt index abb83fc..1f6081f9 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null-expected.txt
@@ -241,7 +241,7 @@ TEST SUCCEEDED: The value was the empty string. [tested HTMLTableCellElement.bgColor] TEST SUCCEEDED: The value was the string 'null'. [tested HTMLTableCellElement.ch] TEST SUCCEEDED: The value was the string 'null'. [tested HTMLTableCellElement.chOff] -TEST SUCCEEDED: The value was the empty string. [tested HTMLTableCellElement.headers] +TEST SUCCEEDED: The value was the string 'null'. [tested HTMLTableCellElement.headers] TEST SUCCEEDED: The value was the string 'null'. [tested HTMLTableCellElement.height] TEST SUCCEEDED: The value was the empty string. [tested HTMLTableCellElement.scope] TEST SUCCEEDED: The value was the string 'null'. [tested HTMLTableCellElement.vAlign]
diff --git a/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null.html b/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null.html index dafd735..a5d26ce 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null.html +++ b/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null.html
@@ -565,7 +565,7 @@ {name: 'bgColor', expectedNull: ''}, {name: 'ch', expectedNull: 'null'}, {name: 'chOff', expectedNull: 'null'}, - {name: 'headers', expectedNull: ''}, + {name: 'headers', expectedNull: 'null'}, {name: 'height', expectedNull: 'null'}, {name: 'scope', expectedNull: ''}, {name: 'vAlign', expectedNull: 'null'},
diff --git a/third_party/WebKit/LayoutTests/fast/text/ellipsis-in-relative-inline-3-expected.html b/third_party/WebKit/LayoutTests/fast/text/ellipsis-in-relative-inline-3-expected.html new file mode 100644 index 0000000..d2a884d --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/ellipsis-in-relative-inline-3-expected.html
@@ -0,0 +1,31 @@ +<style> +.container { + padding: 50px; + width: 400px; +} + +.wrapper { + display: block; + background-color: #ddd; + margin-bottom: 2em; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.rect { + display: inline-block; + width: 45px; + height: 45px; + vertical-align: middle; +} +</style> +<p>crbug.com/786326: There should be an ellipsis below.</p> +<div class="container"> + <span class="wrapper"> + <span class="rect"></span> + <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Iste laowner:meboriosam eum aut porro? Doloremque, accusamus facere fuga dignissimos deleniti illo neque adipisci qui voluptatum in, animi unde sapiente quia veritatis!</span> + <span class="rect"></span> + </span> +</div> +
diff --git a/third_party/WebKit/LayoutTests/fast/text/ellipsis-in-relative-inline-3.html b/third_party/WebKit/LayoutTests/fast/text/ellipsis-in-relative-inline-3.html new file mode 100644 index 0000000..78002cc --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/ellipsis-in-relative-inline-3.html
@@ -0,0 +1,33 @@ +<style> +.container { + padding: 50px; + width: 400px; +} + +.wrapper { + display: block; + background-color: #ddd; + margin-bottom: 2em; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.rect { + display: inline-block; + position: relative; + width: 45px; + height: 45px; + vertical-align: middle; + top: 3px; +} +</style> +<p>crbug.com/786326: There should be an ellipsis below.</p> +<div class="container"> + <span class="wrapper"> + <span class="rect"></span> + <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Iste laowner:meboriosam eum aut porro? Doloremque, accusamus facere fuga dignissimos deleniti illo neque adipisci qui voluptatum in, animi unde sapiente quia veritatis!</span> + <span class="rect"></span> + </span> +</div> +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change-expected.txt new file mode 100644 index 0000000..154117e --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change-expected.txt
@@ -0,0 +1,64 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV class='composited-child'", + "bounds": [100, 100], + "contentsOpaque": true, + "backfaceVisibility": "hidden", + "backgroundColor": "#008000" + }, + { + "name": "Ancestor Clipping Layer", + "position": [0, 200], + "bounds": [200, 200], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV class='composited-child'", + "position": [0, 200], + "bounds": [100, 100], + "contentsOpaque": true, + "backfaceVisibility": "hidden", + "backgroundColor": "#008000" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='composited-child overflow-child'", + "position": [150, 150], + "bounds": [100, 100], + "contentsOpaque": true, + "backfaceVisibility": "hidden", + "backgroundColor": "#008000" + }, + { + "name": "Ancestor Clipping Layer", + "position": [0, 200], + "bounds": [200, 200], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='composited-child overflow-child'", + "position": [150, 350], + "bounds": [100, 100], + "contentsOpaque": true, + "backfaceVisibility": "hidden", + "backgroundColor": "#008000" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutBlockFlow DIV id='overflow1'", + "reason": "style change" + }, + { + "object": "LayoutBlockFlow DIV id='overflow2'", + "reason": "style change" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/clip/caret-ancestor-clip-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/clip/caret-ancestor-clip-change-expected.txt index 63d4e025..0cd7ba0 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/clip/caret-ancestor-clip-change-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/clip/caret-ancestor-clip-change-expected.txt
@@ -8,33 +8,18 @@ "paintInvalidations": [ { "object": "LayoutBlockFlow DIV", - "rect": [8, 8, 105, 112], - "reason": "paint property change" + "rect": [8, 58, 105, 62], + "reason": "incremental" }, { "object": "LayoutTextControl INPUT id='target'", - "rect": [8, 8, 105, 112], - "reason": "paint property change" + "rect": [8, 58, 105, 62], + "reason": "incremental" }, { "object": "LayoutBlockFlow DIV", - "rect": [8, 8, 105, 50], - "reason": "paint property change" - }, - { - "object": "LayoutTextControl INPUT id='target'", - "rect": [8, 8, 105, 50], - "reason": "paint property change" - }, - { - "object": "LayoutBlockFlow DIV", - "rect": [10, 8, 1, 107], - "reason": "paint property change" - }, - { - "object": "LayoutBlockFlow DIV", - "rect": [10, 8, 1, 50], - "reason": "paint property change" + "rect": [10, 58, 1, 57], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/clip/css-clip-change-stacking-child-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/clip/css-clip-change-stacking-child-expected.txt index 943f859a..f768584d 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/clip/css-clip-change-stacking-child-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/clip/css-clip-change-stacking-child-expected.txt
@@ -8,13 +8,13 @@ "paintInvalidations": [ { "object": "LayoutBlockFlow DIV", - "rect": [8, 8, 300, 300], - "reason": "paint property change" + "rect": [8, 8, 300, 200], + "reason": "subtree" }, { "object": "LayoutBlockFlow DIV", - "rect": [8, 8, 300, 200], - "reason": "paint property change" + "rect": [8, 208, 300, 100], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow/repaint-resized-overflow-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow/repaint-resized-overflow-expected.txt index c4d48f8..4bf7fa78 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow/repaint-resized-overflow-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/overflow/repaint-resized-overflow-expected.txt
@@ -7,14 +7,14 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "LayoutBlockFlow DIV", + "object": "LayoutBlockFlow DIV id='s'", "rect": [8, 156, 108, 108], - "reason": "paint property change" + "reason": "geometry" }, { "object": "LayoutBlockFlow DIV", - "rect": [8, 156, 108, 56], - "reason": "paint property change" + "rect": [8, 212, 108, 52], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned-expected.txt index 9a847fc..13bbc22 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned-expected.txt
@@ -7,14 +7,24 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "LayoutBlockFlow DIV", + "object": "InlineTextBox 'x'", "rect": [8, 220, 100, 100], - "reason": "paint property change" + "reason": "geometry" + }, + { + "object": "InlineTextBox 'x'", + "rect": [8, 220, 100, 80], + "reason": "geometry" }, { "object": "LayoutBlockFlow DIV", - "rect": [8, 200, 100, 100], - "reason": "paint property change" + "rect": [8, 300, 100, 20], + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow DIV", + "rect": [8, 200, 100, 20], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/resize-iframe-text-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/resize-iframe-text-expected.txt index 55c04fe0..21efa45 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/resize-iframe-text-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/resize-iframe-text-expected.txt
@@ -14,7 +14,7 @@ { "object": "LayoutBlockFlow HTML", "rect": [8, 300, 60, 22], - "reason": "paint property change" + "reason": "incremental" }, { "object": "LayoutView #document",
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-content-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-content-expected.txt index baba78b..e3d5ae7 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-content-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-content-expected.txt
@@ -12,14 +12,14 @@ "reason": "geometry" }, { - "object": "LayoutSVGRoot svg", + "object": "LayoutSVGRect rect id='targetRect'", "rect": [9, 73, 400, 400], - "reason": "paint property change" + "reason": "geometry" }, { "object": "LayoutSVGRoot svg", - "rect": [9, 73, 100, 400], - "reason": "paint property change" + "rect": [109, 73, 300, 400], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-content-with-resources-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-content-with-resources-expected.txt index 5e7a0f8..a86731b 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-content-with-resources-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-content-with-resources-expected.txt
@@ -12,14 +12,34 @@ "reason": "geometry" }, { - "object": "LayoutSVGRoot svg", + "object": "LayoutSVGEllipse circle", "rect": [47, 111, 324, 324], - "reason": "paint property change" + "reason": "SVG resource change" }, { "object": "LayoutSVGRoot svg", - "rect": [8, 154, 102, 238], - "reason": "paint property change" + "rect": [47, 392, 324, 43], + "reason": "incremental" + }, + { + "object": "LayoutSVGRoot svg", + "rect": [47, 111, 324, 43], + "reason": "incremental" + }, + { + "object": "LayoutSVGRoot svg", + "rect": [110, 154, 261, 238], + "reason": "incremental" + }, + { + "object": "LayoutSVGEllipse circle", + "rect": [8, 154, 170, 238], + "reason": "SVG resource change" + }, + { + "object": "LayoutSVGRoot svg", + "rect": [8, 154, 39, 238], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-image-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-image-expected.txt index b83de76..5a40c5d4 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-image-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-image-expected.txt
@@ -12,14 +12,14 @@ "reason": "geometry" }, { - "object": "LayoutSVGRoot svg", + "object": "LayoutSVGImage image", "rect": [9, 73, 400, 400], - "reason": "paint property change" + "reason": "image" }, { "object": "LayoutSVGRoot svg", - "rect": [9, 73, 100, 400], - "reason": "paint property change" + "rect": [109, 73, 300, 400], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-shadow-tree-content-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-shadow-tree-content-expected.txt index cb0be6f8..c45a8929 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-shadow-tree-content-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/relative-sized-shadow-tree-content-expected.txt
@@ -19,17 +19,17 @@ { "object": "LayoutSVGRect rect id='targetRect1'", "rect": [9, 73, 200, 200], - "reason": "paint property change" + "reason": "geometry" + }, + { + "object": "LayoutSVGRect rect id='targetRect1'", + "rect": [59, 73, 150, 200], + "reason": "incremental" }, { "object": "LayoutSVGContainer use", "rect": [59, 273, 50, 200], "reason": "paint property change" - }, - { - "object": "LayoutSVGRect rect id='targetRect1'", - "rect": [9, 73, 50, 200], - "reason": "paint property change" } ] }
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-frame-errors.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-frame-errors.html deleted file mode 100644 index 27aaf774..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-frame-errors.html +++ /dev/null
@@ -1,33 +0,0 @@ -<!DOCTYPE html> -<title>Credential Manager: get() basics.</title> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script> -add_completion_callback(() => { - if (window.testRunner) - window.testRunner.clearMockCredentialManagerResponse(); -}); - -function create_iframe_test(origin) { - return function (t) { - window.addEventListener("load", _ => { - var frame_tests = 0; - var iframe = document.createElement("iframe"); - iframe.src = origin + "/credentialmanager/resources/iframed-credentialscontainer.html"; - window.addEventListener("message", t.step_func(e => { - if (e.source == iframe.contentWindow) { - assert_equals(e.data.credential, null); - assert_equals(e.data.exception, "SecurityError"); - frame_tests++; - if (frame_tests == 3) - t.done(); - } - })); - document.body.appendChild(iframe); - }); - }; -} - -async_test(create_iframe_test("http://127.0.0.1:8000"), "Same-origin IFrame throws."); -async_test(create_iframe_test("https://example.test:8443"), "Cross-origin IFrame throws."); -</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/iframed-credentialscontainer.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/iframed-credentialscontainer.html index 46151efe..bc8dbdd 100644 --- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/iframed-credentialscontainer.html +++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/iframed-credentialscontainer.html
@@ -32,15 +32,15 @@ }); navigator.credentials.preventSilentAccess() - .then(c => { + .then(_ => { window.top.postMessage({ - "credential": c, + "preventSilentAccess": true, "exception": null }, "*"); }) .catch(omg => { window.top.postMessage({ - "credential": null, + "preventSilentAccess": false, "exception": omg.name }, "*"); });
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests-expected.txt index b25cf792..e745f062 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests-expected.txt
@@ -1,76 +1,75 @@ -Tests that application cache model keeps track of manifest urls and statuses correctly. +Tests that application cache model keeps track of manifest urls and statuses correctly. https://bugs.webkit.org/show_bug.cgi?id=64581 -Bug 64581 Dumping application cache tree: (empty) Dumping application cache model: (empty) Dumping application cache tree: - Manifest URL: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=1 + Manifest URL: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=1 Frame: frame1 (page-with-manifest.php) Dumping application cache model: Frame: frame1 - manifest url: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=1 + manifest url: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=1 status: IDLE Dumping application cache tree: - Manifest URL: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=2 + Manifest URL: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=2 Frame: frame1 (page-with-manifest.php) Dumping application cache model: Frame: frame1 - manifest url: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=2 + manifest url: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=2 status: IDLE Dumping application cache tree: - Manifest URL: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=2 + Manifest URL: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=2 Frame: frame1 (page-with-manifest.php) - Manifest URL: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=1 + Manifest URL: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=1 Frame: frame2 (page-with-manifest.php) Dumping application cache model: Frame: frame1 - manifest url: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=2 + manifest url: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=2 status: IDLE Frame: frame2 - manifest url: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=1 + manifest url: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=1 status: IDLE Dumping application cache tree: - Manifest URL: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=2 + Manifest URL: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=2 Frame: frame1 (page-with-manifest.php) - Manifest URL: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=1 + Manifest URL: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=1 Frame: frame2 (page-with-manifest.php) Frame: frame3 (page-with-manifest.php) Dumping application cache model: Frame: frame1 - manifest url: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=2 + manifest url: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=2 status: IDLE Frame: frame2 - manifest url: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=1 + manifest url: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=1 status: IDLE Frame: frame3 - manifest url: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=1 + manifest url: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=1 status: IDLE Dumping application cache tree: - Manifest URL: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=2 + Manifest URL: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=2 Frame: frame1 (page-with-manifest.php) - Manifest URL: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=1 + Manifest URL: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=1 Frame: frame2 (page-with-manifest.php) Dumping application cache model: Frame: frame1 - manifest url: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=2 + manifest url: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=2 status: IDLE Frame: frame2 - manifest url: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=1 + manifest url: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=1 status: IDLE Dumping application cache tree: - Manifest URL: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=2 + Manifest URL: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=2 Frame: frame1 (page-with-manifest.php) Dumping application cache model: Frame: frame1 - manifest url: http://127.0.0.1:8000/inspector/appcache/resources/manifest.php?manifestId=2 + manifest url: http://127.0.0.1:8000/devtools/appcache/resources/manifest.php?manifestId=2 status: IDLE Dumping application cache tree:
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests.html b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests.js similarity index 79% rename from third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests.html rename to third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests.js index efeb594..10f0d3c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests.html +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests.js
@@ -1,10 +1,17 @@ -<html> -<head> -<script src="../../inspector/inspector-test.js"></script> -<script src="../../inspector/resources-test.js"></script> -<script src="../../inspector/appcache/appcache-test.js"></script> -<script> -function test() { +// 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 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'); + await TestRunner.showPanel('resources'); + await TestRunner.loadHTML(` + <p>Tests that application cache model keeps track of manifest urls and statuses correctly.</p> + <a href="https://bugs.webkit.org/show_bug.cgi?id=64581">Bug 64581</a> + `); + var frameId1; var frameId2; var frameId3; @@ -87,11 +94,4 @@ ApplicationTestRunner.dumpApplicationCache(); TestRunner.completeTest(); } -} -</script> -</head> -<body onload="runTest()"> -<p>Tests that application cache model keeps track of manifest urls and statuses correctly.</p> -<a href="https://bugs.webkit.org/show_bug.cgi?id=64581">Bug 64581</a> -</body> -</html> +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file-expected.txt index 0358ee11..a93aa282 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file-expected.txt
@@ -1,6 +1,5 @@ -Tests that application cache model keeps track of manifest urls and statuses correctly when there is a non existing file listed in manifest. +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 -Bug 64581 Dumping application cache tree: (empty) Dumping application cache model:
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.html b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.html deleted file mode 100644 index b30e72b..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.html +++ /dev/null
@@ -1,40 +0,0 @@ -<html> -<head> -<script src="../../inspector/inspector-test.js"></script> -<script src="../../inspector/resources-test.js"></script> -<script src="../../inspector/appcache/appcache-test.js"></script> -<script> -function test() { - var frameId1; - var frameId2; - var frameId3; - - UI.viewManager.showView('resources'); - ApplicationTestRunner.startApplicationCacheStatusesRecording(); - ApplicationTestRunner.dumpApplicationCache(); - ApplicationTestRunner.createAndNavigateIFrame( - 'resources/page-with-manifest.php?manifestId=with-non-existing-file', step1); - - function step1(frameId) { - frameId1 = frameId; - // Waiting for at least two status events notifications from backend, to make sure - // we are not completing test before loading application cache. - ApplicationTestRunner.ensureFrameStatusEventsReceived(frameId, 2, step2); - } - - function step2() { - ApplicationTestRunner.waitForFrameManifestURLAndStatus(frameId1, '', applicationCache.UNCACHED, step3); - } - - function step3() { - ApplicationTestRunner.dumpApplicationCache(); - TestRunner.completeTest(); - } -} -</script> -</head> -<body onload="runTest()"> -<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> -<a href="https://bugs.webkit.org/show_bug.cgi?id=64581">Bug 64581</a> -</body> -</html>
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 new file mode 100644 index 0000000..c513cdf9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.js
@@ -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. + +(async function() { + 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'); + 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> + <a href="https://bugs.webkit.org/show_bug.cgi?id=64581">Bug 64581</a> + `); + + var frameId1; + var frameId2; + var frameId3; + + UI.viewManager.showView('resources'); + ApplicationTestRunner.startApplicationCacheStatusesRecording(); + ApplicationTestRunner.dumpApplicationCache(); + ApplicationTestRunner.createAndNavigateIFrame( + 'resources/page-with-manifest.php?manifestId=with-non-existing-file', step1); + + function step1(frameId) { + frameId1 = frameId; + // Waiting for at least two status events notifications from backend, to make sure + // we are not completing test before loading application cache. + ApplicationTestRunner.ensureFrameStatusEventsReceived(frameId, 2, step2); + } + + function step2() { + ApplicationTestRunner.waitForFrameManifestURLAndStatus(frameId1, '', applicationCache.UNCACHED, step3); + } + + function step3() { + ApplicationTestRunner.dumpApplicationCache(); + TestRunner.completeTest(); + } +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota-expected.txt index e3ffed62..c4b54ea 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota-expected.txt
@@ -1,6 +1,3 @@ -CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback1 -CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback2 -CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback3 Tests quota reporting. Tree element found: true
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota.html b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota.js similarity index 86% rename from third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota.html rename to third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota.js index ba03ba1..365fbc3 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota.html +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota.js
@@ -1,11 +1,13 @@ -<html> -<head> -<script src="../../inspector/inspector-test.js"></script> -<script src="../../inspector/resources-test.js"></script> -<script src="../../inspector/console-test.js"></script> -<script src="../../inspector/indexeddb/indexeddb-test.js"></script> -<script> -async function test() { +// 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 quota reporting.\n`); + await TestRunner.loadModule('application_test_runner'); + await TestRunner.loadModule('console_test_runner'); + await TestRunner.showPanel('resources'); + var updateListener = null; async function writeArray() { @@ -69,10 +71,4 @@ await dumpWhenMatches(clearStorageView, usage => usage > 5000000); TestRunner.completeTest(); -} -</script> -</head> -<body onload="runTest()"> - <p>Tests quota reporting.</p> -</body> -</html> +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/compiler-source-mapping-debug-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/compiler-source-mapping-debug-expected.txt index 726bc43..4f90209 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/compiler-source-mapping-debug-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/compiler-source-mapping-debug-expected.txt
@@ -1,13 +1,11 @@ -CONSOLE MESSAGE: line 2: button clicked! Tests installing compiler source map in scripts panel. - Running: testSetBreakpoint Script source was shown. Script execution paused. Call stack: - 0) handleClick (source1.js:17) - 1) clickButton (compiler-source-mapping-debug.html:13) + 0) handleClick (add-elements.js:15) + 1) clickButton (compiler-source-mapping-debug.js:18) Script execution resumed.
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/compiler-source-mapping-debug.html b/third_party/WebKit/LayoutTests/http/tests/devtools/compiler-source-mapping-debug.html deleted file mode 100644 index 293cccfc..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/compiler-source-mapping-debug.html +++ /dev/null
@@ -1,48 +0,0 @@ -<html> -<head> -<script src="../inspector/inspector-test.js"></script> -<script src="../inspector/debugger-test.js"></script> -<script src="../inspector/console-test.js"></script> -<script src="../inspector/network-test.js"></script> -<script src="resources/compiled.js"></script> - -<script> - -function clickButton() -{ - document.getElementById('test').click(); -} - -function installScriptWithPoorSourceMap() -{ - var script = document.createElement("script"); - script.setAttribute("src", "resources/compiled-with-wrong-source-map-url.js"); - document.head.appendChild(script); -} - -function test() { - SourcesTestRunner.runDebuggerTestSuite([function testSetBreakpoint(next) { - SourcesTestRunner.showScriptSource('source1.js', didShowSource); - - function didShowSource(sourceFrame) { - TestRunner.addResult('Script source was shown.'); - SourcesTestRunner.setBreakpoint(sourceFrame, 14, '', true); - SourcesTestRunner.waitUntilPaused(paused); - TestRunner.evaluateInPage('setTimeout(clickButton, 0)'); - } - - function paused(callFrames) { - SourcesTestRunner.captureStackTrace(callFrames); - SourcesTestRunner.resumeExecution(next); - } - }]); -}; - -</script> - -</head> - -<body onload="runTest()"> -<p>Tests installing compiler source map in scripts panel.</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/compiler-source-mapping-debug.js b/third_party/WebKit/LayoutTests/http/tests/devtools/compiler-source-mapping-debug.js new file mode 100644 index 0000000..29cd469 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/compiler-source-mapping-debug.js
@@ -0,0 +1,44 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function() { + TestRunner.addResult(`Tests installing compiler source map in scripts panel.\n`); + await TestRunner.loadModule('sources_test_runner'); + await TestRunner.loadModule('console_test_runner'); + await TestRunner.loadModule('network_test_runner'); + await TestRunner.showPanel('sources'); + + await TestRunner.addScriptTag('resources/compiled-2.js'); + + await TestRunner.evaluateInPagePromise(`addElements()`); + await TestRunner.evaluateInPagePromise(` + function clickButton() + { + document.getElementById('test').click(); + } + + function installScriptWithPoorSourceMap() + { + var script = document.createElement("script"); + script.setAttribute("src", "resources/compiled-with-wrong-source-map-url.js"); + document.head.appendChild(script); + } + `); + + SourcesTestRunner.runDebuggerTestSuite([function testSetBreakpoint(next) { + SourcesTestRunner.showScriptSource('add-elements.js', didShowSource); + + function didShowSource(sourceFrame) { + TestRunner.addResult('Script source was shown.'); + SourcesTestRunner.setBreakpoint(sourceFrame, 14, '', true); + SourcesTestRunner.waitUntilPaused(paused); + TestRunner.evaluateInPage('setTimeout(clickButton, 0)'); + } + + function paused(callFrames) { + SourcesTestRunner.captureStackTrace(callFrames); + SourcesTestRunner.resumeExecution(next); + } + }]); +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console-cross-origin-iframe-logging-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console-cross-origin-iframe-logging-expected.txt index bb57dd3..a3824353 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console-cross-origin-iframe-logging-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console-cross-origin-iframe-logging-expected.txt
@@ -1,8 +1,6 @@ -CONSOLE ERROR: line 19: Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('http://127.0.0.1:8000') does not match the recipient window's origin ('http://localhost:8000'). Tests that cross origin errors are logged with source url and line number. - -console-cross-origin…ame-logging.html:19 Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('http://127.0.0.1:8000') does not match the recipient window's origin ('http://localhost:8000'). -accessFrame @ console-cross-origin…ame-logging.html:19 -(anonymous) @ VM:1 +console-cross-origin…frame-logging.js:25 Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('http://127.0.0.1:8000') does not match the recipient window's origin ('http://localhost:8000'). +accessFrame @ console-cross-origin…frame-logging.js:25 +(anonymous) @ console-cross-origin…frame-logging.js:32
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console-cross-origin-iframe-logging.html b/third_party/WebKit/LayoutTests/http/tests/devtools/console-cross-origin-iframe-logging.html deleted file mode 100644 index 3051a02..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console-cross-origin-iframe-logging.html +++ /dev/null
@@ -1,44 +0,0 @@ -<html> -<head> -<script src="../inspector/inspector-test.js"></script> -<script src="../inspector/console-test.js"></script> -<script> -function accessFrame() -{ - // Should fail. - try { - var host = frames[0].location.host; - } catch (e) {} - - // Should fail. - try { - frames[0].location.reload(); - } catch (e) {} - - // Should fail. - frames[0].postMessage("fail", "http://127.0.0.1:8000"); -} - -function test() { - var finishAttemptsLeft = 2; - ConsoleTestRunner.addConsoleSniffer(maybeFinish, true); - Common.settingForTest('monitoringXHREnabled').set(true); - TestRunner.evaluateInPage('accessFrame()', maybeFinish); - - function maybeFinish() { - --finishAttemptsLeft; - if (finishAttemptsLeft) - return; - - Common.settingForTest('monitoringXHREnabled').set(false); - ConsoleTestRunner.dumpConsoleMessages(); - TestRunner.completeTest(); - } -} -</script> -</head> -<body onload="runTest()"> -<p>Tests that cross origin errors are logged with source url and line number.</p> -<iframe src="http://localhost:8000/devtools/resources/cross-origin-iframe.html"></iframe> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console-cross-origin-iframe-logging.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console-cross-origin-iframe-logging.js new file mode 100644 index 0000000..46ffe66 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console-cross-origin-iframe-logging.js
@@ -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. + +(async function() { + TestRunner.addResult(`Tests that cross origin errors are logged with source url and line number.\n`); + await TestRunner.loadModule('console_test_runner'); + await TestRunner.loadHTML(` + <iframe src="http://localhost:8000/devtools/resources/cross-origin-iframe.html"></iframe> + `); + await TestRunner.evaluateInPagePromise(` + function accessFrame() + { + // Should fail. + try { + var host = frames[0].location.host; + } catch (e) {} + + // Should fail. + try { + frames[0].location.reload(); + } catch (e) {} + + // Should fail. + frames[0].postMessage("fail", "http://127.0.0.1:8000"); + } + `); + + var finishAttemptsLeft = 2; + ConsoleTestRunner.addConsoleSniffer(maybeFinish, true); + Common.settingForTest('monitoringXHREnabled').set(true); + TestRunner.evaluateInPage('accessFrame()', maybeFinish); + + function maybeFinish() { + --finishAttemptsLeft; + if (finishAttemptsLeft) + return; + + Common.settingForTest('monitoringXHREnabled').set(false); + ConsoleTestRunner.dumpConsoleMessages(); + TestRunner.completeTest(); + } +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console-fetch-logging.html b/third_party/WebKit/LayoutTests/http/tests/devtools/console-fetch-logging.html deleted file mode 100644 index 5e2c72e..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console-fetch-logging.html +++ /dev/null
@@ -1,82 +0,0 @@ -<html> -<head> -<script src="../inspector/inspector-test.js"></script> -<script src="../inspector/console-test.js"></script> -<script src="../inspector/network-test.js"></script> -<script> -function requestHelper(method, url, callback) -{ - console.log("sending a " + method + " request to " + url); - // Delay invoking callback to let didFinishLoading() a chance to fire and log - // console message. - function delayCallback() - { - setTimeout(callback, 0); - } - makeFetch(url, {method: method}).then(delayCallback); -} - -function makeRequests() -{ - var callback; - var promise = new Promise((fulfill) => callback = fulfill); - step1(); - return promise; - - function step1() - { - // Page that exists. - requestHelper("GET", "resources/xhr-exists.html", step2); - } - - function step2() - { - // Page that doesn't exist. - requestHelper("GET", "resources/xhr-does-not-exist.html", step3); - } - - function step3() - { - // POST to a page. - requestHelper("POST", "resources/post-target.cgi", step4); - } - - function step4() - { - // (Failed) cross-origin request - requestHelper("GET", "http://localhost:8000/devtools/resources/xhr-exists.html", callback); - } -} - -function test() { - step1(); - - function step1() { - Common.settingForTest('monitoringXHREnabled').set(true); - TestRunner.callFunctionInPageAsync('makeRequests').then(step2); - } - - function step2() { - Common.settingForTest('monitoringXHREnabled').set(false); - TestRunner.callFunctionInPageAsync('makeRequests').then(step3); - } - - function step3() { - function finish() { - ConsoleTestRunner.dumpConsoleMessages(); - TestRunner.completeTest(); - } - TestRunner.deprecatedRunAfterPendingDispatches(finish); - } -} -//# sourceURL=console-fetch-logging.html -</script> -</head> - -<body onload="runTest()"> -<p> -Tests that fetch logging works when XMLHttpRequest Logging is Enabled and doesn't show logs when it is Disabled. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console-fetch-logging.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console-fetch-logging.js new file mode 100644 index 0000000..775d2d1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console-fetch-logging.js
@@ -0,0 +1,75 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function() { + TestRunner.addResult( + `Tests that fetch logging works when XMLHttpRequest Logging is Enabled and doesn't show logs when it is Disabled.\n`); + await TestRunner.loadModule('console_test_runner'); + await TestRunner.loadModule('network_test_runner'); + await TestRunner.evaluateInPagePromise(` + function requestHelper(method, url, callback) + { + console.log("sending a " + method + " request to " + url); + // Delay invoking callback to let didFinishLoading() a chance to fire and log + // console message. + function delayCallback() + { + setTimeout(callback, 0); + } + makeFetch(url, {method: method}).then(delayCallback); + } + + function makeRequests() + { + var callback; + var promise = new Promise((fulfill) => callback = fulfill); + step1(); + return promise; + + function step1() + { + // Page that exists. + requestHelper("GET", "resources/xhr-exists.html", step2); + } + + function step2() + { + // Page that doesn't exist. + requestHelper("GET", "resources/xhr-does-not-exist.html", step3); + } + + function step3() + { + // POST to a page. + requestHelper("POST", "resources/post-target.cgi", step4); + } + + function step4() + { + // (Failed) cross-origin request + requestHelper("GET", "http://localhost:8000/devtools/resources/xhr-exists.html", callback); + } + } + `); + + step1(); + + function step1() { + Common.settingForTest('monitoringXHREnabled').set(true); + TestRunner.callFunctionInPageAsync('makeRequests').then(step2); + } + + function step2() { + Common.settingForTest('monitoringXHREnabled').set(false); + TestRunner.callFunctionInPageAsync('makeRequests').then(step3); + } + + function step3() { + function finish() { + ConsoleTestRunner.dumpConsoleMessages(); + TestRunner.completeTest(); + } + TestRunner.deprecatedRunAfterPendingDispatches(finish); + } +})();
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 6af6e45f..97aa84c8 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
@@ -1,21 +1,21 @@ -CONSOLE MESSAGE: line 9: Permission granted. -CONSOLE MESSAGE: line 44: Position unavailable -CONSOLE MESSAGE: line 37: Latitude: 50 Longitude: 100 -CONSOLE MESSAGE: line 37: Latitude: 50 Longitude: 100 -CONSOLE MESSAGE: line 55: PASSED Tests that geolocation emulation with latitude and longitude works as expected. Running: testPermissionGranted +geolocation-emulation-tests.js:14 Permission granted. Running: testGeolocationUnavailable +geolocation-emulation-tests.js:49 Position unavailable Running: testOverridenGeolocation +geolocation-emulation-tests.js:42 Latitude: 50 Longitude: 100 Running: testInvalidParam error: Protocol Error: Invalid type of argument 'latitude' for method 'Emulation.setGeolocationOverride' call. It must be 'number' but it is 'boolean'. Running: testInvalidGeolocation +geolocation-emulation-tests.js:42 Latitude: 50 Longitude: 100 Running: testTimestampOfOverridenPosition +geolocation-emulation-tests.js:60 PASSED
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests.html b/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests.html deleted file mode 100644 index 0eb60fd..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests.html +++ /dev/null
@@ -1,112 +0,0 @@ -<html> -<head> -<script src="../inspector/inspector-test.js"></script> -<script src="../resources/permissions-helper.js"></script> -<script> - -function grantGeolocationPermission() { - PermissionsHelper.setPermission('geolocation', 'granted').then(function(p) { - console.log("Permission granted."); - }); -} - -function serializeGeolocationError(error) { - var result = "Unknown error" - switch (error.code) - { - case error.PERMISSION_DENIED: - result = "Permission denied"; - break; - case error.POSITION_UNAVAILABLE: - result = "Position unavailable"; - break; - case error.TIMEOUT: - result = "Request timed out"; - break; - } - if (error.message) - result += " (" + error.message + ")"; - return result; -} - -function overrideGeolocation() -{ - function testSuccess(position) - { - if (position && position.coords) - console.log("Latitude: " + position.coords.latitude + " Longitude: " + position.coords.longitude); - else - console.log("Unexpected error occured. Test failed."); - } - - function testFailed(error) - { - console.log(serializeGeolocationError(error)); - } - - navigator.geolocation.getCurrentPosition(testSuccess, testFailed); -} - -function overridenTimestampGeolocation() -{ - function testSuccess(position) - { - if ((new Date(position.timestamp)).toDateString() == (new Date()).toDateString()) - console.log("PASSED"); - else - console.log("Unexpected error occured. Test failed."); - } - - function testFailed(error) - { - console.log(serializeGeolocationError(error)); - } - - navigator.geolocation.getCurrentPosition(testSuccess, testFailed); -} - -function test() { - TestRunner.runTestSuite([ - function testPermissionGranted(next) { - ConsoleTestRunner.addConsoleSniffer(next); - TestRunner.evaluateInPage('grantGeolocationPermission()'); - }, - - function testGeolocationUnavailable(next) { - TestRunner.EmulationAgent.setGeolocationOverride(); - ConsoleTestRunner.addConsoleSniffer(next); - TestRunner.evaluateInPage('overrideGeolocation()'); - }, - - function testOverridenGeolocation(next) { - TestRunner.EmulationAgent.setGeolocationOverride(50, 100, 95); - ConsoleTestRunner.addConsoleSniffer(next); - TestRunner.evaluateInPage('overrideGeolocation()'); - }, - - function testInvalidParam(next) { - TestRunner.EmulationAgent.setGeolocationOverride(true, 100, 95); - next(); - }, - - function testInvalidGeolocation(next) { - TestRunner.EmulationAgent.setGeolocationOverride(200, 300, 95); - ConsoleTestRunner.addConsoleSniffer(next); - TestRunner.evaluateInPage('overrideGeolocation()'); - }, - - function testTimestampOfOverridenPosition(next) { - TestRunner.EmulationAgent.setGeolocationOverride(50, 100, 95); - ConsoleTestRunner.addConsoleSniffer(next); - TestRunner.evaluateInPage('overridenTimestampGeolocation()'); - } - ]); -} -</script> -</head> -<body onload="runTest()"> -<p> -Tests that geolocation emulation with latitude and longitude works as expected. -</p> -</body> -</html>
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 new file mode 100644 index 0000000..5f40d37 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests.js
@@ -0,0 +1,117 @@ +// 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 that geolocation emulation with latitude and longitude works as expected.\n`); + + TestRunner.printDevToolsConsole(); + await TestRunner.loadModule('console_test_runner'); + await TestRunner.addScriptTag('../resources/permissions-helper.js'); + await TestRunner.evaluateInPagePromise(` + function grantGeolocationPermission() { + PermissionsHelper.setPermission('geolocation', 'granted').then(function(p) { + console.log("Permission granted."); + }); + } + + function serializeGeolocationError(error) { + var result = "Unknown error" + switch (error.code) + { + case error.PERMISSION_DENIED: + result = "Permission denied"; + break; + case error.POSITION_UNAVAILABLE: + result = "Position unavailable"; + break; + case error.TIMEOUT: + result = "Request timed out"; + break; + } + if (error.message) + result += " (" + error.message + ")"; + return result; + } + + function overrideGeolocation() + { + function testSuccess(position) + { + if (position && position.coords) + console.log("Latitude: " + position.coords.latitude + " Longitude: " + position.coords.longitude); + else + console.log("Unexpected error occured. Test failed."); + } + + function testFailed(error) + { + console.log(serializeGeolocationError(error)); + } + + navigator.geolocation.getCurrentPosition(testSuccess, testFailed); + } + + function overridenTimestampGeolocation() + { + function testSuccess(position) + { + if ((new Date(position.timestamp)).toDateString() == (new Date()).toDateString()) + console.log("PASSED"); + else + console.log("Unexpected error occured. Test failed."); + } + + function testFailed(error) + { + console.log(serializeGeolocationError(error)); + } + + navigator.geolocation.getCurrentPosition(testSuccess, testFailed); + } + `); + + function consoleSniffAndDump(next) { + ConsoleTestRunner.addConsoleSniffer(() => { + ConsoleTestRunner.dumpConsoleMessages(); + Console.ConsoleView.clearConsole(); + next(); + }); + } + + TestRunner.runTestSuite([ + function testPermissionGranted(next) { + consoleSniffAndDump(next); + TestRunner.evaluateInPage('grantGeolocationPermission()'); + }, + + function testGeolocationUnavailable(next) { + TestRunner.EmulationAgent.setGeolocationOverride(); + consoleSniffAndDump(next); + TestRunner.evaluateInPage('overrideGeolocation()'); + }, + + function testOverridenGeolocation(next) { + TestRunner.EmulationAgent.setGeolocationOverride(50, 100, 95); + consoleSniffAndDump(next); + TestRunner.evaluateInPage('overrideGeolocation()'); + }, + + function testInvalidParam(next) { + TestRunner.EmulationAgent.setGeolocationOverride(true, 100, 95); + next(); + }, + + function testInvalidGeolocation(next) { + TestRunner.EmulationAgent.setGeolocationOverride(200, 300, 95); + consoleSniffAndDump(next); + TestRunner.evaluateInPage('overrideGeolocation()'); + }, + + function testTimestampOfOverridenPosition(next) { + TestRunner.EmulationAgent.setGeolocationOverride(50, 100, 95); + consoleSniffAndDump(next); + TestRunner.evaluateInPage('overridenTimestampGeolocation()'); + }, + ]); +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resources/add-elements.js b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/add-elements.js new file mode 100644 index 0000000..da25be1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/add-elements.js
@@ -0,0 +1,17 @@ +function addElements() +{ + var button = document.createElement('button'); + button.id = 'test'; + button.addEventListener('click', handleClick, true); + document.body.appendChild(button); + + var bar = document.createElement('div'); + bar.id = 'barrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr'; + document.body.appendChild(bar); +} + +function handleClick(event) +{ + var handler = new ClickHandler(); + handler.handle(event); +}
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resources/compiled-2.js b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/compiled-2.js new file mode 100644 index 0000000..1e9c34e --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/compiled-2.js
@@ -0,0 +1,19 @@ +function addElements() { + var button = document.createElement('button'); + button.id = 'test'; + button.addEventListener('click', handleClick, true); + document.body.appendChild(button); + var bar = document.createElement('div'); + bar.id = 'barrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr'; + document.body.appendChild(bar); +} +function handleClick(event) { + var handler = new ClickHandler(); + handler.handle(event); +} +function ClickHandler() { +} +ClickHandler.prototype.handle = function (event) { + console.log('button clicked!'); +}; +//# sourceMappingURL=source-map-2.json \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resources/screen-orientation-resource.html b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/screen-orientation-resource.html new file mode 100644 index 0000000..5db6988 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/screen-orientation-resource.html
@@ -0,0 +1,28 @@ +<html> +<script> +if (window.testRunner) { + window.testRunner.disableMockScreenOrientation(); + window.testRunner.setDumpConsoleMessages(false); +} + +var windowOrientationChangeEvent = false; +var screenOrientationChangeEvent = false; + +window.addEventListener("orientationchange", function() { windowOrientationChangeEvent = true; maybeLog(); }); +screen.orientation.addEventListener("change", function() { screenOrientationChangeEvent = true; maybeLog(); }); + +function dump() +{ + return "angle: " + screen.orientation.angle + "; type: " + screen.orientation.type; +} + +function maybeLog() +{ + if (windowOrientationChangeEvent && screenOrientationChangeEvent) { + windowOrientationChangeEvent = false; + screenOrientationChangeEvent = false; + console.log(dump()); + } +} +</script> +</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resources/source-map-2.json b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/source-map-2.json new file mode 100644 index 0000000..9a18c75 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/source-map-2.json
@@ -0,0 +1 @@ +{"version":3,"file":"compiled-2.js","sourceRoot":"","sources":["add-elements.js","source2.js"],"names":[],"mappings":"AAAA;IAEI,IAAI,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC;IACnB,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;IACpD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAElC,IAAI,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACxC,GAAG,CAAC,EAAE,GAAG,ocAAoc,CAAC;IAC9c,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,qBAAqB,KAAK;IAEtB,IAAI,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;IACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AChBD;AAEA,CAAC;AAED,YAAY,CAAC,SAAS,CAAC,MAAM,GAAG,UAAS,KAAK;IAE1C,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AACnC,CAAC,CAAA"} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resources/workers-on-navigation-resource.html b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/workers-on-navigation-resource.html new file mode 100644 index 0000000..21bda6f --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/workers-on-navigation-resource.html
@@ -0,0 +1,7 @@ +<html> +<script> +function startWorker() { + window.worker = new Worker('worker.js'); +} +</script> +</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/screen-orientation-override-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/screen-orientation-override-expected.txt index ee35baa..56485c5 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/screen-orientation-override-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/screen-orientation-override-expected.txt
@@ -1,3 +1,5 @@ +Test screen orientation override. + Running: initial
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/screen-orientation-override.html b/third_party/WebKit/LayoutTests/http/tests/devtools/screen-orientation-override.js similarity index 71% rename from third_party/WebKit/LayoutTests/http/tests/devtools/screen-orientation-override.html rename to third_party/WebKit/LayoutTests/http/tests/devtools/screen-orientation-override.js index 0f038cd..0c7dff56 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/screen-orientation-override.html +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/screen-orientation-override.js
@@ -1,34 +1,15 @@ -<html> -<head> -<script src="../inspector/inspector-test.js"></script> -<script> +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -if (window.testRunner) { - window.testRunner.disableMockScreenOrientation(); - window.testRunner.setDumpConsoleMessages(false); -} +(async function() { + TestRunner.addResult(`Test screen orientation override.\n`); + await TestRunner.loadModule('console_test_runner'); -var windowOrientationChangeEvent = false; -var screenOrientationChangeEvent = false; + TestRunner.printDevToolsConsole(); -window.addEventListener("orientationchange", function() { windowOrientationChangeEvent = true; maybeLog(); }); -screen.orientation.addEventListener("change", function() { screenOrientationChangeEvent = true; maybeLog(); }); + await TestRunner.navigatePromise('resources/screen-orientation-resource.html'); -function dump() -{ - return "angle: " + screen.orientation.angle + "; type: " + screen.orientation.type; -} - -function maybeLog() -{ - if (windowOrientationChangeEvent && screenOrientationChangeEvent) { - windowOrientationChangeEvent = false; - screenOrientationChangeEvent = false; - console.log(dump()); - } -} - -function test() { Protocol.InspectorBackend.Options.suppressRequestErrors = false; function addDumpResult(next) { TestRunner.evaluateInPage('dump()', dumpCallback); @@ -120,11 +101,4 @@ } } ]); -} -</script> -</head> -<body onload="runTest()"> -<p> -</p> -</body> -</html> +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/resources/v8-cache-iframe.html b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/resources/v8-cache-iframe.html index e036a49..dc837b3 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/resources/v8-cache-iframe.html +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/resources/v8-cache-iframe.html
@@ -5,6 +5,7 @@ // This "done" function will be called from the script. done = resolve; let script = document.createElement("script"); + script.charset= 'UTF-8'; script.src = url; document.body.appendChild(script); });
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/resources/v8-cache-worker.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/resources/v8-cache-worker.js index 10bb8a1..8d41df9 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/resources/v8-cache-worker.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/resources/v8-cache-worker.js
@@ -1,13 +1,23 @@ const cacheName = 'c8-cache-test'; const scriptName = 'v8-cache-script.js'; +let continue_install; +let install_finished; +const install_finished_promise = new Promise((r) => { install_finished = r; }); + self.addEventListener('install', (event) => { event.waitUntil( - caches.open(cacheName) - .then((cache) => { - return cache.add(new Request(scriptName)); - }) - ); + new Promise((resolve) => { continue_install = resolve; }) + .then(() => caches.open(cacheName)) + .then((cache) => cache.add(new Request(scriptName))) + .then(() => { install_finished(); })); + }); + +self.addEventListener('message', (event) => { + continue_install(); + install_finished_promise.then(() => { + event.data.port.postMessage(''); + }); }); self.addEventListener('fetch', (event) => {
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-v8-cache-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-v8-cache-expected.txt index 32ae7b7..5f92430 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-v8-cache-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-v8-cache-expected.txt
@@ -1,5 +1,8 @@ Tests V8 cache information of Service Worker Cache Storage in timeline +--- Trace events while installing ------------- +----------------------------------------------- +--- Trace events while executing scripts ------ v8.compile Properties: { data : { @@ -31,4 +34,5 @@ type : "v8.compile" } Text details for v8.compile: v8-cache-script.js:1 +-----------------------------------------------
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 db34497..c5898d2 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
@@ -16,29 +16,44 @@ return iframeWindow.loadScript(url) .then(() => iframeWindow.loadScript(url)); } + function continueInstall() { + const scope = 'resources/v8-cache-iframe.html'; + let reg = registrations[scope]; + if (!reg) + return Promise.reject(new Error('No registration')); + if (!reg.installing) + return Promise.reject(new Error('No installing service worker')); + return new Promise(resolve => { + var channel = new MessageChannel(); + channel.port1.onmessage = () => { resolve(); }; + reg.installing.postMessage({port: channel.port2}, [channel.port2]); + }); + } `); const scriptURL = 'resources/v8-cache-worker.js'; const scope = 'resources/v8-cache-iframe.html'; const frameId = 'frame_id'; - ApplicationTestRunner.registerServiceWorker(scriptURL, scope) - .then(_ => ApplicationTestRunner.waitForActivated(scope)) - .then(() => { - return TestRunner.addIframe(scope, {id: frameId}); - }) - .then(() => { - // Need to suspend targets, because V8 doesn't produce the cache when - // the debugger is loaded. - return SDK.targetManager.suspendAllTargets(); - }) - .then(() => { - return new Promise((r) => { - PerformanceTestRunner.invokeAsyncWithTimeline('loadScript', r); - }); - }) - .then(() => { - PerformanceTestRunner.printTimelineRecordsWithDetails(TimelineModel.TimelineModel.RecordType.CompileScript); - TestRunner.completeTest(); - }); + await ApplicationTestRunner.registerServiceWorker(scriptURL, scope) + // Need to suspend targets, because V8 doesn't produce the cache when the + // debugger is loaded. + await SDK.targetManager.suspendAllTargets(); + await new Promise( + (r) => + PerformanceTestRunner.invokeAsyncWithTimeline('continueInstall', r)); + TestRunner.addResult('--- Trace events while installing -------------'); + PerformanceTestRunner.printTimelineRecordsWithDetails( + TimelineModel.TimelineModel.RecordType.CompileScript); + TestRunner.addResult('-----------------------------------------------'); + await ApplicationTestRunner.waitForActivated(scope); + await TestRunner.addIframe(scope, {id: frameId}); + await new Promise( + (r) => + PerformanceTestRunner.invokeAsyncWithTimeline('loadScript', r)); + TestRunner.addResult('--- Trace events while executing scripts ------'); + PerformanceTestRunner.printTimelineRecordsWithDetails( + TimelineModel.TimelineModel.RecordType.CompileScript); + TestRunner.addResult('-----------------------------------------------'); + TestRunner.completeTest(); })();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/stylesheet-source-mapping.html b/third_party/WebKit/LayoutTests/http/tests/devtools/stylesheet-source-mapping.js similarity index 78% rename from third_party/WebKit/LayoutTests/http/tests/devtools/stylesheet-source-mapping.html rename to third_party/WebKit/LayoutTests/http/tests/devtools/stylesheet-source-mapping.js index 3d594d9..765fdec7 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/stylesheet-source-mapping.html +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/stylesheet-source-mapping.js
@@ -1,19 +1,21 @@ -<html> -<head> -<script src="../inspector/inspector-test.js"></script> -<script src="../inspector/debugger-test.js"></script> +// 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. -<script> -function addStyleSheet() -{ - var style = document.createElement("link"); - style.setAttribute("rel", "stylesheet"); - style.setAttribute("type", "text/css"); - style.setAttribute("href", "http://127.0.0.1:8000/devtools/resources/example.css"); - document.head.appendChild(style); -} +(async function() { + TestRunner.addResult(`Tests SourceMap and StyleSheetMapping.\n`); + await TestRunner.loadModule('sources_test_runner'); + await TestRunner.evaluateInPagePromise(` + function addStyleSheet() + { + var style = document.createElement("link"); + style.setAttribute("rel", "stylesheet"); + style.setAttribute("type", "text/css"); + style.setAttribute("href", "http://127.0.0.1:8000/devtools/resources/example.css"); + document.head.appendChild(style); + } + `); -function test() { var contentReceived; var finalMappedLocation; var target = TestRunner.mainTarget; @@ -47,9 +49,8 @@ var uiLocation = Bindings.cssWorkspaceBinding.rawLocationToUILocation(new SDK.CSSLocation(header, line, column)); TestRunner.assertEquals( uiSourceCode, uiLocation.uiSourceCode, - `Incorrect uiSourceCode, expected ${ - uiSourceCode.url() - }, but got ${location.uiSourceCode ? location.uiSourceCode.url() : null}`); + `Incorrect uiSourceCode, expected ${uiSourceCode.url()}, but got ${ + location.uiSourceCode ? location.uiSourceCode.url() : null}`); var reverseRaw = Bindings.cssWorkspaceBinding.uiLocationToRawLocations(uiLocation)[0]; TestRunner.addResult( `${line}:${column} ${uiLocation.lineNumber}:${uiLocation.columnNumber}` + @@ -87,13 +88,4 @@ TestRunner.addResult('UILocation upon LiveLocation update: ' + finalMappedLocation); TestRunner.completeTest(); } -} - -</script> - -</head> - -<body onload="runTest()"> -<p>Tests SourceMap and StyleSheetMapping.</p> -</body> -</html> +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/network-preserve-selection-on-frame-receive.html b/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/network-preserve-selection-on-frame-receive.js similarity index 72% rename from third_party/WebKit/LayoutTests/http/tests/devtools/websocket/network-preserve-selection-on-frame-receive.html rename to third_party/WebKit/LayoutTests/http/tests/devtools/websocket/network-preserve-selection-on-frame-receive.js index 70657f9..847d121 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/network-preserve-selection-on-frame-receive.html +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/network-preserve-selection-on-frame-receive.js
@@ -1,9 +1,12 @@ -<html> -<head> -<script src="/inspector/inspector-test.js"></script> -<script src="/inspector/network-test.js"></script> -<script> -async function test() { +// 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 that WebSocket network requests do not loose focus on frame being received.\n`); + await TestRunner.loadModule('network_test_runner'); + await TestRunner.showPanel('network'); + NetworkTestRunner.recordNetwork(); const wsUrl = 'ws://localhost:8880/echo'; @@ -29,10 +32,4 @@ function logSelectedNode() { TestRunner.addResult('Selected Request: ' + (dataGrid.selectedNode && dataGrid.selectedNode.request().url()) || ''); } -} -</script> -</head> -<body onload="runTest()"> -<p>Tests that WebSocket network requests do not loose focus on frame being received.</p> -</body> -</html> +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/websocket-frame-error-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/websocket-frame-error-expected.txt index 667a1781..583d08bc 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/websocket-frame-error-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/websocket-frame-error-expected.txt
@@ -1,8 +1,3 @@ -CONSOLE ERROR: line 8: WebSocket connection to 'ws://localhost:8000/does_not_exist' failed: Error during WebSocket handshake: Unexpected response code: 404 -PASS successfullyParsed is true - -TEST COMPLETE -Closed. Tests that WebSocketFrames errors are visible to Web Inspector. 1-error: Error during WebSocket handshake: Unexpected response code: 404
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/websocket-frame-error.html b/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/websocket-frame-error.html deleted file mode 100644 index b0215dd..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/websocket-frame-error.html +++ /dev/null
@@ -1,37 +0,0 @@ -<html> -<head> -<script src="/inspector/inspector-test.js"></script> -<script src="/js-test-resources/js-test.js"></script> -<script> -var ws; -function sendMessages() { - ws = new WebSocket("ws://localhost:8000/does_not_exist"); - ws.onclose = function() - { - debug("Closed."); - }; -} - -function test() { - function onRequest(event) { - var request = event.data; - if (request.resourceType().name() === 'websocket') { - var websocketFrames = request.frames(); - for (var i = 0; i < websocketFrames.length; i++) { - var frame = websocketFrames[i]; - var result = String.sprintf('%d-%s: %s', (i + 1), frame.type, frame.text); - TestRunner.addResult(result); - if (frame.type == SDK.NetworkRequest.WebSocketFrameType.Error) - TestRunner.completeTest(); - } - } - } - TestRunner.networkManager.addEventListener(SDK.NetworkManager.Events.RequestUpdated, onRequest); - TestRunner.evaluateInPage('sendMessages()'); -} -</script> -</head> -<body onload="runTest()"> -<p>Tests that WebSocketFrames errors are visible to Web Inspector.</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/websocket-frame-error.js b/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/websocket-frame-error.js new file mode 100644 index 0000000..749745d --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/websocket/websocket-frame-error.js
@@ -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. + +(async function() { + TestRunner.addResult(`Tests that WebSocketFrames errors are visible to Web Inspector.\n`); + await TestRunner.evaluateInPagePromise(` + var ws; + function sendMessages() { + ws = new WebSocket("ws://localhost:8000/does_not_exist"); + ws.onclose = function() + { + debug("Closed."); + }; + } + `); + + function onRequest(event) { + var request = event.data; + if (request.resourceType().name() === 'websocket') { + var websocketFrames = request.frames(); + for (var i = 0; i < websocketFrames.length; i++) { + var frame = websocketFrames[i]; + var result = String.sprintf('%d-%s: %s', (i + 1), frame.type, frame.text); + TestRunner.addResult(result); + if (frame.type == SDK.NetworkRequest.WebSocketFrameType.Error) + TestRunner.completeTest(); + } + } + } + TestRunner.networkManager.addEventListener(SDK.NetworkManager.Events.RequestUpdated, onRequest); + TestRunner.evaluateInPage('sendMessages()'); +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/workers-on-navigation-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/workers-on-navigation-expected.txt index fc0a321..fd2b6f9 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/workers-on-navigation-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/workers-on-navigation-expected.txt
@@ -2,7 +2,7 @@ Worker added Worker removed -error: Connection is closed, can't dispatch pending Debugger.setBlackboxPatterns Page reloaded. +error: Connection is closed, can't dispatch pending Debugger.setBlackboxPatterns Worker added
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/workers-on-navigation.html b/third_party/WebKit/LayoutTests/http/tests/devtools/workers-on-navigation.js similarity index 64% rename from third_party/WebKit/LayoutTests/http/tests/devtools/workers-on-navigation.html rename to third_party/WebKit/LayoutTests/http/tests/devtools/workers-on-navigation.js index 4582799..92a2ffe 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/workers-on-navigation.html +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/workers-on-navigation.js
@@ -1,13 +1,11 @@ -<html> -<head> -<script src='../inspector/inspector-test.js'></script> -<script> +// 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. -function startWorker() { - window.worker = new Worker('resources/worker.js'); -} +(async function() { + TestRunner.addResult(`Tests that workers are correctly detached upon navigation.\n`); + TestRunner.printDevToolsConsole(); -async function test() { var workerTargetId; var navigated = false; var observer = { @@ -30,17 +28,11 @@ } } }; + await TestRunner.navigatePromise('resources/workers-on-navigation-resource.html'); SDK.targetManager.observeTargets(observer); await TestRunner.evaluateInPagePromise('startWorker()'); - await TestRunner.navigatePromise('http://localhost:8080/devtools/workers-on-navigation.html'); + await TestRunner.reloadPagePromise(); navigated = true; await TestRunner.evaluateInPagePromise('startWorker()'); -} - -</script> -</head> -<body onload='runTest()'> -<p>Tests that workers are correctly detached upon navigation.</p> -</body> -</html> +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp.html b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp-part1.html similarity index 69% rename from third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp.html rename to third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp-part1.html index fd082e4e..0ad22d6 100644 --- a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp.html +++ b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp-part1.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Upload files in ISO-2022-JP form</title> +<title>Upload files in ISO-2022-JP form (part 1)</title> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"> <link rel="author" title="Benjamin C. Wiley Sittler" @@ -50,27 +50,4 @@ 'file-for-drag-to-send3-☺😂.txt'), }); -formPostFileUploadTest({ - fileNameSource: 'JIS X 0201 and JIS X 0208', - fileBaseName: 'file-for-drag-to-send3-★星★.txt', - formEncoding: 'ISO-2022-JP', - expectedEncodedBaseName: 'file-for-drag-to-send3-\x1B$B!z@1!z\x1B(B.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'Unicode', - fileBaseName: 'file-for-drag-to-send3-☺😂.txt', - formEncoding: 'ISO-2022-JP', - expectedEncodedBaseName: 'file-for-drag-to-send3-☺😂.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'Unicode', - fileBaseName: `file-for-drag-to-send3-${kTestChars}.txt`, - formEncoding: 'ISO-2022-JP', - expectedEncodedBaseName: `file-for-drag-to-send3-${ - kTestFallbackIso2022jp - }.txt`, -}); - </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp.html b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp-part2.html similarity index 68% copy from third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp.html copy to third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp-part2.html index fd082e4e..206053e 100644 --- a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp.html +++ b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-iso-2022-jp-part2.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Upload files in ISO-2022-JP form</title> +<title>Upload files in ISO-2022-JP form (part 2)</title> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"> <link rel="author" title="Benjamin C. Wiley Sittler" @@ -28,29 +28,6 @@ 'use strict'; formPostFileUploadTest({ - fileNameSource: 'ASCII', - fileBaseName: 'file-for-drag-to-send3.txt', - formEncoding: 'ISO-2022-JP', - expectedEncodedBaseName: 'file-for-drag-to-send3.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'x-user-defined', - fileBaseName: 'file-for-drag-to-send3-\uF7F0\uF793\uF783\uF7A0.txt', - formEncoding: 'ISO-2022-JP', - expectedEncodedBaseName: ( - 'file-for-drag-to-send3-.txt'), -}); - -formPostFileUploadTest({ - fileNameSource: 'windows-1252', - fileBaseName: 'file-for-drag-to-send3-☺😂.txt', - formEncoding: 'ISO-2022-JP', - expectedEncodedBaseName: ( - 'file-for-drag-to-send3-☺😂.txt'), -}); - -formPostFileUploadTest({ fileNameSource: 'JIS X 0201 and JIS X 0208', fileBaseName: 'file-for-drag-to-send3-★星★.txt', formEncoding: 'ISO-2022-JP',
diff --git a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8.html b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8-part1.html similarity index 70% rename from third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8.html rename to third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8-part1.html index d86dd91..78926c0 100644 --- a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8.html +++ b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8-part1.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Upload files in UTF-8 form</title> +<title>Upload files in UTF-8 form (part 1)</title> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"> <link rel="author" title="Benjamin C. Wiley Sittler" @@ -49,25 +49,4 @@ expectedEncodedBaseName: 'file-for-drag-to-send3-☺😂.txt', }); -formPostFileUploadTest({ - fileNameSource: 'JIS X 0201 and JIS X 0208', - fileBaseName: 'file-for-drag-to-send3-★星★.txt', - formEncoding: 'UTF-8', - expectedEncodedBaseName: 'file-for-drag-to-send3-★星★.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'Unicode', - fileBaseName: 'file-for-drag-to-send3-☺😂.txt', - formEncoding: 'UTF-8', - expectedEncodedBaseName: 'file-for-drag-to-send3-☺😂.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'Unicode', - fileBaseName: `file-for-drag-to-send3-${kTestChars}.txt`, - formEncoding: 'UTF-8', - expectedEncodedBaseName: `file-for-drag-to-send3-${kTestChars}.txt`, -}); - </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8.html b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8-part2.html similarity index 69% copy from third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8.html copy to third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8-part2.html index d86dd91..6da4d9c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8.html +++ b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-utf-8-part2.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Upload files in UTF-8 form</title> +<title>Upload files in UTF-8 form (part 2)</title> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"> <link rel="author" title="Benjamin C. Wiley Sittler" @@ -28,28 +28,6 @@ 'use strict'; formPostFileUploadTest({ - fileNameSource: 'ASCII', - fileBaseName: 'file-for-drag-to-send3.txt', - formEncoding: 'UTF-8', - expectedEncodedBaseName: 'file-for-drag-to-send3.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'x-user-defined', - fileBaseName: 'file-for-drag-to-send3-\uF7F0\uF793\uF783\uF7A0.txt', - formEncoding: 'UTF-8', - expectedEncodedBaseName: ( - 'file-for-drag-to-send3-\uF7F0\uF793\uF783\uF7A0.txt'), -}); - -formPostFileUploadTest({ - fileNameSource: 'windows-1252', - fileBaseName: 'file-for-drag-to-send3-☺😂.txt', - formEncoding: 'UTF-8', - expectedEncodedBaseName: 'file-for-drag-to-send3-☺😂.txt', -}); - -formPostFileUploadTest({ fileNameSource: 'JIS X 0201 and JIS X 0208', fileBaseName: 'file-for-drag-to-send3-★星★.txt', formEncoding: 'UTF-8',
diff --git a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252.html b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252-part1.html similarity index 68% copy from third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252.html copy to third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252-part1.html index 8fdf4e19..94e7f4d 100644 --- a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252.html +++ b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252-part1.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Upload files in Windows-1252 form</title> +<title>Upload files in Windows-1252 form (part 1)</title> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"> <link rel="author" title="Benjamin C. Wiley Sittler" @@ -49,27 +49,4 @@ expectedEncodedBaseName: 'file-for-drag-to-send3-☺😂.txt', }); -formPostFileUploadTest({ - fileNameSource: 'JIS X 0201 and JIS X 0208', - fileBaseName: 'file-for-drag-to-send3-★星★.txt', - formEncoding: 'windows-1252', - expectedEncodedBaseName: 'file-for-drag-to-send3-★星★.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'Unicode', - fileBaseName: 'file-for-drag-to-send3-☺😂.txt', - formEncoding: 'windows-1252', - expectedEncodedBaseName: 'file-for-drag-to-send3-☺😂.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'Unicode', - fileBaseName: `file-for-drag-to-send3-${kTestChars}.txt`, - formEncoding: 'windows-1252', - expectedEncodedBaseName: `file-for-drag-to-send3-${ - kTestFallbackWindows1252 - }.txt`, -}); - </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252.html b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252-part2.html similarity index 69% rename from third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252.html rename to third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252-part2.html index 8fdf4e19..c6ca25d 100644 --- a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252.html +++ b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-windows-1252-part2.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Upload files in Windows-1252 form</title> +<title>Upload files in Windows-1252 form (part 2)</title> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"> <link rel="author" title="Benjamin C. Wiley Sittler" @@ -28,28 +28,6 @@ 'use strict'; formPostFileUploadTest({ - fileNameSource: 'ASCII', - fileBaseName: 'file-for-drag-to-send3.txt', - formEncoding: 'windows-1252', - expectedEncodedBaseName: 'file-for-drag-to-send3.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'x-user-defined', - fileBaseName: 'file-for-drag-to-send3-\uF7F0\uF793\uF783\uF7A0.txt', - formEncoding: 'windows-1252', - expectedEncodedBaseName: ( - 'file-for-drag-to-send3-.txt'), -}); - -formPostFileUploadTest({ - fileNameSource: 'windows-1252', - fileBaseName: 'file-for-drag-to-send3-☺😂.txt', - formEncoding: 'windows-1252', - expectedEncodedBaseName: 'file-for-drag-to-send3-☺😂.txt', -}); - -formPostFileUploadTest({ fileNameSource: 'JIS X 0201 and JIS X 0208', fileBaseName: 'file-for-drag-to-send3-★星★.txt', formEncoding: 'windows-1252',
diff --git a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined.html b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined-part1.html similarity index 68% rename from third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined.html rename to third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined-part1.html index 68e217b..edc24cd9 100644 --- a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined.html +++ b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined-part1.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Upload files in x-user-defined form</title> +<title>Upload files in x-user-defined form (part 1)</title> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"> <link rel="author" title="Benjamin C. Wiley Sittler" @@ -49,27 +49,4 @@ '☺😂.txt'), }); -formPostFileUploadTest({ - fileNameSource: 'JIS X 0201 and JIS X 0208', - fileBaseName: 'file-for-drag-to-send3-★星★.txt', - formEncoding: 'x-user-defined', - expectedEncodedBaseName: 'file-for-drag-to-send3-★星★.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'Unicode', - fileBaseName: 'file-for-drag-to-send3-☺😂.txt', - formEncoding: 'x-user-defined', - expectedEncodedBaseName: 'file-for-drag-to-send3-☺😂.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'Unicode', - fileBaseName: `file-for-drag-to-send3-${kTestChars}.txt`, - formEncoding: 'x-user-defined', - expectedEncodedBaseName: `file-for-drag-to-send3-${ - kTestFallbackXUserDefined - }.txt`, -}); - </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined.html b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined-part2.html similarity index 68% copy from third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined.html copy to third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined-part2.html index 68e217b..ed1b6a66 100644 --- a/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined.html +++ b/third_party/WebKit/LayoutTests/http/tests/fileapi/send-dragged-file-form-x-user-defined-part2.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Upload files in x-user-defined form</title> +<title>Upload files in x-user-defined form (part 2)</title> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"> <link rel="author" title="Benjamin C. Wiley Sittler" @@ -28,28 +28,6 @@ 'use strict'; formPostFileUploadTest({ - fileNameSource: 'ASCII', - fileBaseName: 'file-for-drag-to-send3.txt', - formEncoding: 'x-user-defined', - expectedEncodedBaseName: 'file-for-drag-to-send3.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'x-user-defined', - fileBaseName: 'file-for-drag-to-send3-\uF7F0\uF793\uF783\uF7A0.txt', - formEncoding: 'x-user-defined', - expectedEncodedBaseName: 'file-for-drag-to-send3-𓃠.txt', -}); - -formPostFileUploadTest({ - fileNameSource: 'windows-1252', - fileBaseName: 'file-for-drag-to-send3-☺😂.txt', - formEncoding: 'x-user-defined', - expectedEncodedBaseName: ('file-for-drag-to-send3-' + - '☺😂.txt'), -}); - -formPostFileUploadTest({ fileNameSource: 'JIS X 0201 and JIS X 0208', fileBaseName: 'file-for-drag-to-send3-★星★.txt', formEncoding: 'x-user-defined',
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/redirect-302-with-post-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/redirect-302-with-post-expected.txt new file mode 100644 index 0000000..3162f6b6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/redirect-302-with-post-expected.txt
@@ -0,0 +1,6 @@ +Test to ensure devtools gets post data for redirected navigation requests. + +Got request: http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?status=302 +Post Data: foo=bar +Got request: http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true +
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/redirect-302-with-post.js b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/redirect-302-with-post.js new file mode 100644 index 0000000..cd0eddf --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/redirect-302-with-post.js
@@ -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. + +(async function(testRunner) { + var {page, session, dp} = await testRunner.startBlank(`Test to ensure devtools gets post data for redirected navigation requests.\n`); + + dp.Network.enable(); + dp.Page.enable(); + + dp.Runtime.evaluate({expression: ` + document.body.innerHTML = '<form id="form" method="post" action="/loading/resources/redirect-methods-result.php?status=302"><input type="text" name="foo" value="bar" /></form>'; + var form = document.getElementById('form'); + form.submit(); + `}); + + dp.Network.onRequestWillBeSent(event => { + testRunner.log("Got request: " + event.params.request.url); + if (event.params.request.postData) + testRunner.log("Post Data: " + event.params.request.postData); + }); + dp.Page.onLoadEventFired(() => testRunner.completeTest()); +}); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/workers/resources/shared-worker-usecounter-window.html b/third_party/WebKit/LayoutTests/http/tests/workers/resources/shared-worker-usecounter-window.html similarity index 100% rename from third_party/WebKit/LayoutTests/fast/workers/resources/shared-worker-usecounter-window.html rename to third_party/WebKit/LayoutTests/http/tests/workers/resources/shared-worker-usecounter-window.html
diff --git a/third_party/WebKit/LayoutTests/fast/workers/resources/shared-worker-usecounter.js b/third_party/WebKit/LayoutTests/http/tests/workers/resources/shared-worker-usecounter.js similarity index 100% rename from third_party/WebKit/LayoutTests/fast/workers/resources/shared-worker-usecounter.js rename to third_party/WebKit/LayoutTests/http/tests/workers/resources/shared-worker-usecounter.js
diff --git a/third_party/WebKit/LayoutTests/fast/workers/shared-worker-usecounter.html b/third_party/WebKit/LayoutTests/http/tests/workers/shared-worker-usecounter.html similarity index 100% rename from third_party/WebKit/LayoutTests/fast/workers/shared-worker-usecounter.html rename to third_party/WebKit/LayoutTests/http/tests/workers/shared-worker-usecounter.html
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/import-on-insecure-context.html b/third_party/WebKit/LayoutTests/http/tests/worklet/import-on-insecure-context.html index 12ac80c..1af15a59 100644 --- a/third_party/WebKit/LayoutTests/http/tests/worklet/import-on-insecure-context.html +++ b/third_party/WebKit/LayoutTests/http/tests/worklet/import-on-insecure-context.html
@@ -13,17 +13,13 @@ if (window.location.origin != get_host_info().UNAUTHENTICATED_ORIGIN) { test(t => { assert_not_equals(undefined, CSS.paintWorklet); - assert_not_equals(undefined, window.animationWorklet); - assert_not_equals(undefined, window.audioWorklet); - }, 'Worklets should be available on a secure context.'); + }, 'CSS.paintWorklet should be available on a secure context.'); window.location = get_host_info().UNAUTHENTICATED_ORIGIN + window.location.pathname; } else { test(t => { assert_equals(undefined, CSS.paintWorklet); - assert_equals(undefined, window.animationWorklet); - assert_equals(undefined, window.audioWorklet); - }, 'Worklets should not be available on an insecure context.'); + }, 'CSS.paintWorklet should not be available on an insecure context.'); } </script>
diff --git a/third_party/WebKit/LayoutTests/virtual/pwa-full-code-cache/http/tests/devtools/service-workers/README.txt b/third_party/WebKit/LayoutTests/virtual/pwa-full-code-cache/http/tests/devtools/service-workers/README.txt new file mode 100644 index 0000000..d202a0c --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/pwa-full-code-cache/http/tests/devtools/service-workers/README.txt
@@ -0,0 +1 @@ +This directory is for testing the full code cache install (Tracking bug: https://crbug.com/768705).
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 new file mode 100644 index 0000000..75cad7f --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/pwa-full-code-cache/http/tests/devtools/service-workers/service-worker-v8-cache-expected.txt
@@ -0,0 +1,54 @@ +Tests V8 cache information of Service Worker Cache Storage in timeline + +--- Trace events while installing ------------- +v8.compile Properties: +{ + data : { + cacheProduceOptions : "full code" + columnNumber : 0 + lineNumber : 0 + producedCacheSize : <number> + streamed : <boolean> + url : .../devtools/service-workers/resources/v8-cache-script.js + } + endTime : <number> + startTime : <number> + type : "v8.compile" +} +Text details for v8.compile: :8000/devtools/service-workers/resources/v8-cache-script.js:1 +----------------------------------------------- +--- Trace events while executing scripts ------ +v8.compile Properties: +{ + data : { + cacheConsumeOptions : "code" + cacheRejected : false + columnNumber : 0 + consumedCacheSize : <number> + lineNumber : 0 + streamed : <boolean> + url : .../devtools/service-workers/resources/v8-cache-script.js + } + endTime : <number> + startTime : <number> + type : "v8.compile" +} +Text details for v8.compile: v8-cache-script.js:1 +v8.compile Properties: +{ + data : { + cacheConsumeOptions : "code" + cacheRejected : false + columnNumber : 0 + consumedCacheSize : <number> + lineNumber : 0 + streamed : <boolean> + url : .../devtools/service-workers/resources/v8-cache-script.js + } + endTime : <number> + startTime : <number> + type : "v8.compile" +} +Text details for v8.compile: v8-cache-script.js:1 +----------------------------------------------- +
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/compositing/squashing/add-remove-squashed-layers-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/compositing/squashing/add-remove-squashed-layers-expected.txt index a7cb3c6..b0b7b3c 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/compositing/squashing/add-remove-squashed-layers-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/compositing/squashing/add-remove-squashed-layers-expected.txt
@@ -163,11 +163,6 @@ "bounds": [100, 100], "paintInvalidations": [ { - "object": "LayoutBlockFlow (positioned) DIV id='C' class='overlap3'", - "rect": [160, 160, 100, 100], - "reason": "paint property change" - }, - { "object": "LayoutBlockFlow (positioned) DIV id='A' class='overlap1'", "rect": [0, 0, 100, 100], "reason": "disappeared"
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/caret-ancestor-clip-change-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/caret-ancestor-clip-change-expected.txt index 63d4e025..0cd7ba0 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/caret-ancestor-clip-change-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/caret-ancestor-clip-change-expected.txt
@@ -8,33 +8,18 @@ "paintInvalidations": [ { "object": "LayoutBlockFlow DIV", - "rect": [8, 8, 105, 112], - "reason": "paint property change" + "rect": [8, 58, 105, 62], + "reason": "incremental" }, { "object": "LayoutTextControl INPUT id='target'", - "rect": [8, 8, 105, 112], - "reason": "paint property change" + "rect": [8, 58, 105, 62], + "reason": "incremental" }, { "object": "LayoutBlockFlow DIV", - "rect": [8, 8, 105, 50], - "reason": "paint property change" - }, - { - "object": "LayoutTextControl INPUT id='target'", - "rect": [8, 8, 105, 50], - "reason": "paint property change" - }, - { - "object": "LayoutBlockFlow DIV", - "rect": [10, 8, 1, 107], - "reason": "paint property change" - }, - { - "object": "LayoutBlockFlow DIV", - "rect": [10, 8, 1, 50], - "reason": "paint property change" + "rect": [10, 58, 1, 57], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/clip-unclip-and-change-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/clip-unclip-and-change-expected.txt index 33ee696..55b0fd5 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/clip-unclip-and-change-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/clip-unclip-and-change-expected.txt
@@ -7,14 +7,9 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "LayoutBlockFlow DIV", + "object": "LayoutBlockFlow DIV id='content'", "rect": [8, 120, 100, 300], - "reason": "paint property change" - }, - { - "object": "LayoutBlockFlow DIV", - "rect": [8, 120, 100, 100], - "reason": "paint property change" + "reason": "style change" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/css-clip-change-stacking-child-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/css-clip-change-stacking-child-expected.txt index 943f859a..f768584d 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/css-clip-change-stacking-child-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/clip/css-clip-change-stacking-child-expected.txt
@@ -8,13 +8,13 @@ "paintInvalidations": [ { "object": "LayoutBlockFlow DIV", - "rect": [8, 8, 300, 300], - "reason": "paint property change" + "rect": [8, 8, 300, 200], + "reason": "subtree" }, { "object": "LayoutBlockFlow DIV", - "rect": [8, 8, 300, 200], - "reason": "paint property change" + "rect": [8, 208, 300, 100], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.txt index 7982783..1e1e7982 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.txt
@@ -23,9 +23,14 @@ "bounds": [300, 654], "paintInvalidations": [ { - "object": "LayoutBlockFlow HTML", + "object": "InlineTextBox 'test1'", "rect": [8, 508, 29, 19], - "reason": "paint property change" + "reason": "appeared" + }, + { + "object": "InlineTextBox 'test1'", + "rect": [8, 508, 29, 19], + "reason": "disappeared" }, { "object": "LayoutView #document",
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/overflow/repaint-resized-overflow-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/overflow/repaint-resized-overflow-expected.txt index c4d48f8..4bf7fa78 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/overflow/repaint-resized-overflow-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/overflow/repaint-resized-overflow-expected.txt
@@ -7,14 +7,14 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "LayoutBlockFlow DIV", + "object": "LayoutBlockFlow DIV id='s'", "rect": [8, 156, 108, 108], - "reason": "paint property change" + "reason": "geometry" }, { "object": "LayoutBlockFlow DIV", - "rect": [8, 156, 108, 56], - "reason": "paint property change" + "rect": [8, 212, 108, 52], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned-expected.txt index 9a847fc..13bbc22 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned-expected.txt
@@ -7,14 +7,24 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "LayoutBlockFlow DIV", + "object": "InlineTextBox 'x'", "rect": [8, 220, 100, 100], - "reason": "paint property change" + "reason": "geometry" + }, + { + "object": "InlineTextBox 'x'", + "rect": [8, 220, 100, 80], + "reason": "geometry" }, { "object": "LayoutBlockFlow DIV", - "rect": [8, 200, 100, 100], - "reason": "paint property change" + "rect": [8, 300, 100, 20], + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow DIV", + "rect": [8, 200, 100, 20], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt index 57e2d96..f1ff7826 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt
@@ -9,7 +9,7 @@ { "object": "LayoutBlockFlow (positioned) DIV class='absolute green reflected'", "rect": [250, 280, 100, 100], - "reason": "paint property change" + "reason": "chunk reordered" }, { "object": "LayoutBlockFlow (positioned) DIV id='hideMe' class='absolute red'",
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/resize-iframe-text-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/resize-iframe-text-expected.txt index 55c04fe0..21efa45 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/resize-iframe-text-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/resize-iframe-text-expected.txt
@@ -14,7 +14,7 @@ { "object": "LayoutBlockFlow HTML", "rect": [8, 300, 60, 22], - "reason": "paint property change" + "reason": "incremental" }, { "object": "LayoutView #document",
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt index d1b7bb2..89cb51d 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt
@@ -8,23 +8,13 @@ "paintInvalidations": [ { "object": "LayoutBlockFlow DIV id='target'", - "rect": [8, 8, 100, 200], - "reason": "paint property change" + "rect": [8, 108, 100, 100], + "reason": "incremental" }, { "object": "LayoutBlockFlow DIV id='target'", - "rect": [8, 8, 100, 200], - "reason": "paint property change" - }, - { - "object": "LayoutBlockFlow DIV id='target'", - "rect": [8, 8, 100, 100], - "reason": "paint property change" - }, - { - "object": "LayoutBlockFlow DIV id='target'", - "rect": [8, 8, 100, 100], - "reason": "paint property change" + "rect": [8, 108, 100, 100], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-content-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-content-expected.txt index baba78b..e3d5ae7 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-content-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-content-expected.txt
@@ -12,14 +12,14 @@ "reason": "geometry" }, { - "object": "LayoutSVGRoot svg", + "object": "LayoutSVGRect rect id='targetRect'", "rect": [9, 73, 400, 400], - "reason": "paint property change" + "reason": "geometry" }, { "object": "LayoutSVGRoot svg", - "rect": [9, 73, 100, 400], - "reason": "paint property change" + "rect": [109, 73, 300, 400], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-content-with-resources-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-content-with-resources-expected.txt index 5e7a0f8..a86731b 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-content-with-resources-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-content-with-resources-expected.txt
@@ -12,14 +12,34 @@ "reason": "geometry" }, { - "object": "LayoutSVGRoot svg", + "object": "LayoutSVGEllipse circle", "rect": [47, 111, 324, 324], - "reason": "paint property change" + "reason": "SVG resource change" }, { "object": "LayoutSVGRoot svg", - "rect": [8, 154, 102, 238], - "reason": "paint property change" + "rect": [47, 392, 324, 43], + "reason": "incremental" + }, + { + "object": "LayoutSVGRoot svg", + "rect": [47, 111, 324, 43], + "reason": "incremental" + }, + { + "object": "LayoutSVGRoot svg", + "rect": [110, 154, 261, 238], + "reason": "incremental" + }, + { + "object": "LayoutSVGEllipse circle", + "rect": [8, 154, 170, 238], + "reason": "SVG resource change" + }, + { + "object": "LayoutSVGRoot svg", + "rect": [8, 154, 39, 238], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-image-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-image-expected.txt index b83de76..5a40c5d4 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-image-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-image-expected.txt
@@ -12,14 +12,14 @@ "reason": "geometry" }, { - "object": "LayoutSVGRoot svg", + "object": "LayoutSVGImage image", "rect": [9, 73, 400, 400], - "reason": "paint property change" + "reason": "image" }, { "object": "LayoutSVGRoot svg", - "rect": [9, 73, 100, 400], - "reason": "paint property change" + "rect": [109, 73, 300, 400], + "reason": "incremental" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-shadow-tree-content-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-shadow-tree-content-expected.txt index cb0be6f8..c45a8929 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-shadow-tree-content-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/relative-sized-shadow-tree-content-expected.txt
@@ -19,17 +19,17 @@ { "object": "LayoutSVGRect rect id='targetRect1'", "rect": [9, 73, 200, 200], - "reason": "paint property change" + "reason": "geometry" + }, + { + "object": "LayoutSVGRect rect id='targetRect1'", + "rect": [59, 73, 150, 200], + "reason": "incremental" }, { "object": "LayoutSVGContainer use", "rect": [59, 273, 50, 200], "reason": "paint property change" - }, - { - "object": "LayoutSVGRect rect id='targetRect1'", - "rect": [9, 73, 50, 200], - "reason": "paint property change" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt index 6020b50..3e43b5e2 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
@@ -15,8 +15,18 @@ "paintInvalidations": [ { "object": "LayoutBlockFlow (positioned) DIV id='target'", + "rect": [0, 0, 402, 542], + "reason": "paint property change" + }, + { + "object": "LayoutBlockFlow (positioned) DIV id='target'", "rect": [0, 0, 200, 200], "reason": "full" + }, + { + "object": "LayoutBlockFlow (positioned) DIV id='target'", + "rect": [0, 0, 200, 200], + "reason": "paint property change" } ] },
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/video-mute-repaint-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/video-mute-repaint-expected.txt index 77fd793d..b0d0c1d 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/video-mute-repaint-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/video-mute-repaint-expected.txt
@@ -27,16 +27,6 @@ "bounds": [700, 525], "paintInvalidations": [ { - "object": "LayoutFlexibleBox (relative positioned) DIV", - "rect": [0, 493, 700, 32], - "reason": "paint property change" - }, - { - "object": "LayoutBlockFlow (positioned) DIV", - "rect": [108, 508, 404, 2], - "reason": "paint property change" - }, - { "object": "LayoutBlockFlow (positioned) DIV", "rect": [580, 508, 70, 2], "reason": "disappeared" @@ -44,17 +34,17 @@ { "object": "LayoutBlockFlow (positioned) DIV id='thumb'", "rect": [632, 493, 36, 32], - "reason": "paint property change" + "reason": "full" }, { "object": "LayoutBlockFlow (positioned) DIV id='thumb'", "rect": [562, 493, 36, 32], - "reason": "paint property change" + "reason": "full" }, { - "object": "LayoutBlockFlow (positioned) DIV id='thumb'", - "rect": [90, 493, 36, 32], - "reason": "paint property change" + "object": "LayoutButton INPUT class='muted'", + "rect": [530, 493, 32, 32], + "reason": "full" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/video-unmute-repaint-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/video-unmute-repaint-expected.txt index 6ce2aeaf..01971da1 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/video-unmute-repaint-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/video-unmute-repaint-expected.txt
@@ -27,34 +27,24 @@ "bounds": [700, 525], "paintInvalidations": [ { - "object": "LayoutFlexibleBox (relative positioned) DIV", - "rect": [0, 493, 700, 32], - "reason": "paint property change" - }, - { - "object": "LayoutBlockFlow (positioned) DIV", - "rect": [108, 508, 404, 2], - "reason": "paint property change" - }, - { "object": "LayoutBlockFlow (positioned) DIV id='thumb'", "rect": [597, 493, 36, 32], - "reason": "paint property change" + "reason": "full" }, { "object": "LayoutBlockFlow (positioned) DIV id='thumb'", "rect": [562, 493, 36, 32], - "reason": "paint property change" - }, - { - "object": "LayoutBlockFlow (positioned) DIV id='thumb'", - "rect": [90, 493, 36, 32], - "reason": "paint property change" + "reason": "full" }, { "object": "LayoutBlockFlow (positioned) DIV", "rect": [580, 508, 35, 2], "reason": "appeared" + }, + { + "object": "LayoutButton INPUT", + "rect": [530, 493, 32, 32], + "reason": "full" } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt index d7cad31..06527e53 100644 --- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
@@ -23,12 +23,12 @@ }, { "object": "LayoutView #document", - "rect": [0, 0, 600, 500], + "rect": [0, 0, 600, 235], "reason": "paint property change" }, { "object": "LayoutBlockFlow HTML", - "rect": [168, 8, 423, 482], + "rect": [168, 8, 423, 227], "reason": "paint property change" } ], @@ -257,17 +257,17 @@ }, { "object": "LayoutView #document", - "rect": [0, 0, 939, 235], - "reason": "paint property change" - }, - { - "object": "LayoutBlockFlow HTML", - "rect": [10, 7, 920, 213], + "rect": [0, 0, 400, 600], "reason": "paint property change" }, { "object": "LayoutView #document", - "rect": [0, 0, 400, 600], + "rect": [0, 0, 400, 235], + "reason": "paint property change" + }, + { + "object": "LayoutBlockFlow HTML", + "rect": [10, 7, 390, 213], "reason": "paint property change" }, {
diff --git a/third_party/WebKit/PerformanceTests/DOM/select-long-word.html b/third_party/WebKit/PerformanceTests/DOM/select-long-word.html deleted file mode 100644 index e0fec980..0000000 --- a/third_party/WebKit/PerformanceTests/DOM/select-long-word.html +++ /dev/null
@@ -1,33 +0,0 @@ -<!DOCTYPE html> - -<style> -div { - width: 800px; - word-wrap: break-word; -} -</style> - -<script src="../resources/runner.js"></script> - -<div id="long"> -</div> - -<script> -var longDiv = document.getElementById('long'); -var sel = window.getSelection(); -var text = 'GrumpywizardsmaketoxicbrewfortheevilQueenandJack'; -for (i = 0; i < 12; i++) - text = text + text; -longDiv.appendChild(document.createTextNode(text)); - -PerfTestRunner.measureTime({ - description: "Measures performance of detecting long word boundaries.", - - run: function() { - sel.setPosition(longDiv, 0); - sel.modify("extend", "forward", "word"); - }, - - done: function () { document.body.removeChild(longDiv) } -}); -</script>
diff --git a/third_party/WebKit/Source/bindings/DEPS b/third_party/WebKit/Source/bindings/DEPS index fbae013..6d95688 100644 --- a/third_party/WebKit/Source/bindings/DEPS +++ b/third_party/WebKit/Source/bindings/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+base/memory/scoped_refptr.h", "+bindings", "+core", "+gin/public",
diff --git a/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.h b/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.h index e004636d..9427f3e 100644 --- a/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.h +++ b/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.h
@@ -11,10 +11,10 @@ #ifndef GeneratedCodeHelper_h #define GeneratedCodeHelper_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/V8BindingForCore.h" #include "core/CoreExport.h" -#include "platform/wtf/RefPtr.h" #include "v8/include/v8.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.h b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.h index 579f2bd..3845ed3 100644 --- a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.h +++ b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.h
@@ -31,12 +31,12 @@ #ifndef LocalWindowProxy_h #define LocalWindowProxy_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/WindowProxy.h" #include "core/frame/LocalFrame.h" #include "platform/bindings/DOMWrapperWorld.h" #include "platform/bindings/ScriptState.h" #include "platform/wtf/Assertions.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/text/AtomicString.h" #include "v8/include/v8.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.h b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.h index a2ced9d..f3b0f73 100644 --- a/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.h +++ b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.h
@@ -31,10 +31,10 @@ #ifndef RemoteWindowProxy_h #define RemoteWindowProxy_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/WindowProxy.h" #include "core/frame/RemoteFrame.h" #include "platform/bindings/DOMWrapperWorld.h" -#include "platform/wtf/RefPtr.h" #include "v8/include/v8.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.h b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.h index 3997c096..3b9c325 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.h +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.h
@@ -5,12 +5,12 @@ #ifndef ScriptCustomElementDefinition_h #define ScriptCustomElementDefinition_h +#include "base/memory/scoped_refptr.h" #include "core/CoreExport.h" #include "core/html/custom/CustomElementDefinition.h" #include "platform/bindings/ScriptState.h" #include "platform/bindings/TraceWrapperV8Reference.h" #include "platform/wtf/Noncopyable.h" -#include "platform/wtf/RefPtr.h" #include "v8.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.h b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.h index 33e5e85c..a8403615 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.h +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.h
@@ -5,13 +5,13 @@ #ifndef ScriptCustomElementDefinitionBuilder_h #define ScriptCustomElementDefinitionBuilder_h +#include "base/memory/scoped_refptr.h" #include "core/CoreExport.h" #include "core/html/custom/CustomElementDefinitionBuilder.h" #include "platform/heap/Handle.h" #include "platform/wtf/Allocator.h" #include "platform/wtf/HashSet.h" #include "platform/wtf/Noncopyable.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/text/AtomicString.h" #include "platform/wtf/text/AtomicStringHash.h" #include "platform/wtf/text/StringView.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptEventListener.h b/third_party/WebKit/Source/bindings/core/v8/ScriptEventListener.h index ced9ec3..3b594d2 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptEventListener.h +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptEventListener.h
@@ -31,9 +31,9 @@ #ifndef ScriptEventListener_h #define ScriptEventListener_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ScriptValue.h" #include "bindings/core/v8/V8LazyEventListener.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptPromise.h b/third_party/WebKit/Source/bindings/core/v8/ScriptPromise.h index 2e9db2d..7add04aa 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptPromise.h +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptPromise.h
@@ -31,12 +31,12 @@ #ifndef ScriptPromise_h #define ScriptPromise_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ScriptFunction.h" #include "bindings/core/v8/ScriptValue.h" #include "core/CoreExport.h" #include "platform/heap/Handle.h" #include "platform/wtf/Allocator.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/Vector.h" #include "v8/include/v8.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseProperty.h b/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseProperty.h index 6025624..ab741c7 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseProperty.h +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseProperty.h
@@ -5,12 +5,12 @@ #ifndef ScriptPromiseProperty_h #define ScriptPromiseProperty_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ScriptPromise.h" #include "bindings/core/v8/ScriptPromisePropertyBase.h" #include "bindings/core/v8/ToV8ForCore.h" #include "platform/bindings/ScriptForbiddenScope.h" #include "platform/wtf/Noncopyable.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptPromisePropertyTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptPromisePropertyTest.cpp index 033e9b4..6d0b4bf 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptPromisePropertyTest.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptPromisePropertyTest.cpp
@@ -6,6 +6,7 @@ #include <memory> +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ScriptFunction.h" #include "bindings/core/v8/ScriptPromise.h" #include "bindings/core/v8/ScriptValue.h" @@ -19,7 +20,6 @@ #include "platform/bindings/DOMWrapperWorld.h" #include "platform/bindings/ScriptState.h" #include "platform/heap/Handle.h" -#include "platform/wtf/RefPtr.h" #include "testing/gtest/include/gtest/gtest.h" #include "v8/include/v8.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptString.h b/third_party/WebKit/Source/bindings/core/v8/ScriptString.h index e51de3a..9a85ddc 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptString.h +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptString.h
@@ -31,9 +31,9 @@ #ifndef ScriptString_h #define ScriptString_h +#include "base/memory/scoped_refptr.h" #include "platform/bindings/SharedPersistent.h" #include "platform/wtf/Allocator.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/text/WTFString.h" #include "v8/include/v8.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValue.h b/third_party/WebKit/Source/bindings/core/v8/ScriptValue.h index b1080d3..f8401e5 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptValue.h +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValue.h
@@ -31,12 +31,12 @@ #ifndef ScriptValue_h #define ScriptValue_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/NativeValueTraits.h" #include "core/CoreExport.h" #include "platform/bindings/ScriptState.h" #include "platform/bindings/SharedPersistent.h" #include "platform/wtf/Allocator.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/text/WTFString.h" #include "v8/include/v8.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/UseCounterCallback.cpp b/third_party/WebKit/Source/bindings/core/v8/UseCounterCallback.cpp index 0f3a242..6c859c35 100644 --- a/third_party/WebKit/Source/bindings/core/v8/UseCounterCallback.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/UseCounterCallback.cpp
@@ -22,6 +22,9 @@ case v8::Isolate::kUseAsm: blink_feature = WebFeature::kUseAsm; break; + case v8::Isolate::kWebAssemblyInstantiation: + blink_feature = WebFeature::kWebAssemblyInstantiation; + break; case v8::Isolate::kBreakIterator: blink_feature = WebFeature::kBreakIterator; break;
diff --git a/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.h b/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.h index 838cf7df..d2901c9 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.h +++ b/third_party/WebKit/Source/bindings/core/v8/V0CustomElementConstructorBuilder.h
@@ -31,11 +31,11 @@ #ifndef V0CustomElementConstructorBuilder_h #define V0CustomElementConstructorBuilder_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ScriptValue.h" #include "bindings/core/v8/V8V0CustomElementLifecycleCallbacks.h" #include "core/dom/QualifiedName.h" #include "core/html/custom/V0CustomElementLifecycleCallbacks.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/text/AtomicString.h" #include "v8/include/v8.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.cpp index cc11208..0c99dbef 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.cpp
@@ -26,8 +26,6 @@ namespace { -const intptr_t* g_v8_context_snapshot_reference_table = nullptr; - // TODO(peria): This method is almost a copy of // V8PerContext::ConstructorForTypeSlowCase(), so merge with it. v8::Local<v8::Function> ConstructPlainType(v8::Isolate* isolate, @@ -144,16 +142,6 @@ Member<Document> document; }; -int CountExternalReferenceEntries() { - if (!g_v8_context_snapshot_reference_table) - return 0; - - int count = 0; - for (const intptr_t* p = g_v8_context_snapshot_reference_table; *p; ++p) - ++count; - return count; -} - } // namespace v8::Local<v8::Context> V8ContextSnapshot::CreateContextFromSnapshot( @@ -297,15 +285,6 @@ EnsureInterfaceTemplatesForWorld(isolate, *isolated_world); } -void V8ContextSnapshot::SetReferenceTable(const intptr_t* table) { - DCHECK(!g_v8_context_snapshot_reference_table); - g_v8_context_snapshot_reference_table = table; -} - -const intptr_t* V8ContextSnapshot::GetReferenceTable() { - return g_v8_context_snapshot_reference_table; -} - v8::StartupData V8ContextSnapshot::TakeSnapshot() { DCHECK_EQ(V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate()) ->GetV8ContextSnapshotMode(), @@ -317,9 +296,6 @@ v8::Isolate* isolate = creator->GetIsolate(); CHECK_EQ(isolate, v8::Isolate::GetCurrent()); - VLOG(1) << "External reference table has " << CountExternalReferenceEntries() - << " entries."; - // Disable all runtime enabled features RuntimeEnabledFeatures::SetStableFeaturesEnabled(false); RuntimeEnabledFeatures::SetExperimentalFeaturesEnabled(false);
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.h b/third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.h index ec4580f..e9dd19d 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.h
@@ -50,9 +50,6 @@ static void EnsureInterfaceTemplates(v8::Isolate*); - static void SetReferenceTable(const intptr_t* table); - static const intptr_t* GetReferenceTable(); - // Do not call this in production. static v8::StartupData TakeSnapshot();
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.h b/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.h index c663f28..9780d98 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.h
@@ -31,8 +31,8 @@ #ifndef V8ErrorHandler_h #define V8ErrorHandler_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/V8EventListener.h" -#include "platform/wtf/RefPtr.h" #include "v8/include/v8.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8EventListener.h b/third_party/WebKit/Source/bindings/core/v8/V8EventListener.h index 208ab7ba8..8cd90e1 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8EventListener.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8EventListener.h
@@ -31,8 +31,8 @@ #ifndef V8EventListener_h #define V8EventListener_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/V8AbstractEventListener.h" -#include "platform/wtf/RefPtr.h" #include "v8/include/v8.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp index 900586fb..cfb957e7 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -27,6 +27,7 @@ #include <memory> +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/BindingSecurity.h" #include "bindings/core/v8/ReferrerScriptInfo.h" #include "bindings/core/v8/RejectedPromises.h" @@ -66,7 +67,6 @@ #include "platform/wtf/AddressSanitizer.h" #include "platform/wtf/Assertions.h" #include "platform/wtf/PtrUtil.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/text/WTFString.h" #include "platform/wtf/typed_arrays/ArrayBufferContents.h" #include "public/platform/Platform.h" @@ -589,7 +589,8 @@ ? gin::IsolateHolder::kStableAndExperimentalV8Extras : gin::IsolateHolder::kStableV8Extras; gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, - v8_extras_mode, &array_buffer_allocator); + v8_extras_mode, &array_buffer_allocator, + reference_table); // NOTE: Some threads (namely utility threads) don't have a scheduler. WebScheduler* scheduler = Platform::Current()->CurrentThread()->Scheduler(); @@ -603,14 +604,12 @@ !RuntimeEnabledFeatures::V8ContextSnapshotEnabled()) { v8_context_snapshot_mode = V8PerIsolateData::V8ContextSnapshotMode::kDontUseSnapshot; - reference_table = nullptr; } - V8ContextSnapshot::SetReferenceTable(reference_table); v8::Isolate* isolate = V8PerIsolateData::Initialize( scheduler ? scheduler->V8TaskRunner() : Platform::Current()->CurrentThread()->GetWebTaskRunner(), - reference_table, v8_context_snapshot_mode); + v8_context_snapshot_mode); InitializeV8Common(isolate);
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.h b/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.h index f937dd54..d96d5b0e 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.h
@@ -31,8 +31,8 @@ #ifndef V8LazyEventListener_h #define V8LazyEventListener_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/V8AbstractEventListener.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/text/TextPosition.h" #include "v8/include/v8.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp index bc221b2..1e2a0ce 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
@@ -49,6 +49,7 @@ #include "platform/wtf/Assertions.h" #include "platform/wtf/CurrentTime.h" #include "platform/wtf/Optional.h" +#include "platform/wtf/text/TextEncoding.h" #include "public/platform/Platform.h" #include "public/web/WebSettings.h" @@ -191,7 +192,7 @@ static const int kCacheTagKindSize = 2; -uint32_t CacheTag(CacheTagKind kind, CachedMetadataHandler* cache_handler) { +uint32_t CacheTag(CacheTagKind kind, const String& encoding) { static_assert((1 << kCacheTagKindSize) >= kCacheTagLast, "CacheTagLast must be large enough"); @@ -203,15 +204,14 @@ // about encodings, but the cached data is specific to one encoding. If we // later load the script from the cache and interpret it with a different // encoding, the cached data is not valid for that encoding. - return (v8_cache_data_version | kind) + - StringHash::GetHash(cache_handler->Encoding()); + return (v8_cache_data_version | kind) + StringHash::GetHash(encoding); } // Check previously stored timestamp. bool IsResourceHotForCaching(CachedMetadataHandler* cache_handler, int hot_hours) { const double cache_within_seconds = hot_hours * 60 * 60; - uint32_t tag = CacheTag(kCacheTagTimeStamp, cache_handler); + uint32_t tag = CacheTag(kCacheTagTimeStamp, cache_handler->Encoding()); scoped_refptr<CachedMetadata> cached_metadata = cache_handler->GetCachedMetadata(tag); if (!cached_metadata) @@ -252,7 +252,7 @@ CachedMetadataHandler::kSendToPlatform; cache_handler->ClearCachedMetadata(cache_type); cache_handler->SetCachedMetadata( - CacheTag(kCacheTagParser, cache_handler), + V8ScriptRunner::TagForParserCache(cache_handler), reinterpret_cast<const char*>(new_cached_data->data), new_cached_data->length, cache_type); if (cache_result) { @@ -316,10 +316,9 @@ switch (cache_options) { case kV8CacheOptionsParse: { // Use parser-cache; in-memory only. - uint32_t parser_tag = CacheTag(kCacheTagParser, cache_handler); + uint32_t parser_tag = V8ScriptRunner::TagForParserCache(cache_handler); scoped_refptr<CachedMetadata> parser_cache( - cache_handler ? cache_handler->GetCachedMetadata(parser_tag) - : nullptr); + cache_handler->GetCachedMetadata(parser_tag)); if (parser_cache) { return WTF::Bind(CompileAndConsumeCache, WrapPersistent(cache_handler), std::move(parser_cache), @@ -333,12 +332,11 @@ case kV8CacheOptionsDefault: case kV8CacheOptionsCode: case kV8CacheOptionsAlways: { + uint32_t code_cache_tag = V8ScriptRunner::TagForCodeCache(cache_handler); // Use code caching for recently seen resources. // Use compression depending on the cache option. - scoped_refptr<CachedMetadata> code_cache( - cache_handler ? cache_handler->GetCachedMetadata( - CacheTag(kCacheTagCode, cache_handler)) - : nullptr); + scoped_refptr<CachedMetadata> code_cache = + cache_handler->GetCachedMetadata(code_cache_tag); if (code_cache) { return WTF::Bind(CompileAndConsumeCache, WrapPersistent(cache_handler), std::move(code_cache), @@ -350,7 +348,6 @@ return WTF::Bind(CompileWithoutOptions, v8::ScriptCompiler::kNoCacheBecauseCacheTooCold); } - uint32_t code_cache_tag = CacheTag(kCacheTagCode, cache_handler); return WTF::Bind(CompileAndProduceCache, WrapPersistent(cache_handler), code_cache_tag, v8::ScriptCompiler::kProduceCodeCache, CachedMetadataHandler::kSendToPlatform); @@ -717,17 +714,17 @@ uint32_t V8ScriptRunner::TagForParserCache( CachedMetadataHandler* cache_handler) { - return CacheTag(kCacheTagParser, cache_handler); + return CacheTag(kCacheTagParser, cache_handler->Encoding()); } uint32_t V8ScriptRunner::TagForCodeCache(CachedMetadataHandler* cache_handler) { - return CacheTag(kCacheTagCode, cache_handler); + return CacheTag(kCacheTagCode, cache_handler->Encoding()); } // Store a timestamp to the cache as hint. void V8ScriptRunner::SetCacheTimeStamp(CachedMetadataHandler* cache_handler) { double now = WTF::CurrentTime(); - uint32_t tag = CacheTag(kCacheTagTimeStamp, cache_handler); + uint32_t tag = CacheTag(kCacheTagTimeStamp, cache_handler->Encoding()); cache_handler->ClearCachedMetadata(CachedMetadataHandler::kCacheLocally); cache_handler->SetCachedMetadata(tag, reinterpret_cast<char*>(&now), sizeof(now), @@ -764,6 +761,67 @@ num_args, args, isolate); } +// static +scoped_refptr<CachedMetadata> V8ScriptRunner::GenerateFullCodeCache( + ScriptState* script_state, + const String& script_string, + const String& file_name, + const WTF::TextEncoding& encoding, + OpaqueMode opaque_mode) { + constexpr const char* kTraceEventCategoryGroup = "v8,devtools.timeline"; + TRACE_EVENT_BEGIN1(kTraceEventCategoryGroup, "v8.compile", "fileName", + file_name.Utf8()); + + ScriptState::Scope scope(script_state); + v8::Isolate* isolate = script_state->GetIsolate(); + ReferrerScriptInfo referrer_info; + v8::ScriptOrigin origin( + V8String(isolate, file_name), + v8::Integer::New(isolate, 0), // line_offset + v8::Integer::New(isolate, 0), // column_offset + v8::Boolean::New( + isolate, + opaque_mode == OpaqueMode::kNotOpaque), // is_shared_cross_origin + v8::Local<v8::Integer>(), // script_id + V8String(isolate, String("")), // source_map_url + v8::Boolean::New(isolate, + opaque_mode == OpaqueMode::kOpaque), // is_opaque + v8::False(isolate), // is_wasm + v8::False(isolate), // is_module + referrer_info.ToV8HostDefinedOptions(isolate)); + v8::Local<v8::String> code(V8String(isolate, script_string)); + v8::ScriptCompiler::Source source(code, origin); + scoped_refptr<CachedMetadata> cached_metadata; + const v8::ScriptCompiler::CachedData* cached_data = nullptr; + + v8::Local<v8::UnboundScript> unbound_script; + if (v8::ScriptCompiler::CompileUnboundScript( + isolate, &source, v8::ScriptCompiler::kProduceFullCodeCache) + .ToLocal(&unbound_script)) { + cached_data = source.GetCachedData(); + if (cached_data && cached_data->length) { + cached_metadata = CachedMetadata::Create( + CacheTag(kCacheTagCode, encoding.GetName()), + reinterpret_cast<const char*>(cached_data->data), + cached_data->length); + } + } + + TRACE_EVENT_END1( + kTraceEventCategoryGroup, "v8.compile", "data", + InspectorCompileScriptEvent::Data( + file_name, TextPosition(), + InspectorCompileScriptEvent::V8CacheResult( + InspectorCompileScriptEvent::V8CacheResult::ProduceResult( + v8::ScriptCompiler::kProduceFullCodeCache, + cached_data ? cached_data->length : 0), + Optional< + InspectorCompileScriptEvent::V8CacheResult::ConsumeResult>()), + false)); + + return cached_metadata; +} + STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsDefault, kV8CacheOptionsDefault); STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsNone, kV8CacheOptionsNone); STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsParse, kV8CacheOptionsParse);
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h index 80a1bc9..b514d82 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h
@@ -42,8 +42,13 @@ #include "platform/wtf/text/WTFString.h" #include "v8/include/v8.h" +namespace WTF { +class TextEncoding; +} // namespace WTF + namespace blink { +class CachedMetadata; class CachedMetadataHandler; class ExecutionContext; class ScriptResource; @@ -54,6 +59,11 @@ STATIC_ONLY(V8ScriptRunner); public: + enum class OpaqueMode { + kOpaque, + kNotOpaque, + }; + // For the following methods, the caller sites have to hold // a HandleScope and a ContextScope. static v8::MaybeLocal<v8::Script> CompileScript(ScriptState*, @@ -161,6 +171,13 @@ // V8Initializer and so can't trivially move to platform/bindings. static void ReportException(v8::Isolate*, v8::Local<v8::Value> exception); + static scoped_refptr<CachedMetadata> GenerateFullCodeCache( + ScriptState*, + const String& script_string, + const String& file_name, + const WTF::TextEncoding&, + OpaqueMode); + private: static v8::MaybeLocal<v8::Value> CallExtraHelper(ScriptState*, const char* name,
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8V0CustomElementLifecycleCallbacks.h b/third_party/WebKit/Source/bindings/core/v8/V8V0CustomElementLifecycleCallbacks.h index 8eac2fc..1e573a2 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8V0CustomElementLifecycleCallbacks.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8V0CustomElementLifecycleCallbacks.h
@@ -33,10 +33,10 @@ #include <memory> +#include "base/memory/scoped_refptr.h" #include "core/html/custom/V0CustomElementLifecycleCallbacks.h" #include "platform/bindings/ScopedPersistent.h" #include "platform/bindings/ScriptState.h" -#include "platform/wtf/RefPtr.h" #include "v8/include/v8.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8WorkerOrWorkletEventListener.h b/third_party/WebKit/Source/bindings/core/v8/V8WorkerOrWorkletEventListener.h index 4e2f11b..440f1fff 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8WorkerOrWorkletEventListener.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8WorkerOrWorkletEventListener.h
@@ -31,8 +31,8 @@ #ifndef V8WorkerOrWorkletEventListener_h #define V8WorkerOrWorkletEventListener_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/V8EventListener.h" -#include "platform/wtf/RefPtr.h" #include "v8/include/v8.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h index 715bbac..c594147 100644 --- a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h +++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h
@@ -31,11 +31,11 @@ #ifndef WindowProxy_h #define WindowProxy_h +#include "base/memory/scoped_refptr.h" #include "core/CoreExport.h" #include "platform/bindings/DOMWrapperWorld.h" #include "platform/bindings/ScopedPersistent.h" #include "platform/heap/Handle.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/debug/StackTrace.h" #include "v8/include/v8.h"
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 c4053c2..d9df1e33 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
@@ -31,6 +31,7 @@ #include "bindings/core/v8/V8CSSStyleDeclaration.h" #include <algorithm> +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/V8BindingForCore.h" #include "core/CSSPropertyNames.h" @@ -43,7 +44,6 @@ #include "core/dom/events/EventTarget.h" #include "core/html/custom/CEReactionsScope.h" #include "platform/wtf/ASCIICType.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/StdLibExtras.h" #include "platform/wtf/Vector.h" #include "platform/wtf/text/StringBuilder.h" @@ -222,6 +222,8 @@ return; CEReactionsScope ce_reactions_scope; + ExecutionContext* execution_context = + ToExecutionContext(info.Holder()->CreationContext()); TOSTRING_VOID(V8StringResource<kTreatNullAsNullString>, property_value, value); @@ -229,7 +231,8 @@ info.GetIsolate(), ExceptionState::kSetterContext, "CSSStyleDeclaration", getPropertyName(resolveCSSPropertyID(unresolved_property))); impl->SetPropertyInternal(unresolved_property, String(), property_value, - false, exception_state); + false, execution_context->SecureContextMode(), + exception_state); V8SetReturnValue(info, value); }
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8CustomXPathNSResolver.h b/third_party/WebKit/Source/bindings/core/v8/custom/V8CustomXPathNSResolver.h index 883aca39a..57fd4e33 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8CustomXPathNSResolver.h +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8CustomXPathNSResolver.h
@@ -31,10 +31,10 @@ #ifndef V8CustomXPathNSResolver_h #define V8CustomXPathNSResolver_h +#include "base/memory/scoped_refptr.h" #include "core/xml/XPathNSResolver.h" #include "platform/bindings/ScriptState.h" #include "platform/wtf/Forward.h" -#include "platform/wtf/RefPtr.h" #include "v8/include/v8.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8DocumentCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8DocumentCustom.cpp index d3802a3..830c1515 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8DocumentCustom.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8DocumentCustom.cpp
@@ -31,6 +31,7 @@ #include "bindings/core/v8/V8Document.h" #include <memory> +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ScriptController.h" #include "bindings/core/v8/V8BindingForCore.h" #include "bindings/core/v8/V8EventTarget.h" @@ -46,7 +47,6 @@ #include "core/html/HTMLCollection.h" #include "core/html/HTMLIFrameElement.h" #include "platform/wtf/PtrUtil.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/StdLibExtras.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8MessageChannelCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8MessageChannelCustom.cpp index d7fe76b..1c8603bd0 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8MessageChannelCustom.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8MessageChannelCustom.cpp
@@ -30,12 +30,12 @@ #include "bindings/core/v8/V8MessageChannel.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/V8BindingForCore.h" #include "bindings/core/v8/V8MessagePort.h" #include "core/dom/MessageChannel.h" #include "core/workers/WorkerGlobalScope.h" #include "platform/bindings/V8PrivateProperty.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/UnpackedSerializedScriptValue.h b/third_party/WebKit/Source/bindings/core/v8/serialization/UnpackedSerializedScriptValue.h index e00906ef..983e8e8 100644 --- a/third_party/WebKit/Source/bindings/core/v8/serialization/UnpackedSerializedScriptValue.h +++ b/third_party/WebKit/Source/bindings/core/v8/serialization/UnpackedSerializedScriptValue.h
@@ -5,12 +5,12 @@ #ifndef UnpackedSerializedScriptValue_h #define UnpackedSerializedScriptValue_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/serialization/SerializedScriptValue.h" #include "core/CoreExport.h" #include "platform/heap/GarbageCollected.h" #include "platform/heap/Handle.h" #include "platform/heap/HeapAllocator.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/Vector.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.h b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.h index 06ad1650..3e01a1f9 100644 --- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.h +++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.h
@@ -5,6 +5,7 @@ #ifndef V8ScriptValueDeserializer_h #define V8ScriptValueDeserializer_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/serialization/SerializationTag.h" #include "bindings/core/v8/serialization/SerializedColorParams.h" #include "bindings/core/v8/serialization/SerializedScriptValue.h" @@ -12,7 +13,6 @@ #include "platform/bindings/ScriptState.h" #include "platform/wtf/Allocator.h" #include "platform/wtf/Noncopyable.h" -#include "platform/wtf/RefPtr.h" #include "v8/include/v8.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.h b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.h index bf34ad7..16c0935 100644 --- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.h +++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.h
@@ -5,6 +5,7 @@ #ifndef V8ScriptValueSerializer_h #define V8ScriptValueSerializer_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/serialization/SerializationTag.h" #include "bindings/core/v8/serialization/SerializedColorParams.h" @@ -13,7 +14,6 @@ #include "platform/bindings/ScriptState.h" #include "platform/wtf/Allocator.h" #include "platform/wtf/Noncopyable.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/Vector.h" #include "v8/include/v8.h"
diff --git a/third_party/WebKit/Source/bindings/modules/v8/WebGLAny.h b/third_party/WebKit/Source/bindings/modules/v8/WebGLAny.h index 72c0c73..eb81647 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/WebGLAny.h +++ b/third_party/WebKit/Source/bindings/modules/v8/WebGLAny.h
@@ -5,11 +5,11 @@ #ifndef WebGLAny_h #define WebGLAny_h +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ScriptValue.h" #include "core/typed_arrays/DOMTypedArray.h" #include "modules/webgl/WebGLObject.h" #include "platform/wtf/Forward.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp b/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp index 556c99b..0879783 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp +++ b/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp
@@ -4,6 +4,7 @@ #include "bindings/modules/v8/wasm/WasmResponseExtensions.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/ScriptPromise.h" #include "bindings/core/v8/ScriptPromiseResolver.h" @@ -13,7 +14,6 @@ #include "modules/fetch/FetchDataLoader.h" #include "platform/bindings/ScriptState.h" #include "platform/heap/Handle.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_interface.py index 03e7468..4c2c7f5a 100644 --- a/third_party/WebKit/Source/bindings/scripts/v8_interface.py +++ b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
@@ -61,12 +61,12 @@ 'platform/heap/Handle.h', ]) INTERFACE_CPP_INCLUDES = frozenset([ + 'base/memory/scoped_refptr.h', 'bindings/core/v8/ExceptionState.h', 'bindings/core/v8/V8DOMConfiguration.h', 'platform/bindings/V8ObjectConstructor.h', 'core/dom/ExecutionContext.h', 'platform/wtf/GetPtr.h', - 'platform/wtf/RefPtr.h', ])
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp index 9600f053..66140312 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8ArrayBuffer.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -20,7 +21,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp index ef6b3bf..f98b5ef 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8ArrayBufferView.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -31,7 +32,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/bindings/V8PrivateProperty.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp index 5deefd3..b8bda93 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8DataView.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -20,7 +21,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp index 1b989031..55c5bd2 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8SVGTestInterface.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -20,7 +21,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.cpp index bfa0e7c4..0c7d6907 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestAttributeGetters.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -19,7 +20,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp index 81451d9..c7d3e96 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestCallbackFunctions.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -22,7 +23,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp index c71c2ea..20b14377 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestConstants.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/V8DOMConfiguration.h" #include "core/dom/ExecutionContext.h" @@ -20,7 +21,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/runtime_enabled_features.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp index 44ae1ce..40f5db8 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestIntegerIndexed.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -23,7 +24,6 @@ #include "platform/bindings/ScriptState.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp index 388e84e..0599dede 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestIntegerIndexedGlobal.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -20,7 +21,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp index a13eb58..334d85f1 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestIntegerIndexedPrimaryGlobal.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -20,7 +21,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp index 54afbd6e..f2ab7bd4 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterface.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -37,7 +38,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/runtime_enabled_features.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp index f6aeedf..dc50dc8e 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterface2.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -24,7 +25,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/runtime_enabled_features.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp index 9e74e1d..38001f9 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterface3.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -20,7 +21,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp index 2da9052..cca7010 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceCheckSecurity.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/BindingSecurity.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" @@ -21,7 +22,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp index aa77049a..98780a7 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceConstructor.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/Dictionary.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" @@ -24,7 +25,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/bindings/V8PrivateProperty.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp index a91b772..37003559 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceConstructor2.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/Dictionary.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" @@ -20,7 +21,6 @@ #include "core/frame/LocalDOMWindow.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp index 59c92ea..a401e611 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceConstructor3.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -18,7 +19,6 @@ #include "core/frame/LocalDOMWindow.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp index 5093d532..a78ffee 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceConstructor4.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -19,7 +20,6 @@ #include "core/frame/LocalDOMWindow.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp index 2c89bf7..160c614 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp
@@ -10,13 +10,13 @@ // clang-format off #include "V8TestInterfaceCustomConstructor.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/V8DOMConfiguration.h" #include "core/dom/ExecutionContext.h" #include "core/frame/LocalDOMWindow.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp index fdcc491f..7308df41 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceDocument.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/V8DOMConfiguration.h" #include "bindings/core/v8/V8Location.h" @@ -21,7 +22,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp index 86e5f2a..3f84535 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp
@@ -10,12 +10,12 @@ // clang-format off #include "V8TestInterfaceEmpty.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/V8DOMConfiguration.h" #include "core/dom/ExecutionContext.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp index 130cdf9..451e32c 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceEventInitConstructor.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -20,7 +21,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp index 75f69b0a..013d6e1 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceEventTarget.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/V8DOMConfiguration.h" #include "core/dom/Document.h" @@ -18,7 +19,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/bindings/V8PrivateProperty.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp index e4b722d..83206ff7 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceGarbageCollected.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -23,7 +24,6 @@ #include "platform/bindings/ScriptState.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp index 754a58b12..f776156 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceNamedConstructor.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -21,7 +22,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/bindings/V8PrivateProperty.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp index e0ed1f444..db7077f3 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceNamedConstructor2.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -19,7 +20,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/bindings/V8PrivateProperty.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp index 002ce40..a2f9c61 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceNode.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -23,7 +24,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp index a06ea7c8..b2b1a5b 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceOriginTrialEnabled.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -19,7 +20,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/runtime_enabled_features.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp index 4a209e00..c97bfbf 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfaceSecureContext.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -19,7 +20,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/runtime_enabled_features.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp index 1816e2d..7d8b9e4 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestNode.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -19,7 +20,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp index e2f4e9e..4eb0c96 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestObject.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/BindingSecurity.h" #include "bindings/core/v8/Dictionary.h" #include "bindings/core/v8/ExceptionState.h" @@ -75,7 +76,6 @@ #include "platform/bindings/V8PrivateProperty.h" #include "platform/runtime_enabled_features.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp index bbf7ad261..6c78b13 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestSpecialOperations.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -24,7 +25,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp index 75a2f0d..1c20119f9 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestSpecialOperationsNotEnumerable.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -17,7 +18,6 @@ #include "core/dom/ExecutionContext.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp index 5569aaf..0f1c257 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestTypedefs.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -31,7 +32,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.cpp index 53ae5dfb..5c26cff 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestVariadicConstructorArguments.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -18,7 +19,6 @@ #include "core/frame/LocalDOMWindow.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp index 751f500..03cc433 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8Uint8ClampedArray.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/V8ArrayBuffer.h" #include "bindings/core/v8/V8DOMConfiguration.h" @@ -17,7 +18,6 @@ #include "core/dom/ExecutionContext.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.cpp index ae71e3e..a029a2c 100644 --- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInheritedLegacyUnenumerableNamedProperties.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -18,7 +19,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.cpp index e430f23..55f46c8 100644 --- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterface2Partial.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -22,7 +23,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/runtime_enabled_features.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp index 1330c5c..070ca361 100644 --- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterface5.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -22,7 +23,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/runtime_enabled_features.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp index 1b9ead8c..4cb01fc 100644 --- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestInterfacePartial.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -28,7 +29,6 @@ #include "platform/bindings/V8ObjectConstructor.h" #include "platform/runtime_enabled_features.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.cpp index f2651d83..571cd37 100644 --- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestNotEnumerableNamedGetter.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -17,7 +18,6 @@ #include "core/dom/ExecutionContext.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.cpp index db0fc6c..aa5961c 100644 --- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.cpp
@@ -10,6 +10,7 @@ // clang-format off #include "V8TestSubObject.h" +#include "base/memory/scoped_refptr.h" #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/IDLTypes.h" #include "bindings/core/v8/NativeValueTraitsImpl.h" @@ -18,7 +19,6 @@ #include "platform/bindings/RuntimeCallStats.h" #include "platform/bindings/V8ObjectConstructor.h" #include "platform/wtf/GetPtr.h" -#include "platform/wtf/RefPtr.h" namespace blink {
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 9129d285..50a9de0 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
@@ -57,6 +57,7 @@ property_['superclass'] = superclass 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_)) @@ -101,6 +102,32 @@ property_['custom_apply_functions_value']) or 'custom_apply' in property_.keys())) + 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") + includes.sort() + property_['includes'] = includes + def validate_input(self): # First collect which classes correspond to which properties. class_names_to_properties = defaultdict(list)
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 c8a6e80..967ef06 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
@@ -31,7 +31,7 @@ public: CORE_EXPORT static const CSSProperty& Get(CSSPropertyID); - constexpr CSSProperty(CSSPropertyID id) : id_(id) {} + explicit constexpr CSSProperty(CSSPropertyID id) : id_(id) {} // For backwards compatibility when passing around CSSProperty references. // In case we need to call a function that hasn't been converted to using @@ -40,6 +40,7 @@ virtual bool IsInterpolable() const { return false; } virtual bool IsInherited() const { return false; } + virtual bool IsCompositableProperty() const { return false; } virtual bool IsRepeated() const { return false; } virtual char RepetitionSeparator() const { NOTREACHED(); @@ -85,10 +86,9 @@ const CSSPropertyID id_; }; -const CSSProperty& GetCSSPropertyApplyAtRule(); -const CSSProperty& GetCSSPropertyVariable(); +CORE_EXPORT const CSSProperty& GetCSSPropertyVariable(); {% for property_class_data in property_classes_by_property_id %} -const CSSProperty& Get{{property_class_data.property_id}}(); +CORE_EXPORT const CSSProperty& Get{{property_class_data.property_id}}(); {% endfor %} } // namespace blink
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 820eb81..596a20d9 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
@@ -11,32 +11,9 @@ #include "core/css/properties/{{property.superclass}}.h" {# conditional includes - only used in some property classes #} -{% if property.direction_aware_options %} -#include "core/StylePropertyShorthand.h" -{% endif %} -{% if property.should_implement_apply_functions %} -#include "core/css/resolver/StyleResolverState.h" - {% if property.converter == "CSSPrimitiveValue" %} -#include "core/css/CSSPrimitiveValue.h" -#include "core/css/CSSPrimitiveValueMappings.h" - {% elif property.converter == "CSSIdentifierValue" %} -#include "core/css/CSSIdentifierValue.h" - {% elif property.converter %} -#include "core/css/CSSPrimitiveValueMappings.h" -#include "core/css/resolver/StyleBuilderConverter.h" - {% endif %} - {% if property.font %} -#include "core/css/resolver/FontBuilder.h" - {% elif property.svg %} -#include "core/style/ComputedStyle.h" -#include "core/style/SVGComputedStyle.h" - {% else %} -#include "core/style/ComputedStyle.h" - {% endif %} -{% endif %} -{% if property.runtime_flag %} -#include "platform/runtime_enabled_features.h" -{% endif %} +{% for include in property.includes %} +#include "{{include}}" +{% endfor %} namespace blink { @@ -70,6 +47,9 @@ {% if property.inherited %} bool IsInherited() const override { return true; } {% endif %} + {% if property.compositable %} + bool IsCompositableProperty() const override { return true; } + {% endif %} {% if property.separator != None %} bool IsRepeated() const override { return true; } char RepetitionSeparator() const override { return '{{property.separator}}'; }
diff --git a/third_party/WebKit/Source/build/scripts/templates/InternalRuntimeFlags.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/InternalRuntimeFlags.h.tmpl index 4313346c..a441e5a 100644 --- a/third_party/WebKit/Source/build/scripts/templates/InternalRuntimeFlags.h.tmpl +++ b/third_party/WebKit/Source/build/scripts/templates/InternalRuntimeFlags.h.tmpl
@@ -9,7 +9,7 @@ #include "platform/bindings/ScriptWrappable.h" #include "platform/heap/Handle.h" #include "platform/runtime_enabled_features.h" -#include "platform/wtf/RefPtr.h" +#include "base/memory/scoped_refptr.h" #include "platform/wtf/RefCounted.h" namespace blink {
diff --git a/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.h.tmpl index f7628a54..cdffd595 100644 --- a/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.h.tmpl +++ b/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.h.tmpl
@@ -9,7 +9,7 @@ #include "platform/bindings/ScriptWrappable.h" #include "platform/heap/Handle.h" #include "platform/wtf/RefCounted.h" -#include "platform/wtf/RefPtr.h" +#include "base/memory/scoped_refptr.h" #include "platform/wtf/text/WTFString.h" namespace blink {
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index 52e66d5..d4940786 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -583,6 +583,7 @@ "$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/FlexGrowOrShrink.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",
diff --git a/third_party/WebKit/Source/core/animation/Animation.cpp b/third_party/WebKit/Source/core/animation/Animation.cpp index 1643bd8..eb141c9 100644 --- a/third_party/WebKit/Source/core/animation/Animation.cpp +++ b/third_party/WebKit/Source/core/animation/Animation.cpp
@@ -440,7 +440,8 @@ } } -bool Animation::Affects(const Element& element, CSSPropertyID property) const { +bool Animation::Affects(const Element& element, + const CSSProperty& property) const { if (!content_ || !content_->IsKeyframeEffectReadOnly()) return false;
diff --git a/third_party/WebKit/Source/core/animation/Animation.h b/third_party/WebKit/Source/core/animation/Animation.h index 55760d5..ba0e1e7 100644 --- a/third_party/WebKit/Source/core/animation/Animation.h +++ b/third_party/WebKit/Source/core/animation/Animation.h
@@ -187,7 +187,7 @@ return compositor_player_ ? compositor_player_->Player() : nullptr; } - bool Affects(const Element&, CSSPropertyID) const; + bool Affects(const Element&, const CSSProperty&) const; // Returns whether we should continue with the commit for this animation or // wait until next commit.
diff --git a/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp b/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp index 22947a8..a716c20 100644 --- a/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp +++ b/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp
@@ -10,6 +10,7 @@ #include "core/css/parser/CSSParser.h" #include "core/css/parser/CSSVariableParser.h" #include "core/css/resolver/CSSToStyleMap.h" +#include "core/dom/Document.h" #include "core/frame/Deprecation.h" #include "core/svg/SVGElement.h" #include "core/svg/animation/SVGSMILElement.h" @@ -243,8 +244,14 @@ return nullptr; } + // Fallback to an insecure parsing mode if we weren't provided with a + // document. + SecureContextMode secure_context_mode = + document ? document->SecureContextMode() + : SecureContextMode::kInsecureContext; const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyTransitionTimingFunction, string); + CSSParser::ParseSingleValue(CSSPropertyTransitionTimingFunction, string, + StrictCSSParserContext(secure_context_mode)); if (!value || !value->IsValueList()) { DCHECK(!value || value->IsCSSWideKeyword()); exception_state.ThrowTypeError("'" + string + @@ -265,12 +272,13 @@ if (property.IsCSSProperty()) { return property.IsCSSCustomProperty() ? property.CustomPropertyName() - : CSSPropertyToKeyframeAttribute(property.CssProperty()); + : CSSPropertyToKeyframeAttribute( + property.GetCSSProperty().PropertyID()); } if (property.IsPresentationAttribute()) { return PresentationAttributeToKeyframeAttribute( - property.PresentationAttribute()); + property.PresentationAttribute().PropertyID()); } DCHECK(property.IsSVGAttribute());
diff --git a/third_party/WebKit/Source/core/animation/AnimationInputHelpersTest.cpp b/third_party/WebKit/Source/core/animation/AnimationInputHelpersTest.cpp index 930b27ed..dbcc025f 100644 --- a/third_party/WebKit/Source/core/animation/AnimationInputHelpersTest.cpp +++ b/third_party/WebKit/Source/core/animation/AnimationInputHelpersTest.cpp
@@ -22,7 +22,7 @@ } String PropertyHandleToKeyframeAttribute( - CSSPropertyID property, + const CSSProperty& property, bool is_presentation_attribute = false) { PropertyHandle handle(property, is_presentation_attribute); return AnimationInputHelpers::PropertyHandleToKeyframeAttribute(handle); @@ -160,24 +160,27 @@ TEST_F(AnimationAnimationInputHelpersTest, PropertyHandleToKeyframeAttribute) { // CSS properties. - EXPECT_EQ("top", PropertyHandleToKeyframeAttribute(CSSPropertyTop)); + EXPECT_EQ("top", PropertyHandleToKeyframeAttribute(GetCSSPropertyTop())); EXPECT_EQ("lineHeight", - PropertyHandleToKeyframeAttribute(CSSPropertyLineHeight)); - EXPECT_EQ("cssFloat", PropertyHandleToKeyframeAttribute(CSSPropertyFloat)); - EXPECT_EQ("cssOffset", PropertyHandleToKeyframeAttribute(CSSPropertyOffset)); + PropertyHandleToKeyframeAttribute(GetCSSPropertyLineHeight())); + EXPECT_EQ("cssFloat", + PropertyHandleToKeyframeAttribute(GetCSSPropertyFloat())); + EXPECT_EQ("cssOffset", + PropertyHandleToKeyframeAttribute(GetCSSPropertyOffset())); // CSS custom properties. EXPECT_EQ("--x", PropertyHandleToKeyframeAttribute("--x")); EXPECT_EQ("--test-prop", PropertyHandleToKeyframeAttribute("--test-prop")); // Presentation attributes. - EXPECT_EQ("svg-top", PropertyHandleToKeyframeAttribute(CSSPropertyTop, true)); - EXPECT_EQ("svg-line-height", - PropertyHandleToKeyframeAttribute(CSSPropertyLineHeight, true)); + EXPECT_EQ("svg-top", + PropertyHandleToKeyframeAttribute(GetCSSPropertyTop(), true)); + EXPECT_EQ("svg-line-height", PropertyHandleToKeyframeAttribute( + GetCSSPropertyLineHeight(), true)); EXPECT_EQ("svg-float", - PropertyHandleToKeyframeAttribute(CSSPropertyFloat, true)); + PropertyHandleToKeyframeAttribute(GetCSSPropertyFloat(), true)); EXPECT_EQ("svg-offset", - PropertyHandleToKeyframeAttribute(CSSPropertyOffset, true)); + PropertyHandleToKeyframeAttribute(GetCSSPropertyOffset(), true)); // SVG attributes. EXPECT_EQ("calcMode", PropertyHandleToKeyframeAttribute(QualifiedName(
diff --git a/third_party/WebKit/Source/core/animation/AnimationSimTest.cpp b/third_party/WebKit/Source/core/animation/AnimationSimTest.cpp index 290e765..ebea48d 100644 --- a/third_party/WebKit/Source/core/animation/AnimationSimTest.cpp +++ b/third_party/WebKit/Source/core/animation/AnimationSimTest.cpp
@@ -60,13 +60,14 @@ EXPECT_FALSE(exception_state.HadException()); // target.style.setProperty('--x', '100%'); - target->style()->setProperty("--x", "100%", g_empty_string, exception_state); + target->style()->setProperty(&GetDocument(), "--x", "100%", g_empty_string, + exception_state); EXPECT_FALSE(exception_state.HadException()); // target.animate({'--x': '100%'}, 1000); scoped_refptr<StringKeyframe> keyframe = StringKeyframe::Create(); keyframe->SetCSSPropertyValue("--x", GetDocument().GetPropertyRegistry(), - "100%", + "100%", GetDocument().SecureContextMode(), GetDocument().ElementSheet().Contents()); StringKeyframeVector keyframes; keyframes.push_back(std::move(keyframe)); @@ -80,13 +81,14 @@ Compositor().BeginFrame(1); // target.style.setProperty('--x', '0%'); - target->style()->setProperty("--x", "0%", g_empty_string, exception_state); + target->style()->setProperty(&GetDocument(), "--x", "0%", g_empty_string, + exception_state); EXPECT_FALSE(exception_state.HadException()); // target.animate({'--x': '100%'}, 1000); keyframe = StringKeyframe::Create(); keyframe->SetCSSPropertyValue("--x", GetDocument().GetPropertyRegistry(), - "100%", + "100%", GetDocument().SecureContextMode(), GetDocument().ElementSheet().Contents()); keyframes.clear(); keyframes.push_back(std::move(keyframe));
diff --git a/third_party/WebKit/Source/core/animation/CSSDefaultInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSDefaultInterpolationType.cpp index af57e01..ebf2b30de 100644 --- a/third_party/WebKit/Source/core/animation/CSSDefaultInterpolationType.cpp +++ b/third_party/WebKit/Source/core/animation/CSSDefaultInterpolationType.cpp
@@ -39,7 +39,7 @@ InterpolationEnvironment& environment) const { DCHECK(ToCSSDefaultNonInterpolableValue(non_interpolable_value)->CssValue()); StyleBuilder::ApplyProperty( - GetProperty().CssProperty(), + GetProperty().GetCSSProperty().PropertyID(), ToCSSInterpolationEnvironment(environment).GetState(), *ToCSSDefaultNonInterpolableValue(non_interpolable_value)->CssValue()); }
diff --git a/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp index 95546db..66d1ee9 100644 --- a/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp +++ b/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp
@@ -242,7 +242,9 @@ resolved_tokens = declaration.Value(); } const CSSValue* resolved_value = - resolved_tokens ? resolved_tokens->ParseForSyntax(registration_->Syntax()) + resolved_tokens ? resolved_tokens->ParseForSyntax( + registration_->Syntax(), + state.GetDocument().SecureContextMode()) : nullptr; if (!resolved_value) { return nullptr;
diff --git a/third_party/WebKit/Source/core/animation/CSSInterpolationType.h b/third_party/WebKit/Source/core/animation/CSSInterpolationType.h index d99b731..6136fb6 100644 --- a/third_party/WebKit/Source/core/animation/CSSInterpolationType.h +++ b/third_party/WebKit/Source/core/animation/CSSInterpolationType.h
@@ -35,7 +35,9 @@ protected: CSSInterpolationType(PropertyHandle, const PropertyRegistration* = nullptr); - CSSPropertyID CssProperty() const { return GetProperty().CssProperty(); } + CSSPropertyID CssProperty() const { + return GetProperty().GetCSSProperty().PropertyID(); + } InterpolationValue MaybeConvertSingle(const PropertySpecificKeyframe&, const InterpolationEnvironment&,
diff --git a/third_party/WebKit/Source/core/animation/CSSInterpolationTypesMap.cpp b/third_party/WebKit/Source/core/animation/CSSInterpolationTypesMap.cpp index 68671e0e..74502532 100644 --- a/third_party/WebKit/Source/core/animation/CSSInterpolationTypesMap.cpp +++ b/third_party/WebKit/Source/core/animation/CSSInterpolationTypesMap.cpp
@@ -86,14 +86,14 @@ std::unique_ptr<InterpolationTypes> applicable_types = std::make_unique<InterpolationTypes>(); - CSSPropertyID css_property = property.IsCSSProperty() - ? property.CssProperty() - : property.PresentationAttribute(); + const CSSProperty& css_property = property.IsCSSProperty() + ? property.GetCSSProperty() + : property.PresentationAttribute(); // We treat presentation attributes identically to their CSS property // equivalents when interpolating. PropertyHandle used_property = property.IsCSSProperty() ? property : PropertyHandle(css_property); - switch (css_property) { + switch (css_property.PropertyID()) { case CSSPropertyBaselineShift: case CSSPropertyBorderBottomWidth: case CSSPropertyBorderLeftWidth: @@ -325,7 +325,7 @@ DCHECK_EQ(GetRegistration(registry_.Get(), property), nullptr); break; default: - DCHECK(!CSSProperty::Get(css_property).IsInterpolable()); + DCHECK(!css_property.IsInterpolable()); break; }
diff --git a/third_party/WebKit/Source/core/animation/CSSVarCycleInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSVarCycleInterpolationType.cpp index 2407c8f..ff3456ad 100644 --- a/third_party/WebKit/Source/core/animation/CSSVarCycleInterpolationType.cpp +++ b/third_party/WebKit/Source/core/animation/CSSVarCycleInterpolationType.cpp
@@ -121,7 +121,7 @@ const NonInterpolableValue*, InterpolationEnvironment& environment) const { StyleBuilder::ApplyProperty( - GetProperty().CssProperty(), + GetProperty().GetCSSProperty().PropertyID(), ToCSSInterpolationEnvironment(environment).GetState(), *CSSCustomPropertyDeclaration::Create(GetProperty().CustomPropertyName(), CSSValueUnset));
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp index 09eff13..72a14d5c 100644 --- a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
@@ -86,30 +86,30 @@ bool IsTransformRelatedCSSProperty(const PropertyHandle property) { return property.IsCSSProperty() && - (property.CssProperty() == CSSPropertyRotate || - property.CssProperty() == CSSPropertyScale || - property.CssProperty() == CSSPropertyTransform || - property.CssProperty() == CSSPropertyTranslate); + (property.GetCSSProperty().PropertyID() == CSSPropertyRotate || + property.GetCSSProperty().PropertyID() == CSSPropertyScale || + property.GetCSSProperty().PropertyID() == CSSPropertyTransform || + property.GetCSSProperty().PropertyID() == CSSPropertyTranslate); } bool IsTransformRelatedAnimation(const Element& target_element, const Animation* animation) { - return animation->Affects(target_element, CSSPropertyTransform) || - animation->Affects(target_element, CSSPropertyRotate) || - animation->Affects(target_element, CSSPropertyScale) || - animation->Affects(target_element, CSSPropertyTranslate); + return animation->Affects(target_element, GetCSSPropertyTransform()) || + animation->Affects(target_element, GetCSSPropertyRotate()) || + animation->Affects(target_element, GetCSSPropertyScale()) || + animation->Affects(target_element, GetCSSPropertyTranslate()); } bool HasIncompatibleAnimations(const Element& target_element, const Animation& animation_to_add, const EffectModel& effect_to_add) { const bool affects_opacity = - effect_to_add.Affects(PropertyHandle(CSSPropertyOpacity)); + effect_to_add.Affects(PropertyHandle(GetCSSPropertyOpacity())); const bool affects_transform = effect_to_add.IsTransformRelatedEffect(); const bool affects_filter = - effect_to_add.Affects(PropertyHandle(CSSPropertyFilter)); + effect_to_add.Affects(PropertyHandle(GetCSSPropertyFilter())); const bool affects_backdrop_filter = - effect_to_add.Affects(PropertyHandle(CSSPropertyBackdropFilter)); + effect_to_add.Affects(PropertyHandle(GetCSSPropertyBackdropFilter())); if (!target_element.HasAnimations()) return false; @@ -122,15 +122,15 @@ if (!ConsiderAnimationAsIncompatible(*attached_animation, animation_to_add)) continue; - if ((affects_opacity && - attached_animation->Affects(target_element, CSSPropertyOpacity)) || + if ((affects_opacity && attached_animation->Affects( + target_element, GetCSSPropertyOpacity())) || (affects_transform && IsTransformRelatedAnimation(target_element, attached_animation)) || (affects_filter && - attached_animation->Affects(target_element, CSSPropertyFilter)) || + attached_animation->Affects(target_element, GetCSSPropertyFilter())) || (affects_backdrop_filter && attached_animation->Affects(target_element, - CSSPropertyBackdropFilter))) + GetCSSPropertyBackdropFilter()))) return true; } @@ -139,19 +139,6 @@ } // namespace -bool CompositorAnimations::IsCompositableProperty(CSSPropertyID property) { - for (CSSPropertyID id : kCompositableProperties) { - if (property == id) - return true; - } - return false; -} - -const CSSPropertyID CompositorAnimations::kCompositableProperties[7] = { - CSSPropertyOpacity, CSSPropertyRotate, CSSPropertyScale, - CSSPropertyTransform, CSSPropertyTranslate, CSSPropertyFilter, - CSSPropertyBackdropFilter}; - bool CompositorAnimations::GetAnimatedBoundingBox(FloatBox& box, const EffectModel& effect, double min_value, @@ -272,7 +259,7 @@ // FIXME: Determine candidacy based on the CSSValue instead of a snapshot // AnimatableValue. - switch (property.CssProperty()) { + switch (property.GetCSSProperty().PropertyID()) { case CSSPropertyOpacity: break; case CSSPropertyRotate: @@ -305,7 +292,8 @@ if (property.IsCSSCustomProperty()) { builder.Append(property.CustomPropertyName()); } else { - builder.Append(getPropertyName(property.CssProperty())); + builder.Append( + getPropertyName(property.GetCSSProperty().PropertyID())); } return FailureCode::Actionable(builder.ToString()); } @@ -409,12 +397,12 @@ const Animation& animation_to_add, const EffectModel& effect_to_add) { const bool affects_opacity = - effect_to_add.Affects(PropertyHandle(CSSPropertyOpacity)); + effect_to_add.Affects(PropertyHandle(GetCSSPropertyOpacity())); const bool affects_transform = effect_to_add.IsTransformRelatedEffect(); const bool affects_filter = - effect_to_add.Affects(PropertyHandle(CSSPropertyFilter)); + effect_to_add.Affects(PropertyHandle(GetCSSPropertyFilter())); const bool affects_backdrop_filter = - effect_to_add.Affects(PropertyHandle(CSSPropertyBackdropFilter)); + effect_to_add.Affects(PropertyHandle(GetCSSPropertyBackdropFilter())); if (!target_element.HasAnimations()) return; @@ -427,15 +415,15 @@ if (!ConsiderAnimationAsIncompatible(*attached_animation, animation_to_add)) continue; - if ((affects_opacity && - attached_animation->Affects(target_element, CSSPropertyOpacity)) || + if ((affects_opacity && attached_animation->Affects( + target_element, GetCSSPropertyOpacity())) || (affects_transform && IsTransformRelatedAnimation(target_element, attached_animation)) || (affects_filter && - attached_animation->Affects(target_element, CSSPropertyFilter)) || + attached_animation->Affects(target_element, GetCSSPropertyFilter())) || (affects_backdrop_filter && attached_animation->Affects(target_element, - CSSPropertyBackdropFilter))) + GetCSSPropertyBackdropFilter()))) attached_animation->CancelAnimationOnCompositor(); } } @@ -662,7 +650,7 @@ CompositorTargetProperty::Type target_property; std::unique_ptr<CompositorAnimationCurve> curve; DCHECK(timing.timing_function); - switch (property.CssProperty()) { + switch (property.GetCSSProperty().PropertyID()) { case CSSPropertyOpacity: { target_property = CompositorTargetProperty::OPACITY; std::unique_ptr<CompositorFloatAnimationCurve> float_curve =
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimations.h b/third_party/WebKit/Source/core/animation/CompositorAnimations.h index 590e999..aece02da0 100644 --- a/third_party/WebKit/Source/core/animation/CompositorAnimations.h +++ b/third_party/WebKit/Source/core/animation/CompositorAnimations.h
@@ -52,9 +52,6 @@ STATIC_ONLY(CompositorAnimations); public: - static bool IsCompositableProperty(CSSPropertyID); - static const CSSPropertyID kCompositableProperties[7]; - struct FailureCode { const bool can_composite; const bool web_developer_actionable;
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp index f5dbc70..d82753f 100644 --- a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp +++ b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
@@ -200,7 +200,8 @@ const String& value, double offset = 0) { scoped_refptr<StringKeyframe> keyframe = StringKeyframe::Create(); - keyframe->SetCSSPropertyValue(id, value, nullptr); + keyframe->SetCSSPropertyValue(id, value, + SecureContextMode::kInsecureContext, nullptr); keyframe->SetComposite(EffectModel::kCompositeReplace); keyframe->SetOffset(offset); keyframe->SetEasing(LinearTimingFunction::Shared()); @@ -372,15 +373,16 @@ CanStartEffectOnCompositorKeyframeMultipleCSSProperties) { scoped_refptr<StringKeyframe> keyframe_good_multiple = CreateDefaultKeyframe(CSSPropertyOpacity, EffectModel::kCompositeReplace); - keyframe_good_multiple->SetCSSPropertyValue(CSSPropertyTransform, "none", - nullptr); + keyframe_good_multiple->SetCSSPropertyValue( + CSSPropertyTransform, "none", SecureContextMode::kInsecureContext, + nullptr); EXPECT_TRUE(DuplicateSingleKeyframeAndTestIsCandidateOnResult( keyframe_good_multiple.get())); scoped_refptr<StringKeyframe> keyframe_bad_multiple_id = CreateDefaultKeyframe(CSSPropertyColor, EffectModel::kCompositeReplace); - keyframe_bad_multiple_id->SetCSSPropertyValue(CSSPropertyOpacity, "0.1", - nullptr); + keyframe_bad_multiple_id->SetCSSPropertyValue( + CSSPropertyOpacity, "0.1", SecureContextMode::kInsecureContext, nullptr); EXPECT_FALSE(DuplicateSingleKeyframeAndTestIsCandidateOnResult( keyframe_bad_multiple_id.get())); } @@ -427,13 +429,17 @@ StringKeyframeVector frames_mixed_properties; scoped_refptr<StringKeyframe> keyframe = StringKeyframe::Create(); keyframe->SetOffset(0); - keyframe->SetCSSPropertyValue(CSSPropertyColor, "red", nullptr); - keyframe->SetCSSPropertyValue(CSSPropertyOpacity, "0", nullptr); + keyframe->SetCSSPropertyValue(CSSPropertyColor, "red", + SecureContextMode::kInsecureContext, nullptr); + keyframe->SetCSSPropertyValue(CSSPropertyOpacity, "0", + SecureContextMode::kInsecureContext, nullptr); frames_mixed_properties.push_back(std::move(keyframe)); keyframe = StringKeyframe::Create(); keyframe->SetOffset(1); - keyframe->SetCSSPropertyValue(CSSPropertyColor, "green", nullptr); - keyframe->SetCSSPropertyValue(CSSPropertyOpacity, "1", nullptr); + keyframe->SetCSSPropertyValue(CSSPropertyColor, "green", + SecureContextMode::kInsecureContext, nullptr); + keyframe->SetCSSPropertyValue(CSSPropertyOpacity, "1", + SecureContextMode::kInsecureContext, nullptr); frames_mixed_properties.push_back(std::move(keyframe)); EXPECT_FALSE(CanStartEffectOnCompositor( timing_, *StringKeyframeEffectModel::Create(frames_mixed_properties)));
diff --git a/third_party/WebKit/Source/core/animation/EffectInput.cpp b/third_party/WebKit/Source/core/animation/EffectInput.cpp index d79d159..b201b21 100644 --- a/third_party/WebKit/Source/core/animation/EffectInput.cpp +++ b/third_party/WebKit/Source/core/animation/EffectInput.cpp
@@ -92,9 +92,12 @@ ? keyframe.SetCSSPropertyValue( AtomicString(property), element.GetDocument().GetPropertyRegistry(), value, + element.GetDocument().SecureContextMode(), style_sheet_contents) - : keyframe.SetCSSPropertyValue(css_property, value, - style_sheet_contents); + : keyframe.SetCSSPropertyValue( + css_property, value, + element.GetDocument().SecureContextMode(), + style_sheet_contents); if (!set_result.did_parse && execution_context) { Document& document = ToDocument(*execution_context); if (document.GetFrame()) { @@ -109,8 +112,9 @@ AnimationInputHelpers::KeyframeAttributeToPresentationAttribute(property, element); if (css_property != CSSPropertyInvalid) { - keyframe.SetPresentationAttributeValue(css_property, value, - style_sheet_contents); + keyframe.SetPresentationAttributeValue( + css_property, value, element.GetDocument().SecureContextMode(), + style_sheet_contents); return; } const QualifiedName* svg_attribute =
diff --git a/third_party/WebKit/Source/core/animation/EffectStack.cpp b/third_party/WebKit/Source/core/animation/EffectStack.cpp index 8bf41841..a111405 100644 --- a/third_party/WebKit/Source/core/animation/EffectStack.cpp +++ b/third_party/WebKit/Source/core/animation/EffectStack.cpp
@@ -168,7 +168,7 @@ } bool EffectStack::GetAnimatedBoundingBox(FloatBox& box, - CSSPropertyID property) const { + const CSSProperty& property) const { FloatBox original_box(box); for (const auto& sampled_effect : sampled_effects_) { if (sampled_effect->Effect() &&
diff --git a/third_party/WebKit/Source/core/animation/EffectStack.h b/third_party/WebKit/Source/core/animation/EffectStack.h index fc4ee986..646c4693 100644 --- a/third_party/WebKit/Source/core/animation/EffectStack.h +++ b/third_party/WebKit/Source/core/animation/EffectStack.h
@@ -69,7 +69,7 @@ KeyframeEffectReadOnly::Priority, PropertyHandleFilter = nullptr); - bool GetAnimatedBoundingBox(FloatBox&, CSSPropertyID) const; + bool GetAnimatedBoundingBox(FloatBox&, const CSSProperty&) const; void Trace(blink::Visitor*); private:
diff --git a/third_party/WebKit/Source/core/animation/EffectStackTest.cpp b/third_party/WebKit/Source/core/animation/EffectStackTest.cpp index c838675..c007526e 100644 --- a/third_party/WebKit/Source/core/animation/EffectStackTest.cpp +++ b/third_party/WebKit/Source/core/animation/EffectStackTest.cpp
@@ -52,10 +52,12 @@ StringKeyframeVector keyframes(2); keyframes[0] = StringKeyframe::Create(); keyframes[0]->SetOffset(0.0); - keyframes[0]->SetCSSPropertyValue(id, value, nullptr); + keyframes[0]->SetCSSPropertyValue( + id, value, SecureContextMode::kInsecureContext, nullptr); keyframes[1] = StringKeyframe::Create(); keyframes[1]->SetOffset(1.0); - keyframes[1]->SetCSSPropertyValue(id, value, nullptr); + keyframes[1]->SetCSSPropertyValue( + id, value, SecureContextMode::kInsecureContext, nullptr); return StringKeyframeEffectModel::Create(keyframes); } @@ -76,7 +78,7 @@ double GetFontSizeValue( const ActiveInterpolationsMap& active_interpolations) { const ActiveInterpolations& interpolations = - active_interpolations.at(PropertyHandle(CSSPropertyFontSize)); + active_interpolations.at(PropertyHandle(GetCSSPropertyFontSize())); EnsureInterpolatedValueCached(interpolations, *document, element); const TypedInterpolationValue* typed_value = @@ -91,7 +93,7 @@ double GetZIndexValue(const ActiveInterpolationsMap& active_interpolations) { const ActiveInterpolations& interpolations = - active_interpolations.at(PropertyHandle(CSSPropertyZIndex)); + active_interpolations.at(PropertyHandle(GetCSSPropertyZIndex())); EnsureInterpolatedValueCached(interpolations, *document, element); const TypedInterpolationValue* typed_value =
diff --git a/third_party/WebKit/Source/core/animation/ElementAnimations.cpp b/third_party/WebKit/Source/core/animation/ElementAnimations.cpp index 275bf53..5819c0c5 100644 --- a/third_party/WebKit/Source/core/animation/ElementAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/ElementAnimations.cpp
@@ -47,16 +47,16 @@ const KeyframeEffectReadOnly& effect = *ToKeyframeEffectReadOnly(animation.effect()); if (effect.IsCurrent()) { - if (effect.Affects(PropertyHandle(CSSPropertyOpacity))) + if (effect.Affects(PropertyHandle(GetCSSPropertyOpacity()))) style.SetHasCurrentOpacityAnimation(true); - if (effect.Affects(PropertyHandle(CSSPropertyTransform)) || - effect.Affects(PropertyHandle(CSSPropertyRotate)) || - effect.Affects(PropertyHandle(CSSPropertyScale)) || - effect.Affects(PropertyHandle(CSSPropertyTranslate))) + if (effect.Affects(PropertyHandle(GetCSSPropertyTransform())) || + effect.Affects(PropertyHandle(GetCSSPropertyRotate())) || + effect.Affects(PropertyHandle(GetCSSPropertyScale())) || + effect.Affects(PropertyHandle(GetCSSPropertyTranslate()))) style.SetHasCurrentTransformAnimation(true); - if (effect.Affects(PropertyHandle(CSSPropertyFilter))) + if (effect.Affects(PropertyHandle(GetCSSPropertyFilter()))) style.SetHasCurrentFilterAnimation(true); - if (effect.Affects(PropertyHandle(CSSPropertyBackdropFilter))) + if (effect.Affects(PropertyHandle(GetCSSPropertyBackdropFilter()))) style.SetHasCurrentBackdropFilterAnimation(true); } } @@ -64,22 +64,22 @@ if (style.HasCurrentOpacityAnimation()) { style.SetIsRunningOpacityAnimationOnCompositor( effect_stack_.HasActiveAnimationsOnCompositor( - PropertyHandle(CSSPropertyOpacity))); + PropertyHandle(GetCSSPropertyOpacity()))); } if (style.HasCurrentTransformAnimation()) { style.SetIsRunningTransformAnimationOnCompositor( effect_stack_.HasActiveAnimationsOnCompositor( - PropertyHandle(CSSPropertyTransform))); + PropertyHandle(GetCSSPropertyTransform()))); } if (style.HasCurrentFilterAnimation()) { style.SetIsRunningFilterAnimationOnCompositor( effect_stack_.HasActiveAnimationsOnCompositor( - PropertyHandle(CSSPropertyFilter))); + PropertyHandle(GetCSSPropertyFilter()))); } if (style.HasCurrentBackdropFilterAnimation()) { style.SetIsRunningBackdropFilterAnimationOnCompositor( effect_stack_.HasActiveAnimationsOnCompositor( - PropertyHandle(CSSPropertyBackdropFilter))); + PropertyHandle(GetCSSPropertyBackdropFilter()))); } }
diff --git a/third_party/WebKit/Source/core/animation/InterpolableValueTest.cpp b/third_party/WebKit/Source/core/animation/InterpolableValueTest.cpp index c5d8baf..3d21a2593d 100644 --- a/third_party/WebKit/Source/core/animation/InterpolableValueTest.cpp +++ b/third_party/WebKit/Source/core/animation/InterpolableValueTest.cpp
@@ -20,7 +20,7 @@ // We require a property that maps to CSSNumberInterpolationType. 'z-index' // suffices for this, and also means we can ignore the AnimatableValues for // the compositor (as z-index isn't compositor-compatible). - PropertyHandle property_handle(CSSPropertyZIndex); + PropertyHandle property_handle(GetCSSPropertyZIndex()); CSSNumberInterpolationType interpolation_type(property_handle); InterpolationValue start(InterpolableNumber::Create(a)); InterpolationValue end(InterpolableNumber::Create(b)); @@ -49,7 +49,7 @@ // We require a property that maps to CSSLengthInterpolationType. 'left' // suffices for this, and also means we can ignore the AnimatableValues for // the compositor (as left isn't compositor-compatible). - PropertyHandle property_handle(CSSPropertyLeft); + PropertyHandle property_handle(GetCSSPropertyLeft()); CSSLengthInterpolationType interpolation_type(property_handle); InterpolationValue start(std::move(list_a)); InterpolationValue end(std::move(list_b));
diff --git a/third_party/WebKit/Source/core/animation/InterpolationEffectTest.cpp b/third_party/WebKit/Source/core/animation/InterpolationEffectTest.cpp index 3b9328d..a62c2b9 100644 --- a/third_party/WebKit/Source/core/animation/InterpolationEffectTest.cpp +++ b/third_party/WebKit/Source/core/animation/InterpolationEffectTest.cpp
@@ -28,7 +28,7 @@ // We require a property that maps to CSSNumberInterpolationType. 'z-index' // suffices for this, and also means we can ignore the AnimatableValues for // the compositor (as z-index isn't compositor-compatible). - PropertyHandle property_handle(CSSPropertyZIndex); + PropertyHandle property_handle(GetCSSPropertyZIndex()); CSSNumberInterpolationType interpolation_type(property_handle); InterpolationValue start(InterpolableNumber::Create(from)); InterpolationValue end(InterpolableNumber::Create(to));
diff --git a/third_party/WebKit/Source/core/animation/Keyframe.h b/third_party/WebKit/Source/core/animation/Keyframe.h index 6630384..ca49980 100644 --- a/third_party/WebKit/Source/core/animation/Keyframe.h +++ b/third_party/WebKit/Source/core/animation/Keyframe.h
@@ -132,7 +132,7 @@ // FIXME: Remove this once CompositorAnimations no longer depends on // AnimatableValues virtual bool PopulateAnimatableValue( - CSSPropertyID, + const CSSProperty&, Element&, const ComputedStyle& base_style, const ComputedStyle* parent_style) const {
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp b/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp index 6682e6d..1d8c77c 100644 --- a/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp +++ b/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp
@@ -82,6 +82,22 @@ return changed; } +namespace { + +static const size_t num_compositable_properties = 7; + +const CSSProperty** CompositableProperties() { + static const CSSProperty* + kCompositableProperties[num_compositable_properties] = { + &GetCSSPropertyOpacity(), &GetCSSPropertyRotate(), + &GetCSSPropertyScale(), &GetCSSPropertyTransform(), + &GetCSSPropertyTranslate(), &GetCSSPropertyFilter(), + &GetCSSPropertyBackdropFilter()}; + return kCompositableProperties; +} + +} // namespace + bool KeyframeEffectModelBase::SnapshotNeutralCompositorKeyframes( Element& element, const ComputedStyle& old_style, @@ -89,7 +105,9 @@ const ComputedStyle* parent_style) const { bool updated = false; EnsureKeyframeGroups(); - for (CSSPropertyID property : CompositorAnimations::kCompositableProperties) { + static const CSSProperty** compositable_properties = CompositableProperties(); + for (size_t i = 0; i < num_compositable_properties; i++) { + const CSSProperty& property = *compositable_properties[i]; if (CSSPropertyEquality::PropertiesEqual(PropertyHandle(property), old_style, new_style)) continue; @@ -114,7 +132,9 @@ bool updated = false; bool has_neutral_compositable_keyframe = false; EnsureKeyframeGroups(); - for (CSSPropertyID property : CompositorAnimations::kCompositableProperties) { + static const CSSProperty** compositable_properties = CompositableProperties(); + for (size_t i = 0; i < num_compositable_properties; i++) { + const CSSProperty& property = *compositable_properties[i]; PropertySpecificKeyframeGroup* keyframe_group = keyframe_groups_->at(PropertyHandle(property)); if (!keyframe_group) @@ -176,10 +196,10 @@ } bool KeyframeEffectModelBase::IsTransformRelatedEffect() const { - return Affects(PropertyHandle(CSSPropertyTransform)) || - Affects(PropertyHandle(CSSPropertyRotate)) || - Affects(PropertyHandle(CSSPropertyScale)) || - Affects(PropertyHandle(CSSPropertyTranslate)); + return Affects(PropertyHandle(GetCSSPropertyTransform())) || + Affects(PropertyHandle(GetCSSPropertyRotate())) || + Affects(PropertyHandle(GetCSSPropertyScale())) || + Affects(PropertyHandle(GetCSSPropertyTranslate())); } void KeyframeEffectModelBase::EnsureKeyframeGroups() const {
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectModelTest.cpp b/third_party/WebKit/Source/core/animation/KeyframeEffectModelTest.cpp index 80127b18..c9786b7 100644 --- a/third_party/WebKit/Source/core/animation/KeyframeEffectModelTest.cpp +++ b/third_party/WebKit/Source/core/animation/KeyframeEffectModelTest.cpp
@@ -105,10 +105,12 @@ StringKeyframeVector keyframes(2); keyframes[0] = StringKeyframe::Create(); keyframes[0]->SetOffset(0.0); - keyframes[0]->SetCSSPropertyValue(property, zero_value, nullptr); + keyframes[0]->SetCSSPropertyValue( + property, zero_value, SecureContextMode::kInsecureContext, nullptr); keyframes[1] = StringKeyframe::Create(); keyframes[1]->SetOffset(1.0); - keyframes[1]->SetCSSPropertyValue(property, one_value, nullptr); + keyframes[1]->SetCSSPropertyValue( + property, one_value, SecureContextMode::kInsecureContext, nullptr); return keyframes; } @@ -118,7 +120,7 @@ ToInvalidatableInterpolation(interpolation_value.get()); const PropertyHandle& property_handle = interpolation->GetProperty(); ASSERT_TRUE(property_handle.IsCSSProperty()); - ASSERT_EQ(property, property_handle.CssProperty()); + ASSERT_EQ(property, property_handle.GetCSSProperty().PropertyID()); } Interpolation* FindValue(Vector<scoped_refptr<Interpolation>>& values, @@ -126,7 +128,8 @@ for (auto& value : values) { const PropertyHandle& property = ToInvalidatableInterpolation(value.get())->GetProperty(); - if (property.IsCSSProperty() && property.CssProperty() == id) + if (property.IsCSSProperty() && + property.GetCSSProperty().PropertyID() == id) return value.get(); } return nullptr; @@ -262,7 +265,9 @@ StringKeyframeVector keyframes(1); keyframes[0] = StringKeyframe::Create(); keyframes[0]->SetOffset(0.0); - keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", nullptr); + keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", + SecureContextMode::kInsecureContext, + nullptr); StringKeyframeEffectModel* effect = StringKeyframeEffectModel::Create(keyframes); @@ -276,7 +281,8 @@ StringKeyframeVector keyframes(1); keyframes[0] = StringKeyframe::Create(); keyframes[0]->SetOffset(1.0); - keyframes[0]->SetCSSPropertyValue(CSSPropertyLeft, "5px", nullptr); + keyframes[0]->SetCSSPropertyValue( + CSSPropertyLeft, "5px", SecureContextMode::kInsecureContext, nullptr); StringKeyframeEffectModel* effect = StringKeyframeEffectModel::Create(keyframes); @@ -289,14 +295,19 @@ StringKeyframeVector keyframes(3); keyframes[0] = StringKeyframe::Create(); keyframes[0]->SetOffset(0.0); - keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", nullptr); + keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", + SecureContextMode::kInsecureContext, + nullptr); keyframes[1] = StringKeyframe::Create(); keyframes[1]->SetOffset(0.5); keyframes[1]->SetCSSPropertyValue(CSSPropertyFontFamily, "sans-serif", + SecureContextMode::kInsecureContext, nullptr); keyframes[2] = StringKeyframe::Create(); keyframes[2]->SetOffset(1.0); - keyframes[2]->SetCSSPropertyValue(CSSPropertyFontFamily, "cursive", nullptr); + keyframes[2]->SetCSSPropertyValue(CSSPropertyFontFamily, "cursive", + SecureContextMode::kInsecureContext, + nullptr); StringKeyframeEffectModel* effect = StringKeyframeEffectModel::Create(keyframes); @@ -310,12 +321,18 @@ TEST_F(AnimationKeyframeEffectModel, EndKeyframeOffsetsUnspecified) { StringKeyframeVector keyframes(3); keyframes[0] = StringKeyframe::Create(); - keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", nullptr); + keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", + SecureContextMode::kInsecureContext, + nullptr); keyframes[1] = StringKeyframe::Create(); keyframes[1]->SetOffset(0.5); - keyframes[1]->SetCSSPropertyValue(CSSPropertyFontFamily, "cursive", nullptr); + keyframes[1]->SetCSSPropertyValue(CSSPropertyFontFamily, "cursive", + SecureContextMode::kInsecureContext, + nullptr); keyframes[2] = StringKeyframe::Create(); - keyframes[2]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", nullptr); + keyframes[2]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", + SecureContextMode::kInsecureContext, + nullptr); StringKeyframeEffectModel* effect = StringKeyframeEffectModel::Create(keyframes); @@ -332,13 +349,19 @@ StringKeyframeVector keyframes(3); keyframes[0] = StringKeyframe::Create(); keyframes[0]->SetOffset(0.0); - keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", nullptr); + keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", + SecureContextMode::kInsecureContext, + nullptr); keyframes[1] = StringKeyframe::Create(); keyframes[1]->SetOffset(0.5); - keyframes[1]->SetCSSPropertyValue(CSSPropertyFontFamily, "cursive", nullptr); + keyframes[1]->SetCSSPropertyValue(CSSPropertyFontFamily, "cursive", + SecureContextMode::kInsecureContext, + nullptr); keyframes[2] = StringKeyframe::Create(); keyframes[2]->SetOffset(1.0); - keyframes[2]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", nullptr); + keyframes[2]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", + SecureContextMode::kInsecureContext, + nullptr); StringKeyframeEffectModel* effect = StringKeyframeEffectModel::Create(keyframes); @@ -355,35 +378,48 @@ StringKeyframeVector keyframes(9); keyframes[0] = StringKeyframe::Create(); keyframes[0]->SetOffset(0.0); - keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", nullptr); + keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", + SecureContextMode::kInsecureContext, + nullptr); keyframes[1] = StringKeyframe::Create(); keyframes[1]->SetOffset(0.1); keyframes[1]->SetCSSPropertyValue(CSSPropertyFontFamily, "sans-serif", + SecureContextMode::kInsecureContext, nullptr); keyframes[2] = StringKeyframe::Create(); keyframes[2]->SetOffset(0.1); keyframes[2]->SetCSSPropertyValue(CSSPropertyFontFamily, "monospace", + SecureContextMode::kInsecureContext, nullptr); keyframes[3] = StringKeyframe::Create(); keyframes[3]->SetOffset(0.5); - keyframes[3]->SetCSSPropertyValue(CSSPropertyFontFamily, "cursive", nullptr); + keyframes[3]->SetCSSPropertyValue(CSSPropertyFontFamily, "cursive", + SecureContextMode::kInsecureContext, + nullptr); keyframes[4] = StringKeyframe::Create(); keyframes[4]->SetOffset(0.5); - keyframes[4]->SetCSSPropertyValue(CSSPropertyFontFamily, "fantasy", nullptr); + keyframes[4]->SetCSSPropertyValue(CSSPropertyFontFamily, "fantasy", + SecureContextMode::kInsecureContext, + nullptr); keyframes[5] = StringKeyframe::Create(); keyframes[5]->SetOffset(0.5); keyframes[5]->SetCSSPropertyValue(CSSPropertyFontFamily, "system-ui", + SecureContextMode::kInsecureContext, nullptr); keyframes[6] = StringKeyframe::Create(); keyframes[6]->SetOffset(0.9); - keyframes[6]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", nullptr); + keyframes[6]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", + SecureContextMode::kInsecureContext, + nullptr); keyframes[7] = StringKeyframe::Create(); keyframes[7]->SetOffset(0.9); keyframes[7]->SetCSSPropertyValue(CSSPropertyFontFamily, "sans-serif", + SecureContextMode::kInsecureContext, nullptr); keyframes[8] = StringKeyframe::Create(); keyframes[8]->SetOffset(1.0); keyframes[8]->SetCSSPropertyValue(CSSPropertyFontFamily, "monospace", + SecureContextMode::kInsecureContext, nullptr); StringKeyframeEffectModel* effect = @@ -410,10 +446,12 @@ StringKeyframeVector keyframes(2); keyframes[0] = StringKeyframe::Create(); keyframes[0]->SetOffset(0.0); - keyframes[0]->SetCSSPropertyValue(CSSPropertyLeft, "3px", nullptr); + keyframes[0]->SetCSSPropertyValue( + CSSPropertyLeft, "3px", SecureContextMode::kInsecureContext, nullptr); keyframes[1] = StringKeyframe::Create(); keyframes[1]->SetOffset(1.0); - keyframes[1]->SetCSSPropertyValue(CSSPropertyLeft, "5px", nullptr); + keyframes[1]->SetCSSPropertyValue( + CSSPropertyLeft, "5px", SecureContextMode::kInsecureContext, nullptr); keyframes[1]->SetComposite(EffectModel::kCompositeAdd); StringKeyframeEffectModel* effect = @@ -427,12 +465,20 @@ StringKeyframeVector keyframes(2); keyframes[0] = StringKeyframe::Create(); keyframes[0]->SetOffset(0.0); - keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", nullptr); - keyframes[0]->SetCSSPropertyValue(CSSPropertyFontStyle, "normal", nullptr); + keyframes[0]->SetCSSPropertyValue(CSSPropertyFontFamily, "serif", + SecureContextMode::kInsecureContext, + nullptr); + keyframes[0]->SetCSSPropertyValue(CSSPropertyFontStyle, "normal", + SecureContextMode::kInsecureContext, + nullptr); keyframes[1] = StringKeyframe::Create(); keyframes[1]->SetOffset(1.0); - keyframes[1]->SetCSSPropertyValue(CSSPropertyFontFamily, "cursive", nullptr); - keyframes[1]->SetCSSPropertyValue(CSSPropertyFontStyle, "oblique", nullptr); + keyframes[1]->SetCSSPropertyValue(CSSPropertyFontFamily, "cursive", + SecureContextMode::kInsecureContext, + nullptr); + keyframes[1]->SetCSSPropertyValue(CSSPropertyFontStyle, "oblique", + SecureContextMode::kInsecureContext, + nullptr); StringKeyframeEffectModel* effect = StringKeyframeEffectModel::Create(keyframes); @@ -480,14 +526,17 @@ StringKeyframeVector keyframes(3); keyframes[0] = StringKeyframe::Create(); keyframes[0]->SetOffset(0.0); - keyframes[0]->SetCSSPropertyValue(CSSPropertyLeft, "1px", nullptr); + keyframes[0]->SetCSSPropertyValue( + CSSPropertyLeft, "1px", SecureContextMode::kInsecureContext, nullptr); keyframes[0]->SetComposite(EffectModel::kCompositeAdd); keyframes[1] = StringKeyframe::Create(); keyframes[1]->SetOffset(0.5); - keyframes[1]->SetCSSPropertyValue(CSSPropertyLeft, "1px", nullptr); + keyframes[1]->SetCSSPropertyValue( + CSSPropertyLeft, "1px", SecureContextMode::kInsecureContext, nullptr); keyframes[2] = StringKeyframe::Create(); keyframes[2]->SetOffset(1.0); - keyframes[2]->SetCSSPropertyValue(CSSPropertyLeft, "1px", nullptr); + keyframes[2]->SetCSSPropertyValue( + CSSPropertyLeft, "1px", SecureContextMode::kInsecureContext, nullptr); StringKeyframeEffectModel* effect = StringKeyframeEffectModel::Create(keyframes); @@ -516,12 +565,14 @@ StringKeyframeVector keyframes(1); keyframes[0] = StringKeyframe::Create(); keyframes[0]->SetOffset(0.5); - keyframes[0]->SetCSSPropertyValue(CSSPropertyLeft, "4px", nullptr); + keyframes[0]->SetCSSPropertyValue( + CSSPropertyLeft, "4px", SecureContextMode::kInsecureContext, nullptr); StringKeyframeEffectModel* effect = StringKeyframeEffectModel::Create(keyframes); const StringPropertySpecificKeyframeVector& property_specific_keyframes = - effect->GetPropertySpecificKeyframes(PropertyHandle(CSSPropertyLeft)); + effect->GetPropertySpecificKeyframes( + PropertyHandle(GetCSSPropertyLeft())); EXPECT_EQ(3U, property_specific_keyframes.size()); EXPECT_DOUBLE_EQ(0.0, property_specific_keyframes[0]->Offset()); EXPECT_DOUBLE_EQ(0.5, property_specific_keyframes[1]->Offset());
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.cpp b/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.cpp index fb6063e..608ee50 100644 --- a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.cpp +++ b/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.cpp
@@ -144,10 +144,10 @@ return false; bool affects_transform = - GetAnimation()->Affects(*target_, CSSPropertyTransform) || - GetAnimation()->Affects(*target_, CSSPropertyScale) || - GetAnimation()->Affects(*target_, CSSPropertyRotate) || - GetAnimation()->Affects(*target_, CSSPropertyTranslate); + GetAnimation()->Affects(*target_, GetCSSPropertyTransform()) || + GetAnimation()->Affects(*target_, GetCSSPropertyScale()) || + GetAnimation()->Affects(*target_, GetCSSPropertyRotate()) || + GetAnimation()->Affects(*target_, GetCSSPropertyTranslate()); if (GetAnimation()->HasActiveAnimationsOnCompositor()) { if (target_->GetComputedStyle()->HasOffset() && affects_transform)
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectTest.cpp b/third_party/WebKit/Source/core/animation/KeyframeEffectTest.cpp index 8178536..8518313 100644 --- a/third_party/WebKit/Source/core/animation/KeyframeEffectTest.cpp +++ b/third_party/WebKit/Source/core/animation/KeyframeEffectTest.cpp
@@ -125,10 +125,10 @@ const CSSValue& keyframe1_width = ToStringKeyframe(keyframes[0].get()) - ->CssPropertyValue(PropertyHandle(CSSPropertyWidth)); + ->CssPropertyValue(PropertyHandle(GetCSSPropertyWidth())); const CSSValue& keyframe2_width = ToStringKeyframe(keyframes[1].get()) - ->CssPropertyValue(PropertyHandle(CSSPropertyWidth)); + ->CssPropertyValue(PropertyHandle(GetCSSPropertyWidth())); EXPECT_EQ("100px", keyframe1_width.CssText()); EXPECT_EQ("0px", keyframe2_width.CssText());
diff --git a/third_party/WebKit/Source/core/animation/PropertyHandle.cpp b/third_party/WebKit/Source/core/animation/PropertyHandle.cpp index 9612457..2c2fd9c8 100644 --- a/third_party/WebKit/Source/core/animation/PropertyHandle.cpp +++ b/third_party/WebKit/Source/core/animation/PropertyHandle.cpp
@@ -28,11 +28,11 @@ unsigned PropertyHandle::GetHash() const { switch (handle_type_) { case kHandleCSSProperty: - return css_property_; + return css_property_->PropertyID(); case kHandleCSSCustomProperty: return AtomicStringHash::GetHash(property_name_); case kHandlePresentationAttribute: - return -css_property_; + return -css_property_->PropertyID(); case kHandleSVGAttribute: return QualifiedNameHash::GetHash(*svg_attribute_); default:
diff --git a/third_party/WebKit/Source/core/animation/PropertyHandle.h b/third_party/WebKit/Source/core/animation/PropertyHandle.h index 6d9245ff..d8d8a30 100644 --- a/third_party/WebKit/Source/core/animation/PropertyHandle.h +++ b/third_party/WebKit/Source/core/animation/PropertyHandle.h
@@ -7,6 +7,7 @@ #include "core/CSSPropertyNames.h" #include "core/CoreExport.h" +#include "core/css/properties/CSSProperty.h" #include "core/dom/QualifiedName.h" #include "platform/wtf/Allocator.h" @@ -17,18 +18,18 @@ DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); public: - explicit PropertyHandle(CSSPropertyID property, + explicit PropertyHandle(const CSSProperty& property, bool is_presentation_attribute = false) : handle_type_(is_presentation_attribute ? kHandlePresentationAttribute : kHandleCSSProperty), - css_property_(property) { - DCHECK_NE(property, CSSPropertyInvalid); - DCHECK_NE(property, CSSPropertyVariable); + css_property_(&property) { + DCHECK_NE(property.PropertyID(), CSSPropertyInvalid); + DCHECK_NE(property.PropertyID(), CSSPropertyVariable); } explicit PropertyHandle(const AtomicString& property_name) : handle_type_(kHandleCSSCustomProperty), - svg_attribute_(nullptr), + css_property_(&GetCSSPropertyVariable()), property_name_(property_name) {} explicit PropertyHandle(const QualifiedName& attribute_name) @@ -44,10 +45,9 @@ bool IsCSSProperty() const { return handle_type_ == kHandleCSSProperty || IsCSSCustomProperty(); } - CSSPropertyID CssProperty() const { + const CSSProperty& GetCSSProperty() const { DCHECK(IsCSSProperty()); - return handle_type_ == kHandleCSSProperty ? css_property_ - : CSSPropertyVariable; + return *css_property_; } bool IsCSSCustomProperty() const { @@ -61,9 +61,9 @@ bool IsPresentationAttribute() const { return handle_type_ == kHandlePresentationAttribute; } - CSSPropertyID PresentationAttribute() const { + const CSSProperty& PresentationAttribute() const { DCHECK(IsPresentationAttribute()); - return css_property_; + return *css_property_; } bool IsSVGAttribute() const { return handle_type_ == kHandleSVGAttribute; } @@ -99,7 +99,7 @@ HandleType handle_type_; union { - CSSPropertyID css_property_; + const CSSProperty* css_property_; const QualifiedName* svg_attribute_; }; AtomicString property_name_;
diff --git a/third_party/WebKit/Source/core/animation/PropertyHandleTest.cpp b/third_party/WebKit/Source/core/animation/PropertyHandleTest.cpp index 4c9518ee..f906c13 100644 --- a/third_party/WebKit/Source/core/animation/PropertyHandleTest.cpp +++ b/third_party/WebKit/Source/core/animation/PropertyHandleTest.cpp
@@ -18,25 +18,31 @@ AtomicString name_a = "--a"; AtomicString name_b = "--b"; - EXPECT_TRUE(PropertyHandle(CSSPropertyOpacity) == - PropertyHandle(CSSPropertyOpacity)); - EXPECT_FALSE(PropertyHandle(CSSPropertyOpacity) != - PropertyHandle(CSSPropertyOpacity)); - EXPECT_FALSE(PropertyHandle(CSSPropertyOpacity) == - PropertyHandle(CSSPropertyTransform)); - EXPECT_TRUE(PropertyHandle(CSSPropertyOpacity) != - PropertyHandle(CSSPropertyTransform)); - EXPECT_FALSE(PropertyHandle(CSSPropertyOpacity) == PropertyHandle(name_a)); - EXPECT_TRUE(PropertyHandle(CSSPropertyOpacity) != PropertyHandle(name_a)); - EXPECT_FALSE(PropertyHandle(CSSPropertyOpacity) == + EXPECT_TRUE(PropertyHandle(GetCSSPropertyOpacity()) == + PropertyHandle(GetCSSPropertyOpacity())); + EXPECT_FALSE(PropertyHandle(GetCSSPropertyOpacity()) != + PropertyHandle(GetCSSPropertyOpacity())); + EXPECT_FALSE(PropertyHandle(GetCSSPropertyOpacity()) == + PropertyHandle(GetCSSPropertyTransform())); + EXPECT_TRUE(PropertyHandle(GetCSSPropertyOpacity()) != + PropertyHandle(GetCSSPropertyTransform())); + EXPECT_FALSE(PropertyHandle(GetCSSPropertyOpacity()) == + PropertyHandle(name_a)); + EXPECT_TRUE(PropertyHandle(GetCSSPropertyOpacity()) != + PropertyHandle(name_a)); + EXPECT_FALSE(PropertyHandle(GetCSSPropertyOpacity()) == PropertyHandle(amplitudeAttr)); - EXPECT_TRUE(PropertyHandle(CSSPropertyOpacity) != + EXPECT_TRUE(PropertyHandle(GetCSSPropertyOpacity()) != PropertyHandle(amplitudeAttr)); - EXPECT_FALSE(PropertyHandle(name_a) == PropertyHandle(CSSPropertyOpacity)); - EXPECT_TRUE(PropertyHandle(name_a) != PropertyHandle(CSSPropertyOpacity)); - EXPECT_FALSE(PropertyHandle(name_a) == PropertyHandle(CSSPropertyTransform)); - EXPECT_TRUE(PropertyHandle(name_a) != PropertyHandle(CSSPropertyTransform)); + EXPECT_FALSE(PropertyHandle(name_a) == + PropertyHandle(GetCSSPropertyOpacity())); + EXPECT_TRUE(PropertyHandle(name_a) != + PropertyHandle(GetCSSPropertyOpacity())); + EXPECT_FALSE(PropertyHandle(name_a) == + PropertyHandle(GetCSSPropertyTransform())); + EXPECT_TRUE(PropertyHandle(name_a) != + PropertyHandle(GetCSSPropertyTransform())); EXPECT_TRUE(PropertyHandle(name_a) == PropertyHandle(name_a)); EXPECT_FALSE(PropertyHandle(name_a) != PropertyHandle(name_a)); EXPECT_FALSE(PropertyHandle(name_a) == PropertyHandle(name_b)); @@ -45,9 +51,9 @@ EXPECT_TRUE(PropertyHandle(name_a) != PropertyHandle(amplitudeAttr)); EXPECT_FALSE(PropertyHandle(amplitudeAttr) == - PropertyHandle(CSSPropertyOpacity)); + PropertyHandle(GetCSSPropertyOpacity())); EXPECT_TRUE(PropertyHandle(amplitudeAttr) != - PropertyHandle(CSSPropertyOpacity)); + PropertyHandle(GetCSSPropertyOpacity())); EXPECT_FALSE(PropertyHandle(amplitudeAttr) == PropertyHandle(name_a)); EXPECT_TRUE(PropertyHandle(amplitudeAttr) != PropertyHandle(name_a)); EXPECT_TRUE(PropertyHandle(amplitudeAttr) == PropertyHandle(amplitudeAttr)); @@ -60,17 +66,17 @@ AtomicString name_a = "--a"; AtomicString name_b = "--b"; - EXPECT_TRUE(PropertyHandle(CSSPropertyOpacity).GetHash() == - PropertyHandle(CSSPropertyOpacity).GetHash()); - EXPECT_FALSE(PropertyHandle(CSSPropertyOpacity).GetHash() == + EXPECT_TRUE(PropertyHandle(GetCSSPropertyOpacity()).GetHash() == + PropertyHandle(GetCSSPropertyOpacity()).GetHash()); + EXPECT_FALSE(PropertyHandle(GetCSSPropertyOpacity()).GetHash() == PropertyHandle(name_a).GetHash()); - EXPECT_FALSE(PropertyHandle(CSSPropertyOpacity).GetHash() == - PropertyHandle(CSSPropertyTransform).GetHash()); - EXPECT_FALSE(PropertyHandle(CSSPropertyOpacity).GetHash() == + EXPECT_FALSE(PropertyHandle(GetCSSPropertyOpacity()).GetHash() == + PropertyHandle(GetCSSPropertyTransform()).GetHash()); + EXPECT_FALSE(PropertyHandle(GetCSSPropertyOpacity()).GetHash() == PropertyHandle(amplitudeAttr).GetHash()); EXPECT_FALSE(PropertyHandle(name_a).GetHash() == - PropertyHandle(CSSPropertyOpacity).GetHash()); + PropertyHandle(GetCSSPropertyOpacity()).GetHash()); EXPECT_TRUE(PropertyHandle(name_a).GetHash() == PropertyHandle(name_a).GetHash()); EXPECT_FALSE(PropertyHandle(name_a).GetHash() == @@ -79,7 +85,7 @@ PropertyHandle(exponentAttr).GetHash()); EXPECT_FALSE(PropertyHandle(amplitudeAttr).GetHash() == - PropertyHandle(CSSPropertyOpacity).GetHash()); + PropertyHandle(GetCSSPropertyOpacity()).GetHash()); EXPECT_FALSE(PropertyHandle(amplitudeAttr).GetHash() == PropertyHandle(name_a).GetHash()); EXPECT_TRUE(PropertyHandle(amplitudeAttr).GetHash() == @@ -91,21 +97,23 @@ TEST_F(PropertyHandleTest, Accessors) { AtomicString name = "--x"; - EXPECT_TRUE(PropertyHandle(CSSPropertyOpacity).IsCSSProperty()); + EXPECT_TRUE(PropertyHandle(GetCSSPropertyOpacity()).IsCSSProperty()); EXPECT_TRUE(PropertyHandle(name).IsCSSProperty()); EXPECT_FALSE(PropertyHandle(amplitudeAttr).IsCSSProperty()); - EXPECT_FALSE(PropertyHandle(CSSPropertyOpacity).IsSVGAttribute()); + EXPECT_FALSE(PropertyHandle(GetCSSPropertyOpacity()).IsSVGAttribute()); EXPECT_FALSE(PropertyHandle(name).IsSVGAttribute()); EXPECT_TRUE(PropertyHandle(amplitudeAttr).IsSVGAttribute()); - EXPECT_FALSE(PropertyHandle(CSSPropertyOpacity).IsCSSCustomProperty()); + EXPECT_FALSE(PropertyHandle(GetCSSPropertyOpacity()).IsCSSCustomProperty()); EXPECT_TRUE(PropertyHandle(name).IsCSSCustomProperty()); EXPECT_FALSE(PropertyHandle(amplitudeAttr).IsCSSCustomProperty()); - EXPECT_EQ(PropertyHandle(CSSPropertyOpacity).CssProperty(), - CSSPropertyOpacity); - EXPECT_EQ(PropertyHandle(name).CssProperty(), CSSPropertyVariable); + EXPECT_EQ( + PropertyHandle(GetCSSPropertyOpacity()).GetCSSProperty().PropertyID(), + CSSPropertyOpacity); + EXPECT_EQ(PropertyHandle(name).GetCSSProperty().PropertyID(), + CSSPropertyVariable); EXPECT_EQ(PropertyHandle(name).CustomPropertyName(), name); EXPECT_EQ(PropertyHandle(amplitudeAttr).SvgAttribute(), amplitudeAttr); }
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp index dc419023c..1080145 100644 --- a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp +++ b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp
@@ -25,16 +25,18 @@ const AtomicString& property_name, const PropertyRegistry* registry, const String& value, + SecureContextMode secure_context_mode, StyleSheetContents* style_sheet_contents) { bool is_animation_tainted = true; - return css_property_map_->SetProperty(property_name, registry, value, false, - style_sheet_contents, - is_animation_tainted); + return css_property_map_->SetProperty( + property_name, registry, value, false, secure_context_mode, + style_sheet_contents, is_animation_tainted); } MutableCSSPropertyValueSet::SetResult StringKeyframe::SetCSSPropertyValue( CSSPropertyID property, const String& value, + SecureContextMode secure_context_mode, StyleSheetContents* style_sheet_contents) { DCHECK_NE(property, CSSPropertyInvalid); if (CSSAnimations::IsAnimationAffectingProperty(property)) { @@ -42,8 +44,8 @@ bool did_change = false; return MutableCSSPropertyValueSet::SetResult{did_parse, did_change}; } - return css_property_map_->SetProperty(property, value, false, - style_sheet_contents); + return css_property_map_->SetProperty( + property, value, false, secure_context_mode, style_sheet_contents); } void StringKeyframe::SetCSSPropertyValue(CSSPropertyID property, @@ -56,11 +58,13 @@ void StringKeyframe::SetPresentationAttributeValue( CSSPropertyID property, const String& value, + SecureContextMode secure_context_mode, StyleSheetContents* style_sheet_contents) { DCHECK_NE(property, CSSPropertyInvalid); - if (!CSSAnimations::IsAnimationAffectingProperty(property)) - presentation_attribute_map_->SetProperty(property, value, false, - style_sheet_contents); + if (!CSSAnimations::IsAnimationAffectingProperty(property)) { + presentation_attribute_map_->SetProperty( + property, value, false, secure_context_mode, style_sheet_contents); + } } void StringKeyframe::SetSVGAttributeValue(const QualifiedName& attribute_name, @@ -75,20 +79,22 @@ for (unsigned i = 0; i < css_property_map_->PropertyCount(); ++i) { CSSPropertyValueSet::PropertyReference property_reference = css_property_map_->PropertyAt(i); - DCHECK(!CSSProperty::Get(property_reference.Id()).IsShorthand()) + const CSSProperty& property = property_reference.Property(); + DCHECK(!property.IsShorthand()) << "Web Animations: Encountered unexpanded shorthand CSS property (" - << property_reference.Id() << ")."; - if (property_reference.Id() == CSSPropertyVariable) + << property.PropertyID() << ")."; + if (property.PropertyID() == CSSPropertyVariable) properties.insert(PropertyHandle( ToCSSCustomPropertyDeclaration(property_reference.Value()) .GetName())); else - properties.insert(PropertyHandle(property_reference.Id(), false)); + properties.insert(PropertyHandle(property, false)); } - for (unsigned i = 0; i < presentation_attribute_map_->PropertyCount(); ++i) - properties.insert( - PropertyHandle(presentation_attribute_map_->PropertyAt(i).Id(), true)); + for (unsigned i = 0; i < presentation_attribute_map_->PropertyCount(); ++i) { + properties.insert(PropertyHandle( + presentation_attribute_map_->PropertyAt(i).Property(), true)); + } for (auto* const key : svg_attribute_map_.Keys()) properties.insert(PropertyHandle(*key)); @@ -107,7 +113,7 @@ value = CssPropertyValue(property).CssText(); } else if (property.IsPresentationAttribute()) { const auto& attribute = property.PresentationAttribute(); - value = PresentationAttributeValue(attribute).CssText(); + value = PresentationAttributeValue(attribute.PropertyID()).CssText(); } else { DCHECK(property.IsSVGAttribute()); value = SvgPropertyValue(property.SvgAttribute()); @@ -132,7 +138,8 @@ if (property.IsPresentationAttribute()) { return CSSPropertySpecificKeyframe::Create( offset, &Easing(), - &PresentationAttributeValue(property.PresentationAttribute()), + &PresentationAttributeValue( + property.PresentationAttribute().PropertyID()), Composite()); } @@ -143,7 +150,7 @@ } bool StringKeyframe::CSSPropertySpecificKeyframe::PopulateAnimatableValue( - CSSPropertyID property, + const CSSProperty& property, Element& element, const ComputedStyle& base_style, const ComputedStyle* parent_style) const {
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.h b/third_party/WebKit/Source/core/animation/StringKeyframe.h index 33af19a..90f7cdb 100644 --- a/third_party/WebKit/Source/core/animation/StringKeyframe.h +++ b/third_party/WebKit/Source/core/animation/StringKeyframe.h
@@ -35,12 +35,17 @@ const AtomicString& property_name, const PropertyRegistry*, const String& value, + SecureContextMode, StyleSheetContents*); - MutableCSSPropertyValueSet::SetResult - SetCSSPropertyValue(CSSPropertyID, const String& value, StyleSheetContents*); + MutableCSSPropertyValueSet::SetResult SetCSSPropertyValue( + CSSPropertyID, + const String& value, + SecureContextMode, + StyleSheetContents*); void SetCSSPropertyValue(CSSPropertyID, const CSSValue&); void SetPresentationAttributeValue(CSSPropertyID, const String& value, + SecureContextMode, StyleSheetContents*); void SetSVGAttributeValue(const QualifiedName&, const String& value); @@ -50,7 +55,8 @@ index = css_property_map_->FindPropertyIndex(property.CustomPropertyName()); else - index = css_property_map_->FindPropertyIndex(property.CssProperty()); + index = css_property_map_->FindPropertyIndex( + property.GetCSSProperty().PropertyID()); CHECK_GE(index, 0); return css_property_map_->PropertyAt(static_cast<unsigned>(index)).Value(); } @@ -84,7 +90,7 @@ const CSSValue* Value() const { return value_.Get(); } - bool PopulateAnimatableValue(CSSPropertyID, + bool PopulateAnimatableValue(const CSSProperty&, Element&, const ComputedStyle& base_style, const ComputedStyle* parent_style) const final;
diff --git a/third_party/WebKit/Source/core/animation/TransitionInterpolation.h b/third_party/WebKit/Source/core/animation/TransitionInterpolation.h index 28b83e0..a98df2d 100644 --- a/third_party/WebKit/Source/core/animation/TransitionInterpolation.h +++ b/third_party/WebKit/Source/core/animation/TransitionInterpolation.h
@@ -79,9 +79,8 @@ compositor_end_(std::move(compositor_end)), cached_interpolable_value_(merge_.start_interpolable_value->Clone()) { DCHECK(merge_); - DCHECK_EQ( - compositor_start_ && compositor_end_, - CompositorAnimations::IsCompositableProperty(property_.CssProperty())); + DCHECK_EQ(compositor_start_ && compositor_end_, + property_.GetCSSProperty().IsCompositableProperty()); } private:
diff --git a/third_party/WebKit/Source/core/animation/TransitionKeyframe.cpp b/third_party/WebKit/Source/core/animation/TransitionKeyframe.cpp index 9a267b5..7433fe9 100644 --- a/third_party/WebKit/Source/core/animation/TransitionKeyframe.cpp +++ b/third_party/WebKit/Source/core/animation/TransitionKeyframe.cpp
@@ -14,9 +14,8 @@ void TransitionKeyframe::SetCompositorValue( scoped_refptr<AnimatableValue> compositor_value) { - DCHECK_EQ( - CompositorAnimations::IsCompositableProperty(property_.CssProperty()), - static_cast<bool>(compositor_value.get())); + DCHECK_EQ(property_.GetCSSProperty().IsCompositableProperty(), + static_cast<bool>(compositor_value.get())); compositor_value_ = std::move(compositor_value); }
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp index c3113d0..63520d6 100644 --- a/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp +++ b/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp
@@ -53,11 +53,11 @@ } scoped_refptr<AnimatableValue> CSSAnimatableValueFactory::Create( - CSSPropertyID property, + const CSSProperty& property, const ComputedStyle& style) { - DCHECK(CSSProperty::Get(property).IsInterpolable()); - DCHECK(CompositorAnimations::IsCompositableProperty(property)); - switch (property) { + DCHECK(property.IsInterpolable()); + DCHECK(property.IsCompositableProperty()); + switch (property.PropertyID()) { case CSSPropertyOpacity: return AnimatableDouble::Create(style.Opacity()); case CSSPropertyFilter:
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.h b/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.h index 6ec516e8..21cdd4e 100644 --- a/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.h +++ b/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.h
@@ -34,6 +34,7 @@ #include "base/memory/scoped_refptr.h" #include "core/CSSPropertyNames.h" #include "core/animation/animatable/AnimatableValue.h" +#include "core/css/properties/CSSProperty.h" #include "platform/wtf/Allocator.h" namespace blink { @@ -44,7 +45,7 @@ STATIC_ONLY(CSSAnimatableValueFactory); public: - static scoped_refptr<AnimatableValue> Create(CSSPropertyID, + static scoped_refptr<AnimatableValue> Create(const CSSProperty&, const ComputedStyle&); };
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp index 39dea57..4125200 100644 --- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
@@ -151,9 +151,11 @@ size_t target_index = 0; for (size_t i = 1; i < keyframes.size(); i++) { if (keyframes[i]->Offset() == keyframes[target_index]->Offset()) { - for (const auto& property : keyframes[i]->Properties()) + for (const auto& property : keyframes[i]->Properties()) { keyframes[target_index]->SetCSSPropertyValue( - property.CssProperty(), keyframes[i]->CssPropertyValue(property)); + property.GetCSSProperty().PropertyID(), + keyframes[i]->CssPropertyValue(property)); + } } else { target_index++; keyframes[target_index] = keyframes[i]; @@ -262,8 +264,8 @@ bool update_compositor_keyframes = false; if ((transform_zoom_changed || was_viewport_resized) && - (keyframe_effect->Affects(PropertyHandle(CSSPropertyTransform)) || - keyframe_effect->Affects(PropertyHandle(CSSPropertyTranslate))) && + (keyframe_effect->Affects(PropertyHandle(GetCSSPropertyTransform())) || + keyframe_effect->Affects(PropertyHandle(GetCSSPropertyTranslate()))) && keyframe_effect->SnapshotAllCompositorKeyframes(element, style, parent_style)) { update_compositor_keyframes = true; @@ -610,7 +612,7 @@ if (property.IsCSSCustomProperty()) { animation->setId(property.CustomPropertyName()); } else { - animation->setId(getPropertyName(property.CssProperty())); + animation->setId(getPropertyName(property.GetCSSProperty().PropertyID())); } // Set the current time as the start time for retargeted transitions if (retargeted_compositor_transitions.Contains(property)) { @@ -620,16 +622,16 @@ animation->Update(kTimingUpdateOnDemand); running_transition.animation = animation; transitions_.Set(property, running_transition); - DCHECK(isValidCSSPropertyID(property.CssProperty())); + DCHECK(isValidCSSPropertyID(property.GetCSSProperty().PropertyID())); UseCounter::CountAnimatedCSS(element->GetDocument(), - property.CssProperty()); + property.GetCSSProperty().PropertyID()); // TODO(crbug.com/458925): Remove legacy histogram and counts DEFINE_STATIC_LOCAL(SparseHistogram, property_histogram, ("WebCore.Animation.CSSProperties")); property_histogram.Sample( UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram( - property.CssProperty())); + property.GetCSSProperty().PropertyID())); } ClearPendingUpdate(); } @@ -796,11 +798,11 @@ end_keyframe->SetOffset(1); keyframes.push_back(end_keyframe); - if (CompositorAnimations::IsCompositableProperty(property.CssProperty())) { + if (property.GetCSSProperty().IsCompositableProperty()) { scoped_refptr<AnimatableValue> from = CSSAnimatableValueFactory::Create( - property.CssProperty(), state.old_style); - scoped_refptr<AnimatableValue> to = - CSSAnimatableValueFactory::Create(property.CssProperty(), state.style); + property.GetCSSProperty(), state.old_style); + scoped_refptr<AnimatableValue> to = CSSAnimatableValueFactory::Create( + property.GetCSSProperty(), state.style); delay_keyframe->SetCompositorValue(from); start_keyframe->SetCompositorValue(from); end_keyframe->SetCompositorValue(to); @@ -857,14 +859,16 @@ for (unsigned i = 0; !i || i < property_list.length(); ++i) { CSSPropertyID longhand_id = property_list.length() ? property_list.properties()[i] : resolved_id; - PropertyHandle property = PropertyHandle(longhand_id); DCHECK_GE(longhand_id, firstCSSProperty); + const CSSProperty& property = CSSProperty::Get(longhand_id); + PropertyHandle property_handle = PropertyHandle(property); - if (!animate_all && !CSSProperty::Get(longhand_id).IsInterpolable()) { + if (!animate_all && !property.IsInterpolable()) { continue; } - CalculateTransitionUpdateForProperty(state, property, transition_index); + CalculateTransitionUpdateForProperty(state, property_handle, + transition_index); } } @@ -1169,9 +1173,10 @@ if (current_phase == AnimationEffectReadOnly::kPhaseAfter && current_phase != previous_phase_ && GetDocument().HasListenerType(Document::kTransitionEndListener)) { - String property_name = property_.IsCSSCustomProperty() - ? property_.CustomPropertyName() - : getPropertyNameString(property_.CssProperty()); + String property_name = + property_.IsCSSCustomProperty() + ? property_.CustomPropertyName() + : getPropertyNameString(property_.GetCSSProperty().PropertyID()); 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/ActiveStyleSheetsTest.cpp b/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp index eddf8ae..ae66dc6 100644 --- a/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp +++ b/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp
@@ -25,7 +25,8 @@ protected: static CSSStyleSheet* CreateSheet(const String& css_text = String()) { StyleSheetContents* contents = - StyleSheetContents::Create(CSSParserContext::Create(kHTMLStandardMode)); + StyleSheetContents::Create(CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext)); contents->ParseString(css_text); contents->EnsureRuleSet(MediaQueryEvaluator(), kRuleHasDocumentSecurityOrigin);
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn index 3d6d202..89bb2cc 100644 --- a/third_party/WebKit/Source/core/css/BUILD.gn +++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -516,6 +516,7 @@ "properties/longhands/Filter.cpp", "properties/longhands/FlexBasis.cpp", "properties/longhands/FlexGrowOrShrink.cpp", + "properties/longhands/FloodOrStopOpacity.cpp", "properties/longhands/FontFamily.cpp", "properties/longhands/FontFeatureSettings.cpp", "properties/longhands/FontSize.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSS.idl b/third_party/WebKit/Source/core/css/CSS.idl index 3ffe730..ee1e393 100644 --- a/third_party/WebKit/Source/core/css/CSS.idl +++ b/third_party/WebKit/Source/core/css/CSS.idl
@@ -32,7 +32,7 @@ [ ImplementedAs=DOMWindowCSS ] interface CSS { - static boolean supports(DOMString property, DOMString value); - static boolean supports(DOMString conditionText); + [CallWith=ExecutionContext] static boolean supports(DOMString property, DOMString value); + [CallWith=ExecutionContext] static boolean supports(DOMString conditionText); static DOMString escape(DOMString ident); };
diff --git a/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp b/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp index 96a3ea2..28e08f5 100644 --- a/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp +++ b/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp
@@ -62,7 +62,8 @@ x = 0; MutableCSSPropertyValueSet* property_set = MutableCSSPropertyValueSet::Create(kHTMLQuirksMode); - property_set->SetProperty(CSSPropertyLeft, text); + property_set->SetProperty(CSSPropertyLeft, text, /* important */ false, + SecureContextMode::kInsecureContext); ToCSSPrimitiveValue(property_set->GetPropertyCSSValue(CSSPropertyLeft)) ->AccumulateLengthArray(length_array); return length_array;
diff --git a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp index c6cda14..41f4b05f 100644 --- a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp +++ b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp
@@ -229,7 +229,8 @@ return result.ToString(); } -void CSSComputedStyleDeclaration::setCSSText(const String&, +void CSSComputedStyleDeclaration::setCSSText(const ExecutionContext*, + const String&, ExceptionState& exception_state) { exception_state.ThrowDOMException( kNoModificationAllowedError, @@ -419,10 +420,10 @@ HeapVector<CSSPropertyValue, 256> list; list.ReserveInitialCapacity(properties.size()); for (unsigned i = 0; i < properties.size(); ++i) { - const CSSValue* value = - GetPropertyCSSValue(CSSProperty::Get(properties[i])); + const CSSProperty& property = CSSProperty::Get(properties[i]); + const CSSValue* value = GetPropertyCSSValue(property); if (value) - list.push_back(CSSPropertyValue(properties[i], *value, false)); + list.push_back(CSSPropertyValue(property, *value, false)); } return MutableCSSPropertyValueSet::Create(list.data(), list.size()); } @@ -461,7 +462,8 @@ return false; } -void CSSComputedStyleDeclaration::setProperty(const String& name, +void CSSComputedStyleDeclaration::setProperty(const ExecutionContext*, + const String& name, const String&, const String&, ExceptionState& exception_state) { @@ -501,6 +503,7 @@ const String&, const String&, bool, + SecureContextMode, ExceptionState& exception_state) { // TODO(leviw): This code is currently unreachable, but shouldn't be. exception_state.ThrowDOMException(
diff --git a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h index 59437e0..4dbdc638 100644 --- a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h +++ b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h
@@ -97,7 +97,8 @@ String getPropertyPriority(const String& property_name) override; String GetPropertyShorthand(const String& property_name) override; bool IsPropertyImplicit(const String& property_name) override; - void setProperty(const String& property_name, + void setProperty(const ExecutionContext*, + const String& property_name, const String& value, const String& priority, ExceptionState&) override; @@ -105,7 +106,9 @@ String CssFloat() const; void SetCSSFloat(const String&, ExceptionState&); String cssText() const override; - void setCSSText(const String&, ExceptionState&) override; + void setCSSText(const ExecutionContext*, + const String&, + ExceptionState&) override; const CSSValue* GetPropertyCSSValueInternal(CSSPropertyID) override; const CSSValue* GetPropertyCSSValueInternal( AtomicString custom_property_name) override; @@ -114,6 +117,7 @@ const String& custom_property_name, const String& value, bool important, + SecureContextMode, ExceptionState&) override; bool CssPropertyMatches(CSSPropertyID, const CSSValue*) const override;
diff --git a/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp b/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp index fbd26cd..f4b11a3 100644 --- a/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp +++ b/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp
@@ -64,8 +64,10 @@ } static StyleSheetContents* ParseUASheet(const String& str) { + // UA stylesheets always parse in the insecure context mode. StyleSheetContents* sheet = - StyleSheetContents::Create(CSSParserContext::Create(kUASheetMode)); + StyleSheetContents::Create(CSSParserContext::Create( + kUASheetMode, SecureContextMode::kInsecureContext)); sheet->ParseString(str); // User Agent stylesheets are parsed once for the lifetime of the renderer // process and are intentionally leaked.
diff --git a/third_party/WebKit/Source/core/css/CSSGradientValueTest.cpp b/third_party/WebKit/Source/core/css/CSSGradientValueTest.cpp index 54e0033..d0eac42 100644 --- a/third_party/WebKit/Source/core/css/CSSGradientValueTest.cpp +++ b/third_party/WebKit/Source/core/css/CSSGradientValueTest.cpp
@@ -13,9 +13,11 @@ bool CompareGradients(const char* gradient1, const char* gradient2) { const CSSValue* value1 = CSSParser::ParseSingleValue( - CSSPropertyBackgroundImage, gradient1, StrictCSSParserContext()); + CSSPropertyBackgroundImage, gradient1, + StrictCSSParserContext(SecureContextMode::kInsecureContext)); const CSSValue* value2 = CSSParser::ParseSingleValue( - CSSPropertyBackgroundImage, gradient2, StrictCSSParserContext()); + CSSPropertyBackgroundImage, gradient2, + StrictCSSParserContext(SecureContextMode::kInsecureContext)); return *value1 == *value2; }
diff --git a/third_party/WebKit/Source/core/css/CSSGroupingRule.cpp b/third_party/WebKit/Source/core/css/CSSGroupingRule.cpp index 817376d..92b0fb2 100644 --- a/third_party/WebKit/Source/core/css/CSSGroupingRule.cpp +++ b/third_party/WebKit/Source/core/css/CSSGroupingRule.cpp
@@ -35,6 +35,7 @@ #include "core/css/CSSStyleSheet.h" #include "core/css/parser/CSSParser.h" #include "core/dom/ExceptionCode.h" +#include "core/dom/ExecutionContext.h" #include "core/frame/UseCounter.h" #include "platform/wtf/text/StringBuilder.h" @@ -48,7 +49,8 @@ CSSGroupingRule::~CSSGroupingRule() {} -unsigned CSSGroupingRule::insertRule(const String& rule_string, +unsigned CSSGroupingRule::insertRule(const ExecutionContext* execution_context, + const String& rule_string, unsigned index, ExceptionState& exception_state) { DCHECK_EQ(child_rule_cssom_wrappers_.size(), @@ -63,8 +65,8 @@ } CSSStyleSheet* style_sheet = parentStyleSheet(); - CSSParserContext* context = - CSSParserContext::CreateWithStyleSheet(ParserContext(), style_sheet); + CSSParserContext* context = CSSParserContext::CreateWithStyleSheet( + ParserContext(execution_context->SecureContextMode()), style_sheet); StyleRuleBase* new_rule = CSSParser::ParseRule( context, style_sheet ? style_sheet->Contents() : nullptr, rule_string); if (!new_rule) {
diff --git a/third_party/WebKit/Source/core/css/CSSGroupingRule.h b/third_party/WebKit/Source/core/css/CSSGroupingRule.h index 36e6181..3724698 100644 --- a/third_party/WebKit/Source/core/css/CSSGroupingRule.h +++ b/third_party/WebKit/Source/core/css/CSSGroupingRule.h
@@ -42,7 +42,10 @@ CSSRuleList* cssRules() const override; - unsigned insertRule(const String& rule, unsigned index, ExceptionState&); + unsigned insertRule(const ExecutionContext*, + const String& rule, + unsigned index, + ExceptionState&); void deleteRule(unsigned index, ExceptionState&); // For CSSRuleList
diff --git a/third_party/WebKit/Source/core/css/CSSGroupingRule.idl b/third_party/WebKit/Source/core/css/CSSGroupingRule.idl index 198a3090..b135abf 100644 --- a/third_party/WebKit/Source/core/css/CSSGroupingRule.idl +++ b/third_party/WebKit/Source/core/css/CSSGroupingRule.idl
@@ -6,6 +6,6 @@ interface CSSGroupingRule : CSSRule { [SameObject] readonly attribute CSSRuleList cssRules; - [RaisesException] unsigned long insertRule(DOMString rule, unsigned long index); + [RaisesException, CallWith=ExecutionContext] unsigned long insertRule(DOMString rule, unsigned long index); [RaisesException] void deleteRule(unsigned long index); };
diff --git a/third_party/WebKit/Source/core/css/CSSKeyframesRule.cpp b/third_party/WebKit/Source/core/css/CSSKeyframesRule.cpp index ba6c2af..85d798e 100644 --- a/third_party/WebKit/Source/core/css/CSSKeyframesRule.cpp +++ b/third_party/WebKit/Source/core/css/CSSKeyframesRule.cpp
@@ -30,6 +30,7 @@ #include "core/css/CSSRuleList.h" #include "core/css/CSSStyleSheet.h" #include "core/css/parser/CSSParser.h" +#include "core/dom/ExecutionContext.h" #include "core/frame/UseCounter.h" #include "platform/wtf/text/StringBuilder.h" @@ -94,13 +95,14 @@ keyframes_rule_->SetName(name); } -void CSSKeyframesRule::appendRule(const String& rule_text) { +void CSSKeyframesRule::appendRule(const ExecutionContext* execution_context, + const String& rule_text) { DCHECK_EQ(child_rule_cssom_wrappers_.size(), keyframes_rule_->Keyframes().size()); CSSStyleSheet* style_sheet = parentStyleSheet(); - CSSParserContext* context = - CSSParserContext::CreateWithStyleSheet(ParserContext(), style_sheet); + CSSParserContext* context = CSSParserContext::CreateWithStyleSheet( + ParserContext(execution_context->SecureContextMode()), style_sheet); StyleRuleKeyframe* keyframe = CSSParser::ParseKeyframeRule(context, rule_text); if (!keyframe)
diff --git a/third_party/WebKit/Source/core/css/CSSKeyframesRule.h b/third_party/WebKit/Source/core/css/CSSKeyframesRule.h index 177e25b..0dd55e1 100644 --- a/third_party/WebKit/Source/core/css/CSSKeyframesRule.h +++ b/third_party/WebKit/Source/core/css/CSSKeyframesRule.h
@@ -99,7 +99,7 @@ CSSRuleList* cssRules() const override; - void appendRule(const String& rule); + void appendRule(const ExecutionContext*, const String& rule); void deleteRule(const String& key); CSSKeyframeRule* findRule(const String& key);
diff --git a/third_party/WebKit/Source/core/css/CSSKeyframesRule.idl b/third_party/WebKit/Source/core/css/CSSKeyframesRule.idl index dc04ce0..01e48fd9 100644 --- a/third_party/WebKit/Source/core/css/CSSKeyframesRule.idl +++ b/third_party/WebKit/Source/core/css/CSSKeyframesRule.idl
@@ -32,7 +32,7 @@ attribute DOMString name; readonly attribute CSSRuleList cssRules; - void appendRule(DOMString rule); + [CallWith=ExecutionContext] void appendRule(DOMString rule); void deleteRule(DOMString select); CSSKeyframeRule? findRule(DOMString select);
diff --git a/third_party/WebKit/Source/core/css/CSSPageRule.cpp b/third_party/WebKit/Source/core/css/CSSPageRule.cpp index ce51727..27a570b 100644 --- a/third_party/WebKit/Source/core/css/CSSPageRule.cpp +++ b/third_party/WebKit/Source/core/css/CSSPageRule.cpp
@@ -27,6 +27,7 @@ #include "core/css/PropertySetCSSStyleDeclaration.h" #include "core/css/StyleRule.h" #include "core/css/parser/CSSParser.h" +#include "core/dom/ExecutionContext.h" #include "platform/wtf/text/StringBuilder.h" namespace blink { @@ -54,9 +55,10 @@ return text.ToString(); } -void CSSPageRule::setSelectorText(const String& selector_text) { - CSSParserContext* context = - CSSParserContext::Create(ParserContext(), nullptr); +void CSSPageRule::setSelectorText(const ExecutionContext* execution_context, + const String& selector_text) { + CSSParserContext* context = CSSParserContext::Create( + ParserContext(execution_context->SecureContextMode()), nullptr); DCHECK(context); CSSSelectorList selector_list = CSSParser::ParsePageSelector( *context, parentStyleSheet() ? parentStyleSheet()->Contents() : nullptr,
diff --git a/third_party/WebKit/Source/core/css/CSSPageRule.h b/third_party/WebKit/Source/core/css/CSSPageRule.h index 022e5c1..942b34f 100644 --- a/third_party/WebKit/Source/core/css/CSSPageRule.h +++ b/third_party/WebKit/Source/core/css/CSSPageRule.h
@@ -29,6 +29,7 @@ class CSSStyleDeclaration; class CSSStyleSheet; +class ExecutionContext; class StyleRulePage; class StyleRuleCSSStyleDeclaration; @@ -48,7 +49,7 @@ CSSStyleDeclaration* style() const; String selectorText() const; - void setSelectorText(const String&); + void setSelectorText(const ExecutionContext*, const String&); virtual void Trace(blink::Visitor*);
diff --git a/third_party/WebKit/Source/core/css/CSSPageRule.idl b/third_party/WebKit/Source/core/css/CSSPageRule.idl index b6594334..28d909440 100644 --- a/third_party/WebKit/Source/core/css/CSSPageRule.idl +++ b/third_party/WebKit/Source/core/css/CSSPageRule.idl
@@ -26,7 +26,7 @@ // spec https://drafts.csswg.org/css-page/#at-page-rule allows only // margin at-rules inside @page. interface CSSPageRule : CSSRule { - attribute DOMString selectorText; + [SetterCallWith=ExecutionContext] attribute DOMString selectorText; // TODO(foolip): style should have [PutForwards=cssText]. [SameObject] readonly attribute CSSStyleDeclaration style; };
diff --git a/third_party/WebKit/Source/core/css/CSSPageRuleTest.cpp b/third_party/WebKit/Source/core/css/CSSPageRuleTest.cpp index edb5d86c..637e73c 100644 --- a/third_party/WebKit/Source/core/css/CSSPageRuleTest.cpp +++ b/third_party/WebKit/Source/core/css/CSSPageRuleTest.cpp
@@ -6,6 +6,7 @@ #include "core/css/CSSRuleList.h" #include "core/css/CSSTestHelper.h" +#include "core/dom/Document.h" #include "testing/gtest/include/gtest/gtest.h" @@ -37,19 +38,19 @@ EXPECT_EQ(":left", page_rule->selectorText()); // set invalid page selector. - page_rule->setSelectorText(":hover"); + page_rule->setSelectorText(&helper.GetDocument(), ":hover"); EXPECT_EQ(":left", page_rule->selectorText()); // set invalid page selector. - page_rule->setSelectorText("right { bla"); + page_rule->setSelectorText(&helper.GetDocument(), "right { bla"); EXPECT_EQ(":left", page_rule->selectorText()); // set page pseudo class selector. - page_rule->setSelectorText(":right"); + page_rule->setSelectorText(&helper.GetDocument(), ":right"); EXPECT_EQ(":right", page_rule->selectorText()); // set page type selector. - page_rule->setSelectorText("namedpage"); + page_rule->setSelectorText(&helper.GetDocument(), "namedpage"); EXPECT_EQ("namedpage", page_rule->selectorText()); }
diff --git a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp index a5292960..a37b60f5 100644 --- a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
@@ -53,13 +53,13 @@ GetName(), document, paint_image_generator_observer_); } - if (!ParseInputArguments()) + if (!ParseInputArguments(document)) return nullptr; return generator_->Paint(client, container_size, parsed_input_arguments_); } -bool CSSPaintValue::ParseInputArguments() { +bool CSSPaintValue::ParseInputArguments(const Document& document) { if (input_arguments_invalid_) return false; @@ -80,8 +80,10 @@ parsed_input_arguments_ = new CSSStyleValueVector(); for (size_t i = 0; i < argument_variable_data_.size(); ++i) { - const CSSValue* parsed_value = - argument_variable_data_[i]->ParseForSyntax(input_argument_types[i]); + // If we are parsing a paint() function, we must be a secure context. + DCHECK_EQ(SecureContextMode::kSecureContext, document.SecureContextMode()); + const CSSValue* parsed_value = argument_variable_data_[i]->ParseForSyntax( + input_argument_types[i], SecureContextMode::kSecureContext); if (!parsed_value) { input_arguments_invalid_ = true; parsed_input_arguments_ = nullptr;
diff --git a/third_party/WebKit/Source/core/css/CSSPaintValue.h b/third_party/WebKit/Source/core/css/CSSPaintValue.h index 79ace25..7b01c4bd 100644 --- a/third_party/WebKit/Source/core/css/CSSPaintValue.h +++ b/third_party/WebKit/Source/core/css/CSSPaintValue.h
@@ -82,7 +82,7 @@ void PaintImageGeneratorReady(); - bool ParseInputArguments(); + bool ParseInputArguments(const Document&); bool input_arguments_invalid_ = false;
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5 index a1c7d8f0..87639e724 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.json5 +++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -122,6 +122,13 @@ valid_type: "bool", }, + // - compositable + // The property can be animated by the compositor + compositable: { + default: false, + valid_type: "bool", + }, + // - runtime_flag // The name of the flag on RuntimeEnabledFeatures // (e.g. "CSSScrollBoundaryBehavior") that conditionally enables the @@ -724,6 +731,7 @@ property_class: true, property_methods: ["ParseSingleValue"], interpolable: true, + compositable: true, runtime_flag: "CSSBackdropFilter", field_group: "*", field_template: "external", @@ -1375,6 +1383,7 @@ property_class: true, property_methods: ["ParseSingleValue"], interpolable: true, + compositable: true, field_group: "*", field_template: "external", include_paths: ["core/style/StyleFilterData.h"], @@ -1446,7 +1455,7 @@ }, { name: "flood-opacity", - property_class: "Opacity", + property_class: "FloodOrStopOpacity", property_methods: ["ParseSingleValue"], interpolable: true, svg: true, @@ -1991,9 +2000,10 @@ }, { name: "opacity", - property_class: "Opacity", + property_class: true, property_methods: ["ParseSingleValue"], interpolable: true, + compositable: true, field_group: "*", field_template: "primitive", default_value: "1.0", @@ -2586,7 +2596,7 @@ }, { name: "stop-opacity", - property_class: "Opacity", + property_class: "FloodOrStopOpacity", property_methods: ["ParseSingleValue"], interpolable: true, svg: true, @@ -2875,6 +2885,7 @@ property_class: true, property_methods: ["ParseSingleValue", "IsLayoutDependent"], interpolable: true, + compositable: true, field_group: "*", field_template: "external", include_paths: ["platform/transforms/TransformOperations.h"], @@ -2918,6 +2929,7 @@ property_class: true, property_methods: ["ParseSingleValue", "IsLayoutDependent"], interpolable: true, + compositable: true, runtime_flag: "CSSIndependentTransformProperties", field_group: "*", field_template: "pointer", @@ -2932,6 +2944,7 @@ property_class: true, property_methods: ["ParseSingleValue"], interpolable: true, + compositable: true, runtime_flag: "CSSIndependentTransformProperties", field_group: "*", field_template: "pointer", @@ -2946,6 +2959,7 @@ property_class: true, property_methods: ["ParseSingleValue"], interpolable: true, + compositable: true, runtime_flag: "CSSIndependentTransformProperties", field_group: "*", field_template: "pointer",
diff --git a/third_party/WebKit/Source/core/css/CSSPropertyEquality.cpp b/third_party/WebKit/Source/core/css/CSSPropertyEquality.cpp index fc49355..208e4a8 100644 --- a/third_party/WebKit/Source/core/css/CSSPropertyEquality.cpp +++ b/third_party/WebKit/Source/core/css/CSSPropertyEquality.cpp
@@ -64,7 +64,7 @@ return DataEquivalent(a.GetRegisteredVariable(name), b.GetRegisteredVariable(name)); } - switch (property.CssProperty()) { + switch (property.GetCSSProperty().PropertyID()) { case CSSPropertyBackgroundColor: return a.BackgroundColor() == b.BackgroundColor() && a.VisitedLinkBackgroundColor() == b.VisitedLinkBackgroundColor();
diff --git a/third_party/WebKit/Source/core/css/CSSPropertyValue.cpp b/third_party/WebKit/Source/core/css/CSSPropertyValue.cpp index 59c9876..90bd7a2 100644 --- a/third_party/WebKit/Source/core/css/CSSPropertyValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSPropertyValue.cpp
@@ -27,6 +27,7 @@ struct SameSizeAsCSSPropertyValue { uint32_t bitfields; + void* property; Member<void*> value; }; @@ -38,8 +39,7 @@ return CSSPropertyInvalid; Vector<StylePropertyShorthand, 4> shorthands; - getMatchingShorthandsForLonghand(static_cast<CSSPropertyID>(property_id_), - &shorthands); + getMatchingShorthandsForLonghand(Property().PropertyID(), &shorthands); DCHECK(shorthands.size()); DCHECK_GE(index_in_shorthands_vector_, 0u); DCHECK_LT(index_in_shorthands_vector_, shorthands.size());
diff --git a/third_party/WebKit/Source/core/css/CSSPropertyValue.h b/third_party/WebKit/Source/core/css/CSSPropertyValue.h index 561f5db..f46818e 100644 --- a/third_party/WebKit/Source/core/css/CSSPropertyValue.h +++ b/third_party/WebKit/Source/core/css/CSSPropertyValue.h
@@ -30,13 +30,13 @@ struct CSSPropertyValueMetadata { DISALLOW_NEW(); - CSSPropertyValueMetadata(CSSPropertyID property_id, + CSSPropertyValueMetadata(const CSSProperty& property, bool is_set_from_shorthand, int index_in_shorthands_vector, bool important, bool implicit, bool inherited) - : property_id_(property_id), + : property_(&property), is_set_from_shorthand_(is_set_from_shorthand), index_in_shorthands_vector_(index_in_shorthands_vector), important_(important), @@ -44,8 +44,10 @@ inherited_(inherited) {} CSSPropertyID ShorthandID() const; + const CSSProperty& Property() const { return *property_; } - unsigned property_id_ : 10; + const CSSProperty* property_; + unsigned is_set_from_shorthand_ : 1; // If this property was set as part of an ambiguous shorthand, gives the index // in the shorthands vector. @@ -61,27 +63,26 @@ DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); public: - CSSPropertyValue(CSSPropertyID property_id, + CSSPropertyValue(const CSSProperty& property, const CSSValue& value, bool important = false, bool is_set_from_shorthand = false, int index_in_shorthands_vector = 0, bool implicit = false) - : metadata_(property_id, + : metadata_(property, is_set_from_shorthand, index_in_shorthands_vector, important, implicit, - CSSProperty::Get(property_id).IsInherited()), + property.IsInherited()), value_(value) {} // FIXME: Remove this. CSSPropertyValue(CSSPropertyValueMetadata metadata, const CSSValue& value) : metadata_(metadata), value_(value) {} - CSSPropertyID Id() const { - return static_cast<CSSPropertyID>(metadata_.property_id_); - } + CSSPropertyID Id() const { return metadata_.Property().PropertyID(); } + const CSSProperty& Property() const { return metadata_.Property(); } bool IsSetFromShorthand() const { return metadata_.is_set_from_shorthand_; } CSSPropertyID ShorthandID() const { return metadata_.ShorthandID(); } bool IsImportant() const { return metadata_.important_; }
diff --git a/third_party/WebKit/Source/core/css/CSSPropertyValueSet.cpp b/third_party/WebKit/Source/core/css/CSSPropertyValueSet.cpp index 9368e39..4c18bde 100644 --- a/third_party/WebKit/Source/core/css/CSSPropertyValueSet.cpp +++ b/third_party/WebKit/Source/core/css/CSSPropertyValueSet.cpp
@@ -102,7 +102,7 @@ ImmutableCSSPropertyValueSet::~ImmutableCSSPropertyValueSet() {} -// Convert property into an uint16_t for comparison with metadata's property_id_ +// 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); @@ -117,7 +117,7 @@ uint16_t id, CSSPropertyID property_id) { DCHECK_EQ(id, property_id); - bool result = metadata.property_id_ == id; + bool result = metadata.Property().PropertyID() == id; // Only enabled properties should be part of the style. #if DCHECK_IS_ON() DCHECK(!result || @@ -131,7 +131,7 @@ uint16_t id, const AtomicString& custom_property_name) { DCHECK_EQ(id, CSSPropertyVariable); - return metadata.property_id_ == id && + return metadata.Property().PropertyID() == id && ToCSSCustomPropertyDeclaration(value).GetName() == custom_property_name; } @@ -318,6 +318,7 @@ CSSPropertyID unresolved_property, const String& value, bool important, + SecureContextMode secure_context_mode, StyleSheetContents* context_style_sheet) { DCHECK_GE(unresolved_property, firstCSSProperty); @@ -334,7 +335,7 @@ // end of the list. Firefox preserves the position, and MSIE moves the // property to the beginning. return CSSParser::ParseValue(this, unresolved_property, value, important, - context_style_sheet); + secure_context_mode, context_style_sheet); } MutableCSSPropertyValueSet::SetResult MutableCSSPropertyValueSet::SetProperty( @@ -342,6 +343,7 @@ const PropertyRegistry* registry, const String& value, bool important, + SecureContextMode secure_context_mode, StyleSheetContents* context_style_sheet, bool is_animation_tainted) { if (value.IsEmpty()) { @@ -351,7 +353,7 @@ } return CSSParser::ParseValueForCustomProperty( this, custom_property_name, registry, value, important, - context_style_sheet, is_animation_tainted); + secure_context_mode, context_style_sheet, is_animation_tainted); } void MutableCSSPropertyValueSet::SetProperty(CSSPropertyID property_id, @@ -359,15 +361,16 @@ bool important) { StylePropertyShorthand shorthand = shorthandForProperty(property_id); if (!shorthand.length()) { - SetProperty(CSSPropertyValue(property_id, value, important)); + 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)); + property_vector_.push_back(CSSPropertyValue( + CSSProperty::Get(shorthand.properties()[i]), value, important)); } } @@ -392,13 +395,15 @@ bool MutableCSSPropertyValueSet::SetProperty(CSSPropertyID property_id, CSSValueID identifier, bool important) { - SetProperty(CSSPropertyValue( - property_id, *CSSIdentifierValue::Create(identifier), 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(); @@ -408,7 +413,7 @@ context_style_sheet->ParserContext(), context_style_sheet); context->SetMode(CssParserMode()); } else { - context = CSSParserContext::Create(CssParserMode()); + context = CSSParserContext::Create(CssParserMode(), secure_context_mode); } CSSParser::ParseDeclarationList(context, this, style_declaration); @@ -559,8 +564,10 @@ list.ReserveInitialCapacity(properties.size()); for (unsigned i = 0; i < properties.size(); ++i) { const CSSValue* value = GetPropertyCSSValue(properties[i]); - if (value) - list.push_back(CSSPropertyValue(properties[i], *value, false)); + if (value) { + list.push_back( + CSSPropertyValue(CSSProperty::Get(properties[i]), *value, false)); + } } return MutableCSSPropertyValueSet::Create(list.data(), list.size()); }
diff --git a/third_party/WebKit/Source/core/css/CSSPropertyValueSet.h b/third_party/WebKit/Source/core/css/CSSPropertyValueSet.h index 9902663..e17733f 100644 --- a/third_party/WebKit/Source/core/css/CSSPropertyValueSet.h +++ b/third_party/WebKit/Source/core/css/CSSPropertyValueSet.h
@@ -39,6 +39,7 @@ class MutableCSSPropertyValueSet; class PropertyRegistry; class StyleSheetContents; +enum class SecureContextMode; class CORE_EXPORT CSSPropertyValueSet : public GarbageCollectedFinalized<CSSPropertyValueSet> { @@ -56,7 +57,11 @@ : property_set_(&property_set), index_(index) {} CSSPropertyID Id() const { - return static_cast<CSSPropertyID>(PropertyMetadata().property_id_); + return static_cast<CSSPropertyID>( + PropertyMetadata().Property().PropertyID()); + } + const CSSProperty& Property() const { + return PropertyMetadata().Property(); } CSSPropertyID ShorthandID() const { return PropertyMetadata().ShorthandID(); @@ -238,12 +243,14 @@ // These expand shorthand properties into multiple properties. SetResult SetProperty(CSSPropertyID unresolved_property, const String& value, - bool important = false, + bool important, + SecureContextMode, StyleSheetContents* context_style_sheet = 0); 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); @@ -264,6 +271,7 @@ void Clear(); void ParseDeclarationList(const String& style_declaration, + SecureContextMode, StyleSheetContents* context_style_sheet); CSSStyleDeclaration* EnsureCSSStyleDeclaration();
diff --git a/third_party/WebKit/Source/core/css/CSSRule.cpp b/third_party/WebKit/Source/core/css/CSSRule.cpp index d44534d..44ae22c 100644 --- a/third_party/WebKit/Source/core/css/CSSRule.cpp +++ b/third_party/WebKit/Source/core/css/CSSRule.cpp
@@ -38,10 +38,11 @@ static_assert(sizeof(CSSRule) == sizeof(SameSizeAsCSSRule), "CSSRule should stay small"); -const CSSParserContext* CSSRule::ParserContext() const { +const CSSParserContext* CSSRule::ParserContext( + SecureContextMode secure_context_mode) const { CSSStyleSheet* style_sheet = parentStyleSheet(); return style_sheet ? style_sheet->Contents()->ParserContext() - : StrictCSSParserContext(); + : StrictCSSParserContext(secure_context_mode); } void CSSRule::SetParentStyleSheet(CSSStyleSheet* style_sheet) {
diff --git a/third_party/WebKit/Source/core/css/CSSRule.h b/third_party/WebKit/Source/core/css/CSSRule.h index 79d80790..fbb72929 100644 --- a/third_party/WebKit/Source/core/css/CSSRule.h +++ b/third_party/WebKit/Source/core/css/CSSRule.h
@@ -34,6 +34,7 @@ class CSSRuleList; class CSSStyleSheet; class StyleRuleBase; +enum class SecureContextMode; class CORE_EXPORT CSSRule : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); @@ -92,7 +93,7 @@ has_cached_selector_text_ = has_cached_selector_text; } - const CSSParserContext* ParserContext() const; + const CSSParserContext* ParserContext(SecureContextMode) const; private: mutable unsigned char has_cached_selector_text_ : 1;
diff --git a/third_party/WebKit/Source/core/css/CSSSelectorWatch.cpp b/third_party/WebKit/Source/core/css/CSSSelectorWatch.cpp index b396a081..b7a9c63 100644 --- a/third_party/WebKit/Source/core/css/CSSSelectorWatch.cpp +++ b/third_party/WebKit/Source/core/css/CSSSelectorWatch.cpp
@@ -150,7 +150,9 @@ CSSPropertyValueSet* callback_property_set = ImmutableCSSPropertyValueSet::Create(nullptr, 0, kUASheetMode); - CSSParserContext* context = CSSParserContext::Create(kUASheetMode); + // UA stylesheets always parse in the insecure context mode. + CSSParserContext* context = CSSParserContext::Create( + kUASheetMode, SecureContextMode::kInsecureContext); for (const auto& selector : selectors) { CSSSelectorList selector_list = CSSParser::ParseSelector(context, nullptr, selector);
diff --git a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h index ddf76f9..a61973f 100644 --- a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h +++ b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h
@@ -23,6 +23,7 @@ #include "core/CSSPropertyNames.h" #include "core/CoreExport.h" +#include "core/dom/ExecutionContext.h" #include "platform/bindings/ScriptWrappable.h" #include "platform/wtf/Forward.h" #include "platform/wtf/Noncopyable.h" @@ -34,6 +35,7 @@ class CSSStyleSheet; class CSSValue; class ExceptionState; +enum class SecureContextMode; class CORE_EXPORT CSSStyleDeclaration : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); @@ -44,19 +46,25 @@ virtual CSSRule* parentRule() const = 0; String cssFloat() { return GetPropertyValueInternal(CSSPropertyFloat); } - void setCSSFloat(const String& value, ExceptionState& exception_state) { + void setCSSFloat(const ExecutionContext* execution_context, + const String& value, + ExceptionState& exception_state) { SetPropertyInternal(CSSPropertyFloat, String(), value, false, + execution_context->SecureContextMode(), exception_state); } virtual String cssText() const = 0; - virtual void setCSSText(const String&, ExceptionState&) = 0; + virtual void setCSSText(const ExecutionContext*, + const String&, + ExceptionState&) = 0; virtual unsigned length() const = 0; virtual String item(unsigned index) const = 0; virtual String getPropertyValue(const String& property_name) = 0; virtual String getPropertyPriority(const String& property_name) = 0; virtual String GetPropertyShorthand(const String& property_name) = 0; virtual bool IsPropertyImplicit(const String& property_name) = 0; - virtual void setProperty(const String& property_name, + virtual void setProperty(const ExecutionContext*, + const String& property_name, const String& value, const String& priority, ExceptionState&) = 0; @@ -76,6 +84,7 @@ const String& property_value, const String& value, bool important, + SecureContextMode, ExceptionState&) = 0; virtual bool CssPropertyMatches(CSSPropertyID, const CSSValue*) const = 0;
diff --git a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl index e518566..7712395 100644 --- a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl +++ b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl
@@ -23,19 +23,19 @@ [ DependentLifetime ] interface CSSStyleDeclaration { - [CEReactions, RaisesException=Setter] attribute DOMString cssText; + [CEReactions, RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString cssText; readonly attribute unsigned long length; getter DOMString item(unsigned long index); DOMString getPropertyValue(DOMString property); DOMString getPropertyPriority(DOMString property); // TODO(foolip): The value and priority arguments should have // [TreatNullAs=EmptyString] and should not be nullable. - [CEReactions, RaisesException] void setProperty(DOMString property, DOMString? value, optional DOMString? priority = null); + [CEReactions, RaisesException, CallWith=ExecutionContext] void setProperty(DOMString property, DOMString? value, optional DOMString? priority = null); // void setPropertyValue(DOMString property, [TreatNullAs=EmptyString] DOMString value); // void setPropertyPriority(DOMString property, [TreatNullAs=EmptyString] DOMString priority); [CEReactions, RaisesException] DOMString removeProperty(DOMString property); readonly attribute CSSRule? parentRule; - [CEReactions, RaisesException=Setter, TreatNullAs=EmptyString] attribute DOMString cssFloat; + [CEReactions, SetterCallWith=ExecutionContext, RaisesException=Setter, TreatNullAs=EmptyString] attribute DOMString cssFloat; // The camel-cased and dashed attribute getters have custom bindings. // https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-camel-cased-attribute
diff --git a/third_party/WebKit/Source/core/css/CSSStyleRule.cpp b/third_party/WebKit/Source/core/css/CSSStyleRule.cpp index 5f99fc8..7d50119 100644 --- a/third_party/WebKit/Source/core/css/CSSStyleRule.cpp +++ b/third_party/WebKit/Source/core/css/CSSStyleRule.cpp
@@ -27,6 +27,7 @@ #include "core/css/PropertySetCSSStyleDeclaration.h" #include "core/css/StyleRule.h" #include "core/css/parser/CSSParser.h" +#include "core/dom/ExecutionContext.h" #include "platform/wtf/text/StringBuilder.h" namespace blink { @@ -65,9 +66,10 @@ return text; } -void CSSStyleRule::setSelectorText(const String& selector_text) { - const CSSParserContext* context = - CSSParserContext::Create(ParserContext(), nullptr); +void CSSStyleRule::setSelectorText(const ExecutionContext* execution_context, + const String& selector_text) { + const CSSParserContext* context = CSSParserContext::Create( + ParserContext(execution_context->SecureContextMode()), nullptr); CSSSelectorList selector_list = CSSParser::ParseSelector( context, parentStyleSheet() ? parentStyleSheet()->Contents() : nullptr, selector_text);
diff --git a/third_party/WebKit/Source/core/css/CSSStyleRule.h b/third_party/WebKit/Source/core/css/CSSStyleRule.h index a7f98ea0..3f74a48 100644 --- a/third_party/WebKit/Source/core/css/CSSStyleRule.h +++ b/third_party/WebKit/Source/core/css/CSSStyleRule.h
@@ -28,6 +28,7 @@ namespace blink { class CSSStyleDeclaration; +class ExecutionContext; class StyleRuleCSSStyleDeclaration; class StyleRule; @@ -45,7 +46,7 @@ void Reattach(StyleRuleBase*) override; String selectorText() const; - void setSelectorText(const String&); + void setSelectorText(const ExecutionContext*, const String&); CSSStyleDeclaration* style() const;
diff --git a/third_party/WebKit/Source/core/css/CSSStyleRule.idl b/third_party/WebKit/Source/core/css/CSSStyleRule.idl index 8a9f1230..6d9c168 100644 --- a/third_party/WebKit/Source/core/css/CSSStyleRule.idl +++ b/third_party/WebKit/Source/core/css/CSSStyleRule.idl
@@ -23,6 +23,6 @@ [ DependentLifetime ] interface CSSStyleRule : CSSRule { - attribute DOMString selectorText; + [SetterCallWith=ExecutionContext] attribute DOMString selectorText; [SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style; };
diff --git a/third_party/WebKit/Source/core/css/CSSTestHelper.h b/third_party/WebKit/Source/core/css/CSSTestHelper.h index 9938038..ca8c4e1 100644 --- a/third_party/WebKit/Source/core/css/CSSTestHelper.h +++ b/third_party/WebKit/Source/core/css/CSSTestHelper.h
@@ -53,6 +53,8 @@ CSSTestHelper(); ~CSSTestHelper(); + const Document& GetDocument() { return *document_; }; + void AddCSSRules(const char* rule_text); RuleSet& GetRuleSet(); CSSRuleList* CssRules();
diff --git a/third_party/WebKit/Source/core/css/CSSVariableData.cpp b/third_party/WebKit/Source/core/css/CSSVariableData.cpp index 8d44703..f06d8a8c 100644 --- a/third_party/WebKit/Source/core/css/CSSVariableData.cpp +++ b/third_party/WebKit/Source/core/css/CSSVariableData.cpp
@@ -64,11 +64,12 @@ } const CSSValue* CSSVariableData::ParseForSyntax( - const CSSSyntaxDescriptor& syntax) const { + const CSSSyntaxDescriptor& syntax, + SecureContextMode secure_context_mode) const { DCHECK(!NeedsVariableResolution()); // TODO(timloh): This probably needs a proper parser context for // relative URL resolution. - return syntax.Parse(TokenRange(), StrictCSSParserContext(), + return syntax.Parse(TokenRange(), StrictCSSParserContext(secure_context_mode), is_animation_tainted_); }
diff --git a/third_party/WebKit/Source/core/css/CSSVariableData.h b/third_party/WebKit/Source/core/css/CSSVariableData.h index 39080ad..1ac2ce1 100644 --- a/third_party/WebKit/Source/core/css/CSSVariableData.h +++ b/third_party/WebKit/Source/core/css/CSSVariableData.h
@@ -14,6 +14,7 @@ class CSSParserTokenRange; class CSSSyntaxDescriptor; +enum class SecureContextMode; class CORE_EXPORT CSSVariableData : public RefCounted<CSSVariableData> { WTF_MAKE_NONCOPYABLE(CSSVariableData); @@ -46,7 +47,8 @@ bool NeedsVariableResolution() const { return needs_variable_resolution_; } - const CSSValue* ParseForSyntax(const CSSSyntaxDescriptor&) const; + const CSSValue* ParseForSyntax(const CSSSyntaxDescriptor&, + SecureContextMode) const; private: CSSVariableData(const CSSParserTokenRange&,
diff --git a/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp b/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp index 6ea3fc7..0685b7e 100644 --- a/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp +++ b/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp
@@ -33,12 +33,15 @@ #include "core/css/CSSPropertyValueSet.h" #include "core/css/parser/CSSParser.h" #include "core/css/properties/CSSProperty.h" +#include "core/dom/ExecutionContext.h" #include "platform/wtf/text/StringBuilder.h" #include "platform/wtf/text/WTFString.h" namespace blink { -bool DOMWindowCSS::supports(const String& property, const String& value) { +bool DOMWindowCSS::supports(const ExecutionContext* execution_context, + const String& property, + const String& value) { CSSPropertyID unresolved_property = unresolvedCSSPropertyID(property); if (unresolved_property == CSSPropertyInvalid) return false; @@ -46,9 +49,10 @@ MutableCSSPropertyValueSet* dummy_style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); bool is_animation_tainted = false; - return CSSParser::ParseValueForCustomProperty(dummy_style, "--valid", - nullptr, value, false, - nullptr, is_animation_tainted) + return CSSParser::ParseValueForCustomProperty( + dummy_style, "--valid", nullptr, value, false, + execution_context->SecureContextMode(), nullptr, + is_animation_tainted) .did_parse; } @@ -60,12 +64,15 @@ // This will return false when !important is present MutableCSSPropertyValueSet* dummy_style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); - return CSSParser::ParseValue(dummy_style, unresolved_property, value, false) + return CSSParser::ParseValue(dummy_style, unresolved_property, value, false, + execution_context->SecureContextMode()) .did_parse; } -bool DOMWindowCSS::supports(const String& condition_text) { - return CSSParser::ParseSupportsCondition(condition_text); +bool DOMWindowCSS::supports(const ExecutionContext* execution_context, + const String& condition_text) { + return CSSParser::ParseSupportsCondition( + condition_text, execution_context->SecureContextMode()); } String DOMWindowCSS::escape(const String& ident) {
diff --git a/third_party/WebKit/Source/core/css/DOMWindowCSS.h b/third_party/WebKit/Source/core/css/DOMWindowCSS.h index 1be87290..a69272b 100644 --- a/third_party/WebKit/Source/core/css/DOMWindowCSS.h +++ b/third_party/WebKit/Source/core/css/DOMWindowCSS.h
@@ -36,12 +36,16 @@ namespace blink { +class ExecutionContext; + class DOMWindowCSS : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - static bool supports(const String& property, const String& value); - static bool supports(const String& condition_text); + static bool supports(const ExecutionContext*, + const String& property, + const String& value); + static bool supports(const ExecutionContext*, const String& condition_text); static String escape(const String& ident); private:
diff --git a/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp b/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp index 142accce..b76e978 100644 --- a/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp +++ b/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp
@@ -65,8 +65,8 @@ CSSValueList* src_value_list = CSSValueList::CreateCommaSeparated(); src_value_list->Append(*src); CSSPropertyValue properties[] = { - CSSPropertyValue(CSSPropertyFontFamily, *family_name), - CSSPropertyValue(CSSPropertySrc, *src_value_list)}; + CSSPropertyValue(GetCSSPropertyFontFamily(), *family_name), + CSSPropertyValue(GetCSSPropertySrc(), *src_value_list)}; MutableCSSPropertyValueSet* font_face_descriptor = MutableCSSPropertyValueSet::Create(properties, arraysize(properties));
diff --git a/third_party/WebKit/Source/core/css/FontFaceSetDocument.cpp b/third_party/WebKit/Source/core/css/FontFaceSetDocument.cpp index 4d11d78..d1544d9 100644 --- a/third_party/WebKit/Source/core/css/FontFaceSetDocument.cpp +++ b/third_party/WebKit/Source/core/css/FontFaceSetDocument.cpp
@@ -144,7 +144,8 @@ // CanvasRenderingContext2D. MutableCSSPropertyValueSet* parsed_style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); - CSSParser::ParseValue(parsed_style, CSSPropertyFont, font_string, true); + CSSParser::ParseValue(parsed_style, CSSPropertyFont, font_string, true, + GetDocument()->SecureContextMode()); if (parsed_style->IsEmpty()) return false;
diff --git a/third_party/WebKit/Source/core/css/FontFaceSetWorker.cpp b/third_party/WebKit/Source/core/css/FontFaceSetWorker.cpp index 3056422b..b64e967 100644 --- a/third_party/WebKit/Source/core/css/FontFaceSetWorker.cpp +++ b/third_party/WebKit/Source/core/css/FontFaceSetWorker.cpp
@@ -74,7 +74,8 @@ // CanvasRenderingContext2D. MutableCSSPropertyValueSet* parsed_style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); - CSSParser::ParseValue(parsed_style, CSSPropertyFont, font_string, true); + CSSParser::ParseValue(parsed_style, CSSPropertyFont, font_string, true, + GetExecutionContext()->SecureContextMode()); if (parsed_style->IsEmpty()) return false;
diff --git a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp index bcdad2c..e3ae34b5c 100644 --- a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp +++ b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp
@@ -171,12 +171,15 @@ return PropertySet().AsText(); } -void AbstractPropertySetCSSStyleDeclaration::setCSSText(const String& text, - ExceptionState&) { +void AbstractPropertySetCSSStyleDeclaration::setCSSText( + const ExecutionContext* execution_context, + const String& text, + ExceptionState&) { StyleAttributeMutationScope mutation_scope(this); WillMutate(); - PropertySet().ParseDeclarationList(text, ContextStyleSheet()); + PropertySet().ParseDeclarationList( + text, execution_context->SecureContextMode(), ContextStyleSheet()); DidMutate(kPropertyChanged); @@ -231,6 +234,7 @@ } void AbstractPropertySetCSSStyleDeclaration::setProperty( + const ExecutionContext* execution_context, const String& property_name, const String& value, const String& priority, @@ -244,7 +248,7 @@ return; SetPropertyInternal(property_id, property_name, value, important, - exception_state); + execution_context->SecureContextMode(), exception_state); } String AbstractPropertySetCSSStyleDeclaration::removeProperty( @@ -295,6 +299,7 @@ const String& custom_property_name, const String& value, bool important, + SecureContextMode secure_context_mode, ExceptionState&) { StyleAttributeMutationScope mutation_scope(this); WillMutate(); @@ -304,15 +309,15 @@ AtomicString atomic_name(custom_property_name); bool is_animation_tainted = IsKeyframeStyle(); - did_change = - PropertySet() - .SetProperty(atomic_name, GetPropertyRegistry(), value, important, - ContextStyleSheet(), is_animation_tainted) - .did_change; + did_change = PropertySet() + .SetProperty(atomic_name, GetPropertyRegistry(), value, + important, secure_context_mode, + ContextStyleSheet(), is_animation_tainted) + .did_change; } else { did_change = PropertySet() .SetProperty(unresolved_property, value, important, - ContextStyleSheet()) + secure_context_mode, ContextStyleSheet()) .did_change; }
diff --git a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h index fb42308f..071e11a 100644 --- a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h +++ b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h
@@ -36,6 +36,7 @@ class CSSValue; class Element; class ExceptionState; +class ExecutionContext; class MutableCSSPropertyValueSet; class PropertyRegistry; class StyleSheetContents; @@ -55,7 +56,8 @@ String getPropertyPriority(const String& property_name) final; String GetPropertyShorthand(const String& property_name) final; bool IsPropertyImplicit(const String& property_name) final; - void setProperty(const String& property_name, + void setProperty(const ExecutionContext*, + const String& property_name, const String& value, const String& priority, ExceptionState&) final; @@ -63,7 +65,9 @@ String CssFloat() const; void SetCSSFloat(const String&, ExceptionState&); String cssText() const final; - void setCSSText(const String&, ExceptionState&) final; + void setCSSText(const ExecutionContext*, + const String&, + ExceptionState&) final; const CSSValue* GetPropertyCSSValueInternal(CSSPropertyID) final; const CSSValue* GetPropertyCSSValueInternal( AtomicString custom_property_name) final; @@ -72,6 +76,7 @@ const String& custom_property_name, const String& value, bool important, + SecureContextMode, ExceptionState&) final; bool CssPropertyMatches(CSSPropertyID, const CSSValue*) const final;
diff --git a/third_party/WebKit/Source/core/css/RuleFeatureSetTest.cpp b/third_party/WebKit/Source/core/css/RuleFeatureSetTest.cpp index 6fbd64d..2d677fe 100644 --- a/third_party/WebKit/Source/core/css/RuleFeatureSetTest.cpp +++ b/third_party/WebKit/Source/core/css/RuleFeatureSetTest.cpp
@@ -35,7 +35,8 @@ RuleFeatureSet::SelectorPreMatch CollectFeatures( const String& selector_text) { CSSSelectorList selector_list = CSSParser::ParseSelector( - StrictCSSParserContext(), nullptr, selector_text); + StrictCSSParserContext(SecureContextMode::kInsecureContext), nullptr, + selector_text); StyleRule* style_rule = StyleRule::Create( std::move(selector_list),
diff --git a/third_party/WebKit/Source/core/css/StyleEngineTest.cpp b/third_party/WebKit/Source/core/css/StyleEngineTest.cpp index 6cc6938..2fd46d0 100644 --- a/third_party/WebKit/Source/core/css/StyleEngineTest.cpp +++ b/third_party/WebKit/Source/core/css/StyleEngineTest.cpp
@@ -57,7 +57,8 @@ StyleEngineTest::ScheduleInvalidationsForRules(TreeScope& tree_scope, const String& css_text) { StyleSheetContents* sheet = - StyleSheetContents::Create(CSSParserContext::Create(kHTMLStandardMode)); + StyleSheetContents::Create(CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext)); sheet->ParseString(css_text); HeapHashSet<Member<RuleSet>> rule_sets; RuleSet& rule_set = sheet->EnsureRuleSet(MediaQueryEvaluator(), @@ -745,14 +746,16 @@ // Modify the CSSPropertyValueSet once to make it a mutable set. Subsequent // modifications will not change the CSSPropertyValueSet pointer and cache // hash value will be the same. - style_rule->style()->setProperty("color", "red", "", ASSERT_NO_EXCEPTION); + style_rule->style()->setProperty(&GetDocument(), "color", "red", "", + ASSERT_NO_EXCEPTION); GetDocument().View()->UpdateAllLifecyclePhases(); ASSERT_TRUE(t1->GetComputedStyle()); EXPECT_EQ(MakeRGB(255, 0, 0), t1->GetComputedStyle()->VisitedDependentColor(CSSPropertyColor)); - style_rule->style()->setProperty("color", "green", "", ASSERT_NO_EXCEPTION); + style_rule->style()->setProperty(&GetDocument(), "color", "green", "", + ASSERT_NO_EXCEPTION); GetDocument().View()->UpdateAllLifecyclePhases(); ASSERT_TRUE(t1->GetComputedStyle());
diff --git a/third_party/WebKit/Source/core/css/StyleRuleImport.cpp b/third_party/WebKit/Source/core/css/StyleRuleImport.cpp index 9eb4c32..78159ea 100644 --- a/third_party/WebKit/Source/core/css/StyleRuleImport.cpp +++ b/third_party/WebKit/Source/core/css/StyleRuleImport.cpp
@@ -75,7 +75,12 @@ style_sheet_->ClearOwnerRule(); Document* document = nullptr; - const CSSParserContext* context = StrictCSSParserContext(); + + // Fallback to an insecure context parser if we don't have a parent style + // sheet. + const CSSParserContext* context = + StrictCSSParserContext(SecureContextMode::kInsecureContext); + if (parent_style_sheet_) { document = parent_style_sheet_->SingleOwnerDocument(); context = parent_style_sheet_->ParserContext();
diff --git a/third_party/WebKit/Source/core/css/StyleSheetContentsFuzzer.cpp b/third_party/WebKit/Source/core/css/StyleSheetContentsFuzzer.cpp index 545bda8..af9dec7 100644 --- a/third_party/WebKit/Source/core/css/StyleSheetContentsFuzzer.cpp +++ b/third_party/WebKit/Source/core/css/StyleSheetContentsFuzzer.cpp
@@ -14,9 +14,13 @@ const std::string data_string(reinterpret_cast<const char*>(data), size); const size_t data_hash = std::hash<std::string>()(data_string); const int is_strict_mode = (data_hash & std::numeric_limits<int>::max()) % 2; + const int is_secure_context_mode = + (std::hash<size_t>()(data_hash) & std::numeric_limits<int>::max()) % 2; blink::CSSParserContext* context = blink::CSSParserContext::Create( - is_strict_mode ? blink::kHTMLStandardMode : blink::kHTMLQuirksMode); + is_strict_mode ? blink::kHTMLStandardMode : blink::kHTMLQuirksMode, + is_secure_context_mode ? blink::SecureContextMode::kSecureContext + : blink::SecureContextMode::kInsecureContext); blink::StyleSheetContents* styleSheet = blink::StyleSheetContents::Create(context);
diff --git a/third_party/WebKit/Source/core/css/StyleSheetContentsTest.cpp b/third_party/WebKit/Source/core/css/StyleSheetContentsTest.cpp index 1296f27..7d1e9b1 100644 --- a/third_party/WebKit/Source/core/css/StyleSheetContentsTest.cpp +++ b/third_party/WebKit/Source/core/css/StyleSheetContentsTest.cpp
@@ -11,7 +11,8 @@ namespace blink { TEST(StyleSheetContentsTest, InsertMediaRule) { - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* style_sheet = StyleSheetContents::Create(context); style_sheet->ParseString("@namespace ns url(test);"); @@ -34,7 +35,8 @@ } TEST(StyleSheetContentsTest, InsertFontFaceRule) { - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* style_sheet = StyleSheetContents::Create(context); style_sheet->ParseString("@namespace ns url(test);"); @@ -57,7 +59,8 @@ } TEST(StyleSheetContentsTest, HasViewportRule) { - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* style_sheet = StyleSheetContents::Create(context); style_sheet->ParseString("@viewport { width: 200px}"); @@ -66,7 +69,8 @@ } TEST(StyleSheetContentsTest, HasViewportRuleAfterInsertion) { - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* style_sheet = StyleSheetContents::Create(context); style_sheet->ParseString("body { color: pink }"); @@ -82,7 +86,8 @@ } TEST(StyleSheetContentsTest, HasViewportRuleAfterInsertionIntoMediaRule) { - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* style_sheet = StyleSheetContents::Create(context); style_sheet->ParseString("@media {}");
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.cpp index 23436b60..3e61637 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.cpp
@@ -72,7 +72,7 @@ return CssValueKeywordID(keyword_value_); } -const CSSValue* CSSKeywordValue::ToCSSValue() const { +const CSSValue* CSSKeywordValue::ToCSSValue(SecureContextMode) const { CSSValueID keyword_id = KeywordValueID(); switch (keyword_id) { case (CSSValueInherit):
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.h b/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.h index 94d533c..e951546 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.h
@@ -28,7 +28,7 @@ void setValue(const String& keyword, ExceptionState&); CSSValueID KeywordValueID() const; - const CSSValue* ToCSSValue() const override; + const CSSValue* ToCSSValue(SecureContextMode) const override; private: explicit CSSKeywordValue(const String& keyword) : keyword_value_(keyword) {}
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMathValue.h b/third_party/WebKit/Source/core/css/cssom/CSSMathValue.h index 8589cec..0985bab2 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSMathValue.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSMathValue.h
@@ -31,7 +31,7 @@ // TODO(776173): Implement return false; } - const CSSValue* ToCSSValue() const final { + const CSSValue* ToCSSValue(SecureContextMode) const final { // TODO(776173): Implement return nullptr; }
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.cpp b/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.cpp index 32134d12..7827bff 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.cpp
@@ -39,7 +39,8 @@ return matrix_.Get(); } -const CSSFunctionValue* CSSMatrixComponent::ToCSSValue() const { +const CSSFunctionValue* CSSMatrixComponent::ToCSSValue( + SecureContextMode) const { CSSFunctionValue* result = CSSFunctionValue::Create(is2D() ? CSSValueMatrix : CSSValueMatrix3d);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.h b/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.h index 0f38c3fe05..91202df 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.h
@@ -38,7 +38,7 @@ // Internal methods - from CSSTransformComponent. TransformComponentType GetType() const final { return kMatrixType; } const DOMMatrix* AsMatrix(ExceptionState&) const final; - const CSSFunctionValue* ToCSSValue() const final; + const CSSFunctionValue* ToCSSValue(SecureContextMode) const final; virtual void Trace(blink::Visitor* visitor) { visitor->Trace(matrix_);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSPerspective.cpp b/third_party/WebKit/Source/core/css/cssom/CSSPerspective.cpp index c1973b6..49eafd1 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSPerspective.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSPerspective.cpp
@@ -69,14 +69,15 @@ return matrix; } -const CSSFunctionValue* CSSPerspective::ToCSSValue() const { +const CSSFunctionValue* CSSPerspective::ToCSSValue( + SecureContextMode secure_context_mode) const { if (length_->IsUnitValue() && ToCSSUnitValue(length_)->value() < 0) { // Negative values are invalid. // https://github.com/w3c/css-houdini-drafts/issues/420 return nullptr; } CSSFunctionValue* result = CSSFunctionValue::Create(CSSValuePerspective); - result->Append(*length_->ToCSSValue()); + result->Append(*length_->ToCSSValue(secure_context_mode)); return result; }
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSPerspective.h b/third_party/WebKit/Source/core/css/cssom/CSSPerspective.h index 9003dd60..7a02ece 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSPerspective.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSPerspective.h
@@ -40,7 +40,7 @@ // Internal methods - from CSSTransformComponent. TransformComponentType GetType() const final { return kPerspectiveType; } const DOMMatrix* AsMatrix(ExceptionState&) const final; - const CSSFunctionValue* ToCSSValue() const final; + const CSSFunctionValue* ToCSSValue(SecureContextMode) const final; virtual void Trace(blink::Visitor* visitor) { visitor->Trace(length_);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSPositionValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSPositionValue.cpp index f98a2e50..a52429e 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSPositionValue.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSPositionValue.cpp
@@ -50,8 +50,10 @@ y_ = y; } -const CSSValue* CSSPositionValue::ToCSSValue() const { - return CSSValuePair::Create(x_->ToCSSValue(), y_->ToCSSValue(), +const CSSValue* CSSPositionValue::ToCSSValue( + SecureContextMode secure_context_mode) const { + return CSSValuePair::Create(x_->ToCSSValue(secure_context_mode), + y_->ToCSSValue(secure_context_mode), CSSValuePair::kKeepIdenticalValues); }
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSPositionValue.h b/third_party/WebKit/Source/core/css/cssom/CSSPositionValue.h index ce8f375..17ea75f 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSPositionValue.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSPositionValue.h
@@ -33,7 +33,7 @@ // Internal methods - from CSSStyleValue. StyleValueType GetType() const final { return kPositionType; } - const CSSValue* ToCSSValue() const final; + const CSSValue* ToCSSValue(SecureContextMode) const final; virtual void Trace(blink::Visitor* visitor) { visitor->Trace(x_);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSResourceValueTest.cpp b/third_party/WebKit/Source/core/css/cssom/CSSResourceValueTest.cpp index 89b81b1..e5ef9f49 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSResourceValueTest.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSResourceValueTest.cpp
@@ -15,7 +15,9 @@ FakeCSSResourceValue(ResourceStatus status) : status_(status) {} ResourceStatus Status() const override { return status_; } - const CSSValue* ToCSSValue() const override { return nullptr; } + const CSSValue* ToCSSValue(SecureContextMode) const override { + return nullptr; + } StyleValueType GetType() const override { return kUnknownType; } private:
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSRotation.cpp b/third_party/WebKit/Source/core/css/cssom/CSSRotation.cpp index e6a0782..6c39fdc 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSRotation.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSRotation.cpp
@@ -137,7 +137,7 @@ return matrix; } -const CSSFunctionValue* CSSRotation::ToCSSValue() const { +const CSSFunctionValue* CSSRotation::ToCSSValue(SecureContextMode) const { // TODO(meade): Handle calc angles. CSSUnitValue* angle = ToCSSUnitValue(angle_); CSSFunctionValue* result =
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSRotation.h b/third_party/WebKit/Source/core/css/cssom/CSSRotation.h index 7eccd9c..021bf8f 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSRotation.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSRotation.h
@@ -50,7 +50,7 @@ // Internal methods - from CSSTransformComponent. TransformComponentType GetType() const final { return kRotationType; } const DOMMatrix* AsMatrix(ExceptionState&) const final; - const CSSFunctionValue* ToCSSValue() const final; + const CSSFunctionValue* ToCSSValue(SecureContextMode) const final; virtual void Trace(blink::Visitor* visitor) { visitor->Trace(angle_);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSScale.cpp b/third_party/WebKit/Source/core/css/cssom/CSSScale.cpp index 54ebd5b..4f548f8 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSScale.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSScale.cpp
@@ -62,7 +62,7 @@ } } -const CSSFunctionValue* CSSScale::ToCSSValue() const { +const CSSFunctionValue* CSSScale::ToCSSValue(SecureContextMode) const { CSSFunctionValue* result = CSSFunctionValue::Create(is2D() ? CSSValueScale : CSSValueScale3d);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSScale.h b/third_party/WebKit/Source/core/css/cssom/CSSScale.h index ec74896..68983e6 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSScale.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSScale.h
@@ -43,7 +43,7 @@ DOMMatrix* result = DOMMatrix::Create(); return result->scaleSelf(x_, y_, z_); } - const CSSFunctionValue* ToCSSValue() const final; + const CSSFunctionValue* ToCSSValue(SecureContextMode) const final; private: CSSScale(double x, double y)
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSSkew.cpp b/third_party/WebKit/Source/core/css/cssom/CSSSkew.cpp index 8e31d1d2..cd79026c 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSSkew.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSSkew.cpp
@@ -96,7 +96,7 @@ return result; } -const CSSFunctionValue* CSSSkew::ToCSSValue() const { +const CSSFunctionValue* CSSSkew::ToCSSValue(SecureContextMode) const { // TDOO(meade): Handle calc angles here. CSSUnitValue* ax = ToCSSUnitValue(ax_); CSSUnitValue* ay = ToCSSUnitValue(ay_);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSSkew.h b/third_party/WebKit/Source/core/css/cssom/CSSSkew.h index 1bc87db..b18778f9 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSSkew.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSSkew.h
@@ -44,7 +44,7 @@ // Internal methods - from CSSTransformComponent. const DOMMatrix* AsMatrix(ExceptionState&) const override; TransformComponentType GetType() const override { return kSkewType; } - const CSSFunctionValue* ToCSSValue() const override; + const CSSFunctionValue* ToCSSValue(SecureContextMode) const override; virtual void Trace(blink::Visitor* visitor) { visitor->Trace(ax_);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleImageValueTest.cpp b/third_party/WebKit/Source/core/css/cssom/CSSStyleImageValueTest.cpp index 4f886b9..24211e0 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSStyleImageValueTest.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleImageValueTest.cpp
@@ -22,7 +22,9 @@ bool IsCachePending() const override { return cache_pending_; } IntSize ImageSize() const override { return size_; } - const CSSValue* ToCSSValue() const override { return nullptr; } + const CSSValue* ToCSSValue(SecureContextMode) const override { + return nullptr; + } StyleValueType GetType() const override { return kUnknownType; } private:
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp index d14315a..df5c764 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp
@@ -15,9 +15,11 @@ namespace { -CSSStyleValueVector ParseCSSStyleValue(const String& property_name, - const String& value, - ExceptionState& exception_state) { +CSSStyleValueVector ParseCSSStyleValue( + const ExecutionContext* execution_context, + const String& property_name, + const String& value, + ExceptionState& exception_state) { const CSSPropertyID property_id = cssPropertyID(property_name); // TODO(775804): Handle custom properties @@ -34,8 +36,10 @@ // TODO(crbug.com/783031): This should probably use an existing parser context // (e.g. from execution context) to parse relative URLs correctly. - const CSSValue* css_value = - CSSParser::ParseSingleValue(property_id, value, StrictCSSParserContext()); + const CSSValue* css_value = CSSParser::ParseSingleValue( + property_id, value, + StrictCSSParserContext(execution_context->SecureContextMode())); + if (!css_value) { exception_state.ThrowDOMException( kSyntaxError, "The value provided ('" + value + @@ -52,11 +56,12 @@ } // namespace -CSSStyleValue* CSSStyleValue::parse(const String& property_name, +CSSStyleValue* CSSStyleValue::parse(const ExecutionContext* execution_context, + const String& property_name, const String& value, ExceptionState& exception_state) { - CSSStyleValueVector style_value_vector = - ParseCSSStyleValue(property_name, value, exception_state); + CSSStyleValueVector style_value_vector = ParseCSSStyleValue( + execution_context, property_name, value, exception_state); if (style_value_vector.IsEmpty()) return nullptr; @@ -64,17 +69,26 @@ } Nullable<CSSStyleValueVector> CSSStyleValue::parseAll( + const ExecutionContext* execution_context, const String& property_name, const String& value, ExceptionState& exception_state) { - CSSStyleValueVector style_value_vector = - ParseCSSStyleValue(property_name, value, exception_state); + CSSStyleValueVector style_value_vector = ParseCSSStyleValue( + execution_context, property_name, value, exception_state); if (style_value_vector.IsEmpty()) return nullptr; return style_value_vector; } +String CSSStyleValue::toString( + const ExecutionContext* execution_context) const { + const CSSValue* result = ToCSSValue(execution_context->SecureContextMode()); + // TODO(meade): Remove this once all the number and length types are + // rewritten. + return result ? result->CssText() : ""; +} + String CSSStyleValue::StyleValueTypeToString(StyleValueType type) { switch (type) { case StyleValueType::kNumberType:
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h index 7770b19..bee6cfa 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h
@@ -15,6 +15,8 @@ namespace blink { class ExceptionState; +class ExecutionContext; +enum class SecureContextMode; class CSSStyleValue; using CSSStyleValueVector = HeapVector<Member<CSSStyleValue>>; @@ -50,10 +52,12 @@ kInvalidType, }; - static CSSStyleValue* parse(const String& property_name, + static CSSStyleValue* parse(const ExecutionContext*, + const String& property_name, const String& value, ExceptionState&); - static Nullable<CSSStyleValueVector> parseAll(const String& property_name, + static Nullable<CSSStyleValueVector> parseAll(const ExecutionContext*, + const String& property_name, const String& value, ExceptionState&); @@ -62,16 +66,13 @@ virtual StyleValueType GetType() const = 0; virtual bool ContainsPercent() const { return false; } - virtual const CSSValue* ToCSSValue() const = 0; - virtual const CSSValue* ToCSSValueWithProperty(CSSPropertyID) const { - return ToCSSValue(); + virtual const CSSValue* ToCSSValue(SecureContextMode) const = 0; + virtual const CSSValue* ToCSSValueWithProperty( + CSSPropertyID, + SecureContextMode secure_context_mode) const { + return ToCSSValue(secure_context_mode); } - virtual String toString() const { - const CSSValue* result = ToCSSValue(); - // TODO(meade): Remove this once all the number and length types are - // rewritten. - return result ? result->CssText() : ""; - } + virtual String toString(const ExecutionContext*) const; protected: static String StyleValueTypeToString(StyleValueType);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl index 6eabaa9..072b230 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl +++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl
@@ -9,8 +9,8 @@ [ Exposed(Window CSSTypedOM, PaintWorklet CSSPaintAPI) ] interface CSSStyleValue { - stringifier; + [CallWith=ExecutionContext] stringifier; // Putting Exposed=Window in the next line makes |parse| not exposed to PaintWorklet. - [RaisesException, Exposed=Window] static CSSStyleValue? parse(DOMString property, DOMString cssText); - [RaisesException, Exposed=Window] static sequence<CSSStyleValue>? parseAll(DOMString property, DOMString cssText); + [RaisesException, Exposed=Window, CallWith=ExecutionContext] static CSSStyleValue? parse(DOMString property, DOMString cssText); + [RaisesException, Exposed=Window, CallWith=ExecutionContext] static sequence<CSSStyleValue>? parseAll(DOMString property, DOMString cssText); };
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.cpp b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.cpp index 2100b05..dc2ef3c6 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.cpp
@@ -52,4 +52,12 @@ } } +String CSSTransformComponent::toString( + const ExecutionContext* execution_context) const { + const CSSValue* result = ToCSSValue(execution_context->SecureContextMode()); + // TODO(meade): Remove this once all the number and length types are + // rewritten. + return result ? result->CssText() : ""; +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.h b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.h index e7051c3..9b3746c 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.h
@@ -14,6 +14,8 @@ class DOMMatrix; class ExceptionState; +class ExecutionContext; +enum class SecureContextMode; // CSSTransformComponent is the base class used for the representations of // the individual CSS transforms. They are combined in a CSSTransformValue @@ -41,16 +43,11 @@ // Getters and setters for attributes defined in the IDL. bool is2D() const { return is2D_; } virtual void setIs2D(bool is2D) { is2D_ = is2D; } - virtual String toString() const { - const CSSValue* result = ToCSSValue(); - // TODO(meade): Remove this once all the number and length types are - // rewritten. - return result ? result->CssText() : ""; - } + virtual String toString(const ExecutionContext*) const; // Internal methods. virtual TransformComponentType GetType() const = 0; - virtual const CSSFunctionValue* ToCSSValue() const = 0; + virtual const CSSFunctionValue* ToCSSValue(SecureContextMode) const = 0; virtual const DOMMatrix* AsMatrix(ExceptionState&) const = 0; protected:
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.idl b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.idl index ec592a2..c9ccdc0 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.idl +++ b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.idl
@@ -10,6 +10,6 @@ Exposed=(Window,PaintWorklet), RuntimeEnabled=CSSTypedOM ] interface CSSTransformComponent { - stringifier; + [CallWith=ExecutionContext] stringifier; attribute boolean is2D; };
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTransformValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSTransformValue.cpp index 43b78d5..54e1d8f 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSTransformValue.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSTransformValue.cpp
@@ -47,10 +47,12 @@ return matrix; } -const CSSValue* CSSTransformValue::ToCSSValue() const { +const CSSValue* CSSTransformValue::ToCSSValue( + SecureContextMode secure_context_mode) const { CSSValueList* transform_css_value = CSSValueList::CreateSpaceSeparated(); for (size_t i = 0; i < transform_components_.size(); i++) { - const CSSValue* component = transform_components_[i]->ToCSSValue(); + const CSSValue* component = + transform_components_[i]->ToCSSValue(secure_context_mode); // TODO(meade): Remove this check once numbers and lengths are rewritten. if (!component) return nullptr;
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTransformValue.h b/third_party/WebKit/Source/core/css/cssom/CSSTransformValue.h index 46fa94d3..962376fb2 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSTransformValue.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSTransformValue.h
@@ -33,7 +33,7 @@ DOMMatrix* toMatrix(ExceptionState&) const; - const CSSValue* ToCSSValue() const override; + const CSSValue* ToCSSValue(SecureContextMode) const override; StyleValueType GetType() const override { return kTransformType; }
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTranslation.cpp b/third_party/WebKit/Source/core/css/cssom/CSSTranslation.cpp index b1fb769..6490225 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSTranslation.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSTranslation.cpp
@@ -213,13 +213,14 @@ return matrix->translate(x->value(), y->value(), z->value()); } -const CSSFunctionValue* CSSTranslation::ToCSSValue() const { +const CSSFunctionValue* CSSTranslation::ToCSSValue( + SecureContextMode secure_context_mode) const { CSSFunctionValue* result = CSSFunctionValue::Create( is2D() ? CSSValueTranslate : CSSValueTranslate3d); - result->Append(*x_->ToCSSValue()); - result->Append(*y_->ToCSSValue()); + result->Append(*x_->ToCSSValue(secure_context_mode)); + result->Append(*y_->ToCSSValue(secure_context_mode)); if (!is2D()) - result->Append(*z_->ToCSSValue()); + result->Append(*z_->ToCSSValue(secure_context_mode)); return result; }
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTranslation.h b/third_party/WebKit/Source/core/css/cssom/CSSTranslation.h index afb5ccd..e3959e0 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSTranslation.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSTranslation.h
@@ -51,7 +51,7 @@ // Internal methods - from CSSTransformComponent. TransformComponentType GetType() const final { return kTranslationType; } const DOMMatrix* AsMatrix(ExceptionState&) const final; - const CSSFunctionValue* ToCSSValue() const final; + const CSSFunctionValue* ToCSSValue(SecureContextMode) const final; virtual void Trace(blink::Visitor* visitor) { visitor->Trace(x_);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSURLImageValue.h b/third_party/WebKit/Source/core/css/cssom/CSSURLImageValue.h index f41b7f0..746f365 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSURLImageValue.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSURLImageValue.h
@@ -30,7 +30,9 @@ StyleValueType GetType() const override { return kURLImageType; } - const CSSValue* ToCSSValue() const override { return CssImageValue(); } + const CSSValue* ToCSSValue(SecureContextMode) const override { + return CssImageValue(); + } const String& url() const { return CssImageValue()->RelativeUrl(); }
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.cpp index 0fa5a3dc..eab9ac7 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.cpp
@@ -83,7 +83,7 @@ return StyleValueType::kUnknownType; } -const CSSValue* CSSUnitValue::ToCSSValue() const { +const CSSValue* CSSUnitValue::ToCSSValue(SecureContextMode) const { return CSSPrimitiveValue::Create(value_, unit_); }
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.h b/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.h index 2c884f52..66e839f 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.h
@@ -46,7 +46,7 @@ bool ContainsPercent() const final { return unit_ == CSSPrimitiveValue::UnitType::kPercentage; } - const CSSValue* ToCSSValue() const final; + const CSSValue* ToCSSValue(SecureContextMode) const final; private: CSSUnitValue(double value, CSSPrimitiveValue::UnitType unit)
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp index ea6902e..50390e0 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
@@ -70,7 +70,8 @@ css_variable_reference_value.VariableDataValue()->TokenRange())); } -const CSSValue* CSSUnparsedValue::ToCSSValue() const { +const CSSValue* CSSUnparsedValue::ToCSSValue( + SecureContextMode secure_context_mode) const { StringBuilder input; for (unsigned i = 0; i < tokens_.size(); i++) { @@ -94,7 +95,7 @@ CSSVariableData::Create(CSSParserTokenRange(tokens), false /* isAnimationTainted */, true /* needsVariableResolution */), - *StrictCSSParserContext()); + *StrictCSSParserContext(secure_context_mode)); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h index 3861e0d..f8fbebcc 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
@@ -24,7 +24,7 @@ static CSSUnparsedValue* FromCSSValue(const CSSVariableReferenceValue&); - const CSSValue* ToCSSValue() const override; + const CSSValue* ToCSSValue(SecureContextMode) const override; StyleValueType GetType() const override { return kUnparsedType; }
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnsupportedStyleValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSUnsupportedStyleValue.cpp index da77ba5..8de98bf 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSUnsupportedStyleValue.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSUnsupportedStyleValue.cpp
@@ -9,15 +9,16 @@ namespace blink { -const CSSValue* CSSUnsupportedStyleValue::ToCSSValue() const { +const CSSValue* CSSUnsupportedStyleValue::ToCSSValue(SecureContextMode) const { NOTREACHED(); return nullptr; } const CSSValue* CSSUnsupportedStyleValue::ToCSSValueWithProperty( - CSSPropertyID property_id) const { - return CSSParser::ParseSingleValue(property_id, css_text_, - StrictCSSParserContext()); + CSSPropertyID property_id, + SecureContextMode secure_context_mode) const { + return CSSParser::ParseSingleValue( + property_id, css_text_, StrictCSSParserContext(secure_context_mode)); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnsupportedStyleValue.h b/third_party/WebKit/Source/core/css/cssom/CSSUnsupportedStyleValue.h index 2833f6a..49a4294 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSUnsupportedStyleValue.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSUnsupportedStyleValue.h
@@ -23,9 +23,10 @@ StyleValueType GetType() const override { return StyleValueType::kUnknownType; } - const CSSValue* ToCSSValue() const override; - const CSSValue* ToCSSValueWithProperty(CSSPropertyID) const override; - String toString() const override { return css_text_; } + const CSSValue* ToCSSValue(SecureContextMode) const override; + const CSSValue* ToCSSValueWithProperty(CSSPropertyID, + SecureContextMode) const override; + String toString(const ExecutionContext*) const override { return css_text_; } private: CSSUnsupportedStyleValue(const String& css_text) : css_text_(css_text) {}
diff --git a/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp index 8d32dc65..065ccf8c 100644 --- a/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp +++ b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp
@@ -36,15 +36,19 @@ } const CSSValue* StyleValueToCSSValue(CSSPropertyID property_id, - const CSSStyleValue& style_value) { + const CSSStyleValue& style_value, + SecureContextMode secure_context_mode) { if (!CSSOMTypes::PropertyCanTake(property_id, style_value)) return nullptr; - return style_value.ToCSSValueWithProperty(property_id); + return style_value.ToCSSValueWithProperty(property_id, secure_context_mode); } -const CSSValue* SingleStyleValueAsCSSValue(CSSPropertyID property_id, - const CSSStyleValue& style_value) { - const CSSValue* css_value = StyleValueToCSSValue(property_id, style_value); +const CSSValue* SingleStyleValueAsCSSValue( + CSSPropertyID property_id, + const CSSStyleValue& style_value, + SecureContextMode secure_context_mode) { + const CSSValue* css_value = + StyleValueToCSSValue(property_id, style_value, secure_context_mode); if (!css_value) return nullptr; @@ -59,10 +63,12 @@ const CSSValueList* AsCSSValueList( CSSPropertyID property_id, - const CSSStyleValueVector& style_value_vector) { + const CSSStyleValueVector& style_value_vector, + SecureContextMode secure_context_mode) { CSSValueList* value_list = CssValueListForPropertyID(property_id); for (const CSSStyleValue* value : style_value_vector) { - const CSSValue* css_value = StyleValueToCSSValue(property_id, *value); + const CSSValue* css_value = + StyleValueToCSSValue(property_id, *value, secure_context_mode); if (!css_value) { return nullptr; } @@ -116,20 +122,23 @@ } void InlineStylePropertyMap::set( + const ExecutionContext* execution_context, CSSPropertyID property_id, CSSStyleValueOrCSSStyleValueSequenceOrString& item, ExceptionState& exception_state) { const CSSValue* css_value = nullptr; if (item.IsCSSStyleValue()) { css_value = - SingleStyleValueAsCSSValue(property_id, *item.GetAsCSSStyleValue()); + SingleStyleValueAsCSSValue(property_id, *item.GetAsCSSStyleValue(), + execution_context->SecureContextMode()); } else if (item.IsCSSStyleValueSequence()) { if (!CSSProperty::Get(property_id).IsRepeated()) { exception_state.ThrowTypeError( "Property does not support multiple values"); return; } - css_value = AsCSSValueList(property_id, item.GetAsCSSStyleValueSequence()); + css_value = AsCSSValueList(property_id, item.GetAsCSSStyleValueSequence(), + execution_context->SecureContextMode()); } else { // Parse it. DCHECK(item.IsString()); @@ -145,6 +154,7 @@ } void InlineStylePropertyMap::append( + const ExecutionContext* execution_context, CSSPropertyID property_id, CSSStyleValueOrCSSStyleValueSequenceOrString& item, ExceptionState& exception_state) { @@ -169,7 +179,8 @@ if (item.IsCSSStyleValue()) { const CSSValue* css_value = - StyleValueToCSSValue(property_id, *item.GetAsCSSStyleValue()); + StyleValueToCSSValue(property_id, *item.GetAsCSSStyleValue(), + execution_context->SecureContextMode()); if (!css_value) { exception_state.ThrowTypeError("Invalid type for property"); return; @@ -177,8 +188,8 @@ css_value_list->Append(*css_value); } else if (item.IsCSSStyleValueSequence()) { for (CSSStyleValue* style_value : item.GetAsCSSStyleValueSequence()) { - const CSSValue* css_value = - StyleValueToCSSValue(property_id, *style_value); + const CSSValue* css_value = StyleValueToCSSValue( + property_id, *style_value, execution_context->SecureContextMode()); if (!css_value) { exception_state.ThrowTypeError("Invalid type for property"); return;
diff --git a/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.h b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.h index f5048e78..ae12f5c 100644 --- a/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.h +++ b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.h
@@ -19,10 +19,12 @@ Vector<String> getProperties() override; - void set(CSSPropertyID, + void set(const ExecutionContext*, + CSSPropertyID, CSSStyleValueOrCSSStyleValueSequenceOrString&, ExceptionState&) override; - void append(CSSPropertyID, + void append(const ExecutionContext*, + CSSPropertyID, CSSStyleValueOrCSSStyleValueSequenceOrString&, ExceptionState&) override; void remove(CSSPropertyID, ExceptionState&) override;
diff --git a/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.cpp b/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.cpp index b118b849f..5580554 100644 --- a/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.cpp +++ b/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.cpp
@@ -11,12 +11,13 @@ namespace blink { -void StylePropertyMap::set(const String& property_name, +void StylePropertyMap::set(const ExecutionContext* execution_context, + const String& property_name, CSSStyleValueOrCSSStyleValueSequenceOrString& item, ExceptionState& exception_state) { CSSPropertyID property_id = cssPropertyID(property_name); if (property_id != CSSPropertyInvalid && property_id != CSSPropertyVariable) { - set(property_id, item, exception_state); + set(execution_context, property_id, item, exception_state); return; } // TODO(meade): Handle custom properties here. @@ -24,12 +25,13 @@ } void StylePropertyMap::append( + const ExecutionContext* execution_context, const String& property_name, CSSStyleValueOrCSSStyleValueSequenceOrString& item, ExceptionState& exception_state) { CSSPropertyID property_id = cssPropertyID(property_name); if (property_id != CSSPropertyInvalid && property_id != CSSPropertyVariable) { - append(property_id, item, exception_state); + append(execution_context, property_id, item, exception_state); return; } // TODO(meade): Handle custom properties here.
diff --git a/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.h b/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.h index a65f937..f2c0d8f 100644 --- a/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.h +++ b/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.h
@@ -10,24 +10,29 @@ namespace blink { class ExceptionState; +class ExecutionContext; class CORE_EXPORT StylePropertyMap : public StylePropertyMapReadonly { DEFINE_WRAPPERTYPEINFO(); WTF_MAKE_NONCOPYABLE(StylePropertyMap); public: - void set(const String& property_name, + void set(const ExecutionContext*, + const String& property_name, CSSStyleValueOrCSSStyleValueSequenceOrString& item, ExceptionState&); - void append(const String& property_name, + void append(const ExecutionContext*, + const String& property_name, CSSStyleValueOrCSSStyleValueSequenceOrString& item, ExceptionState&); void remove(const String& property_name, ExceptionState&); - virtual void set(CSSPropertyID, + virtual void set(const ExecutionContext*, + CSSPropertyID, CSSStyleValueOrCSSStyleValueSequenceOrString& item, ExceptionState&) = 0; - virtual void append(CSSPropertyID, + virtual void append(const ExecutionContext*, + CSSPropertyID, CSSStyleValueOrCSSStyleValueSequenceOrString& item, ExceptionState&) = 0; virtual void remove(CSSPropertyID, ExceptionState&) = 0;
diff --git a/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.idl b/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.idl index 16bd61b..9fac99e3 100644 --- a/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.idl +++ b/third_party/WebKit/Source/core/css/cssom/StylePropertyMap.idl
@@ -7,7 +7,7 @@ Exposed=(Window,PaintWorklet), RuntimeEnabled=CSSTypedOM ] interface StylePropertyMap : StylePropertyMapReadonly { - [RaisesException] void append(DOMString property, (CSSStyleValue or sequence<CSSStyleValue> or DOMString) value); + [RaisesException, CallWith=ExecutionContext] void append(DOMString property, (CSSStyleValue or sequence<CSSStyleValue> or DOMString) value); [RaisesException, ImplementedAs=remove] void delete(DOMString property); - [RaisesException] void set(DOMString property, (CSSStyleValue or sequence<CSSStyleValue> or DOMString) value); + [RaisesException, CallWith=ExecutionContext] void set(DOMString property, (CSSStyleValue or sequence<CSSStyleValue> or DOMString) value); };
diff --git a/third_party/WebKit/Source/core/css/parser/CSS.proto b/third_party/WebKit/Source/core/css/parser/CSS.proto index f00a05f4..3712581 100644 --- a/third_party/WebKit/Source/core/css/parser/CSS.proto +++ b/third_party/WebKit/Source/core/css/parser/CSS.proto
@@ -2369,8 +2369,13 @@ kCSSFontFaceRuleMode = 4; kUASheetMode = 5; } + enum SecureContextMode { + kInsecureContext = 0; + kSecureContext = 1; + } required CSSParserMode css_parser_mode = 1; required bool defer_property_parsing = 2; required StyleSheet style_sheet = 3; required bool is_dynamic_profile = 4; + required SecureContextMode secure_context_mode = 5; }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSLazyParsingTest.cpp b/third_party/WebKit/Source/core/css/parser/CSSLazyParsingTest.cpp index 805830d..6f49f4f 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSLazyParsingTest.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSLazyParsingTest.cpp
@@ -33,7 +33,8 @@ }; TEST_F(CSSLazyParsingTest, Simple) { - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* style_sheet = StyleSheetContents::Create(context); String sheet_text = "body { background-color: red; }"; @@ -48,7 +49,8 @@ // Avoid parsing rules with ::before or ::after to avoid causing // collectFeatures() when we trigger parsing for attr(); TEST_F(CSSLazyParsingTest, DontLazyParseBeforeAfter) { - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* style_sheet = StyleSheetContents::Create(context); String sheet_text = @@ -65,7 +67,8 @@ // dangerous API because callers will expect the set of matching rules to be // identical if the stylesheet is not mutated. TEST_F(CSSLazyParsingTest, ShouldConsiderForMatchingRulesDoesntChange1) { - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* style_sheet = StyleSheetContents::Create(context); String sheet_text = "p::first-letter { ,badness, } "; @@ -89,7 +92,8 @@ // Test the same thing as above, with a property that does not get lazy parsed, // to ensure that we perform the optimization where possible. TEST_F(CSSLazyParsingTest, ShouldConsiderForMatchingRulesSimple) { - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* style_sheet = StyleSheetContents::Create(context); String sheet_text = "p::before { ,badness, } "; @@ -109,8 +113,8 @@ std::unique_ptr<DummyPageHolder> dummy_holder = DummyPageHolder::Create(IntSize(500, 500)); CSSParserContext* context = CSSParserContext::Create( - kHTMLStandardMode, CSSParserContext::kDynamicProfile, - &dummy_holder->GetDocument()); + kHTMLStandardMode, SecureContextMode::kInsecureContext, + CSSParserContext::kDynamicProfile, &dummy_holder->GetDocument()); cached_contents_ = StyleSheetContents::Create(context); { CSSStyleSheet* sheet = @@ -163,7 +167,8 @@ } TEST_F(CSSLazyParsingTest, SimpleRuleUsagePercent) { - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* style_sheet = StyleSheetContents::Create(context); std::string usage_metric = "Style.LazyUsage.Percent";
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSParser.cpp index bd108fa..391517a 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParser.cpp
@@ -85,8 +85,10 @@ MutableCSSPropertyValueSet* declaration, CSSPropertyID unresolved_property, const String& string, - bool important) { + bool important, + SecureContextMode secure_context_mode) { return ParseValue(declaration, unresolved_property, string, important, + secure_context_mode, static_cast<StyleSheetContents*>(nullptr)); } @@ -95,6 +97,7 @@ CSSPropertyID unresolved_property, const String& string, bool important, + SecureContextMode secure_context_mode, StyleSheetContents* style_sheet) { if (string.IsEmpty()) { bool did_parse = false; @@ -108,8 +111,8 @@ string, parser_mode); if (value) { bool did_parse = true; - bool did_change = declaration->SetProperty( - CSSPropertyValue(resolved_property, *value, important)); + bool did_change = declaration->SetProperty(CSSPropertyValue( + CSSProperty::Get(resolved_property), *value, important)); return MutableCSSPropertyValueSet::SetResult{did_parse, did_change}; } CSSParserContext* context; @@ -117,7 +120,7 @@ context = CSSParserContext::Create(style_sheet->ParserContext(), nullptr); context->SetMode(parser_mode); } else { - context = CSSParserContext::Create(parser_mode); + context = CSSParserContext::Create(parser_mode, secure_context_mode); } return ParseValue(declaration, unresolved_property, string, important, context); @@ -129,6 +132,7 @@ const PropertyRegistry* registry, const String& value, bool important, + SecureContextMode secure_context_mode, StyleSheetContents* style_sheet, bool is_animation_tainted) { DCHECK(CSSVariableParser::IsValidVariableName(property_name)); @@ -143,7 +147,7 @@ context = CSSParserContext::Create(style_sheet->ParserContext(), nullptr); context->SetMode(parser_mode); } else { - context = CSSParserContext::Create(parser_mode); + context = CSSParserContext::Create(parser_mode, secure_context_mode); } return CSSParserImpl::ParseVariableValue(declaration, property_name, registry, value, important, context, @@ -192,10 +196,11 @@ return ToStyleRuleKeyframe(keyframe); } -bool CSSParser::ParseSupportsCondition(const String& condition) { +bool CSSParser::ParseSupportsCondition(const String& condition, + SecureContextMode secure_context_mode) { CSSTokenizer tokenizer(condition); const auto tokens = tokenizer.TokenizeToEOF(); - CSSParserImpl parser(StrictCSSParserContext()); + CSSParserImpl parser(StrictCSSParserContext(secure_context_mode)); return CSSSupportsParser::SupportsCondition( CSSParserTokenRange(tokens), parser, CSSSupportsParser::kForWindowCSS) == CSSSupportsParser::kSupported; @@ -216,9 +221,14 @@ const CSSValue* value = CSSParserFastPaths::ParseColor( string, strict ? kHTMLStandardMode : kHTMLQuirksMode); // TODO(timloh): Why is this always strict mode? - if (!value) - value = - ParseSingleValue(CSSPropertyColor, string, StrictCSSParserContext()); + if (!value) { + // NOTE(ikilpatrick): We will always parse color value in the insecure + // context mode. If a function/unit/etc will require a secure context check + // in the future, plumbing will need to be added. + value = ParseSingleValue( + CSSPropertyColor, string, + StrictCSSParserContext(SecureContextMode::kInsecureContext)); + } if (!value || !value->IsColorValue()) return false;
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParser.h b/third_party/WebKit/Source/core/css/parser/CSSParser.h index 83e84f9d..4b9945a6 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParser.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParser.h
@@ -22,6 +22,7 @@ class StyleRuleKeyframe; class StyleSheetContents; class CSSValue; +enum class SecureContextMode; // This class serves as the public API for the css/parser subsystem class CORE_EXPORT CSSParser { @@ -50,12 +51,14 @@ MutableCSSPropertyValueSet*, CSSPropertyID unresolved_property, const String&, - bool important); + bool important, + SecureContextMode); static MutableCSSPropertyValueSet::SetResult ParseValue( MutableCSSPropertyValueSet*, CSSPropertyID unresolved_property, const String&, bool important, + SecureContextMode, StyleSheetContents*); static MutableCSSPropertyValueSet::SetResult ParseValueForCustomProperty( @@ -64,14 +67,14 @@ const PropertyRegistry*, const String& value, bool important, + SecureContextMode, StyleSheetContents*, bool is_animation_tainted); // This is for non-shorthands only - static const CSSValue* ParseSingleValue( - CSSPropertyID, - const String&, - const CSSParserContext* = StrictCSSParserContext()); + static const CSSValue* ParseSingleValue(CSSPropertyID, + const String&, + const CSSParserContext*); static const CSSValue* ParseFontFaceDescriptor(CSSPropertyID, const String&, @@ -85,7 +88,7 @@ static StyleRuleKeyframe* ParseKeyframeRule(const CSSParserContext*, const String&); - static bool ParseSupportsCondition(const String&); + static bool ParseSupportsCondition(const String&, SecureContextMode); // The color will only be changed when string contains a valid CSS color, so // callers can set it to a default color and ignore the boolean result.
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserContext.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserContext.cpp index c46c187..53b8c84 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserContext.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserContext.cpp
@@ -28,7 +28,8 @@ return new CSSParserContext( context.Url(), WTF::TextEncoding(), kHTMLStandardMode, kHTMLStandardMode, - kDynamicProfile, referrer, true, false, policy_disposition, + kDynamicProfile, referrer, true, false, context.SecureContextMode(), + policy_disposition, context.IsDocument() ? &ToDocument(context) : nullptr); } @@ -56,7 +57,8 @@ other->base_url_, other->charset_, other->mode_, other->match_mode_, other->profile_, other->referrer_, other->is_html_document_, other->use_legacy_background_size_shorthand_behavior_, - other->should_check_content_security_policy_, use_counter_document); + other->secure_context_mode_, other->should_check_content_security_policy_, + use_counter_document); } // static @@ -71,17 +73,20 @@ Referrer(base_url.StrippedForUseAsReferrer(), referrer_policy), other->is_html_document_, other->use_legacy_background_size_shorthand_behavior_, - other->should_check_content_security_policy_, use_counter_document); + other->secure_context_mode_, other->should_check_content_security_policy_, + use_counter_document); } // static CSSParserContext* CSSParserContext::Create( CSSParserMode mode, + SecureContextMode secure_context_mode, SelectorProfile profile, const Document* use_counter_document) { - return new CSSParserContext( - KURL(), WTF::TextEncoding(), mode, mode, profile, Referrer(), false, - false, kDoNotCheckContentSecurityPolicy, use_counter_document); + return new CSSParserContext(KURL(), WTF::TextEncoding(), mode, mode, profile, + Referrer(), false, false, secure_context_mode, + kDoNotCheckContentSecurityPolicy, + use_counter_document); } // static @@ -125,10 +130,10 @@ else policy_disposition = kCheckContentSecurityPolicy; - return new CSSParserContext(base_url_override, charset, mode, match_mode, - profile, referrer, document.IsHTMLDocument(), - use_legacy_background_size_shorthand_behavior, - policy_disposition, &document); + return new CSSParserContext( + base_url_override, charset, mode, match_mode, profile, referrer, + document.IsHTMLDocument(), use_legacy_background_size_shorthand_behavior, + document.SecureContextMode(), policy_disposition, &document); } CSSParserContext::CSSParserContext( @@ -140,6 +145,7 @@ const Referrer& referrer, bool is_html_document, bool use_legacy_background_size_shorthand_behavior, + SecureContextMode secure_context_mode, ContentSecurityPolicyDisposition policy_disposition, const Document* use_counter_document) : base_url_(base_url), @@ -151,6 +157,7 @@ is_html_document_(is_html_document), use_legacy_background_size_shorthand_behavior_( use_legacy_background_size_shorthand_behavior), + secure_context_mode_(secure_context_mode), should_check_content_security_policy_(policy_disposition), document_(use_counter_document) {} @@ -160,15 +167,23 @@ profile_ == other.profile_ && is_html_document_ == other.is_html_document_ && use_legacy_background_size_shorthand_behavior_ == - other.use_legacy_background_size_shorthand_behavior_; + other.use_legacy_background_size_shorthand_behavior_ && + secure_context_mode_ == other.secure_context_mode_; } -const CSSParserContext* StrictCSSParserContext() { +const CSSParserContext* StrictCSSParserContext( + SecureContextMode secure_context_mode) { DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<Persistent<CSSParserContext>>, strict_context_pool, ()); - Persistent<CSSParserContext>& context = *strict_context_pool; + DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<Persistent<CSSParserContext>>, + secure_strict_context_pool, ()); + + Persistent<CSSParserContext>& context = + secure_context_mode == SecureContextMode::kSecureContext + ? *secure_strict_context_pool + : *strict_context_pool; if (!context) { - context = CSSParserContext::Create(kHTMLStandardMode); + context = CSSParserContext::Create(kHTMLStandardMode, secure_context_mode); context.RegisterAsStaticReference(); }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserContext.h b/third_party/WebKit/Source/core/css/parser/CSSParserContext.h index f6a7f63d..eaa0d57 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserContext.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParserContext.h
@@ -8,6 +8,7 @@ #include "core/CSSPropertyNames.h" #include "core/CoreExport.h" #include "core/css/parser/CSSParserMode.h" +#include "core/dom/ExecutionContext.h" #include "core/frame/WebFeatureForward.h" #include "platform/heap/Handle.h" #include "platform/loader/fetch/ResourceLoaderOptions.h" @@ -19,7 +20,6 @@ class CSSStyleSheet; class Document; -class ExecutionContext; class StyleSheetContents; class CORE_EXPORT CSSParserContext @@ -49,6 +49,7 @@ static CSSParserContext* Create( CSSParserMode, + SecureContextMode, SelectorProfile = kDynamicProfile, const Document* use_counter_document = nullptr); static CSSParserContext* Create(const Document&); @@ -75,6 +76,10 @@ bool IsDynamicProfile() const { return profile_ == kDynamicProfile; } bool IsStaticProfile() const { return profile_ == kStaticProfile; } + SecureContextMode GetSecureContextMode() const { + return secure_context_mode_; + } + // This quirk is to maintain compatibility with Android apps built on // the Android SDK prior to and including version 18. Presumably, this // can be removed any time after 2015. See http://crbug.com/277157. @@ -110,6 +115,7 @@ const Referrer&, bool is_html_document, bool use_legacy_background_size_shorthand_behavior, + SecureContextMode, ContentSecurityPolicyDisposition, const Document* use_counter_document); @@ -121,12 +127,13 @@ Referrer referrer_; bool is_html_document_; bool use_legacy_background_size_shorthand_behavior_; + SecureContextMode secure_context_mode_; ContentSecurityPolicyDisposition should_check_content_security_policy_; WeakMember<const Document> document_; }; -CORE_EXPORT const CSSParserContext* StrictCSSParserContext(); +CORE_EXPORT const CSSParserContext* StrictCSSParserContext(SecureContextMode); } // 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 ff56d5b..81552e1 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
@@ -952,7 +952,7 @@ CSSVariableParser::ParseDeclarationValue(variable_name, range, is_animation_tainted)) { parsed_properties_.push_back( - CSSPropertyValue(CSSPropertyVariable, *value, important)); + CSSPropertyValue(GetCSSPropertyVariable(), *value, important)); context_->Count(context_->Mode(), CSSPropertyVariable); } }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserProtoFuzzer.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserProtoFuzzer.cpp index f4a5fdc..823b919 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserProtoFuzzer.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserProtoFuzzer.cpp
@@ -32,14 +32,21 @@ {Input::kCSSFontFaceRuleMode, blink::kCSSFontFaceRuleMode}, {Input::kUASheetMode, blink::kUASheetMode}}; + static std::unordered_map<Input::SecureContextMode, blink::SecureContextMode> + secure_context_mode_map = { + {Input::kInsecureContext, blink::SecureContextMode::kInsecureContext}, + {Input::kSecureContext, blink::SecureContextMode::kSecureContext}}; + blink::CSSParserMode mode = parser_mode_map[input.css_parser_mode()]; + blink::SecureContextMode secure_context_mode = + secure_context_mode_map[input.secure_context_mode()]; blink::CSSParserContext::SelectorProfile selector_profile; if (input.is_dynamic_profile()) selector_profile = blink::CSSParserContext::kDynamicProfile; else selector_profile = blink::CSSParserContext::kStaticProfile; - blink::CSSParserContext* context = - blink::CSSParserContext::Create(mode, selector_profile); + blink::CSSParserContext* context = blink::CSSParserContext::Create( + mode, secure_context_mode, selector_profile); blink::StyleSheetContents* style_sheet = blink::StyleSheetContents::Create(context);
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp index e28f7aa4..245267d 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
@@ -1559,8 +1559,8 @@ } properties.push_back(CSSPropertyValue( - resolved_property, value, important, set_from_shorthand, shorthand_index, - implicit == IsImplicitProperty::kImplicit)); + CSSProperty::Get(resolved_property), value, important, set_from_shorthand, + shorthand_index, implicit == IsImplicitProperty::kImplicit)); } CSSValue* ConsumeTransformList(CSSParserTokenRange& range,
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserTest.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserTest.cpp index 923e7c84..a1fc06fc 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserTest.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserTest.cpp
@@ -23,15 +23,17 @@ TEST(CSSPropertyParserTest, CSSPaint_Functions) { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyBackgroundImage, "paint(foo, func1(1px, 3px), red)"); + CSSPropertyBackgroundImage, "paint(foo, func1(1px, 3px), red)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(value->CssText(), "paint(foo, func1(1px, 3px), red)"); } TEST(CSSPropertyParserTest, CSSPaint_NoArguments) { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyBackgroundImage, "paint(foo)"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyBackgroundImage, "paint(foo)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(value->CssText(), "paint(foo)"); @@ -39,35 +41,40 @@ TEST(CSSPropertyParserTest, CSSPaint_ValidArguments) { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyBackgroundImage, "paint(bar, 10px, red)"); + CSSPropertyBackgroundImage, "paint(bar, 10px, red)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(value->CssText(), "paint(bar, 10px, red)"); } TEST(CSSPropertyParserTest, CSSPaint_InvalidFormat) { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyBackgroundImage, "paint(foo bar)"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyBackgroundImage, "paint(foo bar)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); // Illegal format should not be parsed. ASSERT_FALSE(value); } TEST(CSSPropertyParserTest, CSSPaint_TrailingComma) { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyBackgroundImage, "paint(bar, 10px, red,)"); + CSSPropertyBackgroundImage, "paint(bar, 10px, red,)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_FALSE(value); } TEST(CSSPropertyParserTest, CSSPaint_PaintArgumentsDiabled) { ScopedCSSPaintAPIArgumentsForTest css_paint_api_arguments(false); const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyBackgroundImage, "paint(bar, 10px, red)"); + CSSPropertyBackgroundImage, "paint(bar, 10px, red)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_FALSE(value); } TEST(CSSPropertyParserTest, GridTrackLimit1) { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyGridTemplateColumns, "repeat(999, 20px)"); + CSSPropertyGridTemplateColumns, "repeat(999, 20px)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 999); @@ -75,7 +82,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit2) { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyGridTemplateRows, "repeat(999, 20px)"); + CSSPropertyGridTemplateRows, "repeat(999, 20px)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 999); @@ -83,7 +91,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit3) { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyGridTemplateColumns, "repeat(1000000, 10%)"); + CSSPropertyGridTemplateColumns, "repeat(1000000, 10%)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000); @@ -91,7 +100,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit4) { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyGridTemplateRows, "repeat(1000000, 10%)"); + CSSPropertyGridTemplateRows, "repeat(1000000, 10%)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000); @@ -100,7 +110,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit5) { const CSSValue* value = CSSParser::ParseSingleValue( CSSPropertyGridTemplateColumns, - "repeat(1000000, [first] min-content [last])"); + "repeat(1000000, [first] min-content [last])", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000); @@ -109,7 +120,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit6) { const CSSValue* value = CSSParser::ParseSingleValue( CSSPropertyGridTemplateRows, - "repeat(1000000, [first] min-content [last])"); + "repeat(1000000, [first] min-content [last])", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000); @@ -117,7 +129,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit7) { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyGridTemplateColumns, "repeat(1000001, auto)"); + CSSPropertyGridTemplateColumns, "repeat(1000001, auto)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000); @@ -125,7 +138,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit8) { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyGridTemplateRows, "repeat(1000001, auto)"); + CSSPropertyGridTemplateRows, "repeat(1000001, auto)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000); @@ -134,7 +148,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit9) { const CSSValue* value = CSSParser::ParseSingleValue( CSSPropertyGridTemplateColumns, - "repeat(400000, 2em minmax(10px, max-content) 0.5fr)"); + "repeat(400000, 2em minmax(10px, max-content) 0.5fr)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 999); @@ -143,7 +158,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit10) { const CSSValue* value = CSSParser::ParseSingleValue( CSSPropertyGridTemplateRows, - "repeat(400000, 2em minmax(10px, max-content) 0.5fr)"); + "repeat(400000, 2em minmax(10px, max-content) 0.5fr)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 999); @@ -152,7 +168,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit11) { const CSSValue* value = CSSParser::ParseSingleValue( CSSPropertyGridTemplateColumns, - "repeat(600000, [first] 3vh 10% 2fr [nav] 10px auto 1fr 6em [last])"); + "repeat(600000, [first] 3vh 10% 2fr [nav] 10px auto 1fr 6em [last])", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 994); @@ -161,7 +178,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit12) { const CSSValue* value = CSSParser::ParseSingleValue( CSSPropertyGridTemplateRows, - "repeat(600000, [first] 3vh 10% 2fr [nav] 10px auto 1fr 6em [last])"); + "repeat(600000, [first] 3vh 10% 2fr [nav] 10px auto 1fr 6em [last])", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 994); @@ -169,7 +187,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit13) { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyGridTemplateColumns, "repeat(100000000000000000000, 10% 1fr)"); + CSSPropertyGridTemplateColumns, "repeat(100000000000000000000, 10% 1fr)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000); @@ -177,7 +196,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit14) { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyGridTemplateRows, "repeat(100000000000000000000, 10% 1fr)"); + CSSPropertyGridTemplateRows, "repeat(100000000000000000000, 10% 1fr)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000); @@ -186,7 +206,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit15) { const CSSValue* value = CSSParser::ParseSingleValue( CSSPropertyGridTemplateColumns, - "repeat(100000000000000000000, 10% 5em 1fr auto auto 15px min-content)"); + "repeat(100000000000000000000, 10% 5em 1fr auto auto 15px min-content)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 994); @@ -195,7 +216,8 @@ TEST(CSSPropertyParserTest, GridTrackLimit16) { const CSSValue* value = CSSParser::ParseSingleValue( CSSPropertyGridTemplateRows, - "repeat(100000000000000000000, 10% 5em 1fr auto auto 15px min-content)"); + "repeat(100000000000000000000, 10% 5em 1fr auto auto 15px min-content)", + StrictCSSParserContext(SecureContextMode::kSecureContext)); ASSERT_TRUE(value); ASSERT_TRUE(value->IsValueList()); EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 994); @@ -211,57 +233,65 @@ } TEST(CSSPropertyParserTest, GridPositionLimit1) { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyGridColumnStart, "999"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyGridColumnStart, "999", + StrictCSSParserContext(SecureContextMode::kSecureContext)); DCHECK(value); EXPECT_EQ(GetGridPositionInteger(*value), 999); } TEST(CSSPropertyParserTest, GridPositionLimit2) { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyGridColumnEnd, "1000000"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyGridColumnEnd, "1000000", + StrictCSSParserContext(SecureContextMode::kSecureContext)); DCHECK(value); EXPECT_EQ(GetGridPositionInteger(*value), 1000); } TEST(CSSPropertyParserTest, GridPositionLimit3) { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyGridRowStart, "1000001"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyGridRowStart, "1000001", + StrictCSSParserContext(SecureContextMode::kSecureContext)); DCHECK(value); EXPECT_EQ(GetGridPositionInteger(*value), 1000); } TEST(CSSPropertyParserTest, GridPositionLimit4) { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyGridRowEnd, "5000000000"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyGridRowEnd, "5000000000", + StrictCSSParserContext(SecureContextMode::kSecureContext)); DCHECK(value); EXPECT_EQ(GetGridPositionInteger(*value), 1000); } TEST(CSSPropertyParserTest, GridPositionLimit5) { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyGridColumnStart, "-999"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyGridColumnStart, "-999", + StrictCSSParserContext(SecureContextMode::kSecureContext)); DCHECK(value); EXPECT_EQ(GetGridPositionInteger(*value), -999); } TEST(CSSPropertyParserTest, GridPositionLimit6) { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyGridColumnEnd, "-1000000"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyGridColumnEnd, "-1000000", + StrictCSSParserContext(SecureContextMode::kSecureContext)); DCHECK(value); EXPECT_EQ(GetGridPositionInteger(*value), -1000); } TEST(CSSPropertyParserTest, GridPositionLimit7) { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyGridRowStart, "-1000001"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyGridRowStart, "-1000001", + StrictCSSParserContext(SecureContextMode::kSecureContext)); DCHECK(value); EXPECT_EQ(GetGridPositionInteger(*value), -1000); } TEST(CSSPropertyParserTest, GridPositionLimit8) { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyGridRowEnd, "-5000000000"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyGridRowEnd, "-5000000000", + StrictCSSParserContext(SecureContextMode::kSecureContext)); DCHECK(value); EXPECT_EQ(GetGridPositionInteger(*value), -1000); }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSSelectorParserTest.cpp b/third_party/WebKit/Source/core/css/parser/CSSSelectorParserTest.cpp index 33afb9b..7614f42 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSSelectorParserTest.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSSelectorParserTest.cpp
@@ -126,7 +126,10 @@ const auto tokens = tokenizer.TokenizeToEOF(); CSSParserTokenRange range(tokens); CSSSelectorList list = CSSSelectorParser::ParseSelector( - range, CSSParserContext::Create(kHTMLStandardMode), nullptr); + range, + CSSParserContext::Create(kHTMLStandardMode, + SecureContextMode::kInsecureContext), + nullptr); EXPECT_STREQ(test_case[1], list.SelectorsText().Ascii().data()); } } @@ -146,7 +149,10 @@ const auto tokens = tokenizer.TokenizeToEOF(); CSSParserTokenRange range(tokens); CSSSelectorList list = CSSSelectorParser::ParseSelector( - range, CSSParserContext::Create(kHTMLStandardMode), nullptr); + range, + CSSParserContext::Create(kHTMLStandardMode, + SecureContextMode::kInsecureContext), + nullptr); EXPECT_FALSE(list.IsValid()); } } @@ -165,7 +171,10 @@ const auto tokens = tokenizer.TokenizeToEOF(); CSSParserTokenRange range(tokens); CSSSelectorList list = CSSSelectorParser::ParseSelector( - range, CSSParserContext::Create(kHTMLStandardMode), nullptr); + range, + CSSParserContext::Create(kHTMLStandardMode, + SecureContextMode::kInsecureContext), + nullptr); EXPECT_TRUE(list.IsValid()); } } @@ -196,7 +205,10 @@ const auto tokens = tokenizer.TokenizeToEOF(); CSSParserTokenRange range(tokens); CSSSelectorList list = CSSSelectorParser::ParseSelector( - range, CSSParserContext::Create(kHTMLStandardMode), nullptr); + range, + CSSParserContext::Create(kHTMLStandardMode, + SecureContextMode::kInsecureContext), + nullptr); EXPECT_FALSE(list.IsValid()); } } @@ -212,7 +224,10 @@ const auto tokens = tokenizer.TokenizeToEOF(); CSSParserTokenRange range(tokens); CSSSelectorList list = CSSSelectorParser::ParseSelector( - range, CSSParserContext::Create(kUASheetMode), nullptr); + range, + CSSParserContext::Create(kUASheetMode, + SecureContextMode::kInsecureContext), + nullptr); EXPECT_TRUE(list.IsValid()); } } @@ -225,7 +240,10 @@ const auto tokens = tokenizer.TokenizeToEOF(); CSSParserTokenRange range(tokens); CSSSelectorList list = CSSSelectorParser::ParseSelector( - range, CSSParserContext::Create(kHTMLStandardMode), nullptr); + range, + CSSParserContext::Create(kHTMLStandardMode, + SecureContextMode::kInsecureContext), + nullptr); EXPECT_TRUE(list.IsValid()); } } @@ -240,7 +258,10 @@ const auto tokens = tokenizer.TokenizeToEOF(); CSSParserTokenRange range(tokens); CSSSelectorList list = CSSSelectorParser::ParseSelector( - range, CSSParserContext::Create(kHTMLStandardMode), nullptr); + range, + CSSParserContext::Create(kHTMLStandardMode, + SecureContextMode::kInsecureContext), + nullptr); EXPECT_FALSE(list.IsValid()); } } @@ -248,7 +269,8 @@ TEST(CSSSelectorParserTest, UnresolvedNamespacePrefix) { const char* test_cases[] = {"ns|div", "div ns|div", "div ns|div "}; - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* sheet = StyleSheetContents::Create(context); for (auto test_case : test_cases) { @@ -274,7 +296,8 @@ {"ns|*::-webkit-volume-slider", "ns|*::-webkit-volume-slider"}, {"ns|*::cue(i)", "ns|*::cue(i)"}}; - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* sheet = StyleSheetContents::Create(context); sheet->ParserAddNamespace("ns", "http://ns.org"); @@ -294,7 +317,8 @@ const char* test_cases[] = {"div >>>> span", "div >>> span", "div >> span"}; CSSParserContext* context = CSSParserContext::Create( - kHTMLStandardMode, CSSParserContext::kDynamicProfile); + kHTMLStandardMode, SecureContextMode::kInsecureContext, + CSSParserContext::kDynamicProfile); StyleSheetContents* sheet = StyleSheetContents::Create(context); for (auto test_case : test_cases) { @@ -313,7 +337,8 @@ "div > >> span", "div > > > span"}; CSSParserContext* context = CSSParserContext::Create( - kHTMLStandardMode, CSSParserContext::kStaticProfile); + kHTMLStandardMode, SecureContextMode::kInsecureContext, + CSSParserContext::kStaticProfile); StyleSheetContents* sheet = StyleSheetContents::Create(context); for (auto test_case : test_cases) { @@ -334,7 +359,8 @@ {"div >/**/>/**/> span", "div >>> span"}}; CSSParserContext* context = CSSParserContext::Create( - kHTMLStandardMode, CSSParserContext::kStaticProfile); + kHTMLStandardMode, SecureContextMode::kInsecureContext, + CSSParserContext::kStaticProfile); StyleSheetContents* sheet = StyleSheetContents::Create(context); for (auto test_case : test_cases) { @@ -352,7 +378,8 @@ TEST(CSSSelectorParserTest, AttributeSelectorUniversalInvalid) { const char* test_cases[] = {"[*]", "[*|*]"}; - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* sheet = StyleSheetContents::Create(context); for (auto test_case : test_cases) { @@ -381,11 +408,17 @@ CSSParserTokenRange range(tokens); CSSSelectorList author_list = CSSSelectorParser::ParseSelector( - range, CSSParserContext::Create(kHTMLStandardMode), nullptr); + range, + CSSParserContext::Create(kHTMLStandardMode, + SecureContextMode::kInsecureContext), + nullptr); EXPECT_FALSE(author_list.IsValid()); CSSSelectorList ua_list = CSSSelectorParser::ParseSelector( - range, CSSParserContext::Create(kUASheetMode), nullptr); + range, + CSSParserContext::Create(kUASheetMode, + SecureContextMode::kInsecureContext), + nullptr); EXPECT_TRUE(ua_list.IsValid()); } } @@ -419,7 +452,8 @@ {".\\212alass", u"\u212alass", SelectorValue}, {"#\\212alass", u"\u212alass", SelectorValue}}; - CSSParserContext* context = CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* sheet = StyleSheetContents::Create(context); for (auto test_case : test_cases) { @@ -443,7 +477,8 @@ {".\\212aLASS", u"\u212alass", SelectorValue}, {"#\\212aLASS", u"\u212alass", SelectorValue}}; - CSSParserContext* context = CSSParserContext::Create(kHTMLQuirksMode); + CSSParserContext* context = CSSParserContext::Create( + kHTMLQuirksMode, SecureContextMode::kInsecureContext); StyleSheetContents* sheet = StyleSheetContents::Create(context); for (auto test_case : test_cases) {
diff --git a/third_party/WebKit/Source/core/css/parser/SizesCalcParserTest.cpp b/third_party/WebKit/Source/core/css/parser/SizesCalcParserTest.cpp index 928d6c6..830c517 100644 --- a/third_party/WebKit/Source/core/css/parser/SizesCalcParserTest.cpp +++ b/third_party/WebKit/Source/core/css/parser/SizesCalcParserTest.cpp
@@ -27,8 +27,9 @@ unsigned viewport_width, unsigned viewport_height) { CSSLengthArray length_array; - const CSSValue* css_value = - CSSParser::ParseSingleValue(CSSPropertyLeft, text); + const CSSValue* css_value = CSSParser::ParseSingleValue( + CSSPropertyLeft, text, + StrictCSSParserContext(SecureContextMode::kInsecureContext)); const CSSPrimitiveValue* primitive_value = ToCSSPrimitiveValue(css_value); if (primitive_value) primitive_value->AccumulateLengthArray(length_array);
diff --git a/third_party/WebKit/Source/core/css/properties/longhands/FloodOrStopOpacity.cpp b/third_party/WebKit/Source/core/css/properties/longhands/FloodOrStopOpacity.cpp new file mode 100644 index 0000000..a543c5cb --- /dev/null +++ b/third_party/WebKit/Source/core/css/properties/longhands/FloodOrStopOpacity.cpp
@@ -0,0 +1,20 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/css/properties/longhands/FloodOrStopOpacity.h" + +#include "core/css/parser/CSSPropertyParserHelpers.h" + +namespace blink { +namespace CSSLonghand { + +const CSSValue* FloodOrStopOpacity::ParseSingleValue( + CSSParserTokenRange& range, + const CSSParserContext& context, + const CSSParserLocalContext&) const { + return CSSPropertyParserHelpers::ConsumeNumber(range, kValueRangeAll); +} + +} // namespace CSSLonghand +} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp index 841ad43..68d3e86 100644 --- a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp +++ b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
@@ -77,7 +77,8 @@ const CSSValue* parsed_value = nullptr; if (new_variable_data) { - parsed_value = new_variable_data->ParseForSyntax(registration->Syntax()); + parsed_value = new_variable_data->ParseForSyntax( + registration->Syntax(), state_.GetDocument().SecureContextMode()); if (!parsed_value) new_variable_data = nullptr; }
diff --git a/third_party/WebKit/Source/core/css/resolver/FontStyleResolverTest.cpp b/third_party/WebKit/Source/core/css/resolver/FontStyleResolverTest.cpp index 9ad1628..53b313e 100644 --- a/third_party/WebKit/Source/core/css/resolver/FontStyleResolverTest.cpp +++ b/third_party/WebKit/Source/core/css/resolver/FontStyleResolverTest.cpp
@@ -12,7 +12,8 @@ TEST(FontStyleResolverTest, Simple) { MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); - CSSParser::ParseValue(style, CSSPropertyFont, "15px Ahem", true); + CSSParser::ParseValue(style, CSSPropertyFont, "15px Ahem", true, + SecureContextMode::kInsecureContext); FontDescription desc = FontStyleResolver::ComputeFont(*style, nullptr); @@ -24,7 +25,8 @@ TEST(FontStyleResolverTest, InvalidSize) { MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); - CSSParser::ParseValue(style, CSSPropertyFont, "-1px Ahem", true); + CSSParser::ParseValue(style, CSSPropertyFont, "-1px Ahem", true, + SecureContextMode::kInsecureContext); FontDescription desc = FontStyleResolver::ComputeFont(*style, nullptr); @@ -36,7 +38,8 @@ TEST(FontStyleResolverTest, InvalidWeight) { MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); - CSSParser::ParseValue(style, CSSPropertyFont, "wrong 1px Ahem", true); + CSSParser::ParseValue(style, CSSPropertyFont, "wrong 1px Ahem", true, + SecureContextMode::kInsecureContext); FontDescription desc = FontStyleResolver::ComputeFont(*style, nullptr); @@ -49,7 +52,7 @@ MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); CSSParser::ParseValue(style, CSSPropertyFont, "wrong wrong wrong 1px Ahem", - true); + true, SecureContextMode::kInsecureContext); FontDescription desc = FontStyleResolver::ComputeFont(*style, nullptr); @@ -61,7 +64,8 @@ TEST(FontStyleResolverTest, RelativeSize) { MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); - CSSParser::ParseValue(style, CSSPropertyFont, "italic 2ex Ahem", true); + CSSParser::ParseValue(style, CSSPropertyFont, "italic 2ex Ahem", true, + SecureContextMode::kInsecureContext); FontDescription desc = FontStyleResolver::ComputeFont(*style, nullptr);
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp index f41d28b..f087df5 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp +++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
@@ -879,8 +879,8 @@ return; } - const CSSValue* parsed_value = - declaration.Value()->ParseForSyntax(registration->Syntax()); + const CSSValue* parsed_value = declaration.Value()->ParseForSyntax( + registration->Syntax(), state.GetDocument().SecureContextMode()); if (parsed_value) { DCHECK(parsed_value); if (is_inherited_property)
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp index 4695b6b..feed454 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp +++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -735,7 +735,7 @@ Element& element, const ComputedStyle& base_style, const ComputedStyle* parent_style, - CSSPropertyID property, + const CSSProperty& property, const CSSValue* value) { // TODO(alancutter): Avoid creating a StyleResolverState just to apply a // single value on a ComputedStyle. @@ -743,7 +743,7 @@ parent_style); state.SetStyle(ComputedStyle::Clone(base_style)); if (value) { - StyleBuilder::ApplyProperty(property, state, *value); + StyleBuilder::ApplyProperty(property.PropertyID(), state, *value); state.GetFontBuilder().CreateFont( state.GetDocument().GetStyleEngine().GetFontSelector(), state.MutableStyleRef()); @@ -1232,9 +1232,10 @@ // they should instead apply in // SVGElement::CollectStyleForPresentationAttribute(). for (const auto& entry : active_interpolations_map) { - CSSPropertyID property = entry.key.IsCSSProperty() - ? entry.key.CssProperty() - : entry.key.PresentationAttribute(); + CSSPropertyID property = + entry.key.IsCSSProperty() + ? entry.key.GetCSSProperty().PropertyID() + : entry.key.PresentationAttribute().PropertyID(); if (!CSSPropertyPriorityData<priority>::PropertyHasPriority(property)) continue; const Interpolation& interpolation = *entry.value.front();
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.h b/third_party/WebKit/Source/core/css/resolver/StyleResolver.h index 918942b..20719c14 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.h +++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.h
@@ -79,7 +79,7 @@ Element&, const ComputedStyle& base_style, const ComputedStyle* parent_style, - CSSPropertyID, + const CSSProperty&, const CSSValue*); scoped_refptr<ComputedStyle> PseudoStyleForElement(
diff --git a/third_party/WebKit/Source/core/css/threaded/CSSParserThreadedTest.cpp b/third_party/WebKit/Source/core/css/threaded/CSSParserThreadedTest.cpp index fef7640..4f6133b 100644 --- a/third_party/WebKit/Source/core/css/threaded/CSSParserThreadedTest.cpp +++ b/third_party/WebKit/Source/core/css/threaded/CSSParserThreadedTest.cpp
@@ -15,7 +15,9 @@ class CSSParserThreadedTest : public MultiThreadedTest { public: static void TestSingle(CSSPropertyID prop, const String& text) { - const CSSValue* value = CSSParser::ParseSingleValue(prop, text); + const CSSValue* value = CSSParser::ParseSingleValue( + prop, text, + StrictCSSParserContext(SecureContextMode::kInsecureContext)); ASSERT_TRUE(value); EXPECT_EQ(text, value->CssText()); } @@ -24,7 +26,8 @@ const String& text) { MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); - CSSParser::ParseValue(style, prop, text, true); + CSSParser::ParseValue(style, prop, text, true, + SecureContextMode::kInsecureContext); return style; } }; @@ -62,7 +65,8 @@ TSAN_TEST_F(CSSParserThreadedTest, FontFaceDescriptor) { RunOnThreads([]() { - CSSParserContext* ctx = CSSParserContext::Create(kCSSFontFaceRuleMode); + CSSParserContext* ctx = CSSParserContext::Create( + kCSSFontFaceRuleMode, SecureContextMode::kInsecureContext); const CSSValue* v = CSSParser::ParseFontFaceDescriptor( CSSPropertySrc, "url(myfont.ttf)", ctx); ASSERT_TRUE(v);
diff --git a/third_party/WebKit/Source/core/css/threaded/FilterOperationResolverThreadedTest.cpp b/third_party/WebKit/Source/core/css/threaded/FilterOperationResolverThreadedTest.cpp index 7b506bf..2de5c008 100644 --- a/third_party/WebKit/Source/core/css/threaded/FilterOperationResolverThreadedTest.cpp +++ b/third_party/WebKit/Source/core/css/threaded/FilterOperationResolverThreadedTest.cpp
@@ -14,8 +14,9 @@ TSAN_TEST(FilterOperationResolverThreadedTest, SimpleMatrixFilter) { RunOnThreads([]() { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyFilter, "sepia(50%)"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyFilter, "sepia(50%)", + StrictCSSParserContext(SecureContextMode::kInsecureContext)); ASSERT_TRUE(value); FilterOperations fo = @@ -28,8 +29,9 @@ TSAN_TEST(FilterOperationResolverThreadedTest, SimpleTransferFilter) { RunOnThreads([]() { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyFilter, "brightness(50%)"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyFilter, "brightness(50%)", + StrictCSSParserContext(SecureContextMode::kInsecureContext)); ASSERT_TRUE(value); FilterOperations fo = @@ -42,8 +44,9 @@ TSAN_TEST(FilterOperationResolverThreadedTest, SimpleBlurFilter) { RunOnThreads([]() { - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyFilter, "blur(10px)"); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyFilter, "blur(10px)", + StrictCSSParserContext(SecureContextMode::kInsecureContext)); ASSERT_TRUE(value); FilterOperations fo = @@ -57,7 +60,8 @@ TSAN_TEST(FilterOperationResolverThreadedTest, SimpleDropShadow) { RunOnThreads([]() { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyFilter, "drop-shadow(10px 5px 1px black)"); + CSSPropertyFilter, "drop-shadow(10px 5px 1px black)", + StrictCSSParserContext(SecureContextMode::kInsecureContext)); ASSERT_TRUE(value); FilterOperations fo = @@ -72,7 +76,8 @@ TSAN_TEST(FilterOperationResolverThreadedTest, CompoundFilter) { RunOnThreads([]() { const CSSValue* value = CSSParser::ParseSingleValue( - CSSPropertyFilter, "sepia(50%) brightness(50%)"); + CSSPropertyFilter, "sepia(50%) brightness(50%)", + StrictCSSParserContext(SecureContextMode::kInsecureContext)); ASSERT_TRUE(value); FilterOperations fo =
diff --git a/third_party/WebKit/Source/core/css/threaded/FontObjectThreadedTest.cpp b/third_party/WebKit/Source/core/css/threaded/FontObjectThreadedTest.cpp index ac04cf0..c9a289e 100644 --- a/third_party/WebKit/Source/core/css/threaded/FontObjectThreadedTest.cpp +++ b/third_party/WebKit/Source/core/css/threaded/FontObjectThreadedTest.cpp
@@ -31,7 +31,8 @@ RunOnThreads([]() { MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); - CSSParser::ParseValue(style, CSSPropertyFont, "15px Ahem", true); + CSSParser::ParseValue(style, CSSPropertyFont, "15px Ahem", true, + SecureContextMode::kInsecureContext); FontDescription desc = FontStyleResolver::ComputeFont(*style, nullptr);
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index fc66257..db1a8c6 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -4399,6 +4399,7 @@ DCHECK(inline_style->IsMutable()); static_cast<MutableCSSPropertyValueSet*>(inline_style.Get()) ->ParseDeclarationList(new_style_string, + GetDocument().SecureContextMode(), GetDocument().ElementSheet().Contents()); } } @@ -4487,6 +4488,7 @@ DCHECK(IsStyledElement()); bool did_change = EnsureMutableInlineStyle() .SetProperty(property_id, value, important, + GetDocument().SecureContextMode(), GetDocument().ElementSheet().Contents()) .did_change; if (did_change) @@ -4544,7 +4546,8 @@ CSSPropertyID property_id, const String& value) { DCHECK(IsStyledElement()); - style->SetProperty(property_id, value, false); + style->SetProperty(property_id, value, false, + GetDocument().SecureContextMode()); } void Element::AddPropertyToPresentationAttributeStyle(
diff --git a/third_party/WebKit/Source/core/dom/ExecutionContext.h b/third_party/WebKit/Source/core/dom/ExecutionContext.h index a02ebc9..f90f75d 100644 --- a/third_party/WebKit/Source/core/dom/ExecutionContext.h +++ b/third_party/WebKit/Source/core/dom/ExecutionContext.h
@@ -69,6 +69,8 @@ kNotAboutToExecuteScript }; +enum class SecureContextMode { kInsecureContext, kSecureContext }; + class CORE_EXPORT ExecutionContext : public ContextLifecycleNotifier, public Supplementable<ExecutionContext> { WTF_MAKE_NONCOPYABLE(ExecutionContext); @@ -174,6 +176,11 @@ virtual bool IsSecureContext(String& error_message) const = 0; virtual bool IsSecureContext() const; + SecureContextMode SecureContextMode() const { + return IsSecureContext() ? SecureContextMode::kSecureContext + : SecureContextMode::kInsecureContext; + } + virtual String OutgoingReferrer() const; // Parses a comma-separated list of referrer policy tokens, and sets // the context's referrer policy to the last one that is a valid
diff --git a/third_party/WebKit/Source/core/editing/EditingStyle.cpp b/third_party/WebKit/Source/core/editing/EditingStyle.cpp index 58c81b40..c41c397 100644 --- a/third_party/WebKit/Source/core/editing/EditingStyle.cpp +++ b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
@@ -144,7 +144,8 @@ static MutableCSSPropertyValueSet* GetPropertiesNotIn( CSSPropertyValueSet* style_with_redundant_properties, - CSSStyleDeclaration* base_style); + CSSStyleDeclaration* base_style, + SecureContextMode); enum LegacyFontSizeMode { kAlwaysUseLegacyFontSize, kUseLegacyFontSizeOnlyIfPixelValuesMatch @@ -228,8 +229,11 @@ identifier_value_->GetValueID(); } -void HTMLElementEquivalent::AddToStyle(Element*, EditingStyle* style) const { - style->SetProperty(property_id_, identifier_value_->CssText()); +void HTMLElementEquivalent::AddToStyle(Element* element, + EditingStyle* style) const { + style->SetProperty(property_id_, identifier_value_->CssText(), + /* important */ false, + element->GetDocument().SecureContextMode()); } class HTMLTextDecorationEquivalent final : public HTMLElementEquivalent { @@ -332,8 +336,10 @@ void HTMLAttributeEquivalent::AddToStyle(Element* element, EditingStyle* style) const { - if (const CSSValue* value = AttributeValueAsCSSValue(element)) - style->SetProperty(property_id_, value->CssText()); + if (const CSSValue* value = AttributeValueAsCSSValue(element)) { + style->SetProperty(property_id_, value->CssText(), /* important */ false, + element->GetDocument().SecureContextMode()); + } } const CSSValue* HTMLAttributeEquivalent::AttributeValueAsCSSValue( @@ -345,7 +351,8 @@ MutableCSSPropertyValueSet* dummy_style = nullptr; dummy_style = MutableCSSPropertyValueSet::Create(kHTMLQuirksMode); - dummy_style->SetProperty(property_id_, value); + dummy_style->SetProperty(property_id_, value, /* important */ false, + element->GetDocument().SecureContextMode()); return dummy_style->GetPropertyCSSValue(property_id_); } @@ -398,9 +405,11 @@ ExtractFontSizeDelta(); } -EditingStyle::EditingStyle(CSSPropertyID property_id, const String& value) +EditingStyle::EditingStyle(CSSPropertyID property_id, + const String& value, + SecureContextMode secure_context_mode) : mutable_style_(nullptr) { - SetProperty(property_id, value); + SetProperty(property_id, value, /* important */ false, secure_context_mode); is_vertical_align_ = property_id == CSSPropertyVerticalAlign && (value == "sub" || value == "super"); } @@ -486,11 +495,17 @@ if (properties_to_include == kEditingPropertiesInEffect) { if (const CSSValue* value = - EditingStyleUtilities::BackgroundColorValueInEffect(node)) - mutable_style_->SetProperty(CSSPropertyBackgroundColor, value->CssText()); + EditingStyleUtilities::BackgroundColorValueInEffect(node)) { + mutable_style_->SetProperty(CSSPropertyBackgroundColor, value->CssText(), + /* important */ false, + node->GetDocument().SecureContextMode()); + } if (const CSSValue* value = computed_style_at_position->GetPropertyCSSValue( - GetCSSPropertyWebkitTextDecorationsInEffect())) - mutable_style_->SetProperty(CSSPropertyTextDecoration, value->CssText()); + GetCSSPropertyWebkitTextDecorationsInEffect())) { + mutable_style_->SetProperty(CSSPropertyTextDecoration, value->CssText(), + /* important */ false, + node->GetDocument().SecureContextMode()); + } } if (node && node->EnsureComputedStyle()) { @@ -508,11 +523,13 @@ CSSPropertyFontSize, CSSPrimitiveValue::Create(computed_style->SpecifiedFontSize(), CSSPrimitiveValue::UnitType::kPixels) - ->CssText()); + ->CssText(), + /* important */ false, node->GetDocument().SecureContextMode()); } RemoveInheritedColorsIfNeeded(computed_style); ReplaceFontSizeByKeywordIfPossible(computed_style, + node->GetDocument().SecureContextMode(), computed_style_at_position); } @@ -537,21 +554,26 @@ void EditingStyle::SetProperty(CSSPropertyID property_id, const String& value, - bool important) { + bool important, + SecureContextMode secure_context_mode) { if (!mutable_style_) mutable_style_ = MutableCSSPropertyValueSet::Create(kHTMLQuirksMode); - mutable_style_->SetProperty(property_id, value, important); + mutable_style_->SetProperty(property_id, value, important, + secure_context_mode); } void EditingStyle::ReplaceFontSizeByKeywordIfPossible( const ComputedStyle* computed_style, + SecureContextMode secure_context_mode, CSSComputedStyleDeclaration* css_computed_style) { DCHECK(computed_style); - if (computed_style->GetFontDescription().KeywordSize()) + if (computed_style->GetFontDescription().KeywordSize()) { mutable_style_->SetProperty( CSSPropertyFontSize, - css_computed_style->GetFontSizeCSSValuePreferringKeyword()->CssText()); + css_computed_style->GetFontSizeCSSValuePreferringKeyword()->CssText(), + /* important */ false, secure_context_mode); + } } void EditingStyle::ExtractFontSizeDelta() { @@ -690,17 +712,20 @@ return block_properties; } -EditingStyle* EditingStyle::ExtractAndRemoveTextDirection() { +EditingStyle* EditingStyle::ExtractAndRemoveTextDirection( + SecureContextMode secure_context_mode) { EditingStyle* text_direction = EditingStyle::Create(); text_direction->mutable_style_ = MutableCSSPropertyValueSet::Create(kHTMLQuirksMode); text_direction->mutable_style_->SetProperty( CSSPropertyUnicodeBidi, CSSValueIsolate, mutable_style_->PropertyIsImportant(CSSPropertyUnicodeBidi)); + text_direction->mutable_style_->SetProperty( CSSPropertyDirection, mutable_style_->GetPropertyValue(CSSPropertyDirection), - mutable_style_->PropertyIsImportant(CSSPropertyDirection)); + mutable_style_->PropertyIsImportant(CSSPropertyDirection), + secure_context_mode); mutable_style_->RemoveProperty(CSSPropertyUnicodeBidi); mutable_style_->RemoveProperty(CSSPropertyDirection); @@ -744,7 +769,8 @@ mutable_style_->RemoveProperty(node_style->PropertyAt(i).Id()); } -void EditingStyle::CollapseTextDecorationProperties() { +void EditingStyle::CollapseTextDecorationProperties( + SecureContextMode secure_context_mode) { if (!mutable_style_) return; @@ -757,7 +783,8 @@ if (text_decorations_in_effect->IsValueList()) { mutable_style_->SetProperty( CSSPropertyTextDecorationLine, text_decorations_in_effect->CssText(), - mutable_style_->PropertyIsImportant(CSSPropertyTextDecorationLine)); + mutable_style_->PropertyIsImportant(CSSPropertyTextDecorationLine), + secure_context_mode); } else { mutable_style_->RemoveProperty(CSSPropertyTextDecorationLine); } @@ -776,18 +803,21 @@ CSSPropertyColor, }; -EditingTriState EditingStyle::TriStateOfStyle(EditingStyle* style) const { +EditingTriState EditingStyle::TriStateOfStyle( + EditingStyle* style, + SecureContextMode secure_context_mode) const { if (!style || !style->mutable_style_) return EditingTriState::kFalse; return TriStateOfStyle(style->mutable_style_->EnsureCSSStyleDeclaration(), - kDoNotIgnoreTextOnlyProperties); + kDoNotIgnoreTextOnlyProperties, secure_context_mode); } EditingTriState EditingStyle::TriStateOfStyle( CSSStyleDeclaration* style_to_compare, - ShouldIgnoreTextOnlyProperties should_ignore_text_only_properties) const { - MutableCSSPropertyValueSet* difference = - GetPropertiesNotIn(mutable_style_.Get(), style_to_compare); + ShouldIgnoreTextOnlyProperties should_ignore_text_only_properties, + SecureContextMode secure_context_mode) const { + MutableCSSPropertyValueSet* difference = GetPropertiesNotIn( + mutable_style_.Get(), style_to_compare, secure_context_mode); if (should_ignore_text_only_properties == kIgnoreTextOnlyProperties) difference->RemovePropertiesInSet(kTextOnlyProperties, @@ -802,13 +832,15 @@ } EditingTriState EditingStyle::TriStateOfStyle( - const VisibleSelection& selection) const { + const VisibleSelection& selection, + SecureContextMode secure_context_mode) const { if (selection.IsNone()) return EditingTriState::kFalse; if (selection.IsCaret()) { return TriStateOfStyle( - EditingStyleUtilities::CreateStyleAtSelectionStart(selection)); + EditingStyleUtilities::CreateStyleAtSelectionStart(selection), + secure_context_mode); } EditingTriState state = EditingTriState::kFalse; @@ -837,7 +869,8 @@ // node.isTextNode() because the node can be an element node. See bug // http://crbug.com/584939. EditingTriState node_state = TriStateOfStyle( - node_style, EditingStyle::kDoNotIgnoreTextOnlyProperties); + node_style, EditingStyle::kDoNotIgnoreTextOnlyProperties, + secure_context_mode); if (node_is_start) { state = node_state; node_is_start = false; @@ -886,7 +919,8 @@ extracted_style->SetProperty( CSSPropertyTextDecorationLine, inline_style->GetPropertyValue(CSSPropertyTextDecorationLine), - inline_style->PropertyIsImportant(CSSPropertyTextDecorationLine)); + inline_style->PropertyIsImportant(CSSPropertyTextDecorationLine), + element->GetDocument().SecureContextMode()); } continue; } @@ -899,10 +933,12 @@ if (!conflicting_properties) return true; conflicting_properties->push_back(CSSPropertyDirection); - if (extracted_style) + if (extracted_style) { extracted_style->SetProperty( property_id, inline_style->GetPropertyValue(property_id), - inline_style->PropertyIsImportant(property_id)); + inline_style->PropertyIsImportant(property_id), + element->GetDocument().SecureContextMode()); + } } if (!conflicting_properties) @@ -910,10 +946,12 @@ conflicting_properties->push_back(property_id); - if (extracted_style) + if (extracted_style) { extracted_style->SetProperty( property_id, inline_style->GetPropertyValue(property_id), - inline_style->PropertyIsImportant(property_id)); + inline_style->PropertyIsImportant(property_id), + element->GetDocument().SecureContextMode()); + } } return conflicting_properties && !conflicting_properties->IsEmpty(); @@ -1058,7 +1096,8 @@ bool EditingStyle::StyleIsPresentInComputedStyleOfNode(Node* node) const { return !mutable_style_ || GetPropertiesNotIn(mutable_style_.Get(), - CSSComputedStyleDeclaration::Create(node)) + CSSComputedStyleDeclaration::Create(node), + node->GetDocument().SecureContextMode()) ->IsEmpty(); } @@ -1363,15 +1402,15 @@ for (unsigned i = 0; i < property_count; ++i) { CSSPropertyValueSet::PropertyReference property = mutable_style_->PropertyAt(i); + const CSSProperty& css_property = property.Property(); const CSSValue& value = property.Value(); if (!value.IsPrimitiveValue()) continue; if (ToCSSPrimitiveValue(value).IsPercentage()) { if (const CSSValue* computed_property_value = - computed_style_for_element->GetPropertyCSSValue( - CSSProperty::Get(property.Id()))) { + computed_style_for_element->GetPropertyCSSValue(css_property)) { from_computed_style->AddRespectingCascade( - CSSPropertyValue(property.Id(), *computed_property_value)); + CSSPropertyValue(css_property, *computed_property_value)); } } } @@ -1402,15 +1441,20 @@ DocumentLifecycle::kStyleClean); DCHECK(element->GetDocument().IsActive()); + SecureContextMode secure_context_mode = + element->GetDocument().SecureContextMode(); + // 1. Remove style from matched rules because style remain without repeating // it in inline style declaration MutableCSSPropertyValueSet* style_from_matched_rules = StyleFromMatchedRulesForElement(element, StyleResolver::kAllButEmptyCSSRules); - if (style_from_matched_rules && !style_from_matched_rules->IsEmpty()) + if (style_from_matched_rules && !style_from_matched_rules->IsEmpty()) { mutable_style_ = GetPropertiesNotIn( mutable_style_.Get(), - style_from_matched_rules->EnsureCSSStyleDeclaration()); + style_from_matched_rules->EnsureCSSStyleDeclaration(), + secure_context_mode); + } // 2. Remove style present in context and not overriden by matched rules. EditingStyle* computed_style = @@ -1425,7 +1469,8 @@ style_from_matched_rules); mutable_style_ = GetPropertiesNotIn( mutable_style_.Get(), - computed_style->mutable_style_->EnsureCSSStyleDeclaration()); + computed_style->mutable_style_->EnsureCSSStyleDeclaration(), + secure_context_mode); } // 3. If this element is a span and has display: inline or float: none, remove @@ -1508,7 +1553,8 @@ } static void ReconcileTextDecorationProperties( - MutableCSSPropertyValueSet* style) { + MutableCSSPropertyValueSet* style, + SecureContextMode secure_context_mode) { const CSSValue* text_decorations_in_effect = style->GetPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect); const CSSValue* text_decoration = @@ -1517,7 +1563,8 @@ // both |textDecorationsInEffect| and |textDecoration| non-null. if (text_decorations_in_effect) { style->SetProperty(CSSPropertyTextDecorationLine, - text_decorations_in_effect->CssText()); + text_decorations_in_effect->CssText(), + /* important */ false, secure_context_mode); style->RemoveProperty(CSSPropertyWebkitTextDecorationsInEffect); text_decoration = text_decorations_in_effect; } @@ -1542,11 +1589,12 @@ CSSComputedStyleDeclaration* computed_style = EnsureComputedStyle(position); // FIXME: take care of background-color in effect - MutableCSSPropertyValueSet* mutable_style = - GetPropertiesNotIn(style->Style(), computed_style); + MutableCSSPropertyValueSet* mutable_style = GetPropertiesNotIn( + style->Style(), computed_style, document->SecureContextMode()); DCHECK(mutable_style); - ReconcileTextDecorationProperties(mutable_style); + ReconcileTextDecorationProperties(mutable_style, + document->SecureContextMode()); if (!document->GetFrame()->GetEditor().ShouldStyleWithCSS()) ExtractTextStyles(document, mutable_style, computed_style->IsMonospaceFont()); @@ -1561,10 +1609,12 @@ // direction to mutableStyle. // FIXME: Shouldn't this be done in getPropertiesNotIn? if (mutable_style->GetPropertyCSSValue(CSSPropertyUnicodeBidi) && - !style->Style()->GetPropertyCSSValue(CSSPropertyDirection)) + !style->Style()->GetPropertyCSSValue(CSSPropertyDirection)) { mutable_style->SetProperty( CSSPropertyDirection, - style->Style()->GetPropertyValue(CSSPropertyDirection)); + style->Style()->GetPropertyValue(CSSPropertyDirection), + /* important */ false, document->SecureContextMode()); + } // Save the result for later css_style_ = mutable_style->AsText().StripWhiteSpace(); @@ -1572,10 +1622,12 @@ static void SetTextDecorationProperty(MutableCSSPropertyValueSet* style, const CSSValueList* new_text_decoration, - CSSPropertyID property_id) { + CSSPropertyID property_id, + SecureContextMode secure_context_mode) { if (new_text_decoration->length()) { style->SetProperty(property_id, new_text_decoration->CssText(), - style->PropertyIsImportant(property_id)); + style->PropertyIsImportant(property_id), + secure_context_mode); } else { // text-decoration: none is redundant since it does not remove any text // decorations. @@ -1634,7 +1686,8 @@ // If trimTextDecorations, delete underline and line-through SetTextDecorationProperty(style, new_text_decoration, - CSSPropertyTextDecorationLine); + CSSPropertyTextDecorationLine, + document->SecureContextMode()); } int vertical_align = GetIdentifierValue(style, CSSPropertyVerticalAlign); @@ -1676,7 +1729,8 @@ static void DiffTextDecorations(MutableCSSPropertyValueSet* style, CSSPropertyID property_id, - const CSSValue* ref_text_decoration) { + const CSSValue* ref_text_decoration, + SecureContextMode secure_context_mode) { const CSSValue* text_decoration = style->GetPropertyCSSValue(property_id); if (!text_decoration || !text_decoration->IsValueList() || !ref_text_decoration || !ref_text_decoration->IsValueList()) @@ -1689,7 +1743,8 @@ for (size_t i = 0; i < values_in_ref_text_decoration->length(); i++) new_text_decoration->RemoveAll(values_in_ref_text_decoration->Item(i)); - SetTextDecorationProperty(style, new_text_decoration, property_id); + SetTextDecorationProperty(style, new_text_decoration, property_id, + secure_context_mode); } static bool FontWeightIsBold(const CSSValue* font_weight) { @@ -1724,7 +1779,8 @@ MutableCSSPropertyValueSet* GetPropertiesNotIn( CSSPropertyValueSet* style_with_redundant_properties, - CSSStyleDeclaration* base_style) { + CSSStyleDeclaration* base_style, + SecureContextMode secure_context_mode) { DCHECK(style_with_redundant_properties); DCHECK(base_style); MutableCSSPropertyValueSet* result = @@ -1736,9 +1792,9 @@ base_style->GetPropertyCSSValueInternal( CSSPropertyWebkitTextDecorationsInEffect); DiffTextDecorations(result, CSSPropertyTextDecorationLine, - base_text_decorations_in_effect); + base_text_decorations_in_effect, secure_context_mode); DiffTextDecorations(result, CSSPropertyWebkitTextDecorationsInEffect, - base_text_decorations_in_effect); + base_text_decorations_in_effect, secure_context_mode); if (const CSSValue* base_font_weight = base_style->GetPropertyCSSValueInternal(CSSPropertyFontWeight)) {
diff --git a/third_party/WebKit/Source/core/editing/EditingStyle.h b/third_party/WebKit/Source/core/editing/EditingStyle.h index 0fc27d3..c0d8c02d 100644 --- a/third_party/WebKit/Source/core/editing/EditingStyle.h +++ b/third_party/WebKit/Source/core/editing/EditingStyle.h
@@ -56,6 +56,7 @@ class ComputedStyle; class CSSPropertyValueSet; enum class EditingTriState; +enum class SecureContextMode; class CORE_EXPORT EditingStyle final : public GarbageCollected<EditingStyle> { public: @@ -92,8 +93,10 @@ return new EditingStyle(style); } - static EditingStyle* Create(CSSPropertyID property_id, const String& value) { - return new EditingStyle(property_id, value); + static EditingStyle* Create(CSSPropertyID property_id, + const String& value, + SecureContextMode secure_context_mode) { + return new EditingStyle(property_id, value, secure_context_mode); } MutableCSSPropertyValueSet* Style() { return mutable_style_.Get(); } @@ -103,17 +106,18 @@ void Clear(); EditingStyle* Copy() const; EditingStyle* ExtractAndRemoveBlockProperties(); - EditingStyle* ExtractAndRemoveTextDirection(); + EditingStyle* ExtractAndRemoveTextDirection(SecureContextMode); void RemoveBlockProperties(); void RemoveStyleAddedByElement(Element*); void RemoveStyleConflictingWithStyleOfElement(Element*); - void CollapseTextDecorationProperties(); + void CollapseTextDecorationProperties(SecureContextMode); enum ShouldIgnoreTextOnlyProperties { kIgnoreTextOnlyProperties, kDoNotIgnoreTextOnlyProperties }; - EditingTriState TriStateOfStyle(EditingStyle*) const; - EditingTriState TriStateOfStyle(const VisibleSelection&) const; + EditingTriState TriStateOfStyle(EditingStyle*, SecureContextMode) const; + EditingTriState TriStateOfStyle(const VisibleSelection&, + SecureContextMode) const; bool ConflictsWithInlineStyleOfElement(HTMLElement* element) const { return ConflictsWithInlineStyleOfElement(element, 0, 0); } @@ -161,7 +165,10 @@ float FontSizeDelta() const { return font_size_delta_; } bool HasFontSizeDelta() const { return font_size_delta_ != no_font_delta_; } - void SetProperty(CSSPropertyID, const String& value, bool important = false); + void SetProperty(CSSPropertyID, + const String& value, + bool important, + SecureContextMode); void Trace(blink::Visitor*); @@ -170,14 +177,16 @@ EditingStyle(ContainerNode*, PropertiesToInclude); EditingStyle(const Position&, PropertiesToInclude); explicit EditingStyle(const CSSPropertyValueSet*); - EditingStyle(CSSPropertyID, const String& value); + EditingStyle(CSSPropertyID, const String& value, SecureContextMode); void Init(Node*, PropertiesToInclude); void RemoveInheritedColorsIfNeeded(const ComputedStyle*); void ReplaceFontSizeByKeywordIfPossible(const ComputedStyle*, + SecureContextMode, CSSComputedStyleDeclaration*); void ExtractFontSizeDelta(); EditingTriState TriStateOfStyle(CSSStyleDeclaration* style_to_compare, - ShouldIgnoreTextOnlyProperties) const; + ShouldIgnoreTextOnlyProperties, + SecureContextMode) const; bool ConflictsWithInlineStyleOfElement( HTMLElement*, EditingStyle* extracted_style,
diff --git a/third_party/WebKit/Source/core/editing/EditingStyleUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingStyleUtilities.cpp index 9ab8668f..8d29b1f 100644 --- a/third_party/WebKit/Source/core/editing/EditingStyleUtilities.cpp +++ b/third_party/WebKit/Source/core/editing/EditingStyleUtilities.cpp
@@ -72,7 +72,8 @@ // Call collapseTextDecorationProperties first or otherwise it'll copy the // value over from in-effect to text-decorations. - wrapping_style->CollapseTextDecorationProperties(); + wrapping_style->CollapseTextDecorationProperties( + context->GetDocument().SecureContextMode()); return wrapping_style; } @@ -162,8 +163,10 @@ (selection.IsRange() || HasTransparentBackgroundColor(style->Style()))) { const EphemeralRange range(selection.ToNormalizedEphemeralRange()); if (const CSSValue* value = - BackgroundColorValueInEffect(range.CommonAncestorContainer())) - style->SetProperty(CSSPropertyBackgroundColor, value->CssText()); + BackgroundColorValueInEffect(range.CommonAncestorContainer())) { + style->SetProperty(CSSPropertyBackgroundColor, value->CssText(), + /* important */ false, document.SecureContextMode()); + } } return style;
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp index 8b3f843..1881c81d 100644 --- a/third_party/WebKit/Source/core/editing/Editor.cpp +++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -870,20 +870,28 @@ bool Editor::SelectionStartHasStyle(CSSPropertyID property_id, const String& value) const { - EditingStyle* style_to_check = EditingStyle::Create(property_id, value); + const SecureContextMode secure_context_mode = + frame_->GetDocument()->SecureContextMode(); + + EditingStyle* style_to_check = + EditingStyle::Create(property_id, value, secure_context_mode); EditingStyle* style_at_start = EditingStyleUtilities::CreateStyleAtSelectionStart( GetFrameSelection().ComputeVisibleSelectionInDOMTreeDeprecated(), property_id == CSSPropertyBackgroundColor, style_to_check->Style()); - return style_to_check->TriStateOfStyle(style_at_start) != + return style_to_check->TriStateOfStyle(style_at_start, secure_context_mode) != EditingTriState::kFalse; } EditingTriState Editor::SelectionHasStyle(CSSPropertyID property_id, const String& value) const { - return EditingStyle::Create(property_id, value) + const SecureContextMode secure_context_mode = + frame_->GetDocument()->SecureContextMode(); + + return EditingStyle::Create(property_id, value, secure_context_mode) ->TriStateOfStyle( - GetFrameSelection().ComputeVisibleSelectionInDOMTreeDeprecated()); + GetFrameSelection().ComputeVisibleSelectionInDOMTreeDeprecated(), + secure_context_mode); } String Editor::SelectionStartCSSPropertyValue(CSSPropertyID property_id) { @@ -1387,7 +1395,7 @@ direction == LeftToRightWritingDirection ? "ltr" : direction == RightToLeftWritingDirection ? "rtl" : "inherit", - false); + /* important */ false, GetFrame().GetDocument()->SecureContextMode()); ApplyParagraphStyleToSelection( style, InputEvent::InputType::kFormatSetBlockTextDirection); }
diff --git a/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp b/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp index fc3e5650..c4ec0d6 100644 --- a/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp +++ b/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp
@@ -264,6 +264,47 @@ primary_direction); } +InlineBoxPosition ComputeInlineBoxPositionForAtomicInline( + const LayoutObject* layout_object, + int caret_offset, + TextDirection primary_direction) { + if (!layout_object->IsBox()) + return InlineBoxPosition(); + InlineBox* const inline_box = ToLayoutBox(layout_object)->InlineBoxWrapper(); + if (!inline_box) + return InlineBoxPosition(); + if ((caret_offset > inline_box->CaretMinOffset() && + caret_offset < inline_box->CaretMaxOffset())) + return InlineBoxPosition(inline_box, caret_offset); + return AdjustInlineBoxPositionForTextDirection( + inline_box, caret_offset, layout_object->Style()->GetUnicodeBidi(), + primary_direction); +} + +template <typename Strategy> +InlineBoxPosition ComputeInlineBoxPositionForBlockFlow( + const PositionTemplate<Strategy>& position, + TextDirection primary_direction) { + // Try a visually equivalent position with possibly opposite editability. This + // helps in case |position| is in an editable block but surrounded by + // non-editable positions. It acts to negate the logic at the beginning of + // |LayoutObject::CreatePositionWithAffinity()|. + const PositionTemplate<Strategy>& downstream_equivalent = + DownstreamIgnoringEditingBoundaries(position); + if (downstream_equivalent != position) { + return ComputeInlineBoxPosition(downstream_equivalent, + TextAffinity::kUpstream, primary_direction); + } + const PositionTemplate<Strategy>& upstream_equivalent = + UpstreamIgnoringEditingBoundaries(position); + if (upstream_equivalent == position || + DownstreamIgnoringEditingBoundaries(upstream_equivalent) == position) + return InlineBoxPosition(); + + return ComputeInlineBoxPosition(upstream_equivalent, TextAffinity::kUpstream, + primary_direction); +} + template <typename Strategy> InlineBoxPosition ComputeInlineBoxPositionTemplate( const PositionTemplate<Strategy>& position, @@ -284,46 +325,15 @@ } if (layout_object->IsAtomicInlineLevel()) { - // TODO(xiaochengh): Wrap the following into a function. - if (!layout_object->IsBox()) - return InlineBoxPosition(); - InlineBox* const inline_box = - ToLayoutBox(layout_object)->InlineBoxWrapper(); - if (!inline_box) - return InlineBoxPosition(); - if ((caret_offset > inline_box->CaretMinOffset() && - caret_offset < inline_box->CaretMaxOffset())) - return InlineBoxPosition(inline_box, caret_offset); - return AdjustInlineBoxPositionForTextDirection( - inline_box, caret_offset, layout_object->Style()->GetUnicodeBidi(), - primary_direction); + return ComputeInlineBoxPositionForAtomicInline(layout_object, caret_offset, + primary_direction); } - if (!layout_object->IsLayoutBlockFlow()) - return InlineBoxPosition(); - // TODO(xiaochengh): Wrap the following into a function. - if (!CanHaveChildrenForEditing(anchor_node) || + if (!layout_object->IsLayoutBlockFlow() || + !CanHaveChildrenForEditing(anchor_node) || !HasRenderedNonAnonymousDescendantsWithHeight(layout_object)) return InlineBoxPosition(); - // Try a visually equivalent position with possibly opposite - // editability. This helps in case |this| is in an editable block - // but surrounded by non-editable positions. It acts to negate the - // logic at the beginning of - // |LayoutObject::createPositionWithAffinity()|. - const PositionTemplate<Strategy>& downstream_equivalent = - DownstreamIgnoringEditingBoundaries(position); - if (downstream_equivalent != position) { - return ComputeInlineBoxPosition(downstream_equivalent, - TextAffinity::kUpstream, primary_direction); - } - const PositionTemplate<Strategy>& upstream_equivalent = - UpstreamIgnoringEditingBoundaries(position); - if (upstream_equivalent == position || - DownstreamIgnoringEditingBoundaries(upstream_equivalent) == position) - return InlineBoxPosition(); - - return ComputeInlineBoxPosition(upstream_equivalent, TextAffinity::kUpstream, - primary_direction); + return ComputeInlineBoxPositionForBlockFlow(position, primary_direction); } template <typename Strategy>
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp index fd8f0d4..96ec367 100644 --- a/third_party/WebKit/Source/core/editing/SelectionController.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -854,6 +854,9 @@ original_base_in_flat_tree_ = PositionInFlatTreeWithAffinity(); } + builder.SetIsDirectional( + frame_->GetEditor().Behavior().ShouldConsiderSelectionAsDirectional() || + new_selection.IsDirectional()); const SelectionInFlatTree& selection_in_flat_tree = builder.Build(); const bool should_show_handle = handle_visibility == HandleVisibility::kVisible;
diff --git a/third_party/WebKit/Source/core/editing/VisiblePositionTest.cpp b/third_party/WebKit/Source/core/editing/VisiblePositionTest.cpp index eff48b2..b8bd4a8b 100644 --- a/third_party/WebKit/Source/core/editing/VisiblePositionTest.cpp +++ b/third_party/WebKit/Source/core/editing/VisiblePositionTest.cpp
@@ -89,13 +89,14 @@ Position position(paragraph->firstChild(), 1); VisiblePosition visible_position1 = CreateVisiblePosition(position); - div->style()->setProperty("color", "red", "important", ASSERT_NO_EXCEPTION); + div->style()->setProperty(&GetDocument(), "color", "red", "important", + ASSERT_NO_EXCEPTION); EXPECT_FALSE(visible_position1.IsValid()); UpdateAllLifecyclePhases(); VisiblePosition visible_position2 = CreateVisiblePosition(position); - div->style()->setProperty("display", "none", "important", + div->style()->setProperty(&GetDocument(), "display", "none", "important", ASSERT_NO_EXCEPTION); EXPECT_FALSE(visible_position2.IsValid());
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp index 860d064..0c3becaa 100644 --- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
@@ -766,8 +766,8 @@ if (embedding_remove_end != remove_start || embedding_remove_end != end) { style_without_embedding = style->Copy(); - embedding_style = - style_without_embedding->ExtractAndRemoveTextDirection(); + embedding_style = style_without_embedding->ExtractAndRemoveTextDirection( + GetDocument().SecureContextMode()); if (ComparePositions(embedding_remove_start, embedding_remove_end) <= 0) { RemoveInlineStyle(embedding_style, embedding_remove_start, @@ -835,7 +835,8 @@ if (!embedding_style) { style_without_embedding = style->Copy(); embedding_style = - style_without_embedding->ExtractAndRemoveTextDirection(); + style_without_embedding->ExtractAndRemoveTextDirection( + GetDocument().SecureContextMode()); } FixRangeAndApplyInlineStyle(embedding_style, embedding_apply_start, embedding_apply_end, editing_state);
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp index 8b5cf47..8b02f30 100644 --- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp
@@ -42,7 +42,8 @@ MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLQuirksMode); - style->SetProperty(CSSPropertyTextAlign, "center"); + style->SetProperty(CSSPropertyTextAlign, "center", /* important */ false, + SecureContextMode::kInsecureContext); ApplyStyleCommand::Create(GetDocument(), EditingStyle::Create(style), InputEvent::InputType::kFormatJustifyCenter, ApplyStyleCommand::kForceBlockProperties) @@ -70,7 +71,8 @@ MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLQuirksMode); - style->SetProperty(CSSPropertyTextAlign, "right"); + style->SetProperty(CSSPropertyTextAlign, "right", /* important */ false, + SecureContextMode::kInsecureContext); ApplyStyleCommand::Create(GetDocument(), EditingStyle::Create(style), InputEvent::InputType::kFormatJustifyCenter, ApplyStyleCommand::kForceBlockProperties)
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp index 6708b0e..b962531e1 100644 --- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -584,6 +584,10 @@ HTMLSpanElement* tab_span = TabSpanElement(pos.ComputeContainerNode()); DCHECK(tab_span); + // TODO(editing-dev): Hoist this UpdateStyleAndLayoutIgnorePendingStylesheets + // to the callers. See crbug.com/590369 for details. + GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets(); + if (pos.OffsetInContainerNode() <= CaretMinOffset(pos.ComputeContainerNode())) return Position::InParentBeforeNode(*tab_span);
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp index bffaf82..0fdd8dc9f 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -275,9 +275,11 @@ InputEvent::InputType input_type, CSSPropertyID property_id, const String& property_value) { + DCHECK(frame.GetDocument()); MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLQuirksMode); - style->SetProperty(property_id, property_value); + style->SetProperty(property_id, property_value, /* important */ false, + frame.GetDocument()->SecureContextMode()); return ApplyCommandToFrame(frame, source, input_type, style); } @@ -326,7 +328,8 @@ // have setPropertyCSSValue. MutableCSSPropertyValueSet* new_mutable_style = MutableCSSPropertyValueSet::Create(kHTMLQuirksMode); - new_mutable_style->SetProperty(property_id, new_style); + new_mutable_style->SetProperty(property_id, new_style, /* important */ false, + frame.GetDocument()->SecureContextMode()); return ApplyCommandToFrame(frame, source, input_type, new_mutable_style); } @@ -348,8 +351,9 @@ style_is_present = frame.GetEditor().SelectionHasStyle( property_id, on_value) == EditingTriState::kTrue; - EditingStyle* style = EditingStyle::Create( - property_id, style_is_present ? off_value : on_value); + EditingStyle* style = + EditingStyle::Create(property_id, style_is_present ? off_value : on_value, + frame.GetDocument()->SecureContextMode()); return ApplyCommandToFrame(frame, source, input_type, style->Style()); } @@ -360,7 +364,8 @@ const String& property_value) { MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLQuirksMode); - style->SetProperty(property_id, property_value); + style->SetProperty(property_id, property_value, /* important */ false, + frame.GetDocument()->SecureContextMode()); // FIXME: We don't call shouldApplyStyle when the source is DOM; is there a // good reason for that? switch (source) {
diff --git a/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp b/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp index eacaa1d5..97c8171 100644 --- a/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp
@@ -57,13 +57,14 @@ // script. Setting to null string removes the property. We don't have internal // version of removeProperty. element_->style()->SetPropertyInternal(property_, String(), String(), false, + GetDocument().SecureContextMode(), IGNORE_EXCEPTION_FOR_TESTING); } void RemoveCSSPropertyCommand::DoUnapply() { - element_->style()->SetPropertyInternal(property_, String(), old_value_, - important_, - IGNORE_EXCEPTION_FOR_TESTING); + element_->style()->SetPropertyInternal( + property_, String(), old_value_, important_, + GetDocument().SecureContextMode(), IGNORE_EXCEPTION_FOR_TESTING); } void RemoveCSSPropertyCommand::Trace(blink::Visitor* visitor) {
diff --git a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp index 256588d..20f23810 100644 --- a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp +++ b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp
@@ -256,11 +256,14 @@ !fully_selected_root_style->Style() || !fully_selected_root_style->Style()->GetPropertyCSSValue( CSSPropertyBackgroundImage)) && - fully_selected_root->hasAttribute(backgroundAttr)) + fully_selected_root->hasAttribute(backgroundAttr)) { fully_selected_root_style->Style()->SetProperty( CSSPropertyBackgroundImage, "url('" + fully_selected_root->getAttribute(backgroundAttr) + - "')"); + "')", + /* important */ false, + fully_selected_root->GetDocument().SecureContextMode()); + } if (fully_selected_root_style->Style()) { // Reset the CSS properties to avoid an assertion error in
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp index 2725631..6cbb452 100644 --- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp +++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
@@ -780,6 +780,12 @@ web_frame_->Client()->DidObserveNewFeatureUsage(feature); } +bool LocalFrameClientImpl::ShouldTrackUseCounter(const KURL& url) { + if (web_frame_->Client()) + return web_frame_->Client()->ShouldTrackUseCounter(url); + return false; +} + void LocalFrameClientImpl::SelectorMatchChanged( const Vector<String>& added_selectors, const Vector<String>& removed_selectors) { @@ -1129,7 +1135,7 @@ } void LocalFrameClientImpl::SetVirtualTimePauser( - ScopedVirtualTimePauser virtual_time_pauser) { + WebScopedVirtualTimePauser virtual_time_pauser) { virtual_time_pauser_ = std::move(virtual_time_pauser); }
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h index ee29706..f9246d5 100644 --- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h +++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h
@@ -35,10 +35,10 @@ #include "base/memory/scoped_refptr.h" #include "core/frame/LocalFrameClient.h" #include "core/frame/WebLocalFrameImpl.h" -#include "platform/ScopedVirtualTimePauser.h" #include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" #include "public/platform/WebInsecureRequestPolicy.h" +#include "public/platform/WebScopedVirtualTimePauser.h" #include <memory> @@ -142,6 +142,7 @@ void DidChangePerformanceTiming() override; void DidObserveLoadingBehavior(WebLoadingBehaviorFlag) override; void DidObserveNewFeatureUsage(mojom::WebFeature) override; + bool ShouldTrackUseCounter(const KURL&) override; void SelectorMatchChanged(const Vector<String>& added_selectors, const Vector<String>& removed_selectors) override; @@ -252,7 +253,7 @@ const WebRect&, const WebRemoteScrollProperties&) override; - void SetVirtualTimePauser(ScopedVirtualTimePauser) override; + void SetVirtualTimePauser(WebScopedVirtualTimePauser) override; private: explicit LocalFrameClientImpl(WebLocalFrameImpl*); @@ -272,7 +273,7 @@ // The hosts for which a legacy certificate warning has been printed. HashSet<String> certificate_warning_hosts_; - mutable ScopedVirtualTimePauser virtual_time_pauser_; + mutable WebScopedVirtualTimePauser virtual_time_pauser_; }; DEFINE_TYPE_CASTS(LocalFrameClientImpl,
diff --git a/third_party/WebKit/Source/core/exported/WebSelector.cpp b/third_party/WebKit/Source/core/exported/WebSelector.cpp index 47b848d..98978c3 100644 --- a/third_party/WebKit/Source/core/exported/WebSelector.cpp +++ b/third_party/WebKit/Source/core/exported/WebSelector.cpp
@@ -38,8 +38,12 @@ WebString CanonicalizeSelector(WebString web_selector, WebSelectorType restriction) { - CSSSelectorList selector_list = - CSSParser::ParseSelector(StrictCSSParserContext(), nullptr, web_selector); + // NOTE: We will always parse the selector in an insecure context mode, if we + // have selectors which are only parsed in secure contexts, this will need to + // accept a SecureContextMode as an argument. + CSSSelectorList selector_list = CSSParser::ParseSelector( + StrictCSSParserContext(SecureContextMode::kInsecureContext), nullptr, + web_selector); if (restriction == kWebSelectorTypeCompound) { for (const CSSSelector* selector = selector_list.First(); selector;
diff --git a/third_party/WebKit/Source/core/exported/WebViewTest.cpp b/third_party/WebKit/Source/core/exported/WebViewTest.cpp index 09b0f24a..327c83c 100644 --- a/third_party/WebKit/Source/core/exported/WebViewTest.cpp +++ b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
@@ -5050,7 +5050,8 @@ ToHTMLObjectElement(main_frame->GetDocument()->body()->firstChild()); EXPECT_TRUE(plugin_element->OwnedPlugin()); - plugin_element->style()->setCSSText("display: none", ASSERT_NO_EXCEPTION); + plugin_element->style()->setCSSText(main_frame->GetDocument(), + "display: none", ASSERT_NO_EXCEPTION); EXPECT_TRUE(plugin_element->OwnedPlugin()); web_view->UpdateAllLifecyclePhases(); EXPECT_FALSE(plugin_element->OwnedPlugin());
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameClient.h b/third_party/WebKit/Source/core/frame/LocalFrameClient.h index 1fc148f4..f391bc2 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameClient.h +++ b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
@@ -42,7 +42,6 @@ #include "core/loader/FrameLoadRequest.h" #include "core/loader/FrameLoaderTypes.h" #include "core/loader/NavigationPolicy.h" -#include "platform/ScopedVirtualTimePauser.h" #include "platform/heap/Handle.h" #include "platform/loader/fetch/ResourceLoadPriority.h" #include "platform/loader/fetch/ResourceLoaderOptions.h" @@ -54,6 +53,7 @@ #include "public/platform/WebEffectiveConnectionType.h" #include "public/platform/WebInsecureRequestPolicy.h" #include "public/platform/WebLoadingBehaviorFlag.h" +#include "public/platform/WebScopedVirtualTimePauser.h" #include "public/platform/WebSuddenTerminationDisablerType.h" #include "public/platform/WebURLRequest.h" #include "public/web/WebTriggeringEventInfo.h" @@ -194,9 +194,12 @@ // propogates renderer loading behavior to the browser process for histograms. virtual void DidObserveLoadingBehavior(WebLoadingBehaviorFlag) {} - // Will be called when a new useCounter feature has been observed in a frame. + // Will be called when a new UseCounter feature has been observed in a frame. // This propogates feature usage to the browser process for histograms. virtual void DidObserveNewFeatureUsage(mojom::WebFeature) {} + // Will be called by a Page upon DidCommitLoad, deciding whether to track + // UseCounter usage or not based on its url. + virtual bool ShouldTrackUseCounter(const KURL&) { return true; } // Transmits the change in the set of watched CSS selectors property that // match any element on the frame. @@ -371,7 +374,7 @@ const WebRemoteScrollProperties&) {} virtual void SetVirtualTimePauser( - ScopedVirtualTimePauser virtual_time_pauser) {} + WebScopedVirtualTimePauser virtual_time_pauser) {} }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/UseCounterTest.cpp b/third_party/WebKit/Source/core/frame/UseCounterTest.cpp index 32f0c98..f00a719 100644 --- a/third_party/WebKit/Source/core/frame/UseCounterTest.cpp +++ b/third_party/WebKit/Source/core/frame/UseCounterTest.cpp
@@ -375,19 +375,19 @@ ExpectHistograms(histogram_tester_, 2, WebFeature::kFetch, 3, CSSPropertyFontWeight, 3); - // Or empty URLs (a main frame with no Document) + // Nor are empty URLs (a main frame with no Document) use_counter.DidCommitLoad(NullURL()); use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame()); use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight); ExpectHistograms(histogram_tester_, 2, WebFeature::kFetch, 3, CSSPropertyFontWeight, 3); - // But file URLs are + // Or file URLs use_counter.DidCommitLoad(URLTestHelpers::ToKURL("file:///c/autoexec.bat")); use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame()); use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight); - ExpectHistograms(histogram_tester_, 3, WebFeature::kFetch, 4, - CSSPropertyFontWeight, 4); + ExpectHistograms(histogram_tester_, 2, WebFeature::kFetch, 3, + CSSPropertyFontWeight, 3); } class DeprecationTest : public ::testing::Test {
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp index a0af0370..3486ae9 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -1686,8 +1686,8 @@ frame_ = frame; local_frame_client_->SetVirtualTimePauser( - frame_ ? frame_->FrameScheduler()->CreateScopedVirtualTimePauser() - : ScopedVirtualTimePauser()); + frame_ ? frame_->FrameScheduler()->CreateWebScopedVirtualTimePauser() + : WebScopedVirtualTimePauser()); } void WebLocalFrameImpl::InitializeCoreFrame(Page& page,
diff --git a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp index a6a63064..eef2ea2 100644 --- a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp +++ b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
@@ -212,6 +212,11 @@ GetUseCounterType(policy->HeaderType())); if (policy->AllowDynamic()) UseCounter::Count(execution_context_, WebFeature::kCSPWithStrictDynamic); + if (policy->AllowEval(nullptr, + SecurityViolationReportingPolicy::kSuppressReporting, + kWillNotThrowException, g_empty_string)) { + UseCounter::Count(execution_context_, WebFeature::kCSPWithUnsafeEval); + } } // We disable 'eval()' even in the case of report-only policies, and rely on
diff --git a/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp b/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp index d9c81249..128d212 100644 --- a/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp +++ b/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp
@@ -29,7 +29,8 @@ } DOMMatrix* matrix = new DOMMatrix(TransformationMatrix()); - matrix->SetMatrixValueFromString(init.GetAsString(), exception_state); + matrix->SetMatrixValueFromString(execution_context, init.GetAsString(), + exception_state); return matrix; } @@ -314,9 +315,10 @@ return this; } -DOMMatrix* DOMMatrix::setMatrixValue(const String& input_string, +DOMMatrix* DOMMatrix::setMatrixValue(const ExecutionContext* execution_context, + const String& input_string, ExceptionState& exception_state) { - SetMatrixValueFromString(input_string, exception_state); + SetMatrixValueFromString(execution_context, input_string, exception_state); return this; }
diff --git a/third_party/WebKit/Source/core/geometry/DOMMatrix.h b/third_party/WebKit/Source/core/geometry/DOMMatrix.h index f40f52e..c6533b3 100644 --- a/third_party/WebKit/Source/core/geometry/DOMMatrix.h +++ b/third_party/WebKit/Source/core/geometry/DOMMatrix.h
@@ -118,7 +118,9 @@ DOMMatrix* perspectiveSelf(double p); DOMMatrix* invertSelf(); - DOMMatrix* setMatrixValue(const String&, ExceptionState&); + DOMMatrix* setMatrixValue(const ExecutionContext*, + const String&, + ExceptionState&); private: DOMMatrix(const TransformationMatrix&, bool is2d = true);
diff --git a/third_party/WebKit/Source/core/geometry/DOMMatrix.idl b/third_party/WebKit/Source/core/geometry/DOMMatrix.idl index 5f3378c..097e920 100644 --- a/third_party/WebKit/Source/core/geometry/DOMMatrix.idl +++ b/third_party/WebKit/Source/core/geometry/DOMMatrix.idl
@@ -69,5 +69,5 @@ DOMMatrix skewYSelf(optional unrestricted double sy = 0); DOMMatrix invertSelf(); - [Exposed=Window, RaisesException] DOMMatrix setMatrixValue(DOMString transformList); + [Exposed=Window, RaisesException, CallWith=ExecutionContext] DOMMatrix setMatrixValue(DOMString transformList); };
diff --git a/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.cpp b/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.cpp index fb19ec8..392bb5a 100644 --- a/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.cpp +++ b/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.cpp
@@ -125,7 +125,8 @@ } DOMMatrixReadOnly* matrix = new DOMMatrixReadOnly(TransformationMatrix()); - matrix->SetMatrixValueFromString(init.GetAsString(), exception_state); + matrix->SetMatrixValueFromString(execution_context, init.GetAsString(), + exception_state); return matrix; } @@ -459,6 +460,7 @@ } void DOMMatrixReadOnly::SetMatrixValueFromString( + const ExecutionContext* execution_context, const String& input_string, ExceptionState& exception_state) { DEFINE_STATIC_LOCAL(String, identity_matrix2d, ("matrix(1, 0, 0, 1, 0, 0)")); @@ -466,8 +468,9 @@ if (string.IsEmpty()) string = identity_matrix2d; - const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyTransform, string); + const CSSValue* value = CSSParser::ParseSingleValue( + CSSPropertyTransform, string, + StrictCSSParserContext(execution_context->SecureContextMode())); if (!value || value->IsCSSWideKeyword()) { exception_state.ThrowDOMException(
diff --git a/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.h b/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.h index f80fdcf..718dfd405 100644 --- a/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.h +++ b/third_party/WebKit/Source/core/geometry/DOMMatrixReadOnly.h
@@ -128,7 +128,9 @@ } } - void SetMatrixValueFromString(const String&, ExceptionState&); + void SetMatrixValueFromString(const ExecutionContext*, + const String&, + ExceptionState&); static bool ValidateAndFixup2D(DOMMatrix2DInit&, ExceptionState&); static bool ValidateAndFixup(DOMMatrixInit&, ExceptionState&);
diff --git a/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp b/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp index b809507a..435dba9 100644 --- a/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp
@@ -70,7 +70,7 @@ GetDocument().GetReferrerPolicy())); image_value->SetInitiator(localName()); style->SetProperty( - CSSPropertyValue(CSSPropertyBackgroundImage, *image_value)); + CSSPropertyValue(GetCSSPropertyBackgroundImage(), *image_value)); } } else if (name == marginwidthAttr || name == leftmarginAttr) { AddHTMLLengthToStyle(style, CSSPropertyMarginRight, value);
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp index 3450387..8ff3278 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -1526,6 +1526,14 @@ SetNeedsCompositingUpdate(); } +void HTMLCanvasElement::RegisterContentsLayer(WebLayer* web_layer) { + GraphicsLayer::RegisterContentsLayer(web_layer); +} + +void HTMLCanvasElement::UnregisterContentsLayer(WebLayer* web_layer) { + GraphicsLayer::UnregisterContentsLayer(web_layer); +} + FontSelector* HTMLCanvasElement::GetFontSelector() { return GetDocument().GetStyleEngine().GetFontSelector(); }
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h index a86ed86..6167745 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
@@ -201,6 +201,8 @@ // SurfaceLayerBridgeObserver implementation void OnWebLayerUpdated() override; + void RegisterContentsLayer(WebLayer*) override; + void UnregisterContentsLayer(WebLayer*) override; // ImageBufferClient implementation void NotifySurfaceInvalid() override;
diff --git a/third_party/WebKit/Source/core/html/HTMLFontElement.cpp b/third_party/WebKit/Source/core/html/HTMLFontElement.cpp index f9f67823..ff8d71bf 100644 --- a/third_party/WebKit/Source/core/html/HTMLFontElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFontElement.cpp
@@ -28,6 +28,7 @@ #include "core/css/CSSValueList.h" #include "core/css/CSSValuePool.h" #include "core/css/parser/CSSParser.h" +#include "core/dom/Document.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/html_names.h" #include "platform/wtf/text/ParsingUtilities.h" @@ -119,12 +120,14 @@ } static const CSSValueList* CreateFontFaceValueWithPool( - const AtomicString& string) { + const AtomicString& string, + SecureContextMode secure_context_mode) { CSSValuePool::FontFaceValueCache::AddResult entry = CssValuePool().GetFontFaceCacheEntry(string); if (!entry.stored_value->value) { - const CSSValue* parsed_value = - CSSParser::ParseSingleValue(CSSPropertyFontFamily, string); + const CSSValue* parsed_value = CSSParser::ParseSingleValue( + CSSPropertyFontFamily, string, + StrictCSSParserContext(secure_context_mode)); if (parsed_value && parsed_value->IsValueList()) entry.stored_value->value = ToCSSValueList(parsed_value); } @@ -183,10 +186,10 @@ } else if (name == colorAttr) { AddHTMLColorToStyle(style, CSSPropertyColor, value); } else if (name == faceAttr && !value.IsEmpty()) { - if (const CSSValueList* font_face_value = - CreateFontFaceValueWithPool(value)) { + if (const CSSValueList* font_face_value = CreateFontFaceValueWithPool( + value, GetDocument().SecureContextMode())) { style->SetProperty( - CSSPropertyValue(CSSPropertyFontFamily, *font_face_value)); + CSSPropertyValue(GetCSSPropertyFontFamily(), *font_face_value)); } } else { HTMLElement::CollectStyleForPresentationAttribute(name, value, style);
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp index 6cb50e14..ea739c1 100644 --- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -103,6 +103,8 @@ } else if (name == scopeAttr) { scope_ = value; Process(); + } else if (name == integrityAttr) { + integrity_ = value; } else if (name == disabledAttr) { UseCounter::Count(GetDocument(), WebFeature::kHTMLLinkElementDisabled); if (LinkStyle* link = GetLinkStyle()) @@ -128,13 +130,15 @@ const String& as, const String& media, const String& nonce, + const String& integrity, ReferrerPolicy referrer_policy, const KURL& url) { - return link_loader_->LoadLink(rel_attribute_, - GetCrossOriginAttributeValue(FastGetAttribute( - HTMLNames::crossoriginAttr)), - type, as, media, nonce, referrer_policy, url, - GetDocument(), NetworkHintsInterfaceImpl()); + return link_loader_->LoadLink( + rel_attribute_, + GetCrossOriginAttributeValue( + FastGetAttribute(HTMLNames::crossoriginAttr)), + type, as, media, nonce, integrity, referrer_policy, url, GetDocument(), + NetworkHintsInterfaceImpl()); } LinkResource* HTMLLinkElement::LinkResourceToProcess() {
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.h b/third_party/WebKit/Source/core/html/HTMLLinkElement.h index 374d2a78..46f77b9 100644 --- a/third_party/WebKit/Source/core/html/HTMLLinkElement.h +++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.h
@@ -57,6 +57,7 @@ String Media() const { return media_; } String TypeValue() const { return type_; } String AsValue() const { return as_; } + String IntegrityValue() const { return integrity_; } ReferrerPolicy GetReferrerPolicy() const { return referrer_policy_; } const LinkRelAttribute& RelAttribute() const { return rel_attribute_; } DOMTokenList& relList() const { @@ -100,6 +101,7 @@ const String& as, const String& media, const String& nonce, + const String& integrity, ReferrerPolicy, const KURL&); bool IsAlternate() const { @@ -157,6 +159,7 @@ String type_; String as_; String media_; + String integrity_; ReferrerPolicy referrer_policy_; Member<DOMTokenList> sizes_; Vector<IntSize> icon_sizes_;
diff --git a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp index fdd8731..6632da99 100644 --- a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
@@ -248,14 +248,19 @@ mover_->GetDocument().ElementSheet().Contents(); MutableCSSPropertyValueSet::SetResult set_result; + SecureContextMode secure_context_mode = + mover_->GetDocument().SecureContextMode(); + scoped_refptr<StringKeyframe> keyframe1 = StringKeyframe::Create(); set_result = keyframe1->SetCSSPropertyValue( - CSSPropertyTransform, parameters.transform_begin, style_sheet_contents); + CSSPropertyTransform, parameters.transform_begin, secure_context_mode, + style_sheet_contents); DCHECK(set_result.did_parse); scoped_refptr<StringKeyframe> keyframe2 = StringKeyframe::Create(); set_result = keyframe2->SetCSSPropertyValue( - CSSPropertyTransform, parameters.transform_end, style_sheet_contents); + CSSPropertyTransform, parameters.transform_end, secure_context_mode, + style_sheet_contents); DCHECK(set_result.did_parse); return StringKeyframeEffectModel::Create( @@ -350,10 +355,11 @@ } if (IsHorizontal()) { - mover_->style()->setProperty("width", "-webkit-max-content", "important", - ASSERT_NO_EXCEPTION); + mover_->style()->setProperty(&GetDocument(), "width", "-webkit-max-content", + "important", ASSERT_NO_EXCEPTION); } else { - mover_->style()->setProperty("height", "-webkit-max-content", "important", + mover_->style()->setProperty(&GetDocument(), "height", + "-webkit-max-content", "important", ASSERT_NO_EXCEPTION); } CSSStyleDeclaration* mover_style =
diff --git a/third_party/WebKit/Source/core/html/HTMLTableCellElement.idl b/third_party/WebKit/Source/core/html/HTMLTableCellElement.idl index 6974c3a..1d63d5d 100644 --- a/third_party/WebKit/Source/core/html/HTMLTableCellElement.idl +++ b/third_party/WebKit/Source/core/html/HTMLTableCellElement.idl
@@ -25,7 +25,7 @@ [CEReactions] attribute unsigned long rowSpan; // TODO(foolip): headers should be a [PutForwards=value] readonly attribute // DOMTokenList. - [CEReactions, Reflect, TreatNullAs=NullString] attribute DOMString headers; + [CEReactions, Reflect] attribute DOMString headers; readonly attribute long cellIndex; // obsolete members
diff --git a/third_party/WebKit/Source/core/html/HTMLTableElement.cpp b/third_party/WebKit/Source/core/html/HTMLTableElement.cpp index 8d3637c..1c0264bf2 100644 --- a/third_party/WebKit/Source/core/html/HTMLTableElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLTableElement.cpp
@@ -334,7 +334,7 @@ Referrer(GetDocument().OutgoingReferrer(), GetDocument().GetReferrerPolicy())); style->SetProperty( - CSSPropertyValue(CSSPropertyBackgroundImage, *image_value)); + CSSPropertyValue(GetCSSPropertyBackgroundImage(), *image_value)); } } else if (name == valignAttr) { if (!value.IsEmpty())
diff --git a/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp b/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp index 64b069c..42fc088 100644 --- a/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp
@@ -65,7 +65,7 @@ Referrer(GetDocument().OutgoingReferrer(), GetDocument().GetReferrerPolicy())); style->SetProperty( - CSSPropertyValue(CSSPropertyBackgroundImage, *image_value)); + CSSPropertyValue(GetCSSPropertyBackgroundImage(), *image_value)); } } else if (name == valignAttr) { if (DeprecatedEqualIgnoringCase(value, "top"))
diff --git a/third_party/WebKit/Source/core/html/ImageData.cpp b/third_party/WebKit/Source/core/html/ImageData.cpp index 52b4428..92c89ed9 100644 --- a/third_party/WebKit/Source/core/html/ImageData.cpp +++ b/third_party/WebKit/Source/core/html/ImageData.cpp
@@ -744,7 +744,7 @@ bool ImageData::ImageDataInCanvasColorSettings( CanvasColorSpace canvas_color_space, CanvasPixelFormat canvas_pixel_format, - std::unique_ptr<uint8_t[]>& converted_pixels, + unsigned char* converted_pixels, DataU8ColorType u8_color_type, const IntRect* src_rect) { if (!data_ && !data_u16_ && !data_f32_) @@ -768,8 +768,7 @@ if (crop_rect) { unsigned char* src_data = static_cast<unsigned char*>(BufferBase()->Data()); - unsigned char* dst_data = - static_cast<unsigned char*>(converted_pixels.get()); + unsigned char* dst_data = static_cast<unsigned char*>(converted_pixels); int src_index = (crop_rect->X() + crop_rect->Y() * width()) * 4; int dst_index = 0; int src_row_stride = width() * 4; @@ -780,7 +779,7 @@ dst_index += dst_row_stride; } } else { - memcpy(converted_pixels.get(), data_->Data(), data_->length()); + memcpy(converted_pixels, data_->Data(), data_->length()); } SwizzleIfNeeded(u8_color_type, crop_rect); return true; @@ -815,8 +814,7 @@ if (crop_rect) { unsigned char* src_data = static_cast<unsigned char*>(BufferBase()->Data()); - unsigned char* dst_data = - static_cast<unsigned char*>(converted_pixels.get()); + unsigned char* dst_data = static_cast<unsigned char*>(converted_pixels); int src_data_type_size = ImageData::StorageFormatDataSize(color_settings_.storageFormat()); int dst_pixel_size = dst_color_params.BytesPerPixel(); @@ -837,7 +835,7 @@ dst_index += dst_row_stride; } } else { - conversion_result = xform->apply(dst_color_format, converted_pixels.get(), + conversion_result = xform->apply(dst_color_format, converted_pixels, src_color_format, src_data, size_.Area(), SkAlphaType::kUnpremul_SkAlphaType); }
diff --git a/third_party/WebKit/Source/core/html/ImageData.h b/third_party/WebKit/Source/core/html/ImageData.h index 195d71e..7585b751 100644 --- a/third_party/WebKit/Source/core/html/ImageData.h +++ b/third_party/WebKit/Source/core/html/ImageData.h
@@ -140,7 +140,7 @@ // used to create an ImageBitmap, kN32ColorType should be used. bool ImageDataInCanvasColorSettings(CanvasColorSpace, CanvasPixelFormat, - std::unique_ptr<uint8_t[]>&, + unsigned char* converted_pixels, DataU8ColorType, const IntRect* = nullptr);
diff --git a/third_party/WebKit/Source/core/html/ImageDataTest.cpp b/third_party/WebKit/Source/core/html/ImageDataTest.cpp index c5d2f28..ecb8512 100644 --- a/third_party/WebKit/Source/core/html/ImageDataTest.cpp +++ b/third_party/WebKit/Source/core/html/ImageDataTest.cpp
@@ -245,7 +245,7 @@ // Convert the image data to the color settings of the canvas. EXPECT_TRUE(image_data->ImageDataInCanvasColorSettings( canvas_color_spaces[k], canvas_pixel_formats[k], - pixels_converted_in_image_data, kRGBAColorType)); + pixels_converted_in_image_data.get(), kRGBAColorType)); // Compare the converted pixels ColorCorrectionTestUtils::CompareColorCorrectedPixels(
diff --git a/third_party/WebKit/Source/core/html/LinkStyle.cpp b/third_party/WebKit/Source/core/html/LinkStyle.cpp index 6d7b7cbd..141ad3a 100644 --- a/third_party/WebKit/Source/core/html/LinkStyle.cpp +++ b/third_party/WebKit/Source/core/html/LinkStyle.cpp
@@ -372,7 +372,8 @@ } if (!owner_->LoadLink(type, as, media, owner_->nonce(), - owner_->GetReferrerPolicy(), href)) + owner_->IntegrityValue(), owner_->GetReferrerPolicy(), + href)) return; if (LoadStylesheetIfNeeded(href, charset, type) == kNotNeeded && sheet_) {
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasFontCache.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasFontCache.cpp index 073151a..74e4f1c 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasFontCache.cpp +++ b/third_party/WebKit/Source/core/html/canvas/CanvasFontCache.cpp
@@ -95,7 +95,8 @@ font_lru_list_.insert(font_string); } else { parsed_style = MutableCSSPropertyValueSet::Create(kHTMLStandardMode); - CSSParser::ParseValue(parsed_style, CSSPropertyFont, font_string, true); + CSSParser::ParseValue(parsed_style, CSSPropertyFont, font_string, true, + document_->SecureContextMode()); if (parsed_style->IsEmpty()) return nullptr; // According to
diff --git a/third_party/WebKit/Source/core/html/forms/FormController.cpp b/third_party/WebKit/Source/core/html/forms/FormController.cpp index 87214fde..2b4ed0b 100644 --- a/third_party/WebKit/Source/core/html/forms/FormController.cpp +++ b/third_party/WebKit/Source/core/html/forms/FormController.cpp
@@ -406,14 +406,14 @@ } void DocumentState::AddControl(HTMLFormControlElementWithState* control) { - auto result = form_controls_.insert(control); - DCHECK(result.is_new_entry); + DCHECK(!control->Next() && !control->Prev()); + form_controls_.Append(control); } void DocumentState::RemoveControl(HTMLFormControlElementWithState* control) { - auto it = form_controls_.find(control); - CHECK(it != form_controls_.end()); - form_controls_.erase(it); + form_controls_.Remove(control); + control->SetPrev(nullptr); + control->SetNext(nullptr); } static String FormStateSignature() { @@ -429,8 +429,8 @@ FormKeyGenerator* key_generator = FormKeyGenerator::Create(); std::unique_ptr<SavedFormStateMap> state_map = WTF::WrapUnique(new SavedFormStateMap); - for (const auto& form_control : form_controls_) { - HTMLFormControlElementWithState* control = form_control.Get(); + for (HTMLFormControlElementWithState* control = form_controls_.Head(); + control; control = control->Next()) { DCHECK(control->isConnected()); if (!control->ShouldSaveAndRestoreFormControlState()) continue;
diff --git a/third_party/WebKit/Source/core/html/forms/FormController.h b/third_party/WebKit/Source/core/html/forms/FormController.h index 7ec8019..c21565d5 100644 --- a/third_party/WebKit/Source/core/html/forms/FormController.h +++ b/third_party/WebKit/Source/core/html/forms/FormController.h
@@ -25,6 +25,7 @@ #include <memory> #include "platform/heap/Handle.h" +#include "platform/heap/HeapAllocator.h" #include "platform/wtf/Allocator.h" #include "platform/wtf/Forward.h" #include "platform/wtf/ListHashSet.h" @@ -91,9 +92,8 @@ Vector<String> ToStateVector(); private: - using FormElementListHashSet = - HeapListHashSet<Member<HTMLFormControlElementWithState>, 64>; - FormElementListHashSet form_controls_; + using FormElementList = HeapDoublyLinkedList<HTMLFormControlElementWithState>; + FormElementList form_controls_; }; class FormController final : public GarbageCollectedFinalized<FormController> {
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLFormControlElementWithState.cpp b/third_party/WebKit/Source/core/html/forms/HTMLFormControlElementWithState.cpp index b8dd24f..740ae5a 100644 --- a/third_party/WebKit/Source/core/html/forms/HTMLFormControlElementWithState.cpp +++ b/third_party/WebKit/Source/core/html/forms/HTMLFormControlElementWithState.cpp
@@ -87,4 +87,10 @@ return true; } +void HTMLFormControlElementWithState::Trace(Visitor* visitor) { + visitor->Trace(prev_); + visitor->Trace(next_); + HTMLFormControlElement::Trace(visitor); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLFormControlElementWithState.h b/third_party/WebKit/Source/core/html/forms/HTMLFormControlElementWithState.h index 31320d6..0a4db72c 100644 --- a/third_party/WebKit/Source/core/html/forms/HTMLFormControlElementWithState.h +++ b/third_party/WebKit/Source/core/html/forms/HTMLFormControlElementWithState.h
@@ -27,13 +27,15 @@ #include "core/CoreExport.h" #include "core/html/forms/HTMLFormControlElement.h" +#include "platform/wtf/DoublyLinkedList.h" namespace blink { class FormControlState; class CORE_EXPORT HTMLFormControlElementWithState - : public HTMLFormControlElement { + : public HTMLFormControlElement, + public DoublyLinkedListNode<HTMLFormControlElementWithState> { public: ~HTMLFormControlElementWithState() override; @@ -46,6 +48,8 @@ virtual void RestoreFormControlState(const FormControlState&) {} void NotifyFormStateChanged(); + void Trace(Visitor*) override; + protected: HTMLFormControlElementWithState(const QualifiedName& tag_name, Document&); @@ -53,6 +57,15 @@ InsertionNotificationRequest InsertedInto(ContainerNode*) override; void RemovedFrom(ContainerNode*) override; bool IsFormControlElementWithState() const final; + + private: + // Pointers for DoublyLinkedListNode<HTMLFormControlElementWithState>. This + // is used for adding an instance to a list of form controls stored in + // DocumentState. Each instance is only added to its containing document's + // DocumentState list. + friend class WTF::DoublyLinkedListNode<HTMLFormControlElementWithState>; + Member<HTMLFormControlElementWithState> prev_; + Member<HTMLFormControlElementWithState> next_; }; DEFINE_TYPE_CASTS(HTMLFormControlElementWithState,
diff --git a/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp index 5d20f0aa..c44e9a5 100644 --- a/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp +++ b/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp
@@ -2141,25 +2141,19 @@ ExceptionState& exception_state) { BLINK_MEDIA_LOG << "setPlaybackRate(" << (void*)this << ", " << rate << ")"; - // TODO(apacible): While visible clamping is currently experimental, do NOT - // clamp the values of |playback_rate_| in |this|. Instead, clamp these - // values in WebMediaPlayerImpl until . if (rate != 0.0 && (rate < kMinRate || rate > kMaxRate)) { UseCounter::Count(GetDocument(), WebFeature::kHTMLMediaElementMediaPlaybackRateOutOfRange); - // Experimental: crbug/747082. // When the proposed playbackRate is unsupported, throw a NotSupportedError // DOMException and don't update the value. - if (RuntimeEnabledFeatures::PreloadDefaultIsMetadataEnabled()) { - exception_state.ThrowDOMException( - kNotSupportedError, "The provided playback rate (" + - String::Number(rate) + ") is not in the " + - "supported playback range."); + exception_state.ThrowDOMException( + kNotSupportedError, "The provided playback rate (" + + String::Number(rate) + ") is not in the " + + "supported playback range."); - // Do not update |playback_rate_|. - return; - } + // Do not update |playback_rate_|. + return; } if (playback_rate_ != rate) {
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp index 5347126..9f75f39a 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -802,7 +802,7 @@ virtual_time_pauser_ = GetDocument() ->GetFrame() ->FrameScheduler() - ->CreateScopedVirtualTimePauser(); + ->CreateWebScopedVirtualTimePauser(); virtual_time_pauser_.PauseVirtualTime(true); }
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h index 7644a622..0eb7390 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h +++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
@@ -287,7 +287,7 @@ bool added_pending_stylesheet_in_body_; bool is_waiting_for_stylesheets_; - ScopedVirtualTimePauser virtual_time_pauser_; + WebScopedVirtualTimePauser virtual_time_pauser_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp index 843610d..3a8401e 100644 --- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp +++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp
@@ -23,6 +23,7 @@ #include "third_party/skia/include/core/SkImageInfo.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSwizzle.h" +#include "third_party/skia/include/effects/SkColorFilterImageFilter.h" namespace blink { @@ -156,8 +157,7 @@ return false; } -SkImageInfo GetSkImageInfo(const scoped_refptr<StaticBitmapImage>& image) { - sk_sp<SkImage> skia_image = image->PaintImageForCurrentFrame().GetSkImage(); +SkImageInfo GetSkImageInfo(sk_sp<SkImage> skia_image) { SkColorType color_type = kN32_SkColorType; if (skia_image->colorSpace() && skia_image->colorSpace()->gammaIsLinear()) color_type = kRGBA_F16_SkColorType; @@ -166,6 +166,11 @@ skia_image->refColorSpace()); } +SkImageInfo GetSkImageInfo(const scoped_refptr<StaticBitmapImage>& image) { + return GetSkImageInfo(image->PaintImageForCurrentFrame().GetSkImage()); +} + +// This function results in a readback due to using SkImage::readPixels(). scoped_refptr<Uint8Array> CopyImageData( const scoped_refptr<StaticBitmapImage>& input, const SkImageInfo& info) { @@ -217,27 +222,24 @@ SkImage::MakeFromRaster(pixmap, freePixels, pixels)); } -scoped_refptr<StaticBitmapImage> NewImageFromRaster( - const SkImageInfo& info, - std::unique_ptr<uint8_t[]>& image_pixels) { - SkPixmap pixmap(info, image_pixels.get(), info.minRowBytes()); - return StaticBitmapImage::Create(SkImage::MakeRasterCopy(pixmap)); +static inline bool ShouldAvoidPremul( + const ImageBitmap::ParsedOptions& options) { + return options.source_is_unpremul && !options.premultiply_alpha; } scoped_refptr<StaticBitmapImage> FlipImageVertically( scoped_refptr<StaticBitmapImage> input, const ImageBitmap::ParsedOptions& parsed_options) { sk_sp<SkImage> image = input->PaintImageForCurrentFrame().GetSkImage(); - // If image is unpremul and premultiply alpha is none, we have to avoid - // SkSurface code path, which only supports premul. This code path may result - // in a GPU readback if |input| is texture backed since CopyImageData() uses - // SkImage::readPixels() to extract the pixels from SkImage. - if (image->alphaType() == kUnpremul_SkAlphaType && - !parsed_options.premultiply_alpha) { + + if (ShouldAvoidPremul(parsed_options)) { + // Unpremul code path may result in a GPU readback if |input| is texture + // backed since CopyImageData() uses SkImage::readPixels() to extract the + // pixels from SkImage. scoped_refptr<Uint8Array> image_pixels = CopyImageData(input); if (!image_pixels) return nullptr; - SkImageInfo info = GetSkImageInfo(input.get()); + SkImageInfo info = GetSkImageInfo(input); unsigned image_row_bytes = info.width() * info.bytesPerPixel(); for (int i = 0; i < info.height() / 2; i++) { unsigned top_first_element = i * image_row_bytes; @@ -250,7 +252,8 @@ return NewImageFromRaster(info, std::move(image_pixels)); } - // Otherwise, we can use Skia to flip the image by drawing it on a surface. + // Since we are allowed to premul the input image if needed, we can use Skia + // to flip the image by drawing it on a surface. sk_sp<SkSurface> surface = SkSurface::MakeRaster(GetSkImageInfo(input)); if (!surface) return nullptr; @@ -258,69 +261,207 @@ canvas->scale(1, -1); canvas->translate(0, -input->height()); canvas->drawImage(image.get(), 0, 0); - return StaticBitmapImage::Create(surface->makeImageSnapshot()); + return StaticBitmapImage::Create(surface->makeImageSnapshot(), + input->ContextProviderWrapper()); } scoped_refptr<StaticBitmapImage> GetImageWithAlphaDisposition( scoped_refptr<StaticBitmapImage>&& image, AlphaDisposition alpha_disposition) { - SkAlphaType alpha_type = kPremul_SkAlphaType; - if (alpha_disposition == kDontPremultiplyAlpha) - alpha_type = kUnpremul_SkAlphaType; + SkAlphaType alpha_type = (alpha_disposition == kPremultiplyAlpha) + ? kPremul_SkAlphaType + : kUnpremul_SkAlphaType; sk_sp<SkImage> skia_image = image->PaintImageForCurrentFrame().GetSkImage(); if (skia_image->alphaType() == alpha_type) return image; SkImageInfo info = GetSkImageInfo(image.get()); info = info.makeAlphaType(alpha_type); - scoped_refptr<Uint8Array> dst_pixels = - CopyImageData(image, info.makeColorSpace(nullptr)); - if (!dst_pixels) + + // For premul to unpremul, we have to readback the pixels. + if (alpha_type == kUnpremul_SkAlphaType || + (image->width() * image->height() < 16384)) { + // Set the color space of the ImageInfo to nullptr to unpremul in gamma + // encoded space + scoped_refptr<Uint8Array> dst_pixels = + CopyImageData(image, info.makeColorSpace(nullptr)); + if (!dst_pixels) + return nullptr; + return NewImageFromRaster(info, std::move(dst_pixels)); + } + + // For unpremul to premul, we can either readback the pixels or draw onto a + // surface. As shown in + // https://fiddle.skia.org/c/1ec3c61ed08f7863d43b9f49ab120a0a, drawing on a + // surface and getting a snapshot is slower if the image is small. Therefore, + // for small images (< 128x128 pixels), we still do read back. + + // Draw on a surface. Avoid sRGB gamma transfer curve. + if (SkColorSpace::Equals(info.colorSpace(), SkColorSpace::MakeSRGB().get())) + info = info.makeColorSpace(nullptr); + sk_sp<SkSurface> surface = SkSurface::MakeRaster(info); + if (!surface) return nullptr; - return NewImageFromRaster(info, std::move(dst_pixels)); + SkPaint paint; + paint.setBlendMode(SkBlendMode::kSrc); + surface->getCanvas()->drawImage(skia_image.get(), 0, 0, &paint); + return StaticBitmapImage::Create(surface->makeImageSnapshot(), + image->ContextProviderWrapper()); } -scoped_refptr<StaticBitmapImage> ScaleImage( - scoped_refptr<StaticBitmapImage>&& image, - unsigned resize_width, - unsigned resize_height, - SkFilterQuality resize_quality) { - auto sk_image = image->PaintImageForCurrentFrame().GetSkImage(); - // SkImage::scalePixels() only works in premul. If the input is unpremul, we - // convert it to premul. - bool converted_to_premul = false; - if (sk_image->alphaType() == kUnpremul_SkAlphaType) { - image = GetImageWithAlphaDisposition(std::move(image), kPremultiplyAlpha); - sk_image = image->PaintImageForCurrentFrame().GetSkImage(); - if (!sk_image.get()) - return nullptr; - converted_to_premul = true; - } +// Resizes an SkImage using scalePixels(). This code path should not be used if +// source image is not premul and premul is not allowed and the requested filter +// quality is high. +sk_sp<SkImage> ScaleSkImage(sk_sp<SkImage> image, + const ImageBitmap::ParsedOptions& parsed_options, + AlphaDisposition alpha_disposition) { auto image_info = GetSkImageInfo(image); + DCHECK(image_info.alphaType() == kPremul_SkAlphaType || + !ShouldAvoidPremul(parsed_options) || + parsed_options.resize_quality != kHigh_SkFilterQuality); // Avoid sRGB transfer function by setting the color space to nullptr. if (SkColorSpace::Equals(image_info.colorSpace(), SkColorSpace::MakeSRGB().get())) image_info = image_info.makeColorSpace(nullptr); - SkImageInfo resized_info = image_info.makeWH(resize_width, resize_height); - auto resized_data = - SkData::MakeUninitialized(resized_info.computeMinByteSize()); - if (!resized_data) + + // Premul if needed + if (alpha_disposition == kPremultiplyAlpha && + image_info.alphaType() == kUnpremul_SkAlphaType) { + image_info = image_info.makeAlphaType(kPremul_SkAlphaType); + sk_sp<SkSurface> surface = SkSurface::MakeRaster(image_info); + if (!surface) + return nullptr; + SkPaint paint; + paint.setBlendMode(SkBlendMode::kSrc); + surface->getCanvas()->drawImage(image.get(), 0, 0, &paint); + image = surface->makeImageSnapshot(); + } + + SkImageInfo resized_info = image_info.makeWH(parsed_options.resize_width, + parsed_options.resize_height); + scoped_refptr<ArrayBuffer> resized_buffer = + ArrayBuffer::CreateOrNull(resized_info.computeMinByteSize(), 1); + if (!resized_buffer) return nullptr; - SkPixmap resized_pixmap(resized_info, resized_data->writable_data(), + scoped_refptr<Uint8Array> resized_pixels = Uint8Array::Create( + std::move(resized_buffer), 0, resized_info.computeMinByteSize()); + if (!resized_pixels) + return nullptr; + SkPixmap resized_pixmap(resized_info, resized_pixels->Data(), resized_info.minRowBytes()); - sk_image->scalePixels(resized_pixmap, resize_quality); + image->scalePixels(resized_pixmap, parsed_options.resize_quality); // Tag the resized Pixmap with the correct color space. resized_pixmap.setColorSpace(GetSkImageInfo(image).refColorSpace()); - auto resized_sk_image = SkImage::MakeRasterCopy(resized_pixmap); - scoped_refptr<StaticBitmapImage> resized_image = StaticBitmapImage::Create( - resized_sk_image, image->ContextProviderWrapper()); - // If the source image was unpremul, unpremul the resized image. - if (converted_to_premul) { - resized_image = GetImageWithAlphaDisposition(std::move(resized_image), - kDontPremultiplyAlpha); + Uint8Array* pixels = resized_pixels.get(); + if (pixels) { + pixels->AddRef(); + resized_pixels = nullptr; } - return resized_image; + return SkImage::MakeFromRaster(resized_pixmap, freePixels, pixels); +} + +scoped_refptr<StaticBitmapImage> ScaleImage( + scoped_refptr<StaticBitmapImage>&& image, + const ImageBitmap::ParsedOptions& parsed_options) { + // Use ScaleSkImage() to resize the image unless the image is unpremul and + // premul code path is not allowed and the filter quality is high. + auto image_info = GetSkImageInfo(image); + if (image_info.alphaType() == kPremul_SkAlphaType || + !ShouldAvoidPremul(parsed_options) || + parsed_options.resize_quality != kHigh_SkFilterQuality) { + auto sk_image = image->PaintImageForCurrentFrame().GetSkImage(); + AlphaDisposition alpha_disposition = kDontPremultiplyAlpha; + if (image_info.alphaType() == kUnpremul_SkAlphaType && + !ShouldAvoidPremul(parsed_options)) + alpha_disposition = kPremultiplyAlpha; + auto resized_sk_image = + ScaleSkImage(sk_image, parsed_options, alpha_disposition); + return StaticBitmapImage::Create(resized_sk_image, + image->ContextProviderWrapper()); + } + + // If source image is unpremul, premul code path is not allowed, and the + // filter quality is high, we cannot use SkImage::scalePixels(), and thus + // ScaleSkImage(), as Skia clamps color channels to alpha in this case. + // Instead, we scale color channels and alpha channel separately: RGBA -> + // RGB/255 and A/255,255,255, scale, merge. + SkScalar set_alpha_255[] = {1, 0, 0, 0, 0, // copy red channel + 0, 1, 0, 0, 0, // copy green channel + 0, 0, 1, 0, 0, // copy blue channel + 0, 0, 0, 0, 255}; // set alpha to 255 + auto color_filter_set_alpha_255 = + SkColorFilter::MakeMatrixFilterRowMajor255(set_alpha_255); + auto image_filter_set_alpha_255 = SkColorFilterImageFilter::Make( + std::move(color_filter_set_alpha_255), nullptr, nullptr); + + SkScalar copy_alpha_to_red[] = {0, 0, 0, 1, 0, // copy alpha to red + 0, 0, 0, 0, 0, // set green to zero + 0, 0, 0, 0, 0, // set blue to zero + 0, 0, 0, 0, 255}; // set alpha to 255 + auto color_filter_copy_alpha_to_red = + SkColorFilter::MakeMatrixFilterRowMajor255(copy_alpha_to_red); + auto image_filter_copy_alpha_to_red = SkColorFilterImageFilter::Make( + std::move(color_filter_copy_alpha_to_red), nullptr, nullptr); + + // separate RGBA to RGB/255 and A,0,0/255 + SkIRect subset; + SkIPoint offset; + auto sk_image = image->PaintImageForCurrentFrame().GetSkImage(); + auto rgb_image = sk_image->makeWithFilter( + image_filter_set_alpha_255.get(), sk_image->bounds(), sk_image->bounds(), + &subset, &offset); + auto alpha_image = sk_image->makeWithFilter( + image_filter_copy_alpha_to_red.get(), sk_image->bounds(), + sk_image->bounds(), &subset, &offset); + + // resize + auto resized_rgb_image = + ScaleSkImage(rgb_image, parsed_options, kDontPremultiplyAlpha); + auto resized_alpha_image = + ScaleSkImage(alpha_image, parsed_options, kDontPremultiplyAlpha); + + // Merge two resized rgb and alpha SkImages together. + // A better solution would be using SkImageFilter and SkBlendMode to merge + // the images: convert RGB/255 to RGB/0, convert A,0,0/255 to 0,0,0/A, merge + // using kSrc and kLighten blend modes. Unfortunately, this doesn't work as + // SkImageFilter clamps color channels to zero when setting alpha to zero. + // Therefore, we use a pixmap here. + scoped_refptr<Uint8Array> rgb_data = + CopyImageData(StaticBitmapImage::Create(resized_rgb_image)); + scoped_refptr<Uint8Array> alpha_data = + CopyImageData(StaticBitmapImage::Create(resized_alpha_image)); + SkImageInfo resized_image_info = GetSkImageInfo(resized_rgb_image); + if (resized_image_info.colorType() == kRGBA_F16_SkColorType) { + uint16_t* rgb_data_iter = static_cast<uint16_t*>((void*)(rgb_data->Data())); + uint16_t* alpha_data_iter = + static_cast<uint16_t*>((void*)(alpha_data->Data())); + for (int i = 0; + i < resized_image_info.width() * resized_image_info.height(); i++) + *(rgb_data_iter + i * 4 + 3) = *(alpha_data_iter + i * 4); + } else { + uint8_t* rgb_data_iter = static_cast<uint8_t*>(rgb_data->Data()); + uint8_t* alpha_data_iter = static_cast<uint8_t*>(alpha_data->Data()); + int red_channel_locator = + (kN32_SkColorType == kRGBA_8888_SkColorType) ? 0 : 2; + for (int i = 0; + i < resized_image_info.width() * resized_image_info.height(); i++) { + *(rgb_data_iter + i * 4 + 3) = + *(alpha_data_iter + i * 4 + red_channel_locator); + } + } + + SkImageInfo resized_unpremul_info = + resized_image_info.makeAlphaType(kUnpremul_SkAlphaType); + SkPixmap pixmap(resized_unpremul_info, rgb_data->Data(), + resized_unpremul_info.minRowBytes()); + Uint8Array* pixels = rgb_data.get(); + if (pixels) { + pixels->AddRef(); + rgb_data = nullptr; + } + return StaticBitmapImage::Create( + SkImage::MakeFromRaster(pixmap, freePixels, pixels)); } scoped_refptr<StaticBitmapImage> ApplyColorSpaceConversion( @@ -399,6 +540,17 @@ skia_image = ImageBitmap::GetSkImageFromDecoder(std::move(decoder)); if (!skia_image) return nullptr; + + // In the case where the source image is lazy-decoded, image_ may not be in + // a decoded state, we trigger it here. + SkPixmap pixmap; + if (!skia_image->isTextureBacked() && !skia_image->peekPixels(&pixmap)) { + sk_sp<SkSurface> surface = + SkSurface::MakeRaster(GetSkImageInfo(StaticBitmapImage::Create( + skia_image, image->ContextProviderWrapper()))); + surface->getCanvas()->drawImage(skia_image.get(), 0, 0); + skia_image = surface->makeImageSnapshot(); + } } if (src_rect != img_rect) @@ -413,32 +565,41 @@ (parsed_options.resize_width * parsed_options.resize_height < result->Size().Area()); bool up_scaling = parsed_options.should_scale_input && !down_scaling; + // resize if down-scaling if (down_scaling) { - result = - ScaleImage(std::move(result), parsed_options.resize_width, - parsed_options.resize_height, parsed_options.resize_quality); + result = ScaleImage(std::move(result), parsed_options); + if (!result) + return nullptr; } // flip if needed - if (parsed_options.flip_y) + if (parsed_options.flip_y) { result = FlipImageVertically(std::move(result), parsed_options); + if (!result) + return nullptr; + } // color convert if needed - if (parsed_options.has_color_space_conversion) + if (parsed_options.has_color_space_conversion) { result = ApplyColorSpaceConversion(std::move(result), parsed_options); + if (!result) + return nullptr; + } + + // resize if up-scaling + if (up_scaling) { + result = ScaleImage(std::move(result), parsed_options); + if (!result) + return nullptr; + } // premultiply / unpremultiply if needed result = GetImageWithAlphaDisposition(std::move(result), parsed_options.premultiply_alpha ? kPremultiplyAlpha : kDontPremultiplyAlpha); - // resize if up-scaling - if (up_scaling) { - result = - ScaleImage(std::move(result), parsed_options.resize_width, - parsed_options.resize_height, parsed_options.resize_quality); - } + return result; } @@ -449,6 +610,9 @@ scoped_refptr<Image> input = image->CachedImage()->GetImage(); ParsedOptions parsed_options = ParseOptions(options, crop_rect, image->BitmapSourceSize()); + parsed_options.source_is_unpremul = + (input->PaintImageForCurrentFrame().GetSkImage()->alphaType() == + kUnpremul_SkAlphaType); if (DstBufferSizeHasOverflow(parsed_options)) return; @@ -457,27 +621,6 @@ if (!image_) return; - // In the case where the source image is lazy-decoded, m_image may not be in - // a decoded state, we trigger it here. - sk_sp<SkImage> sk_image = image_->PaintImageForCurrentFrame().GetSkImage(); - SkPixmap pixmap; - if (!sk_image->isTextureBacked() && !sk_image->peekPixels(&pixmap)) { - sk_sp<SkColorSpace> dst_color_space = - parsed_options.color_params.GetSkColorSpace(); - SkColorType dst_color_type = parsed_options.color_params.GetSkColorType(); - SkImageInfo image_info = - SkImageInfo::Make(sk_image->width(), sk_image->height(), dst_color_type, - kPremul_SkAlphaType, dst_color_space); - sk_sp<SkSurface> surface = SkSurface::MakeRaster(image_info); - surface->getCanvas()->drawImage(sk_image, 0, 0); - image_ = ApplyColorSpaceConversion( - StaticBitmapImage::Create(surface->makeImageSnapshot(), - input->ContextProviderWrapper()), - parsed_options); - } - if (!image_) - return; - image_->SetOriginClean( !image->WouldTaintOrigin(document->GetSecurityOrigin())); } @@ -586,6 +729,8 @@ const ImageBitmapOptions& options) { ParsedOptions parsed_options = ParseOptions(options, crop_rect, data->BitmapSourceSize()); + // ImageData is always unpremul. + parsed_options.source_is_unpremul = true; if (DstBufferSizeHasOverflow(parsed_options)) return; @@ -601,19 +746,43 @@ return; } - int byte_length = - src_rect.Size().Area() * parsed_options.color_params.BytesPerPixel(); - std::unique_ptr<uint8_t[]> image_pixels(new uint8_t[byte_length]); + // Copy / color convert the pixels + scoped_refptr<ArrayBuffer> pixels_buffer = ArrayBuffer::CreateOrNull( + src_rect.Size().Area(), parsed_options.color_params.BytesPerPixel()); + if (!pixels_buffer) + return; + unsigned byte_length = pixels_buffer->ByteLength(); + scoped_refptr<Uint8Array> image_pixels = + Uint8Array::Create(std::move(pixels_buffer), 0, byte_length); + if (!image_pixels) + return; if (!data->ImageDataInCanvasColorSettings( parsed_options.color_params.ColorSpace(), - parsed_options.color_params.PixelFormat(), image_pixels, + parsed_options.color_params.PixelFormat(), image_pixels->Data(), kN32ColorType, &src_rect)) return; + + // Create Image object SkImageInfo info = SkImageInfo::Make( src_rect.Width(), src_rect.Height(), parsed_options.color_params.GetSkColorType(), kUnpremul_SkAlphaType, parsed_options.color_params.GetSkColorSpaceForSkSurfaces()); - image_ = NewImageFromRaster(info, image_pixels); + image_ = NewImageFromRaster(info, std::move(image_pixels)); + if (!image_) + return; + + // down-scaling has higher priority than other tasks, up-scaling has lower. + bool down_scaling = + parsed_options.should_scale_input && + (parsed_options.resize_width * parsed_options.resize_height < + image_->Size().Area()); + bool up_scaling = parsed_options.should_scale_input && !down_scaling; + + // resize if down-scaling + if (down_scaling) + image_ = ScaleImage(std::move(image_), parsed_options); + if (!image_) + return; // premultiply if needed if (parsed_options.premultiply_alpha) @@ -624,15 +793,12 @@ // flip if needed if (parsed_options.flip_y) image_ = FlipImageVertically(std::move(image_), parsed_options); + if (!image_) + return; - // resize if needed - if (parsed_options.should_scale_input) { - image_ = - ScaleImage(std::move(image_), parsed_options.resize_width, - parsed_options.resize_height, parsed_options.resize_quality); - if (!image_) - return; - } + // resize if up-scaling + if (up_scaling) + image_ = ScaleImage(std::move(image_), parsed_options); } ImageBitmap::ImageBitmap(ImageBitmap* bitmap, @@ -643,6 +809,9 @@ return; ParsedOptions parsed_options = ParseOptions(options, crop_rect, input->Size()); + parsed_options.source_is_unpremul = + (input->PaintImageForCurrentFrame().GetSkImage()->alphaType() == + kUnpremul_SkAlphaType); if (DstBufferSizeHasOverflow(parsed_options)) return; @@ -660,6 +829,9 @@ bool origin_clean = image->OriginClean(); ParsedOptions parsed_options = ParseOptions(options, crop_rect, image->Size()); + parsed_options.source_is_unpremul = + (image->PaintImageForCurrentFrame().GetSkImage()->alphaType() == + kUnpremul_SkAlphaType); if (DstBufferSizeHasOverflow(parsed_options)) return;
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.h b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.h index d6e3091e..c13637b 100644 --- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.h +++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.h
@@ -134,6 +134,7 @@ bool premultiply_alpha = true; bool should_scale_input = false; bool has_color_space_conversion = false; + bool source_is_unpremul = false; unsigned resize_width = 0; unsigned resize_height = 0; IntRect crop_rect;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp index de193abc..cb393ae 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -108,8 +108,8 @@ const String& old_text, const String& longhand, const String& new_value) { - StyleSheetContents* style_sheet_contents = - StyleSheetContents::Create(StrictCSSParserContext()); + StyleSheetContents* style_sheet_contents = StyleSheetContents::Create( + StrictCSSParserContext(document->SecureContextMode())); String text = " div { " + shorthand + ": " + old_text + "; }"; CSSParser::ParseSheet(CSSParserContext::Create(*document), style_sheet_contents, text); @@ -118,8 +118,8 @@ CSSStyleRule* rule = ToCSSStyleRule(style_sheet->item(0)); CSSStyleDeclaration* style = rule->style(); DummyExceptionStateForTesting exception_state; - style->setProperty(longhand, new_value, style->getPropertyPriority(longhand), - exception_state); + style->setProperty(document, longhand, new_value, + style->getPropertyPriority(longhand), exception_state); return style->getPropertyValue(shorthand); }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp index 1217247..3993f90 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -598,9 +598,12 @@ Maybe<String> referrer, Maybe<String> transitionType, String* out_frame_id, + Maybe<String>* out_loader_id, Maybe<String>* errorText) { LocalFrame* frame = inspected_frames_->Root(); *out_frame_id = IdentifiersFactory::FrameId(frame); + DocumentLoader* loader = frame->Loader().GetDocumentLoader(); + *out_loader_id = IdentifiersFactory::LoaderId(loader); return Response::OK(); } @@ -937,7 +940,8 @@ const AtomicString& window_name, const WebWindowFeatures& window_features, bool user_gesture) { - GetFrontend()->windowOpen(document->CompleteURL(url).GetString(), window_name, + KURL completed_url = url.IsEmpty() ? BlankURL() : document->CompleteURL(url); + GetFrontend()->windowOpen(completed_url.GetString(), window_name, GetEnabledWindowFeatures(window_features), user_gesture); }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h index 7d5fc2b..46f7be7 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h
@@ -125,6 +125,7 @@ Maybe<String> referrer, Maybe<String> transitionType, String* frame_id, + Maybe<String>* loader_id, Maybe<String>* errorText) override; protocol::Response stopLoading() override; protocol::Response setAdBlockingEnabled(bool) override;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp index dd9ef86e..99aa8e2d 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp
@@ -65,8 +65,9 @@ namespace { static const CSSParserContext* ParserContextForDocument(Document* document) { + // Fallback to an insecure context parser if no document is present. return document ? CSSParserContext::Create(*document) - : StrictCSSParserContext(); + : StrictCSSParserContext(SecureContextMode::kInsecureContext); } String FindMagicComment(const String& content, const String& name) { @@ -343,7 +344,7 @@ bool VerifyRuleText(Document* document, const String& rule_text) { DEFINE_STATIC_LOCAL(String, bogus_property_name, ("-webkit-boguz-propertee")); StyleSheetContents* style_sheet = - StyleSheetContents::Create(StrictCSSParserContext()); + StyleSheetContents::Create(ParserContextForDocument(document)); CSSRuleSourceDataList* source_data = new CSSRuleSourceDataList(); String text = rule_text + " div { " + bogus_property_name + ": none; }"; StyleSheetHandler handler(text, document, source_data); @@ -380,7 +381,7 @@ bool VerifyKeyframeKeyText(Document* document, const String& key_text) { StyleSheetContents* style_sheet = - StyleSheetContents::Create(StrictCSSParserContext()); + StyleSheetContents::Create(ParserContextForDocument(document)); CSSRuleSourceDataList* source_data = new CSSRuleSourceDataList(); String text = "@keyframes boguzAnim { " + key_text + " { -webkit-boguz-propertee : none; } }"; @@ -410,7 +411,7 @@ bool VerifySelectorText(Document* document, const String& selector_text) { DEFINE_STATIC_LOCAL(String, bogus_property_name, ("-webkit-boguz-propertee")); StyleSheetContents* style_sheet = - StyleSheetContents::Create(StrictCSSParserContext()); + StyleSheetContents::Create(ParserContextForDocument(document)); CSSRuleSourceDataList* source_data = new CSSRuleSourceDataList(); String text = selector_text + " { " + bogus_property_name + ": none; }"; StyleSheetHandler handler(text, document, source_data); @@ -439,7 +440,7 @@ bool VerifyMediaText(Document* document, const String& media_text) { DEFINE_STATIC_LOCAL(String, bogus_property_name, ("-webkit-boguz-propertee")); StyleSheetContents* style_sheet = - StyleSheetContents::Create(StrictCSSParserContext()); + StyleSheetContents::Create(ParserContextForDocument(document)); CSSRuleSourceDataList* source_data = new CSSRuleSourceDataList(); String text = "@media " + media_text + " { div { " + bogus_property_name + ": none; } }"; @@ -1037,7 +1038,7 @@ } CSSStyleRule* style_rule = InspectorCSSAgent::AsCSSStyleRule(rule); - style_rule->setSelectorText(text); + style_rule->setSelectorText(page_style_sheet_->OwnerDocument(), text); ReplaceText(source_data->rule_header_range, text, new_range, old_text); OnStyleSheetTextChanged(); @@ -1115,7 +1116,7 @@ style = ToCSSStyleRule(rule)->style(); else if (rule->type() == CSSRule::kKeyframeRule) style = ToCSSKeyframeRule(rule)->style(); - style->setCSSText(text, exception_state); + style->setCSSText(page_style_sheet_->OwnerDocument(), text, exception_state); ReplaceText(source_data->rule_body_range, text, new_range, old_text); OnStyleSheetTextChanged(); @@ -1208,7 +1209,8 @@ break; } - media_rule->insertRule(rule_text, index, exception_state); + media_rule->insertRule(page_style_sheet_->OwnerDocument(), rule_text, index, + exception_state); CSSRule* rule = media_rule->Item(index); CSSStyleRule* style_rule = InspectorCSSAgent::AsCSSStyleRule(rule); if (!style_rule) {
diff --git a/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp b/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp index 8e3df75b0..49c1bc42 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp
@@ -1073,6 +1073,12 @@ consume_options == v8::ScriptCompiler::kConsumeCodeCache); } +InspectorCompileScriptEvent::V8CacheResult::V8CacheResult( + Optional<ProduceResult> produce_result, + Optional<ConsumeResult> consume_result) + : produce_result(std::move(produce_result)), + consume_result(std::move(consume_result)) {} + std::unique_ptr<TracedValue> InspectorCompileScriptEvent::Data( const String& url, const TextPosition& text_position,
diff --git a/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.h b/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.h index a7ce435..22dbeee 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.h +++ b/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.h
@@ -410,6 +410,9 @@ int cache_size; bool rejected; }; + V8CacheResult() {} + V8CacheResult(Optional<ProduceResult>, Optional<ConsumeResult>); + Optional<ProduceResult> produce_result; Optional<ConsumeResult> consume_result; };
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index 0602f26..a89bef3 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -355,6 +355,7 @@ ], "returns": [ { "name": "frameId", "$ref": "FrameId", "description": "Frame id that has navigated (or failed to navigate)" }, + { "name": "loaderId", "$ref": "Network.LoaderId", "optional": true, "description": "Loader identifier.", "experimental": true }, { "name": "errorText", "type": "string", "optional": true, "description": "User friendly error message, present if and only if navigation has failed." } ], "description": "Navigates current page to the given URL."
diff --git a/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.cpp b/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.cpp index 656075bc..b7b4cc6f 100644 --- a/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.cpp +++ b/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.cpp
@@ -45,9 +45,11 @@ void ElementIntersectionObserverData::ActivateValidIntersectionObservers( Node& node) { for (auto& observer : intersection_observers_) { - observer->TrackingDocument() - .EnsureIntersectionObserverController() - .AddTrackedObserver(*observer); + Document* document = observer->TrackingDocument(); + if (!document) + continue; + document->EnsureIntersectionObserverController().AddTrackedObserver( + *observer); } for (auto& observation : intersection_observations_) observation.value->UpdateShouldReportRootBoundsAfterDomChange();
diff --git a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp index 5660c043..06ef996 100644 --- a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp +++ b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp
@@ -214,8 +214,8 @@ } if (root) root->EnsureIntersectionObserverData().AddObserver(*this); - TrackingDocument().EnsureIntersectionObserverController().AddTrackedObserver( - *this); + if (Document* document = TrackingDocument()) + document->EnsureIntersectionObserverController().AddTrackedObserver(*this); } void IntersectionObserver::ClearWeakMembers(Visitor* visitor) { @@ -230,13 +230,14 @@ return RootIsImplicit() || root(); } -Document& IntersectionObserver::TrackingDocument() const { +Document* IntersectionObserver::TrackingDocument() const { if (RootIsImplicit()) { - DCHECK(delegate_->GetExecutionContext()); - return *ToDocument(delegate_->GetExecutionContext()); + if (!delegate_->GetExecutionContext()) + return nullptr; + return ToDocument(delegate_->GetExecutionContext()); } DCHECK(root()); - return root()->GetDocument(); + return &root()->GetDocument(); } void IntersectionObserver::observe(Element* target,
diff --git a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.h b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.h index 0757e34..975aa19 100644 --- a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.h +++ b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.h
@@ -66,7 +66,8 @@ // This is the document which is responsible for running // computeIntersectionObservations at frame generation time. - Document& TrackingDocument() const; + // This can return nullptr when no tracking document is available. + Document* TrackingDocument() const; const Length& TopMargin() const { return top_margin_; } const Length& RightMargin() const { return right_margin_; }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp index cf3024d4..3e754f94 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
@@ -422,8 +422,9 @@ if (needs_scroll_anchoring) GetScrollableArea()->GetScrollAnchor()->NotifyBeforeLayout(); - // Table cells call layoutBlock directly, so don't add any logic here. Put - // code into layoutBlock(). + // Table cells call UpdateBlockLayout directly, as does + // PaintLayerScrollableArea for nested scrollbar layouts. Most logic should be + // in UpdateBlockLayout instead of UpdateLayout. UpdateBlockLayout(false); // It's safe to check for control clip here, since controls can never be table
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockTest.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockTest.cpp index 82960c91..451d1425 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockTest.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlockTest.cpp
@@ -45,7 +45,7 @@ 150 - list_box->VerticalScrollbarWidth()); DummyExceptionStateForTesting exception_state; - list_element->style()->setCSSText("width:150px;height:100px;", + list_element->style()->setCSSText(&GetDocument(), "width:150px;height:100px;", exception_state); ASSERT_FALSE(exception_state.HadException()); GetDocument().View()->UpdateAllLifecyclePhases();
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp index b506d8e..6458aef 100644 --- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
@@ -1638,6 +1638,8 @@ bool LayoutGrid::IsBaselineAlignmentForChild(const LayoutBox& child, GridAxis baseline_axis) const { + if (child.IsOutOfFlowPositioned()) + return false; ItemPosition align = SelfAlignmentForChild(baseline_axis, child).GetPosition(); bool has_auto_margins = baseline_axis == kGridColumnAxis
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp index 22e2b166..b381a56 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -158,8 +158,8 @@ void* LayoutObject::operator new(size_t sz) { DCHECK(IsMainThread()); - return WTF::PartitionAlloc(WTF::Partitions::LayoutPartition(), sz, - WTF_HEAP_PROFILER_TYPE_NAME(LayoutObject)); + return WTF::Partitions::LayoutPartition()->Alloc( + sz, WTF_HEAP_PROFILER_TYPE_NAME(LayoutObject)); } void LayoutObject::operator delete(void* ptr) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.cpp b/third_party/WebKit/Source/core/layout/LayoutView.cpp index 103dbc8..560a002 100644 --- a/third_party/WebKit/Source/core/layout/LayoutView.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutView.cpp
@@ -218,16 +218,6 @@ return !owner->IsDisplayNone(); } -void LayoutView::LayoutContent() { - DCHECK(NeedsLayout()); - - LayoutBlockFlow::UpdateLayout(); - -#if DCHECK_IS_ON() - CheckLayoutState(); -#endif -} - #if DCHECK_IS_ON() void LayoutView::CheckLayoutState() { DCHECK(!layout_state_->Next()); @@ -252,6 +242,42 @@ } } +void LayoutView::UpdateBlockLayout(bool relayout_children) { + SubtreeLayoutScope layout_scope(*this); + + // Use calcWidth/Height to get the new width/height, since this will take the + // full page zoom factor into account. + relayout_children |= + !ShouldUsePrintingLayout() && + (!frame_view_ || LogicalWidth() != ViewLogicalWidthForBoxSizing() || + LogicalHeight() != ViewLogicalHeightForBoxSizing()); + + if (relayout_children) { + layout_scope.SetChildNeedsLayout(this); + for (LayoutObject* child = FirstChild(); child; + child = child->NextSibling()) { + if (child->IsSVGRoot()) + continue; + + if ((child->IsBox() && ToLayoutBox(child)->HasRelativeLogicalHeight()) || + child->Style()->LogicalHeight().IsPercentOrCalc() || + child->Style()->LogicalMinHeight().IsPercentOrCalc() || + child->Style()->LogicalMaxHeight().IsPercentOrCalc()) + layout_scope.SetChildNeedsLayout(child); + } + + if (GetDocument().SvgExtensions()) + GetDocument() + .AccessSVGExtensions() + .InvalidateSVGRootsWithRelativeLengthDescendents(&layout_scope); + } + + if (!NeedsLayout()) + return; + + LayoutBlockFlow::UpdateBlockLayout(relayout_children); +} + void LayoutView::UpdateLayout() { if (!GetDocument().Paginated()) SetPageLogicalHeight(LayoutUnit()); @@ -278,42 +304,10 @@ pagination_state_changed_ = true; } - SubtreeLayoutScope layout_scope(*this); - - // Use calcWidth/Height to get the new width/height, since this will take the - // full page zoom factor into account. - bool relayout_children = - !ShouldUsePrintingLayout() && - (!frame_view_ || LogicalWidth() != ViewLogicalWidthForBoxSizing() || - LogicalHeight() != ViewLogicalHeightForBoxSizing()); - - if (relayout_children) { - layout_scope.SetChildNeedsLayout(this); - for (LayoutObject* child = FirstChild(); child; - child = child->NextSibling()) { - if (child->IsSVGRoot()) - continue; - - if ((child->IsBox() && ToLayoutBox(child)->HasRelativeLogicalHeight()) || - child->Style()->LogicalHeight().IsPercentOrCalc() || - child->Style()->LogicalMinHeight().IsPercentOrCalc() || - child->Style()->LogicalMaxHeight().IsPercentOrCalc()) - layout_scope.SetChildNeedsLayout(child); - } - - if (GetDocument().SvgExtensions()) - GetDocument() - .AccessSVGExtensions() - .InvalidateSVGRootsWithRelativeLengthDescendents(&layout_scope); - } - DCHECK(!layout_state_); - if (!NeedsLayout()) - return; - LayoutState root_layout_state(*this); - LayoutContent(); + LayoutBlockFlow::UpdateLayout(); #if DCHECK_IS_ON() CheckLayoutState();
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.h b/third_party/WebKit/Source/core/layout/LayoutView.h index d0f85307..f0148d44 100644 --- a/third_party/WebKit/Source/core/layout/LayoutView.h +++ b/third_party/WebKit/Source/core/layout/LayoutView.h
@@ -264,7 +264,8 @@ bool CanHaveChildren() const override; - void LayoutContent(); + void UpdateBlockLayout(bool relayout_children) override; + #if DCHECK_IS_ON() void CheckLayoutState(); #endif
diff --git a/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp b/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp index f48ef85..8eaf784 100644 --- a/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp +++ b/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp
@@ -97,11 +97,9 @@ class ScrollbarsTestWithVirtualTimer : public ScrollbarsTest { public: - void TearDown() override { - // The SimTest destructor calls runPendingTasks. This is a problem because - // if there are any repeating tasks, advancing virtual time will cause the - // runloop to busy loop. Disabling virtual time here fixes that. - WebView().Scheduler()->DisableVirtualTimeForTesting(); + void SetUp() override { + ScrollbarsTest::SetUp(); + WebView().Scheduler()->EnableVirtualTime(); } void TimeAdvance() { @@ -141,9 +139,9 @@ WebView().Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); - request.Complete( - "<!DOCTYPE html>" - "<style> body { width: 1600px; height: 1200px; } </style>"); + request.Complete(R"HTML( + <!DOCTYPE html> + <style> body { width: 1600px; height: 1200px; } </style>)HTML"); auto* layout_viewport = GetDocument().View()->LayoutViewportScrollableArea(); Compositor().BeginFrame(); @@ -992,25 +990,26 @@ SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); - request.Complete( - "<!DOCTYPE html>" - "<style type='text/css'>" - "body {" - " height: 10000px;" - " margin: 0;" - "}" - "#d1 {" - " height: 200px;" - " width: 200px;" - " overflow: auto;" - "}" - "#d2 {" - " height: 2000px;" - "}" - "</style>" - "<div id='d1'>" - " <div id='d2'/>" - "</div>"); + request.Complete(R"HTML( + <!DOCTYPE html> + <style type='text/css'> + body { + height: 10000px; + margin: 0; + } + #d1 { + height: 200px; + width: 200px; + overflow: auto; + } + #d2 { + height: 2000px; + } + </style> + <div id='d1'> + <div id='d2'/> + </div> + )HTML"); Compositor().BeginFrame(); @@ -1079,28 +1078,29 @@ SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); - request.Complete( - "<!DOCTYPE html>" - "<style type='text/css'>" - "body {" - " height: 10000px;" - " margin: 0;" - "}" - "#d1 {" - " height: 200px;" - " width: 200px;" - " overflow: auto;" - "}" - "#d2 {" - " height: 2000px;" - "}" - "::-webkit-scrollbar {" - " width: 10px;" - "}" - "</style>" - "<div id='d1'>" - " <div id='d2'/>" - "</div>"); + request.Complete(R"HTML( + <!DOCTYPE html> + <style type='text/css'> + body { + height: 10000px; + margin: 0; + } + #d1 { + height: 200px; + width: 200px; + overflow: auto; + } + #d2 { + height: 2000px; + } + ::-webkit-scrollbar { + width: 10px; + } + </style> + <div id='d1'> + <div id='d2'/> + </div> + )HTML"); Compositor().BeginFrame(); @@ -1164,27 +1164,28 @@ SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); - request.Complete( - "<!DOCTYPE html>" - "<style type='text/css'>" - "#d1 {" - " height: 200px;" - " width: 200px;" - " overflow: auto;" - "}" - "#d2 {" - " height: 2000px;" - "}" - "::-webkit-scrollbar {" - " width: 10px;" - "}" - ".custom::-webkit-scrollbar {" - " width: 5px;" - "}" - "</style>" - "<div id='d1'>" - " <div id='d2'></div>" - "</div>"); + request.Complete(R"HTML( + <!DOCTYPE html> + <style type='text/css'> + #d1 { + height: 200px; + width: 200px; + overflow: auto; + } + #d2 { + height: 2000px; + } + ::-webkit-scrollbar { + width: 10px; + } + .custom::-webkit-scrollbar { + width: 5px; + } + </style> + <div id='d1'> + <div id='d2'></div> + </div> + )HTML"); Compositor().BeginFrame(); @@ -1220,8 +1221,6 @@ #else TEST_P(ScrollbarsTestWithVirtualTimer, TestNonCompositedOverlayScrollbarsFade) { #endif - // Will crash if move EnableVirtualTime before test body. - WebView().Scheduler()->EnableVirtualTime(); TimeAdvance(); constexpr double kMockOverlayFadeOutDelayInSeconds = 5.0; constexpr double kMockOverlayFadeOutDelayMS = @@ -1373,9 +1372,9 @@ WebView().Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); - request.Complete( - "<!DOCTYPE html>" - "<style> body { width: 1000000px; height: 1000000px; } </style>"); + request.Complete(R"HTML( + <!DOCTYPE html> + <style> body { width: 1000000px; height: 1000000px; } </style>)HTML"); ScrollableArea* scrollable_area = GetDocument().View()->LayoutViewportScrollableArea(); @@ -1399,9 +1398,9 @@ WebView().Resize(WebSize(1000, 1000)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); - request.Complete( - "<!DOCTYPE html>" - "<style> body { margin: 0px; height: 10000000px; } </style>"); + request.Complete(R"HTML( + <!DOCTYPE html> + <style> body { margin: 0px; height: 10000000px; } </style>)HTML"); ScrollableArea* scrollable_area = GetDocument().View()->LayoutViewportScrollableArea();
diff --git a/third_party/WebKit/Source/core/layout/line/InlineBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineBox.cpp index 1cad2ef5..a901486 100644 --- a/third_party/WebKit/Source/core/layout/line/InlineBox.cpp +++ b/third_party/WebKit/Source/core/layout/line/InlineBox.cpp
@@ -78,8 +78,8 @@ } void* InlineBox::operator new(size_t sz) { - return WTF::PartitionAlloc(WTF::Partitions::LayoutPartition(), sz, - WTF_HEAP_PROFILER_TYPE_NAME(InlineBox)); + return WTF::Partitions::LayoutPartition()->Alloc( + sz, WTF_HEAP_PROFILER_TYPE_NAME(InlineBox)); } void InlineBox::operator delete(void* ptr) {
diff --git a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp index 06bc222..4208628 100644 --- a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp +++ b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
@@ -1241,6 +1241,10 @@ } logical_layout_overflow.Unite(child_layout_overflow); } else { + if (logical_layout_overflow.IsEmpty()) { + logical_layout_overflow = + LogicalFrameRectIncludingLineHeight(line_top, line_bottom); + } AddReplacedChildOverflow(curr, logical_layout_overflow, logical_visual_overflow); }
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 fcfa107..87750d5 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
@@ -304,11 +304,14 @@ LayoutUnit* position, NGInlineBoxState* box, NGTextFragmentBuilder* text_builder) { + unsigned start_offset = shape_result->StartIndexForResult(); + unsigned end_offset = shape_result->EndIndexForResult(); LayoutUnit inline_size = shape_result->SnappedWidth(); text_builder->SetText(std::move(style), std::move(shape_result), inline_size, box->text_metrics.LineHeight()); scoped_refptr<NGPhysicalTextFragment> text_fragment = - text_builder->ToTextFragment(std::numeric_limits<unsigned>::max(), 0, 0); + text_builder->ToTextFragment(std::numeric_limits<unsigned>::max(), + start_offset, end_offset); line_box_.AddChild(std::move(text_fragment), {*position, box->text_top}); *position += inline_size; }
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.cpp b/third_party/WebKit/Source/core/loader/EmptyClients.cpp index d7c52f96..274f73e3 100644 --- a/third_party/WebKit/Source/core/loader/EmptyClients.cpp +++ b/third_party/WebKit/Source/core/loader/EmptyClients.cpp
@@ -86,8 +86,8 @@ return WebFrameScheduler::FrameType::kSubframe; } WebViewScheduler* GetWebViewScheduler() const override { return nullptr; } - ScopedVirtualTimePauser CreateScopedVirtualTimePauser() { - return ScopedVirtualTimePauser(); + WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser() { + return WebScopedVirtualTimePauser(); } void DidStartProvisionalLoad(bool is_main_frame) override {} void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
diff --git a/third_party/WebKit/Source/core/loader/LinkLoader.cpp b/third_party/WebKit/Source/core/loader/LinkLoader.cpp index 9d263e2a..cb9dfd6 100644 --- a/third_party/WebKit/Source/core/loader/LinkLoader.cpp +++ b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
@@ -47,11 +47,13 @@ #include "core/inspector/ConsoleMessage.h" #include "core/loader/DocumentLoader.h" #include "core/loader/NetworkHintsInterface.h" +#include "core/loader/SubresourceIntegrityHelper.h" #include "core/loader/modulescript/ModuleScriptFetchRequest.h" #include "core/loader/private/PrerenderHandle.h" #include "core/loader/resource/LinkFetchResource.h" #include "platform/Prerender.h" #include "platform/loader/LinkHeader.h" +#include "platform/loader/SubresourceIntegrity.h" #include "platform/loader/fetch/FetchParameters.h" #include "platform/loader/fetch/ResourceClient.h" #include "platform/loader/fetch/ResourceFetcher.h" @@ -400,6 +402,7 @@ const String& as, const String& media, const String& nonce, + const String& integrity, CrossOriginAttributeValue cross_origin, ViewportDescription* viewport_description, ReferrerPolicy referrer_policy, @@ -473,7 +476,13 @@ // Step 8. "Let integrity metadata be the value of the integrity attribute, if // it is specified, or the empty string otherwise." [spec text] - // TODO(ksakamoto): Support integrity attribute. + IntegrityMetadataSet integrity_metadata; + if (!integrity.IsEmpty()) { + SubresourceIntegrity::ReportInfo report_info; + SubresourceIntegrity::ParseIntegrityAttribute(integrity, integrity_metadata, + &report_info); + SubresourceIntegrityHelper::DoReport(document, report_info); + } // Step 9. "Let options be a script fetch options whose cryptographic nonce is // cryptographic nonce, integrity metadata is integrity metadata, parser @@ -481,7 +490,7 @@ // mode." [spec text] ModuleScriptFetchRequest request( href, referrer_policy, - ScriptFetchOptions(nonce, IntegrityMetadataSet(), String(), + ScriptFetchOptions(nonce, integrity_metadata, integrity, kNotParserInserted, credentials_mode)); // Step 10. "Fetch a single module script given url, settings object, @@ -579,9 +588,9 @@ PrefetchIfNeeded(*document, url, rel_attribute, cross_origin, kReferrerPolicyDefault); ModulePreloadIfNeeded(rel_attribute, url, *document, header.As(), - header.Media(), header.Nonce(), cross_origin, - viewport_description, kReferrerPolicyDefault, - nullptr); + header.Media(), header.Nonce(), header.Integrity(), + cross_origin, viewport_description, + kReferrerPolicyDefault, nullptr); } if (rel_attribute.IsServiceWorker()) { UseCounter::Count(&frame, WebFeature::kLinkHeaderServiceWorker); @@ -597,6 +606,7 @@ const String& as, const String& media, const String& nonce, + const String& integrity, ReferrerPolicy referrer_policy, const KURL& href, Document& document, @@ -625,7 +635,8 @@ finish_observer_ = new FinishObserver(this, resource); ModulePreloadIfNeeded(rel_attribute, href, document, as, media, nonce, - cross_origin, nullptr, referrer_policy, this); + integrity, cross_origin, nullptr, referrer_policy, + this); if (const unsigned prerender_rel_types = PrerenderRelTypesFromRelAttribute(rel_attribute, document)) {
diff --git a/third_party/WebKit/Source/core/loader/LinkLoader.h b/third_party/WebKit/Source/core/loader/LinkLoader.h index 5f40848..597e24bb 100644 --- a/third_party/WebKit/Source/core/loader/LinkLoader.h +++ b/third_party/WebKit/Source/core/loader/LinkLoader.h
@@ -74,6 +74,7 @@ const String& as, const String& media, const String& nonce, + const String& integrity, ReferrerPolicy, const KURL&, Document&,
diff --git a/third_party/WebKit/Source/core/loader/LinkLoaderTest.cpp b/third_party/WebKit/Source/core/loader/LinkLoaderTest.cpp index 7c45cd1..eca0c34 100644 --- a/third_party/WebKit/Source/core/loader/LinkLoaderTest.cpp +++ b/third_party/WebKit/Source/core/loader/LinkLoaderTest.cpp
@@ -134,7 +134,8 @@ URLTestHelpers::RegisterMockedErrorURLLoad(href_url); loader->LoadLink(LinkRelAttribute("preload"), kCrossOriginAttributeNotSet, test_case.type, test_case.as, test_case.media, - test_case.nonce, test_case.referrer_policy, href_url, + test_case.nonce, String() /* integrity */, + test_case.referrer_policy, href_url, dummy_page_holder->GetDocument(), NetworkHintsMock()); if (test_case.expecting_load && test_case.priority != kResourceLoadPriorityUnresolved) { @@ -324,6 +325,7 @@ struct ModulePreloadTestParams { const char* href; const char* nonce; + const char* integrity; CrossOriginAttributeValue cross_origin; ReferrerPolicy referrer_policy; bool expecting_load; @@ -331,15 +333,20 @@ }; constexpr ModulePreloadTestParams kModulePreloadTestParams[] = { - {"", nullptr, kCrossOriginAttributeNotSet, kReferrerPolicyDefault, false, + {"", nullptr, nullptr, kCrossOriginAttributeNotSet, kReferrerPolicyDefault, + false, network::mojom::FetchCredentialsMode::kOmit}, + {"http://example.test/cat.js", nullptr, nullptr, + kCrossOriginAttributeNotSet, kReferrerPolicyDefault, true, network::mojom::FetchCredentialsMode::kOmit}, - {"http://example.test/cat.js", nullptr, kCrossOriginAttributeNotSet, - kReferrerPolicyDefault, true, network::mojom::FetchCredentialsMode::kOmit}, - {"http://example.test/cat.js", nullptr, kCrossOriginAttributeAnonymous, - kReferrerPolicyDefault, true, + {"http://example.test/cat.js", nullptr, nullptr, + kCrossOriginAttributeAnonymous, kReferrerPolicyDefault, true, network::mojom::FetchCredentialsMode::kSameOrigin}, - {"http://example.test/cat.js", "nonce", kCrossOriginAttributeNotSet, - kReferrerPolicyNever, true, network::mojom::FetchCredentialsMode::kOmit}}; + {"http://example.test/cat.js", "nonce", nullptr, + kCrossOriginAttributeNotSet, kReferrerPolicyNever, true, + network::mojom::FetchCredentialsMode::kOmit}, + {"http://example.test/cat.js", nullptr, "sha384-abc", + kCrossOriginAttributeNotSet, kReferrerPolicyDefault, true, + network::mojom::FetchCredentialsMode::kOmit}}; class LinkLoaderModulePreloadTest : public ::testing::TestWithParam<ModulePreloadTestParams> {}; @@ -361,6 +368,8 @@ request.Options().CredentialsMode()); EXPECT_EQ(AtomicString(), request.GetReferrer()); EXPECT_EQ(params_->referrer_policy, request.GetReferrerPolicy()); + EXPECT_EQ(params_->integrity, + request.Options().GetIntegrityAttributeValue()); } bool fetched() const { return fetched_; } @@ -385,7 +394,8 @@ KURL href_url = KURL(NullURL(), test_case.href); loader->LoadLink(LinkRelAttribute("modulepreload"), test_case.cross_origin, String() /* type */, String() /* as */, String() /* media */, - test_case.nonce, test_case.referrer_policy, href_url, + test_case.nonce, test_case.integrity, + test_case.referrer_policy, href_url, dummy_page_holder->GetDocument(), NetworkHintsMock()); ASSERT_EQ(test_case.expecting_load, modulator->fetched()); } @@ -426,7 +436,7 @@ KURL href_url = KURL(NullURL(), test_case.href); URLTestHelpers::RegisterMockedErrorURLLoad(href_url); loader->LoadLink(LinkRelAttribute("prefetch"), kCrossOriginAttributeNotSet, - test_case.type, "", test_case.media, "", + test_case.type, "", test_case.media, "", "", test_case.referrer_policy, href_url, dummy_page_holder->GetDocument(), NetworkHintsMock()); ASSERT_TRUE(dummy_page_holder->GetDocument().Fetcher()); @@ -472,7 +482,7 @@ NetworkHintsMock network_hints; loader->LoadLink(LinkRelAttribute("dns-prefetch"), kCrossOriginAttributeNotSet, String(), String(), String(), - String(), kReferrerPolicyDefault, href_url, + String(), String(), kReferrerPolicyDefault, href_url, dummy_page_holder->GetDocument(), network_hints); EXPECT_FALSE(network_hints.DidPreconnect()); EXPECT_EQ(test_case.should_load, network_hints.DidDnsPrefetch()); @@ -505,7 +515,7 @@ KURL href_url = KURL(KURL(String("http://example.com")), test_case.href); NetworkHintsMock network_hints; loader->LoadLink(LinkRelAttribute("preconnect"), test_case.cross_origin, - String(), String(), String(), String(), + String(), String(), String(), String(), String(), kReferrerPolicyDefault, href_url, dummy_page_holder->GetDocument(), network_hints); EXPECT_EQ(test_case.should_load, network_hints.DidPreconnect()); @@ -527,7 +537,7 @@ URLTestHelpers::RegisterMockedErrorURLLoad(href_url); loader->LoadLink(LinkRelAttribute("preload prefetch"), kCrossOriginAttributeNotSet, "application/javascript", - "script", "", "", kReferrerPolicyDefault, href_url, + "script", "", "", "", kReferrerPolicyDefault, href_url, dummy_page_holder->GetDocument(), NetworkHintsMock()); ASSERT_EQ(1, fetcher->CountPreloads()); Resource* resource = loader->GetResourceForTesting();
diff --git a/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.cpp b/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.cpp index a09aaa7..9144833 100644 --- a/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.cpp +++ b/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.cpp
@@ -80,15 +80,19 @@ return; if (request.GetFrameType() == WebURLRequest::kFrameTypeTopLevel || - request.GetFrameType() == WebURLRequest::kFrameTypeNested) { - WillStartLoadingMainResource(request); - } else { - WillStartLoadingResource(request); - } + request.GetFrameType() == WebURLRequest::kFrameTypeNested) + WillStartLoadingMainResource(request.Url(), request.HttpMethod()); + + if (!host_) + return; + + int host_id = host_->GetHostID(); + if (host_id != WebApplicationCacheHost::kAppCacheNoHostId) + request.SetAppCacheHostID(host_id); } -void ApplicationCacheHost::WillStartLoadingMainResource( - ResourceRequest& request) { +void ApplicationCacheHost::WillStartLoadingMainResource(const KURL& url, + const String& method) { // We defer creating the outer host object to avoid spurious // creation/destruction around creating empty documents. At this point, we're // initiating a main resource load for the document, so its for real. @@ -101,8 +105,6 @@ if (!host_) return; - WrappedResourceRequest wrapped(request); - const WebApplicationCacheHost* spawning_host = nullptr; Frame* spawning_frame = frame.Tree().Parent(); if (!spawning_frame || !spawning_frame->IsLocalFrame()) @@ -117,7 +119,7 @@ : nullptr; } - host_->WillStartMainResourceRequest(wrapped, spawning_host); + host_->WillStartMainResourceRequest(url, method, spawning_host); // NOTE: The semantics of this method, and others in this interface, are // subtly different than the method names would suggest. For example, in this @@ -189,13 +191,6 @@ host_->DidFinishLoadingMainResource(true); } -void ApplicationCacheHost::WillStartLoadingResource(ResourceRequest& request) { - if (host_) { - WrappedResourceRequest wrapped(request); - host_->WillStartSubResourceRequest(wrapped); - } -} - void ApplicationCacheHost::SetApplicationCache( ApplicationCache* dom_application_cache) { DCHECK(!dom_application_cache_ || !dom_application_cache);
diff --git a/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.h b/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.h index ae6642d..eaf4fd0 100644 --- a/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.h +++ b/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.h
@@ -162,8 +162,7 @@ private: explicit ApplicationCacheHost(DocumentLoader*); - void WillStartLoadingMainResource(ResourceRequest&); - void WillStartLoadingResource(ResourceRequest&); + void WillStartLoadingMainResource(const KURL&, const String&); // WebApplicationCacheHostClient implementation void DidChangeCacheAssociation() final;
diff --git a/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResourceTest.cpp b/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResourceTest.cpp index f08c20b..8ac2788 100644 --- a/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResourceTest.cpp +++ b/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResourceTest.cpp
@@ -93,8 +93,8 @@ ResourceResponse(css_url, "style/css", 0, g_null_atom), nullptr); css_resource->FinishForTest(); - CSSParserContext* parser_context = - CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* parser_context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* contents = StyleSheetContents::Create(parser_context); CSSStyleSheet* sheet = CSSStyleSheet::Create(contents, GetDocument()); EXPECT_TRUE(sheet); @@ -114,8 +114,8 @@ TEST_F(CSSStyleSheetResourceTest, CreateFromCacheRestoresOriginalSheet) { CSSStyleSheetResource* css_resource = CreateAndSaveTestStyleSheetResource(); - CSSParserContext* parser_context = - CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* parser_context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* contents = StyleSheetContents::Create(parser_context); CSSStyleSheet* sheet = CSSStyleSheet::Create(contents, GetDocument()); ASSERT_TRUE(sheet); @@ -138,8 +138,8 @@ CreateFromCacheWithMediaQueriesCopiesOriginalSheet) { CSSStyleSheetResource* css_resource = CreateAndSaveTestStyleSheetResource(); - CSSParserContext* parser_context = - CSSParserContext::Create(kHTMLStandardMode); + CSSParserContext* parser_context = CSSParserContext::Create( + kHTMLStandardMode, SecureContextMode::kInsecureContext); StyleSheetContents* contents = StyleSheetContents::Create(parser_context); CSSStyleSheet* sheet = CSSStyleSheet::Create(contents, GetDocument()); ASSERT_TRUE(sheet);
diff --git a/third_party/WebKit/Source/core/page/Page.cpp b/third_party/WebKit/Source/core/page/Page.cpp index 2c6d167..c6071e8 100644 --- a/third_party/WebKit/Source/core/page/Page.cpp +++ b/third_party/WebKit/Source/core/page/Page.cpp
@@ -33,6 +33,7 @@ #include "core/frame/DOMTimer.h" #include "core/frame/EventHandlerRegistry.h" #include "core/frame/FrameConsole.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/LocalFrameView.h" #include "core/frame/PageScaleConstraints.h" #include "core/frame/PageScaleConstraintsSet.h" @@ -627,7 +628,8 @@ // TODO(rbyers): Most of this doesn't appear to take into account that each // SVGImage gets it's own Page instance. GetConsoleMessageStorage().Clear(); - GetUseCounter().DidCommitLoad(url); + if (frame->Client() && frame->Client()->ShouldTrackUseCounter(url)) + GetUseCounter().DidCommitLoad(url); GetDeprecation().ClearSuppression(); GetVisualViewport().SendUMAMetrics();
diff --git a/third_party/WebKit/Source/core/paint/ClipRectsCache.h b/third_party/WebKit/Source/core/paint/ClipRectsCache.h index 9d06932..97856de 100644 --- a/third_party/WebKit/Source/core/paint/ClipRectsCache.h +++ b/third_party/WebKit/Source/core/paint/ClipRectsCache.h
@@ -22,7 +22,11 @@ kRootRelativeClipRectsIgnoringViewportClip, // Relative to the LayoutView's layer. Used for compositing overlap testing. - kAbsoluteClipRects, + // TODO(bokan): Overlap testing currently ignores the clip on the root layer. + // Overlap testing has some bugs when inside non-root layers which extend to + // the root layer when root-layer-scrolling is turned on unless we do this. + // crbug.com/783532. + kAbsoluteClipRectsIgnoringViewportClip, // Relative to painting ancestor. Used for SPv1 compositing. kPaintingClipRects,
diff --git a/third_party/WebKit/Source/core/paint/OWNERS b/third_party/WebKit/Source/core/paint/OWNERS index d928fd5b..ffef4fe 100644 --- a/third_party/WebKit/Source/core/paint/OWNERS +++ b/third_party/WebKit/Source/core/paint/OWNERS
@@ -4,12 +4,11 @@ enne@chromium.org fmalita@chromium.org fs@opera.com -jbroman@chromium.org junov@chromium.org pdr@chromium.org schenney@chromium.org senorblanco@chromium.org -vollick@chromium.org +trchen@chromium.org wangxianzhu@chromium.org # TEAM: paint-dev@chromium.org
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp index 1ecf53a8..93fb17e 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -440,7 +440,7 @@ // clip rects here. ClearClipRects(); } else if (has_transform) { - ClearClipRects(kAbsoluteClipRects); + ClearClipRects(kAbsoluteClipRectsIgnoringViewportClip); } UpdateTransformationMatrix(); @@ -1264,8 +1264,8 @@ } void* PaintLayer::operator new(size_t sz) { - return WTF::PartitionAlloc(WTF::Partitions::LayoutPartition(), sz, - WTF_HEAP_PROFILER_TYPE_NAME(PaintLayer)); + return WTF::Partitions::LayoutPartition()->Alloc( + sz, WTF_HEAP_PROFILER_TYPE_NAME(PaintLayer)); } void PaintLayer::operator delete(void* ptr) {
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipper.h b/third_party/WebKit/Source/core/paint/PaintLayerClipper.h index 39ff197..c5592cf 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerClipper.h +++ b/third_party/WebKit/Source/core/paint/PaintLayerClipper.h
@@ -81,7 +81,8 @@ ? kIgnoreOverflowClip : kRespectOverflowClip), respect_overflow_clip_for_viewport( - slot == kRootRelativeClipRectsIgnoringViewportClip + (slot == kRootRelativeClipRectsIgnoringViewportClip || + slot == kAbsoluteClipRectsIgnoringViewportClip) ? kIgnoreOverflowClip : kRespectOverflowClip) {}
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositingInputsUpdater.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositingInputsUpdater.cpp index a52d8ee4..b94d8f3 100644 --- a/third_party/WebKit/Source/core/paint/compositing/CompositingInputsUpdater.cpp +++ b/third_party/WebKit/Source/core/paint/compositing/CompositingInputsUpdater.cpp
@@ -161,7 +161,9 @@ ClipRect clip_rect; layer->Clipper(PaintLayer::kDoNotUseGeometryMapper) .CalculateBackgroundClipRect( - ClipRectsContext(root_layer_, kAbsoluteClipRects), clip_rect); + ClipRectsContext(root_layer_, + kAbsoluteClipRectsIgnoringViewportClip), + clip_rect); IntRect snapped_clip_rect = PixelSnappedIntRect(clip_rect.Rect()); properties.clipped_absolute_bounding_box = properties.unclipped_absolute_bounding_box;
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositingRequirementsUpdater.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositingRequirementsUpdater.cpp index 4920b397..5c703e9 100644 --- a/third_party/WebKit/Source/core/paint/compositing/CompositingRequirementsUpdater.cpp +++ b/third_party/WebKit/Source/core/paint/compositing/CompositingRequirementsUpdater.cpp
@@ -301,6 +301,10 @@ false) & kCompositingReasonOverflowScrollingTouch); + bool use_clipped_bounding_rect = + !has_composited_scrolling_ancestor || + layer->AncestorScrollingLayer()->IsRootLayer(); + // We have to promote the sticky element to work around the bug // (https://crbug.com/698358) of not being able to invalidate the ancestor // after updating the sticky layer position. @@ -373,14 +377,14 @@ } } - const IntRect& abs_bounds = has_composited_scrolling_ancestor - ? layer->UnclippedAbsoluteBoundingBox() - : layer->ClippedAbsoluteBoundingBox(); + const IntRect& abs_bounds = use_clipped_bounding_rect + ? layer->ClippedAbsoluteBoundingBox() + : layer->UnclippedAbsoluteBoundingBox(); absolute_descendant_bounding_box = abs_bounds; if (current_recursion_data.testing_overlap_ && !RequiresCompositingOrSquashing(direct_reasons)) { - bool overlaps = overlap_map.OverlapsLayers( - abs_bounds, !has_composited_scrolling_ancestor); + bool overlaps = + overlap_map.OverlapsLayers(abs_bounds, use_clipped_bounding_rect); overlap_compositing_reason = overlaps ? kCompositingReasonOverlap : kCompositingReasonNone; } @@ -527,7 +531,7 @@ // for overlap. if (child_recursion_data.compositing_ancestor_ && !child_recursion_data.compositing_ancestor_->IsRootLayer()) - overlap_map.Add(layer, abs_bounds, !has_composited_scrolling_ancestor); + overlap_map.Add(layer, abs_bounds, use_clipped_bounding_rect); // Now check for reasons to become composited that depend on the state of // descendant layers. @@ -545,7 +549,7 @@ // second-from-top context of the stack. overlap_map.BeginNewOverlapTestingContext(); overlap_map.Add(layer, absolute_descendant_bounding_box, - !has_composited_scrolling_ancestor); + use_clipped_bounding_rect); will_be_composited_or_squashed = true; }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp index bc7853a..8d021cc 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp +++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -654,17 +654,19 @@ for (CSSPropertyID property_id : *value->NativeInvalidationProperties()) { // TODO(ikilpatrick): remove IsInterpolableProperty check once // CSSPropertyEquality::PropertiesEqual correctly handles all properties. - if (!CSSProperty::Get(property_id).IsInterpolable() || - !CSSPropertyEquality::PropertiesEqual(PropertyHandle(property_id), - *this, other)) + const CSSProperty& property = CSSProperty::Get(property_id); + if (!property.IsInterpolable() || + !CSSPropertyEquality::PropertiesEqual(PropertyHandle(property), *this, + other)) return true; } if (InheritedVariables() || NonInheritedVariables() || other.InheritedVariables() || other.NonInheritedVariables()) { - for (const AtomicString& property : + for (const AtomicString& property_name : *value->CustomInvalidationProperties()) { - if (!DataEquivalent(GetVariable(property), other.GetVariable(property))) + if (!DataEquivalent(GetVariable(property_name), + other.GetVariable(property_name))) return true; } }
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp index ccdce9d5..5abbc73 100644 --- a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
@@ -501,8 +501,9 @@ MutableCSSPropertyValueSet* property_set = targetElement()->EnsureAnimatedSMILStyleProperties(); if (property_set - ->SetProperty(css_property_id_, animated_value_->ValueAsString(), - false, nullptr) + ->SetProperty( + css_property_id_, animated_value_->ValueAsString(), false, + targetElement()->GetDocument().SecureContextMode(), nullptr) .did_change) { targetElement()->SetNeedsStyleRecalc( kLocalStyleChange,
diff --git a/third_party/WebKit/Source/core/svg/SVGLength.cpp b/third_party/WebKit/Source/core/svg/SVGLength.cpp index a8e4a12..b5a5322 100644 --- a/third_party/WebKit/Source/core/svg/SVGLength.cpp +++ b/third_party/WebKit/Source/core/svg/SVGLength.cpp
@@ -145,8 +145,11 @@ return SVGParseStatus::kNoError; } - CSSParserContext* svg_parser_context = - CSSParserContext::Create(kSVGAttributeMode); + // NOTE(ikilpatrick): We will always parse svg lengths in the insecure + // context mode. If a function/unit/etc will require a secure context check + // in the future, plumbing will need to be added. + CSSParserContext* svg_parser_context = CSSParserContext::Create( + kSVGAttributeMode, SecureContextMode::kInsecureContext); const CSSValue* parsed = CSSParser::ParseSingleValue(CSSPropertyX, string, svg_parser_context); if (!parsed || !parsed->IsPrimitiveValue())
diff --git a/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp b/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp index 9d68994..050597b 100644 --- a/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp
@@ -76,12 +76,8 @@ backing_thread_->InitializeOnThread(); DCHECK(!isolate_); - // Use nullptr for |external_reference_table|, since it's used for the context - // snapshot feature which workers don't use. - intptr_t* external_reference_table = nullptr; isolate_ = V8PerIsolateData::Initialize( backing_thread_->PlatformThread().GetWebTaskRunner(), - external_reference_table, V8PerIsolateData::V8ContextSnapshotMode::kDontUseSnapshot); AddWorkerIsolate(isolate_); V8Initializer::InitializeWorker(isolate_);
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/AppcacheTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/AppcacheTestRunner.js index e3a9d48..02adce9e 100644 --- a/third_party/WebKit/Source/devtools/front_end/application_test_runner/AppcacheTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/AppcacheTestRunner.js
@@ -185,7 +185,7 @@ ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId] = {count: eventsLeft, callback: callback}; }; -TestRunner.initAsync(` +TestRunner.deprecatedInitAsync(` var framesCount = 0; function createAndNavigateIFrame(url) {
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/CacheStorageTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/CacheStorageTestRunner.js index 5d9755f3..1bca8590 100644 --- a/third_party/WebKit/Source/devtools/front_end/application_test_runner/CacheStorageTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/CacheStorageTestRunner.js
@@ -135,7 +135,7 @@ return TestRunner.callFunctionInPageAsync('clearAllCaches'); }; -TestRunner.initAsync(` +TestRunner.deprecatedInitAsync(` function onCacheStorageError(e) { console.error('CacheStorage error: ' + e); }
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/IndexedDBTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/IndexedDBTestRunner.js index f43af7e..d56d1d5 100644 --- a/third_party/WebKit/Source/devtools/front_end/application_test_runner/IndexedDBTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/IndexedDBTestRunner.js
@@ -133,7 +133,7 @@ 'addIDBValueAsync(\'' + databaseName + '\', \'' + objectStoreName + '\', \'' + key + '\', \'' + value + '\')'); }; -TestRunner.initAsync(` +TestRunner.deprecatedInitAsync(` function dispatchCallback(callbackId) { console.log(callbackId); }
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 5a12ef2..26d6838 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
@@ -100,7 +100,7 @@ return TestRunner.mainTarget.model(Resources.IndexedDBModel); }; -TestRunner.initAsync(` +TestRunner.deprecatedInitAsync(` function _openWebSQLDatabase(name) { return new Promise(resolve => openDatabase(name, '1.0', '', 1024 * 1024, resolve)); }
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js index edf9e14..21fdfeb 100644 --- a/third_party/WebKit/Source/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js
@@ -62,7 +62,7 @@ TestRunner.callFunctionInPageAsync('makeFetchInServiceWorker', [scope, url, requestInitializer]).then(callback); }; -TestRunner.initAsync(` +TestRunner.deprecatedInitAsync(` var registrations = {}; function registerServiceWorker(script, scope) {
diff --git a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js index a35b2dd..786c3ae 100644 --- a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js +++ b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
@@ -561,13 +561,14 @@ * @return {boolean} */ isGroupable() { - var isJSError = this.source === ConsoleModel.ConsoleMessage.MessageSource.JS && - this.level === ConsoleModel.ConsoleMessage.MessageLevel.Error; + var isUngroupableError = this.level === ConsoleModel.ConsoleMessage.MessageLevel.Error && + (this.source === ConsoleModel.ConsoleMessage.MessageSource.JS || + this.source === ConsoleModel.ConsoleMessage.MessageSource.Network); return ( this.source !== ConsoleModel.ConsoleMessage.MessageSource.ConsoleAPI && this.type !== ConsoleModel.ConsoleMessage.MessageType.Command && this.type !== ConsoleModel.ConsoleMessage.MessageType.Result && - this.type !== ConsoleModel.ConsoleMessage.MessageType.System && !isJSError); + this.type !== ConsoleModel.ConsoleMessage.MessageType.System && !isUngroupableError); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/ExtensionsAuditsTestRunner.js b/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/ExtensionsAuditsTestRunner.js index 30184d0..f87b7268 100644 --- a/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/ExtensionsAuditsTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/ExtensionsAuditsTestRunner.js
@@ -36,7 +36,7 @@ TestRunner.addResult('Progress: ' + Math.round(100 * progress.value / progress.max) + '%'); }; -TestRunner.initAsync(` +TestRunner.deprecatedInitAsync(` function extension_runAudits(callback) { evaluateOnFrontend('ExtensionsTestRunner.startExtensionAudits(reply);', callback); }
diff --git a/third_party/WebKit/Source/devtools/front_end/network_test_runner/NetworkTestRunner.js b/third_party/WebKit/Source/devtools/front_end/network_test_runner/NetworkTestRunner.js index 2fa390e..0cc5756 100644 --- a/third_party/WebKit/Source/devtools/front_end/network_test_runner/NetworkTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/network_test_runner/NetworkTestRunner.js
@@ -145,7 +145,7 @@ NetworkTestRunner.HARPropertyFormattersWithSize = JSON.parse(JSON.stringify(NetworkTestRunner.HARPropertyFormatters)); NetworkTestRunner.HARPropertyFormattersWithSize.size = 'formatAsTypeName'; -TestRunner.initAsync(` +TestRunner.deprecatedInitAsync(` var lastXHRIndex = 0; function xhrLoadedCallback() {
diff --git a/third_party/WebKit/Source/devtools/front_end/performance_test_runner/TimelineTestRunner.js b/third_party/WebKit/Source/devtools/front_end/performance_test_runner/TimelineTestRunner.js index bf0dabd..993b38e 100644 --- a/third_party/WebKit/Source/devtools/front_end/performance_test_runner/TimelineTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/performance_test_runner/TimelineTestRunner.js
@@ -183,14 +183,14 @@ }; PerformanceTestRunner.printTimelineRecords = function(name) { - for (let event of PerformanceTestRunner.timelineModel().mainThreadEvents()) { + for (let event of PerformanceTestRunner.timelineModel().inspectedTargetEvents()) { if (event.name === name) PerformanceTestRunner.printTraceEventProperties(event); } }; PerformanceTestRunner.printTimelineRecordsWithDetails = function(name) { - for (let event of PerformanceTestRunner.timelineModel().mainThreadEvents()) { + for (let event of PerformanceTestRunner.timelineModel().inspectedTargetEvents()) { if (name === event.name) PerformanceTestRunner.printTraceEventPropertiesWithDetails(event); } @@ -369,7 +369,7 @@ return promise; }; -TestRunner.initAsync(` +TestRunner.deprecatedInitAsync(` function wrapCallFunctionForTimeline(f) { var script = document.createElement('script'); script.textContent = '(' + f.toString() + ')()\\n//# sourceURL=wrapCallFunctionForTimeline.js';
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/DebuggerTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/DebuggerTestRunner.js index 9a146616..78be309 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/DebuggerTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/DebuggerTestRunner.js
@@ -755,7 +755,7 @@ } }; -TestRunner.initAsync(` +TestRunner.deprecatedInitAsync(` function scheduleTestFunction() { setTimeout(testFunction, 0); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SearchTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SearchTestRunner.js index bb71f3a4..775940f 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SearchTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SearchTestRunner.js
@@ -140,7 +140,7 @@ } }; -TestRunner.initAsync(` +TestRunner.deprecatedInitAsync(` if (window.GCController) GCController.collect(); `);
diff --git a/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js b/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js index a494211..8a13bb0 100644 --- a/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js
@@ -12,7 +12,7 @@ /** @type {!{logToStderr: function(), notifyDone: function()}|undefined} */ self.testRunner; -TestRunner.executeTestScript = function() { +TestRunner._executeTestScript = function() { var testScriptURL = /** @type {string} */ (Runtime.queryParam('test')); fetch(testScriptURL) .then(data => data.text()) @@ -562,9 +562,20 @@ TestRunner._pendingInits = 0; /** + * The old test framework executed certain snippets in the inspected page + * context as part of loading a test helper file. + * + * This is deprecated because: + * 1) it makes the testing API less intuitive (need to read the various *TestRunner.js + * files to know which helper functions are available in the inspected page). + * 2) it complicates the test framework's module loading process. + * + * In most cases, this is used to set up inspected page functions (e.g. makeSimpleXHR) + * which should become a *TestRunner method (e.g. NetworkTestRunner.makeSimpleXHR) + * that calls evaluateInPageAnonymously(...). * @param {string} code */ -TestRunner.initAsync = async function(code) { +TestRunner.deprecatedInitAsync = async function(code) { TestRunner._pendingInits++; await TestRunner.RuntimeAgent.invoke_evaluate({expression: code, objectGroup: 'console'}); TestRunner._pendingInits--; @@ -1276,7 +1287,7 @@ /** * @implements {SDK.TargetManager.Observer} */ -TestRunner.TestObserver = class { +TestRunner._TestObserver = class { /** * @param {!SDK.Target} target * @override @@ -1286,7 +1297,7 @@ return; TestRunner._startedTest = true; TestRunner._setupTestHelpers(target); - TestRunner.runTest(); + TestRunner._runTest(); } /** @@ -1297,7 +1308,7 @@ } }; -TestRunner.runTest = async function() { +TestRunner._runTest = async function() { var testPath = TestRunner.url(); await TestRunner.loadHTML(` <head> @@ -1306,12 +1317,12 @@ <body> </body> `); - TestRunner.executeTestScript(); + TestRunner._executeTestScript(); }; // Old-style tests start test using inspector-test.js if (Runtime.queryParam('test')) - SDK.targetManager.observeTargets(new TestRunner.TestObserver()); + SDK.targetManager.observeTargets(new TestRunner._TestObserver()); (function() { /**
diff --git a/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js b/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js index 1458153..65f49f3 100644 --- a/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js +++ b/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js
@@ -406,7 +406,7 @@ const components = inputPath.slice(inputPath.indexOf('LayoutTests/')).split('/'); const folder = inputPath.indexOf('LayoutTests/inspector') === -1 ? components[4] : components[2]; if (folder.endsWith('.html')) - return; + return []; const panel = panelByFolder[folder]; if (panel) panels.add(panel);
diff --git a/third_party/WebKit/Source/modules/animationworklet/WindowAnimationWorklet.cpp b/third_party/WebKit/Source/modules/animationworklet/WindowAnimationWorklet.cpp index 5daf68b..511aa87 100644 --- a/third_party/WebKit/Source/modules/animationworklet/WindowAnimationWorklet.cpp +++ b/third_party/WebKit/Source/modules/animationworklet/WindowAnimationWorklet.cpp
@@ -13,6 +13,11 @@ // static AnimationWorklet* WindowAnimationWorklet::animationWorklet( LocalDOMWindow& window) { + // TODO(nhiroki): Replace this with the [SecureContext] attribute when it's + // supported (https://crbug.com/782121) + String error_message; + if (!window.GetExecutionContext()->IsSecureContext(error_message)) + return nullptr; if (!window.GetFrame()) return nullptr; return From(window).animation_worklet_.Get();
diff --git a/third_party/WebKit/Source/modules/animationworklet/WindowAnimationWorklet.idl b/third_party/WebKit/Source/modules/animationworklet/WindowAnimationWorklet.idl index 075ddbf..7914676 100644 --- a/third_party/WebKit/Source/modules/animationworklet/WindowAnimationWorklet.idl +++ b/third_party/WebKit/Source/modules/animationworklet/WindowAnimationWorklet.idl
@@ -4,8 +4,9 @@ [ ImplementedAs=WindowAnimationWorklet, - RuntimeEnabled=AnimationWorklet, - SecureContext + RuntimeEnabled=AnimationWorklet + // TODO(nhiroki): Specify the [SecureContext] attribute when it's supported. + // (https://crbug.com/782121) ] partial interface Window { readonly attribute Worklet animationWorklet; };
diff --git a/third_party/WebKit/Source/modules/cachestorage/Cache.cpp b/third_party/WebKit/Source/modules/cachestorage/Cache.cpp index 165c9441..8f18b2e 100644 --- a/third_party/WebKit/Source/modules/cachestorage/Cache.cpp +++ b/third_party/WebKit/Source/modules/cachestorage/Cache.cpp
@@ -12,9 +12,11 @@ #include "bindings/core/v8/NativeValueTraitsImpl.h" #include "bindings/core/v8/ScriptPromiseResolver.h" #include "bindings/core/v8/V8BindingForCore.h" +#include "bindings/core/v8/V8ScriptRunner.h" #include "bindings/modules/v8/V8Response.h" #include "core/dom/DOMException.h" #include "core/dom/ExecutionContext.h" +#include "core/html/parser/TextResourceDecoder.h" #include "core/inspector/ConsoleMessage.h" #include "modules/cachestorage/CacheStorageError.h" #include "modules/fetch/BodyStreamBuffer.h" @@ -26,8 +28,10 @@ #include "platform/Histogram.h" #include "platform/bindings/ScriptState.h" #include "platform/bindings/V8ThrowException.h" +#include "platform/loader/fetch/CachedMetadata.h" #include "platform/network/http_names.h" #include "platform/network/mime/MIMETypeRegistry.h" +#include "platform/runtime_enabled_features.h" #include "public/platform/modules/cache_storage/cache_storage.mojom-blink.h" #include "public/platform/modules/serviceworker/WebServiceWorkerCache.h" #include "services/network/public/interfaces/fetch_api.mojom-blink.h" @@ -192,6 +196,24 @@ return false; } +bool ShouldGenerateV8CodeCache(ScriptState* script_state, + const Response* response) { + if (!RuntimeEnabledFeatures::PWAFullCodeCacheEnabled()) + return false; + ExecutionContext* context = ExecutionContext::From(script_state); + if (!context->IsServiceWorkerGlobalScope()) + return false; + if (!ToServiceWorkerGlobalScope(context)->IsInstalling()) + return false; + if (!MIMETypeRegistry::IsSupportedJavaScriptMIMEType( + response->InternalMIMEType())) { + return false; + } + if (!response->InternalBodyBuffer()) + return false; + return true; +} + } // namespace // TODO(nhiroki): Unfortunately, we have to go through V8 to wait for the fetch @@ -238,7 +260,7 @@ return ScriptValue(GetScriptState(), put_promise.V8Value()); } - virtual void Trace(blink::Visitor* visitor) { + void Trace(blink::Visitor* visitor) override { visitor->Trace(cache_); visitor->Trace(requests_); ScriptFunction::Trace(visitor); @@ -324,7 +346,8 @@ blob_data_handle->GetType())) { continue; } - global_scope->CountCacheStorageInstalledScript(blob_data_handle->size()); + global_scope->CountCacheStorageInstalledScript( + blob_data_handle->size(), operation.response.SideDataBlobSize()); } } @@ -365,7 +388,7 @@ barrier_callback_->OnError("network error"); } - virtual void Trace(blink::Visitor* visitor) { + void Trace(blink::Visitor* visitor) override { visitor->Trace(barrier_callback_); FetchDataLoader::Client::Trace(visitor); } @@ -378,6 +401,88 @@ WebServiceWorkerResponse web_response_; }; +class Cache::CodeCacheHandleCallbackForPut final + : public GarbageCollectedFinalized<CodeCacheHandleCallbackForPut>, + public FetchDataLoader::Client { + USING_GARBAGE_COLLECTED_MIXIN(CodeCacheHandleCallbackForPut); + + public: + CodeCacheHandleCallbackForPut(ScriptState* script_state, + size_t index, + BarrierCallbackForPut* barrier_callback, + Request* request, + Response* response) + : script_state_(script_state), + index_(index), + barrier_callback_(barrier_callback), + mime_type_(response->InternalMIMEType()) { + request->PopulateWebServiceWorkerRequest(web_request_); + response->PopulateWebServiceWorkerResponse(web_response_); + } + ~CodeCacheHandleCallbackForPut() override {} + + void DidFetchDataLoadedArrayBuffer(DOMArrayBuffer* array_buffer) override { + WebServiceWorkerCache::BatchOperation batch_operation; + batch_operation.operation_type = WebServiceWorkerCache::kOperationTypePut; + batch_operation.request = web_request_; + batch_operation.response = web_response_; + + std::unique_ptr<BlobData> blob_data = BlobData::Create(); + blob_data->SetContentType(mime_type_); + blob_data->AppendBytes(array_buffer->Data(), array_buffer->ByteLength()); + batch_operation.response.SetBlobDataHandle(BlobDataHandle::Create( + std::move(blob_data), array_buffer->ByteLength())); + + // Currently we only support UTF8 encoding. + // TODO(horo): Use the charset in Content-type header of the response. + // See crbug.com/743311. + std::unique_ptr<TextResourceDecoder> text_decoder = + TextResourceDecoder::Create( + TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText()); + + scoped_refptr<CachedMetadata> cached_metadata = + V8ScriptRunner::GenerateFullCodeCache( + script_state_.get(), + text_decoder->Decode(static_cast<const char*>(array_buffer->Data()), + array_buffer->ByteLength()), + web_request_.Url().GetString(), text_decoder->Encoding(), + web_response_.ResponseType() == + network::mojom::FetchResponseType::kOpaque + ? V8ScriptRunner::OpaqueMode::kOpaque + : V8ScriptRunner::OpaqueMode::kNotOpaque); + if (!cached_metadata) { + barrier_callback_->OnSuccess(index_, batch_operation); + return; + } + const Vector<char>& serialized_data = cached_metadata->SerializedData(); + std::unique_ptr<BlobData> side_data_blob_data = BlobData::Create(); + side_data_blob_data->AppendBytes(serialized_data.data(), + serialized_data.size()); + + batch_operation.response.SetSideDataBlobDataHandle(BlobDataHandle::Create( + std::move(side_data_blob_data), serialized_data.size())); + barrier_callback_->OnSuccess(index_, batch_operation); + } + + void DidFetchDataLoadFailed() override { + barrier_callback_->OnError("network error"); + } + + void Trace(blink::Visitor* visitor) override { + visitor->Trace(barrier_callback_); + FetchDataLoader::Client::Trace(visitor); + } + + private: + const scoped_refptr<ScriptState> script_state_; + const size_t index_; + Member<BarrierCallbackForPut> barrier_callback_; + const String mime_type_; + + WebServiceWorkerRequest web_request_; + WebServiceWorkerResponse web_response_; +}; + Cache* Cache::Create(GlobalFetch::ScopedFetcher* fetcher, std::unique_ptr<WebServiceWorkerCache> web_cache) { return new Cache(fetcher, std::move(web_cache)); @@ -654,6 +759,15 @@ } BodyStreamBuffer* buffer = responses[i]->InternalBodyBuffer(); + + if (ShouldGenerateV8CodeCache(script_state, responses[i])) { + FetchDataLoader* loader = FetchDataLoader::CreateLoaderAsArrayBuffer(); + buffer->StartLoading(loader, new CodeCacheHandleCallbackForPut( + script_state, i, barrier_callback, + requests[i], responses[i])); + continue; + } + if (buffer) { // If the response has body, read the all data and create // the blob handle and dispatch the put batch asynchronously.
diff --git a/third_party/WebKit/Source/modules/cachestorage/Cache.h b/third_party/WebKit/Source/modules/cachestorage/Cache.h index 107c5a0..e90de0d 100644 --- a/third_party/WebKit/Source/modules/cachestorage/Cache.h +++ b/third_party/WebKit/Source/modules/cachestorage/Cache.h
@@ -70,6 +70,7 @@ private: class BarrierCallbackForPut; class BlobHandleCallbackForPut; + class CodeCacheHandleCallbackForPut; class FetchResolvedForAdd; friend class FetchResolvedForAdd; Cache(GlobalFetch::ScopedFetcher*, std::unique_ptr<WebServiceWorkerCache>);
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp index 5b509b1..dcd8a3f 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp
@@ -410,13 +410,16 @@ return GetState().UnparsedFilter(); } -void BaseRenderingContext2D::setFilter(const String& filter_string) { +void BaseRenderingContext2D::setFilter( + const ExecutionContext* execution_context, + const String& filter_string) { if (filter_string == GetState().UnparsedFilter()) return; - const CSSValue* filter_value = - CSSParser::ParseSingleValue(CSSPropertyFilter, filter_string, - CSSParserContext::Create(kHTMLStandardMode)); + const CSSValue* filter_value = CSSParser::ParseSingleValue( + CSSPropertyFilter, filter_string, + CSSParserContext::Create(kHTMLStandardMode, + execution_context->SecureContextMode())); if (!filter_value || filter_value->IsCSSWideKeyword()) return; @@ -1757,8 +1760,9 @@ 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, kRGBAColorType)) { + if (data->ImageDataInCanvasColorSettings(ColorSpace(), PixelFormat(), + converted_pixels.get(), + kRGBAColorType)) { buffer->PutByteArray(converted_pixels.get(), IntSize(data->width(), data->height()), source_rect, IntPoint(dest_offset));
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.h index 34021d61..82b49da4 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.h
@@ -82,7 +82,7 @@ void setGlobalCompositeOperation(const String&); String filter() const; - void setFilter(const String&); + void setFilter(const ExecutionContext*, const String&); void save(); void restore();
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.idl b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.idl index 9cd73554..67faefc 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.idl +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.idl
@@ -66,7 +66,7 @@ // compositing attribute unrestricted double globalAlpha; // (default 1.0) attribute DOMString globalCompositeOperation; // (default source-over) - [MeasureAs=Canvas2DFilter] attribute DOMString filter; // (default 'none') + [MeasureAs=Canvas2DFilter, SetterCallWith=ExecutionContext] attribute DOMString filter; // (default 'none') // image smoothing attribute boolean imageSmoothingEnabled; // (default True)
diff --git a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp index 553d474..485dcf8 100644 --- a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
@@ -300,7 +300,8 @@ return; } - CSSParser::ParseValue(style, CSSPropertyFont, new_font, true); + CSSParser::ParseValue(style, CSSPropertyFont, new_font, true, + Host()->GetTopExecutionContext()->SecureContextMode()); FontDescription desc = FontStyleResolver::ComputeFont(*style, Host()->GetFontSelector());
diff --git a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl index 256d375..227586a9 100644 --- a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl +++ b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl
@@ -28,7 +28,7 @@ // compositing attribute unrestricted double globalAlpha; // (default 1.0) attribute DOMString globalCompositeOperation; // (default source-over) - [MeasureAs=Canvas2DFilter]attribute DOMString filter; + [MeasureAs=Canvas2DFilter, SetterCallWith=ExecutionContext] attribute DOMString filter; // image smoothing attribute boolean imageSmoothingEnabled; // (default True)
diff --git a/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp b/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp index 5abbf6a..f80fcf45 100644 --- a/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp +++ b/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp
@@ -43,6 +43,20 @@ namespace blink { namespace { +bool IsSameOriginWithAncestors(Frame* frame) { + if (!frame) + return true; + + Frame* current = frame; + SecurityOrigin* origin = frame->GetSecurityContext()->GetSecurityOrigin(); + while (current->Tree().Parent()) { + current = current->Tree().Parent(); + if (!origin->CanAccess(current->GetSecurityContext()->GetSecurityOrigin())) + return false; + } + return true; +} + void RejectDueToCredentialManagerError(ScriptPromiseResolver* resolver, WebCredentialManagerError reason) { switch (reason) { @@ -87,16 +101,6 @@ } bool CheckBoilerplate(ScriptPromiseResolver* resolver) { - Frame* frame = ToDocument(ExecutionContext::From(resolver->GetScriptState())) - ->GetFrame(); - if (!frame || frame != frame->Tree().Top()) { - resolver->Reject(DOMException::Create(kSecurityError, - "CredentialContainer methods may " - "only be executed in a top-level " - "document.")); - return false; - } - String error_message; if (!ExecutionContext::From(resolver->GetScriptState()) ->IsSecureContext(error_message)) { @@ -141,15 +145,22 @@ WTF_MAKE_NONCOPYABLE(NotificationCallbacks); public: - explicit NotificationCallbacks(ScriptPromiseResolver* resolver) - : resolver_(resolver) {} + enum class SameOriginRequirement { kMustBeSameOrigin, kCanBeCrossOrigin }; + + explicit NotificationCallbacks(ScriptPromiseResolver* resolver, + SameOriginRequirement same_origin_requirement) + : resolver_(resolver), + same_origin_requirement_(same_origin_requirement) {} ~NotificationCallbacks() override {} void OnSuccess() override { Frame* frame = ToDocument(ExecutionContext::From(resolver_->GetScriptState())) ->GetFrame(); - SECURITY_CHECK(!frame || frame == frame->Tree().Top()); + SECURITY_CHECK(!frame || + same_origin_requirement_ == + SameOriginRequirement::kCanBeCrossOrigin || + IsSameOriginWithAncestors(frame)); resolver_->Resolve(); } @@ -160,6 +171,7 @@ private: const Persistent<ScriptPromiseResolver> resolver_; + const SameOriginRequirement same_origin_requirement_; }; class RequestCallbacks : public WebCredentialManagerClient::RequestCallbacks { @@ -176,7 +188,7 @@ if (!context) return; Frame* frame = ToDocument(context)->GetFrame(); - SECURITY_CHECK(!frame || frame == frame->Tree().Top()); + SECURITY_CHECK(!frame || IsSameOriginWithAncestors(frame)); std::unique_ptr<WebCredential> credential = WTF::WrapUnique(web_credential.release()); @@ -272,10 +284,22 @@ const CredentialRequestOptions& options) { ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); + ExecutionContext* context = ExecutionContext::From(script_state); + + Frame* frame = ToDocument(context)->GetFrame(); + if ((options.hasPassword() || options.hasFederated()) && + !IsSameOriginWithAncestors(frame)) { + resolver->Reject(DOMException::Create( + kNotAllowedError, + "`PasswordCredential` and `FederatedCredential` objects may only be " + "retrieved in a document which is same-origin with all of its " + "ancestors.")); + return promise; + } + if (!CheckBoilerplate(resolver)) return promise; - ExecutionContext* context = ExecutionContext::From(script_state); // Set the default mediation option if none is provided. // If both 'unmediated' and 'mediation' are set log a warning if they are // contradicting. @@ -335,6 +359,18 @@ Credential* credential) { ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); + + Frame* frame = ToDocument(ExecutionContext::From(script_state))->GetFrame(); + if ((credential->type() == "password" || credential->type() == "federated") && + !IsSameOriginWithAncestors(frame)) { + resolver->Reject( + DOMException::Create(kNotAllowedError, + "`PasswordCredential` and `FederatedCredential` " + "objects may only be stored in a document which " + "is same-origin with all of its ancestors.")); + return promise; + } + if (!CheckBoilerplate(resolver)) return promise; @@ -347,7 +383,11 @@ auto web_credential = WebCredential::Create(credential->GetPlatformCredential()); CredentialManagerClient::From(ExecutionContext::From(script_state)) - ->DispatchStore(*web_credential, new NotificationCallbacks(resolver)); + ->DispatchStore( + *web_credential, + new NotificationCallbacks( + resolver, + NotificationCallbacks::SameOriginRequirement::kMustBeSameOrigin)); return promise; } @@ -404,7 +444,9 @@ return promise; CredentialManagerClient::From(ExecutionContext::From(script_state)) - ->DispatchPreventSilentAccess(new NotificationCallbacks(resolver)); + ->DispatchPreventSilentAccess(new NotificationCallbacks( + resolver, + NotificationCallbacks::SameOriginRequirement::kCanBeCrossOrigin)); return promise; }
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.idl b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.idl index 7acb4a3..9edfdb3 100644 --- a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.idl +++ b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.idl
@@ -24,7 +24,7 @@ // compositing attribute unrestricted double globalAlpha; // (default 1.0) attribute DOMString globalCompositeOperation; // (default source-over) - attribute DOMString filter; + [SetterCallWith=ExecutionContext] attribute DOMString filter; // image smoothing attribute boolean imageSmoothingEnabled; // (default True)
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp index cc8178b..87a3d11f 100644 --- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp +++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
@@ -154,8 +154,9 @@ // false to make sure the overlay does not appear. Document& document = media_element.GetDocument(); if (document.GetSettings() && - !document.GetSettings()->GetMediaControlsEnabled()) + !document.GetSettings()->GetMediaControlsEnabled()) { return false; + } // The page disabled the button via the attribute. if (media_element.ControlsListInternal()->ShouldHideRemotePlayback()) { @@ -1479,10 +1480,10 @@ bottom_str_value.append(kPx); right_str_value.append(kPx); - popup_menu->style()->setProperty("bottom", bottom_str_value, kImportant, - ASSERT_NO_EXCEPTION); - popup_menu->style()->setProperty("right", right_str_value, kImportant, - ASSERT_NO_EXCEPTION); + popup_menu->style()->setProperty(&GetDocument(), "bottom", bottom_str_value, + kImportant, ASSERT_NO_EXCEPTION); + popup_menu->style()->setProperty(&GetDocument(), "right", right_str_value, + kImportant, ASSERT_NO_EXCEPTION); } void MediaControlsImpl::Invalidate(Element* element) {
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp index b5cb845..a118cf2e 100644 --- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp +++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
@@ -1206,4 +1206,52 @@ GetHistogramTester().ExpectTotalCount(kTimeToActionHistogramName, 0); } +TEST_F(MediaControlsImplTest, CastOverlayDefaultHidesOnTimer) { + Element* cast_overlay_button = GetElementByShadowPseudoId( + MediaControls(), "-internal-media-controls-overlay-cast-button"); + ASSERT_NE(nullptr, cast_overlay_button); + + SimulateRouteAvailable(); + EXPECT_TRUE(IsElementVisible(*cast_overlay_button)); + + // Starts playback because overlay never hides if paused. + MediaControls().MediaElement().SetSrc("http://example.com"); + MediaControls().MediaElement().Play(); + testing::RunPendingTasks(); + + SimulateHideMediaControlsTimerFired(); + EXPECT_FALSE(IsElementVisible(*cast_overlay_button)); +} + +TEST_F(MediaControlsImplTest, CastOverlayShowsOnSomeEvents) { + Element* cast_overlay_button = GetElementByShadowPseudoId( + MediaControls(), "-internal-media-controls-overlay-cast-button"); + ASSERT_NE(nullptr, cast_overlay_button); + + Element* overlay_enclosure = GetElementByShadowPseudoId( + MediaControls(), "-webkit-media-controls-overlay-enclosure"); + ASSERT_NE(nullptr, overlay_enclosure); + + SimulateRouteAvailable(); + EXPECT_TRUE(IsElementVisible(*cast_overlay_button)); + + // Starts playback because overlay never hides if paused. + MediaControls().MediaElement().SetSrc("http://example.com"); + MediaControls().MediaElement().Play(); + testing::RunPendingTasks(); + + SimulateRouteAvailable(); + SimulateHideMediaControlsTimerFired(); + EXPECT_FALSE(IsElementVisible(*cast_overlay_button)); + + for (const auto& event_name : + {"gesturetap", "click", "pointerover", "pointermove"}) { + overlay_enclosure->DispatchEvent(Event::Create(event_name)); + EXPECT_TRUE(IsElementVisible(*cast_overlay_button)); + + SimulateHideMediaControlsTimerFired(); + EXPECT_FALSE(IsElementVisible(*cast_overlay_button)); + } +} + } // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsRotateToFullscreenDelegateTest.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsRotateToFullscreenDelegateTest.cpp index 5d79f885..14d86bd8 100644 --- a/third_party/WebKit/Source/modules/media_controls/MediaControlsRotateToFullscreenDelegateTest.cpp +++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsRotateToFullscreenDelegateTest.cpp
@@ -561,8 +561,8 @@ EXPECT_TRUE(ObservedVisibility()); // Move video offscreen. - GetDocument().body()->style()->setProperty("margin-top", "-999px", "", - ASSERT_NO_EXCEPTION); + GetDocument().body()->style()->setProperty(&GetDocument(), "margin-top", + "-999px", "", ASSERT_NO_EXCEPTION); UpdateVisibilityObserver();
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElement.cpp index 56dea39e..c61f4a82 100644 --- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElement.cpp +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElement.cpp
@@ -133,9 +133,11 @@ void MediaControlLoadingPanelElement::SetAnimationIterationCount( const String& count_value) { - mask1_background_->style()->setProperty(kAnimationIterationCountName, + mask1_background_->style()->setProperty(&GetDocument(), + kAnimationIterationCountName, count_value, "", ASSERT_NO_EXCEPTION); - mask2_background_->style()->setProperty(kAnimationIterationCountName, + mask2_background_->style()->setProperty(&GetDocument(), + kAnimationIterationCountName, count_value, "", ASSERT_NO_EXCEPTION); }
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayEnclosureElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayEnclosureElement.cpp index d0b974a..9c66e97 100644 --- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayEnclosureElement.cpp +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayEnclosureElement.cpp
@@ -15,19 +15,17 @@ SetShadowPseudoId(AtomicString("-webkit-media-controls-overlay-enclosure")); } -EventDispatchHandlingState* -MediaControlOverlayEnclosureElement::PreDispatchEventHandler(Event* event) { - // When the media element is clicked or touched we want to make the overlay - // cast button visible (if the other requirements are right) even if - // JavaScript is doing its own handling of the event. Doing it in - // preDispatchEventHandler prevents any interference from JavaScript. - // Note that we can't simply test for click, since JS handling of touch events - // can prevent their translation to click events. - if (event && (event->type() == EventTypeNames::click || - event->type() == EventTypeNames::touchstart)) { +void MediaControlOverlayEnclosureElement::DefaultEventHandler(Event* event) { + // When the user interacts with the media element, the Cast overlay button + // needs to be shown. + if (event->type() == EventTypeNames::gesturetap || + event->type() == EventTypeNames::click || + event->type() == EventTypeNames::pointerover || + event->type() == EventTypeNames::pointermove) { GetMediaControls().ShowOverlayCastButtonIfNeeded(); } - return MediaControlDivElement::PreDispatchEventHandler(event); + + MediaControlDivElement::DefaultEventHandler(event); } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayEnclosureElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayEnclosureElement.h index da808cce..662bcb55 100644 --- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayEnclosureElement.h +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayEnclosureElement.h
@@ -10,7 +10,6 @@ namespace blink { class Event; -class EventDispatchHandlingState; class MediaControlsImpl; class MediaControlOverlayEnclosureElement final @@ -18,8 +17,7 @@ public: explicit MediaControlOverlayEnclosureElement(MediaControlsImpl&); - private: - EventDispatchHandlingState* PreDispatchEventHandler(Event*) override; + void DefaultEventHandler(Event*) override; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/notifications/Notification.cpp b/third_party/WebKit/Source/modules/notifications/Notification.cpp index 7c9932e..ca614779 100644 --- a/third_party/WebKit/Source/modules/notifications/Notification.cpp +++ b/third_party/WebKit/Source/modules/notifications/Notification.cpp
@@ -65,8 +65,8 @@ namespace blink { namespace { -WebNotificationManager* GetNotificationManager() { - return Platform::Current()->GetNotificationManager(); +WebNotificationManager* GetWebNotificationManager() { + return Platform::Current()->GetWebNotificationManager(); } } // namespace @@ -151,7 +151,7 @@ type_(type), state_(State::kLoading), data_(data) { - DCHECK(GetNotificationManager()); + DCHECK(GetWebNotificationManager()); } Notification::~Notification() {} @@ -190,8 +190,8 @@ SecurityOrigin* origin = GetExecutionContext()->GetSecurityOrigin(); DCHECK(origin); - GetNotificationManager()->Show(WebSecurityOrigin(origin), data_, - loader->GetResources(), this); + GetWebNotificationManager()->Show(WebSecurityOrigin(origin), data_, + loader->GetResources(), this); loader_.Clear(); state_ = State::kShowing; @@ -210,7 +210,7 @@ WrapPersistent(this))); state_ = State::kClosing; - GetNotificationManager()->Close(this); + GetWebNotificationManager()->Close(this); return; } @@ -219,8 +219,8 @@ SecurityOrigin* origin = GetExecutionContext()->GetSecurityOrigin(); DCHECK(origin); - GetNotificationManager()->ClosePersistent(WebSecurityOrigin(origin), - data_.tag, notification_id_); + GetWebNotificationManager()->ClosePersistent(WebSecurityOrigin(origin), + data_.tag, notification_id_); } void Notification::DispatchShowEvent() { @@ -444,7 +444,7 @@ } void Notification::ContextDestroyed(ExecutionContext*) { - GetNotificationManager()->NotifyDelegateDestroyed(this); + GetWebNotificationManager()->NotifyDelegateDestroyed(this); state_ = State::kClosed;
diff --git a/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp b/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp index 83bf933..c42edb1d 100644 --- a/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp +++ b/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp
@@ -126,7 +126,7 @@ resolver); WebNotificationManager* notification_manager = - Platform::Current()->GetNotificationManager(); + Platform::Current()->GetWebNotificationManager(); DCHECK(notification_manager); notification_manager->GetNotifications( @@ -188,7 +188,7 @@ DCHECK(loaders_.Contains(loader)); WebNotificationManager* notification_manager = - Platform::Current()->GetNotificationManager(); + Platform::Current()->GetWebNotificationManager(); DCHECK(notification_manager); notification_manager->ShowPersistent(
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp index 569e1ca..99ea468 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
@@ -315,15 +315,25 @@ } void ServiceWorkerGlobalScope::CountCacheStorageInstalledScript( - uint64_t script_size) { + uint64_t script_size, + uint64_t script_metadata_size) { ++cache_storage_installed_script_count_; cache_storage_installed_script_total_size_ += script_size; + cache_storage_installed_script_metadata_total_size_ += script_metadata_size; DEFINE_THREAD_SAFE_STATIC_LOCAL( CustomCountHistogram, script_size_histogram, ("ServiceWorker.CacheStorageInstalledScript.ScriptSize", 1000, 5000000, 50)); script_size_histogram.Count(script_size); + + if (script_metadata_size) { + DEFINE_THREAD_SAFE_STATIC_LOCAL( + CustomCountHistogram, script_metadata_size_histogram, + ("ServiceWorker.CacheStorageInstalledScript.CachedMetadataSize", 1000, + 50000000, 50)); + script_metadata_size_histogram.Count(script_metadata_size); + } } void ServiceWorkerGlobalScope::SetIsInstalling(bool is_installing) { @@ -344,6 +354,16 @@ 50000000, 50)); cache_storage_installed_script_total_size_histogram.Count( cache_storage_installed_script_total_size_); + + if (cache_storage_installed_script_metadata_total_size_) { + DEFINE_THREAD_SAFE_STATIC_LOCAL( + CustomCountHistogram, + cache_storage_installed_script_metadata_total_size_histogram, + ("ServiceWorker.CacheStorageInstalledScript.CachedMetadataTotalSize", + 1000, 50000000, 50)); + cache_storage_installed_script_metadata_total_size_histogram.Count( + cache_storage_installed_script_metadata_total_size_); + } } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h index b0a1942..b7d4efc3 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h
@@ -107,7 +107,8 @@ bool IsInstalling() const { return is_installing_; } void SetIsInstalling(bool is_installing); - void CountCacheStorageInstalledScript(uint64_t script_size); + void CountCacheStorageInstalledScript(uint64_t script_size, + uint64_t script_metadata_size); DEFINE_ATTRIBUTE_EVENT_LISTENER(install); DEFINE_ATTRIBUTE_EVENT_LISTENER(activate); @@ -147,6 +148,7 @@ bool is_installing_ = false; size_t cache_storage_installed_script_count_ = 0; uint64_t cache_storage_installed_script_total_size_ = 0; + uint64_t cache_storage_installed_script_metadata_total_size_ = 0; }; DEFINE_TYPE_CASTS(ServiceWorkerGlobalScope,
diff --git a/third_party/WebKit/Source/modules/storage/StorageNamespaceController.cpp b/third_party/WebKit/Source/modules/storage/StorageNamespaceController.cpp index 896f07c9..d659efc 100644 --- a/third_party/WebKit/Source/modules/storage/StorageNamespaceController.cpp +++ b/third_party/WebKit/Source/modules/storage/StorageNamespaceController.cpp
@@ -4,10 +4,13 @@ #include "modules/storage/StorageNamespaceController.h" +#include <memory> + #include "core/frame/ContentSettingsClient.h" #include "modules/storage/InspectorDOMStorageAgent.h" #include "modules/storage/StorageNamespace.h" #include "platform/wtf/PtrUtil.h" +#include "public/platform/Platform.h" #include "public/platform/WebStorageNamespace.h" #include "public/web/WebViewClient.h" @@ -54,8 +57,9 @@ if (!web_view_client_) return nullptr; - return WTF::WrapUnique(new StorageNamespace( - WTF::WrapUnique(web_view_client_->CreateSessionStorageNamespace()))); + return std::make_unique<StorageNamespace>( + Platform::Current()->CreateSessionStorageNamespace( + web_view_client_->GetSessionStorageNamespaceId())); } bool StorageNamespaceController::CanAccessStorage(LocalFrame* frame,
diff --git a/third_party/WebKit/Source/modules/webaudio/WindowAudioWorklet.cpp b/third_party/WebKit/Source/modules/webaudio/WindowAudioWorklet.cpp index 630331b..ed7be33 100644 --- a/third_party/WebKit/Source/modules/webaudio/WindowAudioWorklet.cpp +++ b/third_party/WebKit/Source/modules/webaudio/WindowAudioWorklet.cpp
@@ -11,6 +11,11 @@ namespace blink { AudioWorklet* WindowAudioWorklet::audioWorklet(LocalDOMWindow& window) { + // TODO(nhiroki): Replace this with the [SecureContext] attribute when it's + // supported (https://crbug.com/782121) + String error_message; + if (!window.GetExecutionContext()->IsSecureContext(error_message)) + return nullptr; if (!window.GetFrame()) return nullptr; return From(window).audio_worklet_.Get();
diff --git a/third_party/WebKit/Source/modules/webaudio/WindowAudioWorklet.idl b/third_party/WebKit/Source/modules/webaudio/WindowAudioWorklet.idl index da5d51c..95cf5a9d 100644 --- a/third_party/WebKit/Source/modules/webaudio/WindowAudioWorklet.idl +++ b/third_party/WebKit/Source/modules/webaudio/WindowAudioWorklet.idl
@@ -6,8 +6,9 @@ [ ImplementedAs=WindowAudioWorklet, - RuntimeEnabled=AudioWorklet, - SecureContext + RuntimeEnabled=AudioWorklet + // TODO(nhiroki): Specify the [SecureContext] attribute when it's supported. + // (https://crbug.com/782121) ] partial interface Window { readonly attribute Worklet audioWorklet; };
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index da9d78c2..c4e0fb2 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -311,7 +311,6 @@ "ResolutionUnits.h", "ScopedOrientationChangeIndicator.cpp", "ScopedOrientationChangeIndicator.h", - "ScopedVirtualTimePauser.h", "SecureTextInput.cpp", "SecureTextInput.h", "SerializedResource.h", @@ -1755,6 +1754,7 @@ "animation/TimingFunctionTest.cpp", "audio/PushPullFIFOMultithreadTest.cpp", "audio/PushPullFIFOTest.cpp", + "audio/VectorMathTest.cpp", "bindings/RuntimeCallStatsTest.cpp", "exported/FilePathConversionTest.cpp", "exported/WebCORSPreflightResultCacheTest.cpp",
diff --git a/third_party/WebKit/Source/platform/ScopedVirtualTimePauser.h b/third_party/WebKit/Source/platform/ScopedVirtualTimePauser.h deleted file mode 100644 index 26fc16a..0000000 --- a/third_party/WebKit/Source/platform/ScopedVirtualTimePauser.h +++ /dev/null
@@ -1,44 +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 ScopedVirtualTimePauser_h -#define ScopedVirtualTimePauser_h - -#include "platform/PlatformExport.h" - -namespace blink { -namespace scheduler { -class RendererSchedulerImpl; -} // namespace scheduler - -// A move only RAII style helper which makes it easier for subsystems to pause -// virtual time while performing an asynchronous operation. -class PLATFORM_EXPORT ScopedVirtualTimePauser { - public: - // Note simply creating a ScopedVirtualTimePauser doesn't cause VirtualTime to - // pause, instead you need to call PauseVirtualTime. - explicit ScopedVirtualTimePauser(scheduler::RendererSchedulerImpl*); - - ScopedVirtualTimePauser(); - ~ScopedVirtualTimePauser(); - - ScopedVirtualTimePauser(ScopedVirtualTimePauser&& other); - ScopedVirtualTimePauser& operator=(ScopedVirtualTimePauser&& other); - - ScopedVirtualTimePauser(const ScopedVirtualTimePauser&) = delete; - ScopedVirtualTimePauser& operator=(const ScopedVirtualTimePauser&) = delete; - - // Virtual time will be paused if any ScopedVirtualTimePauser votes to pause - // it, and only unpaused only if all ScopedVirtualTimePausers are either - // destroyed or vote to unpause. - void PauseVirtualTime(bool paused); - - private: - bool paused_ = false; - scheduler::RendererSchedulerImpl* scheduler_; // NOT OWNED -}; - -} // namespace blink - -#endif // ScopedVirtualTimePauser_h
diff --git a/third_party/WebKit/Source/platform/WebFrameScheduler.h b/third_party/WebKit/Source/platform/WebFrameScheduler.h index 3663a9b..3c10064 100644 --- a/third_party/WebKit/Source/platform/WebFrameScheduler.h +++ b/third_party/WebKit/Source/platform/WebFrameScheduler.h
@@ -6,8 +6,8 @@ #define WebFrameScheduler_h #include "base/memory/scoped_refptr.h" -#include "platform/ScopedVirtualTimePauser.h" #include "public/platform/TaskType.h" +#include "public/platform/WebScopedVirtualTimePauser.h" #include <memory> @@ -122,12 +122,13 @@ // Returns the parent WebViewScheduler. virtual WebViewScheduler* GetWebViewScheduler() const = 0; - // Returns a ScopedVirtualTimePauser which can be used to vote for pausing - // virtual time. Virtual time will be paused if any ScopedVirtualTimePauser - // votes to pause it, and only unpaused only if all ScopedVirtualTimePausers - // are either destroyed or vote to unpause. Note the ScopedVirtualTimePauser - // returned by this method is initially unpaused. - virtual ScopedVirtualTimePauser CreateScopedVirtualTimePauser() = 0; + // Returns a WebScopedVirtualTimePauser which can be used to vote for pausing + // virtual time. Virtual time will be paused if any WebScopedVirtualTimePauser + // votes to pause it, and only unpaused only if all + // WebScopedVirtualTimePausers are either destroyed or vote to unpause. Note + // the WebScopedVirtualTimePauser returned by this method is initially + // unpaused. + virtual WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser() = 0; // Tells the scheduler that a provisional load has started, the scheduler may // reset the task cost estimators and the UserModel. Must be called from the
diff --git a/third_party/WebKit/Source/platform/audio/VectorMathTest.cpp b/third_party/WebKit/Source/platform/audio/VectorMathTest.cpp new file mode 100644 index 0000000..cf9929b --- /dev/null +++ b/third_party/WebKit/Source/platform/audio/VectorMathTest.cpp
@@ -0,0 +1,418 @@ +// 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/audio/VectorMath.h" + +#include <algorithm> +#include <array> +#include <cmath> +#include <limits> +#include <numeric> +#include <random> +#include <vector> + +#include "platform/wtf/MathExtras.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { +namespace VectorMath { +namespace { + +struct MemoryLayout { + size_t byte_alignment; + size_t stride; +}; + +// This is the minimum aligned needed by AVX on x86 family architectures. +constexpr size_t kMaxBitAlignment = 256u; +constexpr size_t kMaxByteAlignment = kMaxBitAlignment / 8u; + +constexpr size_t kMaxStride = 2u; + +constexpr MemoryLayout kMemoryLayouts[] = { + {kMaxByteAlignment / 2u - kMaxByteAlignment / 4u, 1u}, + {kMaxByteAlignment / 2u, 1u}, + {kMaxByteAlignment / 2u + kMaxByteAlignment / 4u, 1u}, + {kMaxByteAlignment, 1u}, + {0u, kMaxStride}}; +constexpr size_t kMemoryLayoutCount = + sizeof(kMemoryLayouts) / sizeof(*kMemoryLayouts); + +// This is the minimum vector size in bytes needed for MSA instructions on +// MIPS. +constexpr size_t kMaxVectorSizeInBytes = 1024u; +constexpr size_t kVectorSizesInBytes[] = { + kMaxVectorSizeInBytes, + // This vector size in bytes is chosen so that the following optimization + // paths can be tested on x86 family architectures using different memory + // layouts: + // * AVX + SSE + scalar + // * scalar + SSE + AVX + // * SSE + AVX + scalar + // * scalar + AVX + SSE + // On other architectures, this vector size in bytes results in either + // optimization + scalar path or scalar path to be tested. + kMaxByteAlignment + kMaxByteAlignment / 2u + kMaxByteAlignment / 4u}; +constexpr size_t kVectorSizeCount = + sizeof(kVectorSizesInBytes) / sizeof(*kVectorSizesInBytes); + +// Compare two floats and consider all NaNs to be equal. +bool Equal(float a, float b) { + if (std::isnan(a)) + return std::isnan(b); + return a == b; +} + +// This represents a real source or destination vector which is aligned, can be +// non-contiguous and can be used as a source or destination vector for +// blink::VectorMath functions. +template <typename T> +class TestVector { + class Iterator { + public: + // These types are used by std::iterator_traits used by std::equal used by + // TestVector::operator==. + using difference_type = ptrdiff_t; + using iterator_category = std::input_iterator_tag; + using pointer = T*; + using reference = T&; + using value_type = T; + + Iterator(T* p, int stride) : p_(p), stride_(stride) {} + + Iterator& operator++() { + p_ += stride_; + return *this; + } + Iterator operator++(int) { + Iterator iter = *this; + ++(*this); + return iter; + } + bool operator==(const Iterator& other) const { return p_ == other.p_; } + bool operator!=(const Iterator& other) const { return !(*this == other); } + T& operator*() const { return *p_; } + + private: + T* p_; + size_t stride_; + }; + + public: + // These types are used internally by Google Test. + using const_iterator = Iterator; + using iterator = Iterator; + + TestVector() = default; + TestVector(T* base, const MemoryLayout* memory_layout, size_t size) + : p_(GetAligned(base, memory_layout->byte_alignment)), + memory_layout_(memory_layout), + size_(size) {} + TestVector(T* base, const TestVector<const T>& primary_vector) + : TestVector(base, + primary_vector.memory_layout(), + primary_vector.size()) {} + + Iterator begin() const { return Iterator(p_, stride()); } + Iterator end() const { return Iterator(p_ + size() * stride(), stride()); } + const MemoryLayout* memory_layout() const { return memory_layout_; } + T* p() const { return p_; } + size_t size() const { return size_; } + int stride() const { return static_cast<int>(memory_layout()->stride); } + + bool operator==(const TestVector& other) const { + return std::equal(begin(), end(), other.begin(), other.end(), Equal); + } + T& operator[](size_t i) const { return p_[i * stride()]; } + + private: + static T* GetAligned(T* base, size_t byte_alignment) { + size_t base_byte_alignment = GetByteAlignment(base); + size_t byte_offset = + (byte_alignment - base_byte_alignment + kMaxByteAlignment) % + kMaxByteAlignment; + T* p = base + byte_offset / sizeof(T); + size_t p_byte_alignment = GetByteAlignment(p); + CHECK_EQ(byte_alignment % kMaxByteAlignment, p_byte_alignment); + return p; + } + static size_t GetByteAlignment(T* p) { + return reinterpret_cast<size_t>(p) % kMaxByteAlignment; + } + + T* p_; + const MemoryLayout* memory_layout_; + size_t size_; +}; + +// Get primary input vectors with difference memory layout and size +// combinations. +template <typename T> +std::array<TestVector<const T>, kVectorSizeCount * kMemoryLayoutCount> +GetPrimaryVectors(const T* base) { + std::array<TestVector<const T>, kVectorSizeCount * kMemoryLayoutCount> + vectors; + for (auto& vector : vectors) { + ptrdiff_t i = &vector - &vectors[0]; + ptrdiff_t memory_layout_index = i % kMemoryLayoutCount; + ptrdiff_t size_index = i / kMemoryLayoutCount; + vector = TestVector<const T>(base, &kMemoryLayouts[memory_layout_index], + kVectorSizesInBytes[size_index] / sizeof(T)); + } + return vectors; +} + +// Get secondary input or output vectors. As the size of a secondary vector +// must always be the same as the size of the primary input vector, there are +// only two interesting secondary vectors: +// - A vector with the same memory layout as the primary input vector has and +// which therefore is aligned whenever the primary input vector is aligned. +// - A vector with a different memory layout than the primary input vector has +// and which therefore is not aligned when the primary input vector is +// aligned. +template <typename T> +std::array<TestVector<T>, 2u> GetSecondaryVectors( + T* base, + const TestVector<const float>& primary_vector) { + std::array<TestVector<T>, 2u> vectors; + const MemoryLayout* primary_memory_layout = primary_vector.memory_layout(); + const MemoryLayout* other_memory_layout = + &kMemoryLayouts[primary_memory_layout == &kMemoryLayouts[0]]; + CHECK_NE(primary_memory_layout, other_memory_layout); + vectors[0] = TestVector<T>(base, primary_vector); + vectors[1] = TestVector<T>(base, other_memory_layout, primary_vector.size()); + return vectors; +} + +class VectorMathTest : public testing::Test { + protected: + enum { + kDestinationCount = 4u, + kFloatArraySize = + (kMaxStride * kMaxVectorSizeInBytes + kMaxByteAlignment - 1u) / + sizeof(float), + kFullyFiniteSource = 4u, + kFullyNonNanSource = 5u, + kSourceCount = 6u + }; + + // Get a destination buffer containing initially uninitialized floats. + float* GetDestination(size_t i) { + CHECK_LT(i, kDestinationCount); + return destinations_[i]; + } + // Get a source buffer containing random floats. + const float* GetSource(size_t i) { + CHECK_LT(i, kSourceCount); + return sources_[i]; + } + + static void SetUpTestCase() { + std::minstd_rand generator(3141592653u); + // Fill in source buffers with finite random floats. + std::uniform_real_distribution<float> float_distribution(-10.0f, 10.0f); + std::generate_n(&**sources_, sizeof(sources_) / sizeof(**sources_), + [&]() { return float_distribution(generator); }); + // Add INFINITYs and NANs to most source buffers. + std::uniform_int_distribution<size_t> index_distribution( + 0u, kFloatArraySize / 2u - 1u); + for (size_t i = 0u; i < kSourceCount; ++i) { + if (i == kFullyFiniteSource) + continue; + sources_[i][index_distribution(generator)] = INFINITY; + sources_[i][index_distribution(generator)] = -INFINITY; + if (i != kFullyNonNanSource) + sources_[i][index_distribution(generator)] = NAN; + } + }; + + private: + static float destinations_[kDestinationCount][kFloatArraySize]; + static float sources_[kSourceCount][kFloatArraySize]; +}; + +float VectorMathTest::destinations_[kDestinationCount][kFloatArraySize]; +float VectorMathTest::sources_[kSourceCount][kFloatArraySize]; + +TEST_F(VectorMathTest, Vadd) { + for (const auto& source1 : GetPrimaryVectors(GetSource(0u))) { + for (const auto& source2 : GetSecondaryVectors(GetSource(1u), source1)) { + TestVector<float> expected_dest(GetDestination(0u), source1); + for (size_t i = 0u; i < source1.size(); ++i) + expected_dest[i] = source1[i] + source2[i]; + for (auto& dest : GetSecondaryVectors(GetDestination(1u), source1)) { + Vadd(source1.p(), source1.stride(), source2.p(), source2.stride(), + dest.p(), dest.stride(), source1.size()); + EXPECT_EQ(expected_dest, dest); + } + } + } +} + +TEST_F(VectorMathTest, Vclip) { + // Vclip does not accept NaNs thus let's use only sources without NaNs. + for (const auto& source : GetPrimaryVectors(GetSource(kFullyNonNanSource))) { + const float* thresholds = GetSource(kFullyFiniteSource); + const float low_threshold = std::min(thresholds[0], thresholds[1]); + const float high_threshold = std::max(thresholds[0], thresholds[1]); + TestVector<float> expected_dest(GetDestination(0u), source); + for (size_t i = 0u; i < source.size(); ++i) + expected_dest[i] = clampTo(source[i], low_threshold, high_threshold); + for (auto& dest : GetSecondaryVectors(GetDestination(1u), source)) { + Vclip(source.p(), source.stride(), &low_threshold, &high_threshold, + dest.p(), dest.stride(), source.size()); + EXPECT_EQ(expected_dest, dest); + } + } +} + +TEST_F(VectorMathTest, Vmaxmgv) { + const auto maxmg = [](float init, float x) { + return std::max(init, std::abs(x)); + }; + // Vmaxmgv does not accept NaNs thus let's use only sources without NaNs. + for (const float* source_base : + {GetSource(kFullyFiniteSource), GetSource(kFullyNonNanSource)}) { + for (const auto& source : GetPrimaryVectors(source_base)) { + const float expected_max = + std::accumulate(source.begin(), source.end(), 0.0f, maxmg); + float max; + Vmaxmgv(source.p(), source.stride(), &max, source.size()); + EXPECT_EQ(expected_max, max) << testing::PrintToString(source); + } + } +} + +TEST_F(VectorMathTest, Vmul) { + for (const auto& source1 : GetPrimaryVectors(GetSource(0u))) { + for (const auto& source2 : GetSecondaryVectors(GetSource(1u), source1)) { + TestVector<float> expected_dest(GetDestination(0u), source1); + for (size_t i = 0u; i < source1.size(); ++i) + expected_dest[i] = source1[i] * source2[i]; + for (auto& dest : GetSecondaryVectors(GetDestination(1u), source1)) { + Vmul(source1.p(), source1.stride(), source2.p(), source2.stride(), + dest.p(), dest.stride(), source1.size()); + EXPECT_EQ(expected_dest, dest); + } + } + } +} + +TEST_F(VectorMathTest, Vsma) { + for (const auto& source : GetPrimaryVectors(GetSource(0u))) { + const float scale = *GetSource(1u); + const TestVector<const float> dest_source(GetSource(2u), source); + TestVector<float> expected_dest(GetDestination(0u), source); + for (size_t i = 0u; i < source.size(); ++i) + expected_dest[i] = dest_source[i] + scale * source[i]; + for (auto& dest : GetSecondaryVectors(GetDestination(1u), source)) { + std::copy(dest_source.begin(), dest_source.end(), dest.begin()); + Vsma(source.p(), source.stride(), &scale, dest.p(), dest.stride(), + source.size()); + // Different optimizations may use different precisions for intermediate + // results which may result in different rounding errors thus let's + // expect only mostly equal floats. + for (size_t i = 0u; i < source.size(); ++i) { + if (std::isfinite(expected_dest[i])) + EXPECT_FLOAT_EQ(expected_dest[i], dest[i]); + else + EXPECT_PRED2(Equal, expected_dest[i], dest[i]); + } + } + } +} + +TEST_F(VectorMathTest, Vsmul) { + for (const auto& source : GetPrimaryVectors(GetSource(0u))) { + const float scale = *GetSource(1u); + TestVector<float> expected_dest(GetDestination(0u), source); + for (size_t i = 0u; i < source.size(); ++i) + expected_dest[i] = scale * source[i]; + for (auto& dest : GetSecondaryVectors(GetDestination(1u), source)) { + Vsmul(source.p(), source.stride(), &scale, dest.p(), dest.stride(), + source.size()); + EXPECT_EQ(expected_dest, dest); + } + } +} + +TEST_F(VectorMathTest, Vsvesq) { + const auto sqsum = [](float init, float x) { return init + x * x; }; + for (const float* source_base : + {GetSource(0u), GetSource(kFullyFiniteSource)}) { + for (const auto& source : GetPrimaryVectors(source_base)) { + const float expected_sum = + std::accumulate(source.begin(), source.end(), 0.0f, sqsum); + float sum; + Vsvesq(source.p(), source.stride(), &sum, source.size()); + if (std::isfinite(expected_sum)) { + // Optimized paths in Vsvesq use parallel partial sums which may result + // in different rounding errors than the non-partial sum algorithm used + // here and in non-optimized paths in Vsvesq. + EXPECT_FLOAT_EQ(expected_sum, sum); + } else if (std::isnan(expected_sum)) { + EXPECT_TRUE(std::isnan(sum)); + } else { // +INFINITY or -INFINITY + EXPECT_EQ(expected_sum, sum); + } + } + } +} + +TEST_F(VectorMathTest, Zvmul) { + constexpr float kMax = std::numeric_limits<float>::max(); + std::vector<std::array<float, kFloatArraySize + 1u>> sources(4u); + for (size_t i = 0u; i < sources.size(); ++i) { + // Initialize a local source with a randomized test case source. + std::copy_n(GetSource(i), kFloatArraySize, sources[i].begin()); + // Put +FLT_MAX and -FLT_MAX in the middle of the source. Use a different + // sequence for each source in order to get 16 different combinations. + for (size_t j = 0u; j < 16u; ++j) + sources[i][kFloatArraySize / 2u + j] = ((j >> i) & 1) ? -kMax : kMax; + } + for (const auto& real1 : GetPrimaryVectors(sources[0u].data())) { + if (real1.stride() != 1) + continue; + const TestVector<const float> imag1(sources[1u].data(), real1); + const TestVector<const float> real2(sources[2u].data(), real1); + const TestVector<const float> imag2(sources[3u].data(), real1); + TestVector<float> expected_dest_real(GetDestination(0u), real1); + TestVector<float> expected_dest_imag(GetDestination(1u), real1); + for (size_t i = 0u; i < real1.size(); ++i) { + expected_dest_real[i] = real1[i] * real2[i] - imag1[i] * imag2[i]; + expected_dest_imag[i] = real1[i] * imag2[i] + imag1[i] * real2[i]; + if (&real1[i] >= &sources[0u][kFloatArraySize / 2u] && + &real1[i] < &sources[0u][kFloatArraySize / 2u] + 16u) { + // FLT_MAX products should have overflowed. + EXPECT_TRUE(std::isinf(expected_dest_real[i]) || + std::isinf(expected_dest_imag[i])); + EXPECT_TRUE(std::isnan(expected_dest_real[i]) || + std::isnan(expected_dest_imag[i])); + } + } + for (auto& dest_real : GetSecondaryVectors(GetDestination(2u), real1)) { + TestVector<float> dest_imag(GetDestination(3u), real1); + ASSERT_EQ(1, dest_real.stride()); + Zvmul(real1.p(), imag1.p(), real2.p(), imag2.p(), dest_real.p(), + dest_imag.p(), real1.size()); + // Different optimizations may use different precisions for intermediate + // results which may result in different rounding errors thus let's + // expect only mostly equal floats. + for (size_t i = 0u; i < real1.size(); ++i) { + if (std::isfinite(expected_dest_real[i])) + EXPECT_FLOAT_EQ(expected_dest_real[i], dest_real[i]); + else + EXPECT_PRED2(Equal, expected_dest_real[i], dest_real[i]); + if (std::isfinite(expected_dest_imag[i])) + EXPECT_FLOAT_EQ(expected_dest_imag[i], dest_imag[i]); + else + EXPECT_PRED2(Equal, expected_dest_imag[i], dest_imag[i]); + } + } + } +} + +} // namespace +} // namespace VectorMath +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.cpp b/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.cpp index 813e3a3..90bd269 100644 --- a/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.cpp +++ b/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.cpp
@@ -60,7 +60,6 @@ V8PerIsolateData::V8PerIsolateData( WebTaskRunner* task_runner, - const intptr_t* table, V8ContextSnapshotMode v8_context_snapshot_mode) : v8_context_snapshot_mode_(v8_context_snapshot_mode), isolate_holder_( @@ -68,7 +67,6 @@ gin::IsolateHolder::kSingleThread, IsMainThread() ? gin::IsolateHolder::kDisallowAtomicsWait : gin::IsolateHolder::kAllowAtomicsWait, - table, v8_context_snapshot_mode_ == V8ContextSnapshotMode::kUseSnapshot ? &startup_data_ : nullptr), @@ -96,9 +94,9 @@ // This constructor is used for taking a V8 context snapshot. It must run on the // main thread. -V8PerIsolateData::V8PerIsolateData(const intptr_t* reference_table) +V8PerIsolateData::V8PerIsolateData() : v8_context_snapshot_mode_(V8ContextSnapshotMode::kTakeSnapshot), - isolate_holder_(reference_table, &startup_data_), + isolate_holder_(&startup_data_), interface_template_map_for_v8_context_snapshot_(GetIsolate()), string_cache_(WTF::WrapUnique(new StringCache(GetIsolate()))), private_property_(V8PrivateProperty::Create()), @@ -120,17 +118,12 @@ } v8::Isolate* V8PerIsolateData::Initialize(WebTaskRunner* task_runner, - const intptr_t* reference_table, V8ContextSnapshotMode context_mode) { - DCHECK(context_mode == V8ContextSnapshotMode::kDontUseSnapshot || - reference_table); - V8PerIsolateData* data = nullptr; if (context_mode == V8ContextSnapshotMode::kTakeSnapshot) { - CHECK(reference_table); - data = new V8PerIsolateData(reference_table); + data = new V8PerIsolateData(); } else { - data = new V8PerIsolateData(task_runner, reference_table, context_mode); + data = new V8PerIsolateData(task_runner, context_mode); } DCHECK(data);
diff --git a/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.h b/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.h index d19af1f..2d98b24 100644 --- a/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.h +++ b/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.h
@@ -100,7 +100,6 @@ }; static v8::Isolate* Initialize(WebTaskRunner*, - const intptr_t* reference_table, V8ContextSnapshotMode); static V8PerIsolateData* From(v8::Isolate* isolate) { @@ -236,9 +235,8 @@ private: V8PerIsolateData(WebTaskRunner*, - const intptr_t* reference_table, V8ContextSnapshotMode); - explicit V8PerIsolateData(const intptr_t* reference_table); + V8PerIsolateData(); ~V8PerIsolateData(); // A really simple hash function, which makes lookups faster. The set of
diff --git a/third_party/WebKit/Source/platform/exported/Platform.cpp b/third_party/WebKit/Source/platform/exported/Platform.cpp index 11bb6c0..f8bf06e 100644 --- a/third_party/WebKit/Source/platform/exported/Platform.cpp +++ b/third_party/WebKit/Source/platform/exported/Platform.cpp
@@ -210,6 +210,11 @@ return nullptr; } +std::unique_ptr<WebStorageNamespace> Platform::CreateSessionStorageNamespace( + int64_t namespace_id) { + return nullptr; +} + std::unique_ptr<WebServiceWorkerCacheStorage> Platform::CreateCacheStorage( const WebSecurityOrigin&) { return nullptr;
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp index cf4b34f..296b9ff 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -27,6 +27,7 @@ #include <memory> #include "base/memory/ptr_util.h" +#include "components/viz/common/resources/transferable_resource.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "platform/Histogram.h" #include "platform/WebTaskRunner.h" @@ -614,8 +615,8 @@ return resource_provider_.get(); } -bool Canvas2DLayerBridge::PrepareTextureMailbox( - viz::TextureMailbox* out_mailbox, +bool Canvas2DLayerBridge::PrepareTransferableResource( + viz::TransferableResource* out_resource, std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) { if (destruction_in_progress_) { // It can be hit in the following sequence. @@ -651,9 +652,9 @@ } FlushRecording(); - if (resource_provider_->PrepareTextureMailbox(out_mailbox, - out_release_callback)) { - out_mailbox->set_color_space(color_params_.GetSamplerGfxColorSpace()); + if (resource_provider_->PrepareTransferableResource(out_resource, + out_release_callback)) { + out_resource->color_space = color_params_.GetSamplerGfxColorSpace(); return true; } return false;
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h index b6dc6ad..2a50ae8 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
@@ -86,9 +86,9 @@ ~Canvas2DLayerBridge() override; // cc::TextureLayerClient implementation. - bool PrepareTextureMailbox(viz::TextureMailbox* out_mailbox, - std::unique_ptr<viz::SingleReleaseCallback>* - out_release_callback) override; + bool PrepareTransferableResource(viz::TransferableResource* out_resource, + std::unique_ptr<viz::SingleReleaseCallback>* + out_release_callback) override; // ImageBufferSurface implementation void FinalizeFrame() override;
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp index eabd4d6..39049e0 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
@@ -28,8 +28,8 @@ #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" #include "build/build_config.h" -#include "components/viz/common/quads/texture_mailbox.h" #include "components/viz/common/resources/single_release_callback.h" +#include "components/viz/common/resources/transferable_resource.h" #include "components/viz/test/test_gpu_memory_buffer_manager.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/common/capabilities.h" @@ -245,10 +245,10 @@ // GL frames for the compositor or not, so fail to generate frames. gl_.SetIsContextLost(true); - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; EXPECT_FALSE( - bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback)); + bridge->PrepareTransferableResource(&resource, &release_callback)); } void PrepareMailboxWhenContextIsLostWithFailedRestore() { @@ -269,14 +269,14 @@ // restore while the GPU process is down. bridge->Restore(); - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; EXPECT_FALSE( - bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback)); + bridge->PrepareTransferableResource(&resource, &release_callback)); } void ReleaseCallbackWithNullContextProviderWrapperTest() { - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; { @@ -286,7 +286,7 @@ CanvasColorParams()))); bridge->FinalizeFrame(); EXPECT_TRUE( - bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback)); + bridge->PrepareTransferableResource(&resource, &release_callback)); } bool lost_resource = true; @@ -307,10 +307,10 @@ Canvas2DLayerBridge::kForceAccelerationForTesting, CanvasColorParams(), IsUnitTest()))); bridge->FinalizeFrame(); - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; EXPECT_TRUE( - bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback)); + bridge->PrepareTransferableResource(&resource, &release_callback)); bool lost_resource = true; release_callback->Run(gpu::SyncToken(), lost_resource); @@ -318,7 +318,7 @@ // Retry with mailbox released while bridge destruction is in progress. { - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; { @@ -327,7 +327,7 @@ Canvas2DLayerBridge::kForceAccelerationForTesting, CanvasColorParams(), IsUnitTest()))); bridge->FinalizeFrame(); - bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback); + bridge->PrepareTransferableResource(&resource, &release_callback); // |bridge| goes out of scope and would normally be destroyed, but // object is kept alive by self references. } @@ -1004,11 +1004,11 @@ platform->RunUntilIdle(); ::testing::Mock::VerifyAndClearExpectations(mock_logger_ptr); - // Test prepareMailbox while hibernating - viz::TextureMailbox texture_mailbox; + // Test PrepareTransferableResource() while hibernating + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; EXPECT_FALSE( - bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback)); + bridge->PrepareTransferableResource(&resource, &release_callback)); EXPECT_TRUE(bridge->IsValid()); // Tear down the bridge on the thread so that 'bridge' can go out of scope @@ -1060,10 +1060,10 @@ EXPECT_TRUE(bridge->IsValid()); // Test prepareMailbox while background rendering - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; EXPECT_FALSE( - bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback)); + bridge->PrepareTransferableResource(&resource, &release_callback)); EXPECT_TRUE(bridge->IsValid()); } @@ -1075,8 +1075,8 @@ ->GetCapabilities()) .texture_format_bgra8888 = true; - viz::TextureMailbox texture_mailbox1; - viz::TextureMailbox texture_mailbox2; + viz::TransferableResource resource1; + viz::TransferableResource resource2; std::unique_ptr<viz::SingleReleaseCallback> release_callback1; std::unique_ptr<viz::SingleReleaseCallback> release_callback2; const GLuint texture_id1 = 1; @@ -1094,7 +1094,7 @@ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id1)); DrawSomething(bridge); bridge->FinalizeFrame(); - bridge->PrepareTextureMailbox(&texture_mailbox1, &release_callback1); + bridge->PrepareTransferableResource(&resource1, &release_callback1); ::testing::Mock::VerifyAndClearExpectations(&gl_); @@ -1102,7 +1102,7 @@ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id2)); DrawSomething(bridge); bridge->FinalizeFrame(); - bridge->PrepareTextureMailbox(&texture_mailbox2, &release_callback2); + bridge->PrepareTransferableResource(&resource2, &release_callback2); ::testing::Mock::VerifyAndClearExpectations(&gl_); @@ -1141,8 +1141,8 @@ ->GetCapabilities()) .texture_format_bgra8888 = true; - viz::TextureMailbox texture_mailbox1; - viz::TextureMailbox texture_mailbox2; + viz::TransferableResource resource1; + viz::TransferableResource resource2; std::unique_ptr<viz::SingleReleaseCallback> release_callback1; std::unique_ptr<viz::SingleReleaseCallback> release_callback2; const GLuint texture_id1 = 1; @@ -1160,7 +1160,7 @@ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id1)); DrawSomething(bridge); bridge->FinalizeFrame(); - bridge->PrepareTextureMailbox(&texture_mailbox1, &release_callback1); + bridge->PrepareTransferableResource(&resource1, &release_callback1); ::testing::Mock::VerifyAndClearExpectations(&gl_); @@ -1168,7 +1168,7 @@ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id2)); DrawSomething(bridge); bridge->FinalizeFrame(); - bridge->PrepareTextureMailbox(&texture_mailbox2, &release_callback2); + bridge->PrepareTransferableResource(&resource2, &release_callback2); ::testing::Mock::VerifyAndClearExpectations(&gl_); @@ -1206,7 +1206,7 @@ ->GetCapabilities()) .texture_format_bgra8888 = true; - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; const GLuint texture_id = 1; const GLuint image_id = 2; @@ -1221,7 +1221,7 @@ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id)); DrawSomething(bridge); bridge->FinalizeFrame(); - bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback); + bridge->PrepareTransferableResource(&resource, &release_callback); ::testing::Mock::VerifyAndClearExpectations(&gl_);
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.cpp b/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.cpp index 2a8c594..0527b064 100644 --- a/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.cpp +++ b/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.cpp
@@ -6,6 +6,7 @@ #include "cc/paint/skia_paint_canvas.h" #include "components/viz/common/resources/single_release_callback.h" +#include "components/viz/common/resources/transferable_resource.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" @@ -45,19 +46,20 @@ bool IsValid() const final { return GetSkSurface() && !IsGpuContextLost(); } bool IsAccelerated() const final { return true; } - bool CanPrepareTextureMailbox() const final { return true; } + bool CanPrepareTransferableResource() const final { return true; } protected: virtual bool isOverlayCandidate() { return false; } - void ResourceToMailbox(CanvasResource* resource, - GLenum target, - viz::TextureMailbox* out_mailbox) { + void TransferResource(CanvasResource* resource, + GLenum target, + viz::TransferableResource* out_resource) { auto gl = ContextGL(); auto gr = GetGrContext(); DCHECK(gl && gr); GLuint texture_id = resource->TextureId(); + GLuint filter = UseNearestNeighbor() ? GL_NEAREST : GL_LINEAR; gl->BindTexture(target, texture_id); gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GetGLFilter()); @@ -72,12 +74,10 @@ gpu::SyncToken sync_token; gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); - *out_mailbox = viz::TextureMailbox(mailbox, sync_token, target, - gfx::Size(Size()), isOverlayCandidate()); - - gfx::ColorSpace color_space = ColorParams().GetStorageGfxColorSpace(); - out_mailbox->set_color_space(color_space); - out_mailbox->set_nearest_neighbor(UseNearestNeighbor()); + *out_resource = viz::TransferableResource::MakeGLOverlay( + mailbox, filter, target, sync_token, gfx::Size(Size()), + isOverlayCandidate()); + out_resource->color_space = ColorParams().GetStorageGfxColorSpace(); gl->BindTexture(target, 0); @@ -94,8 +94,8 @@ return StaticBitmapImage::Create(image, ContextProviderWrapper()); } - std::unique_ptr<CanvasResource> DoPrepareTextureMailbox( - viz::TextureMailbox* out_mailbox) override { + std::unique_ptr<CanvasResource> DoPrepareTransferableResource( + viz::TransferableResource* out_resource) override { DCHECK(GetSkSurface()); if (IsGpuContextLost()) @@ -122,7 +122,7 @@ if (!resource) return nullptr; - ResourceToMailbox(resource.get(), GL_TEXTURE_2D, out_mailbox); + TransferResource(resource.get(), GL_TEXTURE_2D, out_resource); image->getTexture()->textureParamsModified(); return resource; @@ -175,8 +175,8 @@ ContextProviderWrapper()); } - std::unique_ptr<CanvasResource> DoPrepareTextureMailbox( - viz::TextureMailbox* out_mailbox) final { + std::unique_ptr<CanvasResource> DoPrepareTransferableResource( + viz::TransferableResource* out_resource) final { DCHECK(GetSkSurface()); if (IsGpuContextLost()) @@ -185,8 +185,8 @@ std::unique_ptr<CanvasResource> output_resource = NewOrRecycledResource(); if (!output_resource) { // GpuMemoryBuffer creation failed, fallback to Texture resource - return CanvasResourceProvider_Texture::DoPrepareTextureMailbox( - out_mailbox); + return CanvasResourceProvider_Texture::DoPrepareTransferableResource( + out_resource); } auto gl = ContextGL(); @@ -211,7 +211,7 @@ false /*unpackPremultiplyAlpha*/, false /*unpackUnmultiplyAlpha*/); - ResourceToMailbox(output_resource.get(), target, out_mailbox); + TransferResource(output_resource.get(), target, out_resource); return output_resource; } }; @@ -235,7 +235,7 @@ bool IsValid() const final { return GetSkSurface(); } bool IsAccelerated() const final { return false; } - bool CanPrepareTextureMailbox() const final { return false; } + bool CanPrepareTransferableResource() const final { return false; } private: scoped_refptr<StaticBitmapImage> CreateSnapshot() override { @@ -245,8 +245,8 @@ return StaticBitmapImage::Create(image); } - std::unique_ptr<CanvasResource> DoPrepareTextureMailbox( - viz::TextureMailbox* out_mailbox) final { + std::unique_ptr<CanvasResource> DoPrepareTransferableResource( + viz::TransferableResource* out_resource) final { NOTREACHED(); // Not directly compositable. return nullptr; } @@ -456,12 +456,12 @@ return CreateResource(); } -bool CanvasResourceProvider::PrepareTextureMailbox( - viz::TextureMailbox* out_mailbox, +bool CanvasResourceProvider::PrepareTransferableResource( + viz::TransferableResource* out_resource, std::unique_ptr<viz::SingleReleaseCallback>* out_callback) { - DCHECK(CanPrepareTextureMailbox()); + DCHECK(CanPrepareTransferableResource()); std::unique_ptr<CanvasResource> resource = - DoPrepareTextureMailbox(out_mailbox); + DoPrepareTransferableResource(out_resource); if (!resource) return false; auto func =
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.h b/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.h index adad603..91191c9b 100644 --- a/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.h +++ b/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.h
@@ -34,7 +34,7 @@ namespace viz { class SingleReleaseCallback; -class TextureMailbox; +struct TransferableResource; } // namespace viz @@ -82,12 +82,13 @@ const CanvasColorParams& ColorParams() const { return color_params_; } scoped_refptr<StaticBitmapImage> Snapshot(); void SetFilterQuality(SkFilterQuality quality) { filter_quality_ = quality; } - bool PrepareTextureMailbox(viz::TextureMailbox*, - std::unique_ptr<viz::SingleReleaseCallback>*); + bool PrepareTransferableResource( + viz::TransferableResource*, + std::unique_ptr<viz::SingleReleaseCallback>*); const IntSize& Size() const { return size_; } virtual bool IsValid() const = 0; virtual bool IsAccelerated() const = 0; - virtual bool CanPrepareTextureMailbox() const = 0; + virtual bool CanPrepareTransferableResource() const = 0; uint32_t ContentUniqueID() const; void ClearRecycledResources(); void RecycleResource(std::unique_ptr<CanvasResource>); @@ -119,8 +120,8 @@ virtual sk_sp<SkSurface> CreateSkSurface() const = 0; virtual scoped_refptr<StaticBitmapImage> CreateSnapshot() = 0; virtual std::unique_ptr<CanvasResource> CreateResource(); - virtual std::unique_ptr<CanvasResource> DoPrepareTextureMailbox( - viz::TextureMailbox* out_mailbox) = 0; + virtual std::unique_ptr<CanvasResource> DoPrepareTransferableResource( + viz::TransferableResource* out_resource) = 0; WeakPtrFactory<CanvasResourceProvider> weak_ptr_factory_; WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
diff --git a/third_party/WebKit/Source/platform/graphics/SurfaceLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/SurfaceLayerBridge.cpp index b1ccf66..d4da8f0 100644 --- a/third_party/WebKit/Source/platform/graphics/SurfaceLayerBridge.cpp +++ b/third_party/WebKit/Source/platform/graphics/SurfaceLayerBridge.cpp
@@ -13,7 +13,6 @@ #include "components/viz/common/surfaces/surface_info.h" #include "components/viz/common/surfaces/surface_sequence.h" #include "media/base/media_switches.h" -#include "platform/graphics/GraphicsLayer.h" #include "platform/mojo/MojoHelper.h" #include "platform/wtf/Functional.h" #include "public/platform/InterfaceProvider.h" @@ -100,7 +99,8 @@ web_layer_ = Platform::Current()->CompositorSupport()->CreateLayerFromCCLayer( cc_layer_.get()); - GraphicsLayer::RegisterContentsLayer(web_layer_.get()); + if (observer_) + observer_->RegisterContentsLayer(web_layer_.get()); } void SurfaceLayerBridge::OnFirstSurfaceActivation( @@ -109,7 +109,8 @@ // First time a SurfaceId is received current_surface_id_ = surface_info.id(); if (web_layer_) { - GraphicsLayer::UnregisterContentsLayer(web_layer_.get()); + if (observer_) + observer_->UnregisterContentsLayer(web_layer_.get()); web_layer_->RemoveFromParent(); } @@ -124,7 +125,8 @@ web_layer_ = Platform::Current()->CompositorSupport()->CreateLayerFromCCLayer( cc_layer_.get()); - GraphicsLayer::RegisterContentsLayer(web_layer_.get()); + if (observer_) + observer_->RegisterContentsLayer(web_layer_.get()); } else if (current_surface_id_ != surface_info.id()) { // A different SurfaceId is received, prompting change to existing // SurfaceLayer
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.cpp b/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.cpp index 137b27b..fd7bfc6b 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.cpp
@@ -42,9 +42,7 @@ // so need to subtract off the layer offset. rect.Rect().Move(-layer_bounds_.x(), -layer_bounds_.y()); rect.Rect().Inflate(chunk.outset_for_raster_effects); - return Intersection( - EnclosingIntRect(rect.Rect()), - IntRect(0, 0, layer_bounds_.width(), layer_bounds_.height())); + return ClipByLayerBounds(EnclosingIntRect(rect.Rect())); } TransformationMatrix CompositedLayerRasterInvalidator::ChunkToLayerTransform( @@ -56,6 +54,24 @@ return matrix; } +// Returns the clip rect when we know it is precise (no radius, no complex +// transform, no pixel moving filter, etc.) +FloatClipRect CompositedLayerRasterInvalidator::ChunkToLayerClip( + const PaintChunk& chunk) const { + FloatClipRect clip_rect; + if (chunk.properties.property_tree_state.Effect() != layer_state_.Effect()) { + // Don't bother GeometryMapper because we don't need the rect when it's not + // tight because of the effect nodes. + clip_rect.ClearIsTight(); + } else { + clip_rect = GeometryMapper::LocalToAncestorClipRect( + chunk.properties.property_tree_state, layer_state_); + if (clip_rect.IsTight()) + clip_rect.MoveBy(FloatPoint(-layer_bounds_.x(), -layer_bounds_.y())); + } + return clip_rect; +} + size_t CompositedLayerRasterInvalidator::MatchNewChunkToOldChunk( const PaintChunk& new_chunk, size_t old_index) { @@ -70,32 +86,50 @@ return kNotFound; } -bool CompositedLayerRasterInvalidator::ChunkPropertiesChanged( +PaintInvalidationReason +CompositedLayerRasterInvalidator::ChunkPropertiesChanged( const PaintChunkInfo& new_chunk, const PaintChunkInfo& old_chunk) const { if (new_chunk.properties.backface_hidden != old_chunk.properties.backface_hidden) - return true; - - // Treat the chunk property as changed if clip or effect node is different, - // or the value of clip or effect nodes changed between the layer state and - // the the chunk state. - const auto& new_chunk_state = new_chunk.properties.property_tree_state; - const auto& old_chunk_state = old_chunk.properties.property_tree_state; - if (new_chunk_state.Clip() != old_chunk_state.Clip() || - new_chunk_state.Clip()->Changed(*layer_state_.Clip()) || - new_chunk_state.Effect() != old_chunk_state.Effect() || - new_chunk_state.Effect()->Changed(*layer_state_.Effect())) - return true; + return PaintInvalidationReason::kPaintProperty; // Special case for transform changes because we may create or delete some // transform nodes when no raster invalidation is needed. For example, when // a composited layer previously not transformed now gets transformed. // Check for real accumulated transform change instead. if (new_chunk.chunk_to_layer_transform != old_chunk.chunk_to_layer_transform) - return true; + return PaintInvalidationReason::kPaintProperty; - return false; + // Treat the chunk property as changed if the effect node pointer is + // different, or the effect node's value changed between the layer state and + // the chunk state. + const auto& new_chunk_state = new_chunk.properties.property_tree_state; + const auto& old_chunk_state = old_chunk.properties.property_tree_state; + if (new_chunk_state.Effect() != old_chunk_state.Effect() || + new_chunk_state.Effect()->Changed(*layer_state_.Effect())) + return PaintInvalidationReason::kPaintProperty; + + // Check for accumulated clip rect change, if the clip rects are tight. + if (new_chunk.chunk_to_layer_clip.IsTight() && + old_chunk.chunk_to_layer_clip.IsTight()) { + if (new_chunk.chunk_to_layer_clip == old_chunk.chunk_to_layer_clip) + return PaintInvalidationReason::kNone; + // Ignore differences out of the current layer bounds. + if (ClipByLayerBounds(new_chunk.chunk_to_layer_clip.Rect()) == + ClipByLayerBounds(old_chunk.chunk_to_layer_clip.Rect())) + return PaintInvalidationReason::kNone; + return PaintInvalidationReason::kIncremental; + } + + // Otherwise treat the chunk property as changed if the clip node pointer is + // different, or the clip node's value changed between the layer state and the + // chunk state. + if (new_chunk_state.Clip() != old_chunk_state.Clip() || + new_chunk_state.Clip()->Changed(*layer_state_.Clip())) + return PaintInvalidationReason::kPaintProperty; + + return PaintInvalidationReason::kNone; } // Generates raster invalidations by checking changes (appearing, disappearing, @@ -120,58 +154,61 @@ const auto& new_chunk_info = new_chunks_info[new_index]; if (!new_chunk.is_cacheable) { - InvalidateRasterForNewChunk(new_chunk_info, - PaintInvalidationReason::kChunkUncacheable); + FullyInvalidateNewChunk(new_chunk_info, + PaintInvalidationReason::kChunkUncacheable); continue; } size_t matched_old_index = MatchNewChunkToOldChunk(new_chunk, old_index); if (matched_old_index == kNotFound) { // The new chunk doesn't match any old chunk. - InvalidateRasterForNewChunk(new_chunk_info, - PaintInvalidationReason::kAppeared); + FullyInvalidateNewChunk(new_chunk_info, + PaintInvalidationReason::kAppeared); continue; } DCHECK(!old_chunks_matched[matched_old_index]); old_chunks_matched[matched_old_index] = true; - bool moved_earlier = matched_old_index < max_matched_old_index; - max_matched_old_index = std::max(max_matched_old_index, matched_old_index); - bool properties_changed = ChunkPropertiesChanged( - new_chunk_info, paint_chunks_info_[matched_old_index]); - if (!properties_changed && !moved_earlier) { - // Add the raster invalidations found by PaintController within the chunk. - AddDisplayItemRasterInvalidations(new_chunk); - } else { + auto& old_chunk_info = paint_chunks_info_[matched_old_index]; + // Clip the old chunk bounds by the new layer bounds. + old_chunk_info.bounds_in_layer = + ClipByLayerBounds(old_chunk_info.bounds_in_layer); + + PaintInvalidationReason reason = + matched_old_index < max_matched_old_index + ? PaintInvalidationReason::kChunkReordered + : ChunkPropertiesChanged(new_chunk_info, old_chunk_info); + + if (IsFullPaintInvalidationReason(reason)) { // Invalidate both old and new bounds of the chunk if the chunk's paint // properties changed, or is moved backward and may expose area that was // previously covered by it. - const auto& old_chunk_info = paint_chunks_info_[matched_old_index]; - PaintInvalidationReason reason = - properties_changed ? PaintInvalidationReason::kPaintProperty - : PaintInvalidationReason::kChunkReordered; - InvalidateRasterForOldChunk(old_chunk_info, reason); - if (old_chunk_info.bounds_in_layer != new_chunk_info.bounds_in_layer) - InvalidateRasterForNewChunk(new_chunk_info, reason); + FullyInvalidateChunk(old_chunk_info, new_chunk_info, reason); // Ignore the display item raster invalidations because we have fully // invalidated the chunk. + } else { + if (reason == PaintInvalidationReason::kIncremental) + IncrementallyInvalidateChunk(old_chunk_info, new_chunk_info); + + // Add the raster invalidations found by PaintController within the chunk. + AddDisplayItemRasterInvalidations(new_chunk); } old_index = matched_old_index + 1; if (old_index == paint_chunks_info_.size()) old_index = 0; + max_matched_old_index = std::max(max_matched_old_index, matched_old_index); } // Invalidate remaining unmatched (disappeared or uncacheable) old chunks. for (size_t i = 0; i < paint_chunks_info_.size(); ++i) { if (old_chunks_matched[i]) continue; - InvalidateRasterForOldChunk( - paint_chunks_info_[i], - paint_chunks_info_[i].is_cacheable - ? PaintInvalidationReason::kDisappeared - : PaintInvalidationReason::kChunkUncacheable); + FullyInvalidateOldChunk(paint_chunks_info_[i], + paint_chunks_info_[i].is_cacheable + ? PaintInvalidationReason::kDisappeared + : PaintInvalidationReason::kChunkUncacheable); } } @@ -196,31 +233,53 @@ } } -void CompositedLayerRasterInvalidator::InvalidateRasterForNewChunk( - const PaintChunkInfo& info, - PaintInvalidationReason reason) { - raster_invalidation_function_(info.bounds_in_layer); - - if (tracking_info_) { - tracking_info_->tracking.AddInvalidation(&info.id.client, - info.id.client.DebugName(), - info.bounds_in_layer, reason); +void CompositedLayerRasterInvalidator::IncrementallyInvalidateChunk( + const PaintChunkInfo& old_chunk, + const PaintChunkInfo& new_chunk) { + SkRegion diff(old_chunk.bounds_in_layer); + diff.op(new_chunk.bounds_in_layer, SkRegion::kXOR_Op); + for (SkRegion::Iterator it(diff); !it.done(); it.next()) { + const SkIRect& r = it.rect(); + AddRasterInvalidation(IntRect(r.x(), r.y(), r.width(), r.height()), + &new_chunk.id.client, + PaintInvalidationReason::kIncremental); } } -void CompositedLayerRasterInvalidator::InvalidateRasterForOldChunk( +void CompositedLayerRasterInvalidator::FullyInvalidateChunk( + const PaintChunkInfo& old_chunk, + const PaintChunkInfo& new_chunk, + PaintInvalidationReason reason) { + FullyInvalidateOldChunk(old_chunk, reason); + if (old_chunk.bounds_in_layer != new_chunk.bounds_in_layer) + FullyInvalidateNewChunk(new_chunk, reason); +} + +void CompositedLayerRasterInvalidator::FullyInvalidateNewChunk( const PaintChunkInfo& info, PaintInvalidationReason reason) { - auto bounds = info.bounds_in_layer; - bounds.Intersect( - IntRect(0, 0, layer_bounds_.width(), layer_bounds_.height())); - raster_invalidation_function_(bounds); + AddRasterInvalidation(info.bounds_in_layer, &info.id.client, reason); +} +void CompositedLayerRasterInvalidator::FullyInvalidateOldChunk( + const PaintChunkInfo& info, + PaintInvalidationReason reason) { + String debug_name; + if (tracking_info_) + debug_name = tracking_info_->old_client_debug_names.at(&info.id.client); + AddRasterInvalidation(info.bounds_in_layer, &info.id.client, reason, + &debug_name); +} + +void CompositedLayerRasterInvalidator::AddRasterInvalidation( + const IntRect& rect, + const DisplayItemClient* client, + PaintInvalidationReason reason, + const String* debug_name) { + raster_invalidation_function_(rect); if (tracking_info_) { tracking_info_->tracking.AddInvalidation( - &info.id.client, - tracking_info_->old_client_debug_names.at(&info.id.client), - info.bounds_in_layer, reason); + client, debug_name ? *debug_name : client->DebugName(), rect, reason); } } @@ -245,10 +304,9 @@ Vector<PaintChunkInfo> new_chunks_info; new_chunks_info.ReserveCapacity(paint_chunks.size()); for (const auto* chunk : paint_chunks) { - auto chunk_to_layer_transform = ChunkToLayerTransform(*chunk); - new_chunks_info.push_back( - PaintChunkInfo(MapRectFromChunkToLayer(chunk->bounds, *chunk), - chunk_to_layer_transform, *chunk)); + new_chunks_info.push_back(PaintChunkInfo( + MapRectFromChunkToLayer(chunk->bounds, *chunk), + ChunkToLayerTransform(*chunk), ChunkToLayerClip(*chunk), *chunk)); if (tracking_info_) { tracking_info_->new_client_debug_names.insert( &chunk->id.client, chunk->id.client.DebugName());
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.h b/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.h index 3c2db3b..a4a6e74 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.h +++ b/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidator.h
@@ -5,6 +5,7 @@ #ifndef CompositedLayerRasterInvalidator_h #define CompositedLayerRasterInvalidator_h +#include "platform/graphics/paint/FloatClipRect.h" #include "platform/graphics/paint/PaintChunk.h" #include "platform/graphics/paint/RasterInvalidationTracking.h" #include "platform/wtf/HashMap.h" @@ -46,12 +47,16 @@ const gfx::Rect& LayerBounds() const { return layer_bounds_; } private: + friend class CompositedLayerRasterInvalidatorTest; + struct PaintChunkInfo { PaintChunkInfo(const IntRect& bounds, const TransformationMatrix& chunk_to_layer_transform, + const FloatClipRect& chunk_to_layer_clip, const PaintChunk& chunk) : bounds_in_layer(bounds), chunk_to_layer_transform(chunk_to_layer_transform), + chunk_to_layer_clip(chunk_to_layer_clip), id(chunk.id), is_cacheable(chunk.is_cacheable), properties(chunk.properties) {} @@ -62,6 +67,7 @@ IntRect bounds_in_layer; TransformationMatrix chunk_to_layer_transform; + FloatClipRect chunk_to_layer_clip; PaintChunk::Id id; bool is_cacheable; PaintChunkProperties properties; @@ -69,18 +75,36 @@ IntRect MapRectFromChunkToLayer(const FloatRect&, const PaintChunk&) const; TransformationMatrix ChunkToLayerTransform(const PaintChunk&) const; + FloatClipRect ChunkToLayerClip(const PaintChunk&) const; void GenerateRasterInvalidations( const Vector<const PaintChunk*>& new_chunks, const Vector<PaintChunkInfo>& new_chunks_info); size_t MatchNewChunkToOldChunk(const PaintChunk& new_chunk, size_t old_index); void AddDisplayItemRasterInvalidations(const PaintChunk&); - void InvalidateRasterForNewChunk(const PaintChunkInfo&, - PaintInvalidationReason); - void InvalidateRasterForOldChunk(const PaintChunkInfo&, - PaintInvalidationReason); - bool ChunkPropertiesChanged(const PaintChunkInfo& new_chunk, - const PaintChunkInfo& old_chunk) const; + void IncrementallyInvalidateChunk(const PaintChunkInfo& old_chunk, + const PaintChunkInfo& new_chunk); + void FullyInvalidateChunk(const PaintChunkInfo& old_chunk, + const PaintChunkInfo& new_chunk, + PaintInvalidationReason); + ALWAYS_INLINE void FullyInvalidateNewChunk(const PaintChunkInfo&, + PaintInvalidationReason); + ALWAYS_INLINE void FullyInvalidateOldChunk(const PaintChunkInfo&, + PaintInvalidationReason); + ALWAYS_INLINE void AddRasterInvalidation(const IntRect&, + const DisplayItemClient*, + PaintInvalidationReason, + const String* debug_name = nullptr); + PaintInvalidationReason ChunkPropertiesChanged( + const PaintChunkInfo& new_chunk, + const PaintChunkInfo& old_chunk) const; + + // Clip a rect in the layer space by the layer bounds. + template <typename Rect> + Rect ClipByLayerBounds(const Rect& r) const { + return Intersection( + r, Rect(0, 0, layer_bounds_.width(), layer_bounds_.height())); + } RasterInvalidationFunction raster_invalidation_function_; gfx::Rect layer_bounds_;
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidatorTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidatorTest.cpp index 547cfc86..8befb3f 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidatorTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/CompositedLayerRasterInvalidatorTest.cpp
@@ -64,42 +64,48 @@ return EnclosingIntRect(r); } - static void ExpectDisplayItemInvalidations( - const Vector<RasterInvalidationInfo>& invalidations, - size_t index, - const PaintChunk& chunk, - const IntPoint& chunk_offset_from_layer = - -kDefaultLayerBounds.Location()) { - for (size_t i = 0; i < chunk.raster_invalidation_rects.size(); ++i) { - SCOPED_TRACE(index + i); - const auto& info = invalidations[index + i]; - EXPECT_EQ(ChunkRectToLayer(chunk.raster_invalidation_rects[i], - chunk_offset_from_layer), - info.rect); - EXPECT_EQ(&chunk.id.client, info.client); - EXPECT_EQ(chunk.raster_invalidation_tracking[i].reason, info.reason); - } - } - - static void ExpectChunkInvalidation( - const Vector<RasterInvalidationInfo>& invalidations, - size_t index, - const PaintChunk& chunk, - PaintInvalidationReason reason, - const IntPoint& layer_offset = -kDefaultLayerBounds.Location()) { - SCOPED_TRACE(index); - const auto& info = invalidations[index]; - EXPECT_EQ(ChunkRectToLayer(chunk.bounds, layer_offset), info.rect); - EXPECT_EQ(&chunk.id.client, info.client); - EXPECT_EQ(reason, info.reason); - } - CompositedLayerRasterInvalidator::RasterInvalidationFunction kNoopRasterInvalidation = [this](const IntRect& rect) {}; Vector<IntRect> raster_invalidations_; }; +#define EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, index, chunk) \ + do { \ + for (size_t i = 0; i < (chunk).raster_invalidation_rects.size(); ++i) { \ + SCOPED_TRACE(index + i); \ + const auto& info = (invalidations)[index + i]; \ + EXPECT_EQ(ChunkRectToLayer((chunk).raster_invalidation_rects[i], \ + -kDefaultLayerBounds.Location()), \ + info.rect); \ + EXPECT_EQ(&(chunk).id.client, info.client); \ + EXPECT_EQ((chunk).raster_invalidation_tracking[i].reason, info.reason); \ + } \ + } while (false) + +#define EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET( \ + invalidations, index, chunk, expected_reason, layer_offset) \ + do { \ + const auto& info = (invalidations)[index]; \ + EXPECT_EQ(ChunkRectToLayer((chunk).bounds, layer_offset), info.rect); \ + EXPECT_EQ(&(chunk).id.client, info.client); \ + EXPECT_EQ(expected_reason, info.reason); \ + } while (false) + +#define EXPECT_CHUNK_INVALIDATION(invalidations, index, chunk, reason) \ + EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET( \ + invalidations, index, chunk, reason, -kDefaultLayerBounds.Location()) + +#define EXPECT_INCREMENTAL_INVALIDATION(invalidations, index, chunk, \ + chunk_rect) \ + do { \ + const auto& info = (invalidations)[index]; \ + EXPECT_EQ(ChunkRectToLayer(chunk_rect, -kDefaultLayerBounds.Location()), \ + info.rect); \ + EXPECT_EQ(&(chunk).id.client, info.client); \ + EXPECT_EQ(PaintInvalidationReason::kIncremental, info.reason); \ + } while (false) + #define CHUNKS(name, ...) \ PaintChunk name##_array[] = {__VA_ARGS__}; \ Vector<const PaintChunk*> name; \ @@ -125,11 +131,11 @@ // Change of layer origin causes change of chunk0's transform to layer. const auto& invalidations = TrackedRasterInvalidations(invalidator); ASSERT_EQ(2u, invalidations.size()); - ExpectChunkInvalidation(invalidations, 0, *chunks[0], - PaintInvalidationReason::kPaintProperty); - ExpectChunkInvalidation(invalidations, 1, *chunks[0], - PaintInvalidationReason::kPaintProperty, - -new_layer_bounds.Location()); + EXPECT_CHUNK_INVALIDATION(invalidations, 0, *chunks[0], + PaintInvalidationReason::kPaintProperty); + EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET( + invalidations, 1, *chunks[0], PaintInvalidationReason::kPaintProperty, + -new_layer_bounds.Location()); } TEST_F(CompositedLayerRasterInvalidatorTest, ReorderChunks) { @@ -150,14 +156,14 @@ // CompositedLayerRasterInvalidator (which is according to the first chunk's // id). For matched chunk, we issue raster invalidations if any found by // PaintController. - ExpectDisplayItemInvalidations(invalidations, 0, *new_chunks[0]); - ExpectDisplayItemInvalidations(invalidations, 2, *new_chunks[1]); + EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, *new_chunks[0]); + EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 2, *new_chunks[1]); // Invalidated new chunk 2's old (as chunks[1]) and new (as new_chunks[2]) // bounds. - ExpectChunkInvalidation(invalidations, 6, *chunks[1], - PaintInvalidationReason::kChunkReordered); - ExpectChunkInvalidation(invalidations, 7, *new_chunks[2], - PaintInvalidationReason::kChunkReordered); + EXPECT_CHUNK_INVALIDATION(invalidations, 6, *chunks[1], + PaintInvalidationReason::kChunkReordered); + EXPECT_CHUNK_INVALIDATION(invalidations, 7, *new_chunks[2], + PaintInvalidationReason::kChunkReordered); } TEST_F(CompositedLayerRasterInvalidatorTest, ReorderChunkSubsequences) { @@ -180,19 +186,19 @@ // CompositedLayerRasterInvalidator (which is according to the first chunk's // id). For matched chunk, we issue raster invalidations if any found by // PaintController. - ExpectDisplayItemInvalidations(invalidations, 0, *new_chunks[0]); - ExpectDisplayItemInvalidations(invalidations, 2, *new_chunks[1]); - ExpectDisplayItemInvalidations(invalidations, 5, *new_chunks[2]); + EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, *new_chunks[0]); + EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 2, *new_chunks[1]); + EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 5, *new_chunks[2]); // Invalidated new chunk 3's old (as chunks[1]) and new (as new_chunks[3]) // bounds. - ExpectChunkInvalidation(invalidations, 9, *chunks[1], - PaintInvalidationReason::kChunkReordered); - ExpectChunkInvalidation(invalidations, 10, *new_chunks[3], - PaintInvalidationReason::kChunkReordered); + EXPECT_CHUNK_INVALIDATION(invalidations, 9, *chunks[1], + PaintInvalidationReason::kChunkReordered); + EXPECT_CHUNK_INVALIDATION(invalidations, 10, *new_chunks[3], + PaintInvalidationReason::kChunkReordered); // Invalidated new chunk 4's new bounds. Didn't invalidate old bounds because // it's the same as the new bounds. - ExpectChunkInvalidation(invalidations, 11, *new_chunks[4], - PaintInvalidationReason::kChunkReordered); + EXPECT_CHUNK_INVALIDATION(invalidations, 11, *new_chunks[4], + PaintInvalidationReason::kChunkReordered); } TEST_F(CompositedLayerRasterInvalidatorTest, AppearAndDisappear) { @@ -209,15 +215,15 @@ DefaultPropertyTreeState()); const auto& invalidations = TrackedRasterInvalidations(invalidator); ASSERT_EQ(6u, invalidations.size()); - ExpectDisplayItemInvalidations(invalidations, 0, *new_chunks[0]); - ExpectChunkInvalidation(invalidations, 2, *new_chunks[1], - PaintInvalidationReason::kAppeared); - ExpectChunkInvalidation(invalidations, 3, *new_chunks[2], - PaintInvalidationReason::kAppeared); - ExpectChunkInvalidation(invalidations, 4, *chunks[1], - PaintInvalidationReason::kDisappeared); - ExpectChunkInvalidation(invalidations, 5, *chunks[2], - PaintInvalidationReason::kDisappeared); + EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, *new_chunks[0]); + EXPECT_CHUNK_INVALIDATION(invalidations, 2, *new_chunks[1], + PaintInvalidationReason::kAppeared); + EXPECT_CHUNK_INVALIDATION(invalidations, 3, *new_chunks[2], + PaintInvalidationReason::kAppeared); + EXPECT_CHUNK_INVALIDATION(invalidations, 4, *chunks[1], + PaintInvalidationReason::kDisappeared); + EXPECT_CHUNK_INVALIDATION(invalidations, 5, *chunks[2], + PaintInvalidationReason::kDisappeared); } TEST_F(CompositedLayerRasterInvalidatorTest, AppearAtEnd) { @@ -232,11 +238,11 @@ DefaultPropertyTreeState()); const auto& invalidations = TrackedRasterInvalidations(invalidator); ASSERT_EQ(4u, invalidations.size()); - ExpectDisplayItemInvalidations(invalidations, 0, *new_chunks[0]); - ExpectChunkInvalidation(invalidations, 2, *new_chunks[1], - PaintInvalidationReason::kAppeared); - ExpectChunkInvalidation(invalidations, 3, *new_chunks[2], - PaintInvalidationReason::kAppeared); + EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, *new_chunks[0]); + EXPECT_CHUNK_INVALIDATION(invalidations, 2, *new_chunks[1], + PaintInvalidationReason::kAppeared); + EXPECT_CHUNK_INVALIDATION(invalidations, 3, *new_chunks[2], + PaintInvalidationReason::kAppeared); } TEST_F(CompositedLayerRasterInvalidatorTest, UncacheableChunks) { @@ -253,18 +259,22 @@ DefaultPropertyTreeState()); const auto& invalidations = TrackedRasterInvalidations(invalidator); ASSERT_EQ(7u, invalidations.size()); - ExpectDisplayItemInvalidations(invalidations, 0, *new_chunks[0]); - ExpectDisplayItemInvalidations(invalidations, 2, *new_chunks[1]); - ExpectChunkInvalidation(invalidations, 5, *new_chunks[2], - PaintInvalidationReason::kChunkUncacheable); - ExpectChunkInvalidation(invalidations, 6, *chunks[1], - PaintInvalidationReason::kChunkUncacheable); + EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, *new_chunks[0]); + EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 2, *new_chunks[1]); + EXPECT_CHUNK_INVALIDATION(invalidations, 5, *new_chunks[2], + PaintInvalidationReason::kChunkUncacheable); + EXPECT_CHUNK_INVALIDATION(invalidations, 6, *chunks[1], + PaintInvalidationReason::kChunkUncacheable); } -TEST_F(CompositedLayerRasterInvalidatorTest, ClipPropertyChange) { +// Tests the path based on ClipPaintPropertyNode::Changed(). +TEST_F(CompositedLayerRasterInvalidatorTest, ClipPropertyChangeRounded) { CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation); CHUNKS(chunks, Chunk(0), Chunk(1), Chunk(2)); - FloatRoundedRect clip_rect(-100000, -100000, 200000, 200000); + FloatRoundedRect::Radii radii(FloatSize(1, 2), FloatSize(2, 3), + FloatSize(3, 4), FloatSize(4, 5)); + FloatRoundedRect clip_rect(FloatRect(-1000, -1000, 2000, 2000), radii); + LOG(ERROR) << "new_clip_rect: " << clip_rect.ToString(); scoped_refptr<ClipPaintPropertyNode> clip0 = ClipPaintPropertyNode::Create( ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(), clip_rect); @@ -279,29 +289,33 @@ PropertyTreeState(TransformPaintPropertyNode::Root(), clip2.get(), EffectPaintPropertyNode::Root())); + GeometryMapperClipCache::ClearCache(); invalidator.SetTracksRasterInvalidations(true); invalidator.Generate(kDefaultLayerBounds, chunks, layer_state); EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty()); // Change both clip0 and clip2. + LOG(ERROR) << "22222222222222222222222222222222222222222222"; CHUNKS(new_chunks, Chunk(0), Chunk(1), Chunk(2)); - FloatRoundedRect new_clip_rect(-200000, -200000, 400000, 400000); + FloatRoundedRect new_clip_rect(FloatRect(-2000, -2000, 4000, 4000), radii); + LOG(ERROR) << "new_clip_rect: " << new_clip_rect.ToString(); clip0->Update(clip0->Parent(), clip0->LocalTransformSpace(), new_clip_rect); clip2->Update(clip2->Parent(), clip2->LocalTransformSpace(), new_clip_rect); new_chunks_array[0].properties = chunks[0]->properties; new_chunks_array[1].properties = chunks[1]->properties; new_chunks_array[2].properties = chunks[2]->properties; - GeometryMapperTransformCache::ClearCache(); + GeometryMapperClipCache::ClearCache(); invalidator.Generate(kDefaultLayerBounds, new_chunks, layer_state); const auto& invalidations = TrackedRasterInvalidations(invalidator); ASSERT_EQ(1u, invalidations.size()); // Property change in the layer state should not trigger raster invalidation. // |clip2| change should trigger raster invalidation. - ExpectChunkInvalidation(invalidations, 0, *new_chunks[2], - PaintInvalidationReason::kPaintProperty); + EXPECT_CHUNK_INVALIDATION(invalidations, 0, *new_chunks[2], + PaintInvalidationReason::kPaintProperty); invalidator.SetTracksRasterInvalidations(false); clip2->ClearChangedToRoot(); + LOG(ERROR) << "333333333333333333333333333333333333333333333"; // Change chunk1's properties to use a different property tree state. CHUNKS(new_chunks1, Chunk(0), Chunk(1), Chunk(2)); @@ -309,15 +323,103 @@ new_chunks1_array[1].properties = chunks[2]->properties; new_chunks1_array[2].properties = chunks[2]->properties; + GeometryMapperClipCache::ClearCache(); invalidator.SetTracksRasterInvalidations(true); invalidator.Generate(kDefaultLayerBounds, new_chunks1, layer_state); const auto& invalidations1 = TrackedRasterInvalidations(invalidator); ASSERT_EQ(1u, invalidations1.size()); - ExpectChunkInvalidation(invalidations1, 0, *new_chunks1[1], - PaintInvalidationReason::kPaintProperty); + EXPECT_CHUNK_INVALIDATION(invalidations1, 0, *new_chunks1[1], + PaintInvalidationReason::kPaintProperty); invalidator.SetTracksRasterInvalidations(false); } +// Tests the path detecting change of PaintChunkInfo::chunk_to_layer_clip. +TEST_F(CompositedLayerRasterInvalidatorTest, ClipPropertyChangeSimple) { + CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation); + CHUNKS(chunks, Chunk(0), Chunk(1)); + FloatRoundedRect clip_rect(-1000, -1000, 2000, 2000); + scoped_refptr<ClipPaintPropertyNode> clip0 = ClipPaintPropertyNode::Create( + ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(), + clip_rect); + scoped_refptr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::Create( + clip0, TransformPaintPropertyNode::Root(), clip_rect); + + PropertyTreeState layer_state = PropertyTreeState::Root(); + chunks_array[0].properties = PaintChunkProperties( + PropertyTreeState(TransformPaintPropertyNode::Root(), clip0.get(), + EffectPaintPropertyNode::Root())); + chunks_array[0].bounds = clip_rect.Rect(); + chunks_array[1].properties = PaintChunkProperties( + PropertyTreeState(TransformPaintPropertyNode::Root(), clip1.get(), + EffectPaintPropertyNode::Root())); + chunks_array[1].bounds = clip_rect.Rect(); + + GeometryMapperClipCache::ClearCache(); + invalidator.SetTracksRasterInvalidations(true); + invalidator.Generate(kDefaultLayerBounds, chunks, layer_state); + EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty()); + + // Change clip1 to bigger, which is still bound by clip0, resulting no actual + // visual change. + CHUNKS(new_chunks1, Chunk(0), Chunk(1)); + FloatRoundedRect new_clip_rect1(-2000, -2000, 4000, 4000); + clip1->Update(clip1->Parent(), clip1->LocalTransformSpace(), new_clip_rect1); + new_chunks1_array[0].properties = chunks[0]->properties; + new_chunks1_array[0].bounds = chunks[0]->bounds; + new_chunks1_array[1].properties = chunks[1]->properties; + new_chunks1_array[1].bounds = chunks[1]->bounds; + + GeometryMapperClipCache::ClearCache(); + invalidator.Generate(kDefaultLayerBounds, new_chunks1, layer_state); + EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty()); + clip1->ClearChangedToRoot(); + + // Change clip1 to smaller. + CHUNKS(new_chunks2, Chunk(0), Chunk(1)); + FloatRoundedRect new_clip_rect2(-500, -500, 1000, 1000); + clip1->Update(clip1->Parent(), clip1->LocalTransformSpace(), new_clip_rect2); + new_chunks2_array[0].properties = chunks[0]->properties; + new_chunks2_array[0].bounds = chunks[0]->bounds; + new_chunks2_array[1].properties = chunks[1]->properties; + new_chunks2_array[1].bounds = new_clip_rect2.Rect(); + + GeometryMapperClipCache::ClearCache(); + invalidator.Generate(kDefaultLayerBounds, new_chunks2, layer_state); + const auto& invalidations = TrackedRasterInvalidations(invalidator); + ASSERT_EQ(4u, invalidations.size()); + // |clip1| change should trigger incremental raster invalidation. + EXPECT_INCREMENTAL_INVALIDATION(invalidations, 0, *new_chunks2[1], + IntRect(-1000, -1000, 2000, 500)); + EXPECT_INCREMENTAL_INVALIDATION(invalidations, 1, *new_chunks2[1], + IntRect(-1000, -500, 500, 1000)); + EXPECT_INCREMENTAL_INVALIDATION(invalidations, 2, *new_chunks2[1], + IntRect(500, -500, 500, 1000)); + EXPECT_INCREMENTAL_INVALIDATION(invalidations, 3, *new_chunks2[1], + IntRect(-1000, 500, 2000, 500)); + invalidator.SetTracksRasterInvalidations(false); + clip1->ClearChangedToRoot(); + + // Change clip1 bigger at one side. + CHUNKS(new_chunks3, Chunk(0), Chunk(1)); + FloatRoundedRect new_clip_rect3(-500, -500, 2000, 1000); + clip1->Update(clip1->Parent(), clip1->LocalTransformSpace(), new_clip_rect3); + new_chunks3_array[0].properties = chunks[0]->properties; + new_chunks3_array[0].bounds = chunks[0]->bounds; + new_chunks3_array[1].properties = chunks[1]->properties; + new_chunks3_array[1].bounds = new_clip_rect3.Rect(); + + GeometryMapperClipCache::ClearCache(); + invalidator.SetTracksRasterInvalidations(true); + invalidator.Generate(kDefaultLayerBounds, new_chunks3, layer_state); + const auto& invalidations1 = TrackedRasterInvalidations(invalidator); + ASSERT_EQ(1u, invalidations1.size()); + // |clip1| change should trigger incremental raster invalidation. + EXPECT_INCREMENTAL_INVALIDATION(invalidations1, 0, *new_chunks3[1], + IntRect(500, -500, 500, 1000)); + invalidator.SetTracksRasterInvalidations(false); + clip1->ClearChangedToRoot(); +} + TEST_F(CompositedLayerRasterInvalidatorTest, TransformPropertyChange) { CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation); CHUNKS(chunks, Chunk(0), Chunk(1)); @@ -408,12 +510,14 @@ invalidator.Generate(kDefaultLayerBounds, new_chunks3, layer_state); const auto& invalidations = TrackedRasterInvalidations(invalidator); ASSERT_EQ(2u, invalidations.size()); - ExpectChunkInvalidation(invalidations, 0, *new_chunks3[0], - PaintInvalidationReason::kPaintProperty, - -kDefaultLayerBounds.Location() + IntSize(10, 20)); - ExpectChunkInvalidation(invalidations, 1, *new_chunks3[0], - PaintInvalidationReason::kPaintProperty, - -kDefaultLayerBounds.Location() + IntSize(30, 50)); + EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET( + invalidations, 0, *new_chunks3[0], + PaintInvalidationReason::kPaintProperty, + -kDefaultLayerBounds.Location() + IntSize(10, 20)); + EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET( + invalidations, 1, *new_chunks3[0], + PaintInvalidationReason::kPaintProperty, + -kDefaultLayerBounds.Location() + IntSize(30, 50)); invalidator.SetTracksRasterInvalidations(false); }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp index aa85912..1a040baf 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -35,6 +35,7 @@ #include "build/build_config.h" #include "components/viz/common/quads/shared_bitmap.h" +#include "components/viz/common/resources/transferable_resource.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" @@ -176,6 +177,8 @@ want_stencil_(want_stencil), storage_color_space_(color_params.GetStorageGfxColorSpace()), sampler_color_space_(color_params.GetSamplerGfxColorSpace()), + use_half_float_storage_(color_params.PixelFormat() == + kF16CanvasPixelFormat), chromium_image_usage_(chromium_image_usage) { // Used by browser tests to detect the use of a DrawingBuffer. TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation", @@ -258,17 +261,17 @@ return Platform::Current()->AllocateSharedBitmap(size_); } -bool DrawingBuffer::PrepareTextureMailbox( - viz::TextureMailbox* out_mailbox, +bool DrawingBuffer::PrepareTransferableResource( + viz::TransferableResource* out_resource, std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) { ScopedStateRestorer scoped_state_restorer(this); bool force_gpu_result = false; - return PrepareTextureMailboxInternal(out_mailbox, out_release_callback, - force_gpu_result); + return PrepareTransferableResourceInternal(out_resource, out_release_callback, + force_gpu_result); } -bool DrawingBuffer::PrepareTextureMailboxInternal( - viz::TextureMailbox* out_mailbox, +bool DrawingBuffer::PrepareTransferableResourceInternal( + viz::TransferableResource* out_resource, std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback, bool force_gpu_result) { DCHECK(state_restorer_); @@ -296,15 +299,16 @@ ResolveIfNeeded(); if (!using_gpu_compositing_ && !force_gpu_result) { - return FinishPrepareTextureMailboxSoftware(out_mailbox, - out_release_callback); + return FinishPrepareTransferableResourceSoftware(out_resource, + out_release_callback); } else { - return FinishPrepareTextureMailboxGpu(out_mailbox, out_release_callback); + return FinishPrepareTransferableResourceGpu(out_resource, + out_release_callback); } } -bool DrawingBuffer::FinishPrepareTextureMailboxSoftware( - viz::TextureMailbox* out_mailbox, +bool DrawingBuffer::FinishPrepareTransferableResourceSoftware( + viz::TransferableResource* out_resource, std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) { DCHECK(state_restorer_); std::unique_ptr<viz::SharedBitmap> bitmap = CreateOrRecycleBitmap(); @@ -325,8 +329,9 @@ op); } - *out_mailbox = viz::TextureMailbox(bitmap.get(), size_); - out_mailbox->set_color_space(storage_color_space_); + *out_resource = viz::TransferableResource::MakeSoftware( + bitmap->id(), bitmap->sequence_number(), size_); + out_resource->color_space = storage_color_space_; // This holds a ref on the DrawingBuffer that will keep it alive until the // mailbox is released (and while the release callback is running). It also @@ -344,8 +349,8 @@ return true; } -bool DrawingBuffer::FinishPrepareTextureMailboxGpu( - viz::TextureMailbox* out_mailbox, +bool DrawingBuffer::FinishPrepareTransferableResourceGpu( + viz::TransferableResource* out_resource, std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) { DCHECK(state_restorer_); if (webgl_version_ > kWebGL1) { @@ -410,11 +415,11 @@ // Populate the output mailbox and callback. { bool is_overlay_candidate = color_buffer_for_mailbox->image_id != 0; - *out_mailbox = viz::TextureMailbox( - color_buffer_for_mailbox->mailbox, - color_buffer_for_mailbox->produce_sync_token, texture_target_, - gfx::Size(size_), is_overlay_candidate); - out_mailbox->set_color_space(sampler_color_space_); + *out_resource = viz::TransferableResource::MakeGLOverlay( + color_buffer_for_mailbox->mailbox, GL_LINEAR, texture_target_, + color_buffer_for_mailbox->produce_sync_token, gfx::Size(size_), + is_overlay_candidate); + out_resource->color_space = sampler_color_space_; // This holds a ref on the DrawingBuffer that will keep it alive until the // mailbox is released (and while the release callback is running). @@ -482,13 +487,13 @@ // grContext(). GrContext* gr_context = ContextProvider()->GetGrContext(); - viz::TextureMailbox texture_mailbox; + viz::TransferableResource transferable_resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; bool success = false; if (gr_context) { bool force_gpu_result = true; - success = PrepareTextureMailboxInternal(&texture_mailbox, &release_callback, - force_gpu_result); + success = PrepareTransferableResourceInternal( + &transferable_resource, &release_callback, force_gpu_result); } if (!success) { // If we can't get a mailbox, return an transparent black ImageBitmap. @@ -500,34 +505,36 @@ return StaticBitmapImage::Create(surface->makeImageSnapshot()); } - DCHECK_EQ(size_.Width(), texture_mailbox.size_in_pixels().width()); - DCHECK_EQ(size_.Height(), texture_mailbox.size_in_pixels().height()); + DCHECK_EQ(size_.Width(), transferable_resource.size.width()); + DCHECK_EQ(size_.Height(), transferable_resource.size.height()); // Make our own textureId that is a reference on the same texture backing // being used as the front buffer (which was returned from - // PrepareTextureMailbox()). We do not need to wait on the sync token in - // |textureMailbox| since the mailbox was produced on the same |m_gl| context - // that we are using here. Similarly, the |releaseCallback| will run on the - // same context so we don't need to send a sync token for this consume action - // back to it. - // TODO(danakj): Instead of using PrepareTextureMailbox(), we could just use - // the actual texture id and avoid needing to produce/consume a mailbox. + // PrepareTransferableResourceInternal()). We do not need to wait on the sync + // token in |transferable_resource| since the mailbox was produced on the same + // |m_gl| context that we are using here. Similarly, the |release_callback| + // will run on the same context so we don't need to send a sync token for this + // consume action back to it. + // TODO(danakj): Instead of using PrepareTransferableResourceInternal(), we + // could just use the actual texture id and avoid needing to produce/consume a + // mailbox. GLuint texture_id = gl_->CreateAndConsumeTextureCHROMIUM( - GL_TEXTURE_2D, texture_mailbox.name()); + GL_TEXTURE_2D, transferable_resource.mailbox_holder.mailbox.name); // Return the mailbox but report that the resource is lost to prevent trying // to use the backing for future frames. We keep it alive with our own // reference to the backing via our |textureId|. - release_callback->Run(gpu::SyncToken(), true /* lostResource */); + release_callback->Run(gpu::SyncToken(), true /* lost_resource */); // We reuse the same mailbox name from above since our texture id was consumed // from it. - const auto& sk_image_mailbox = texture_mailbox.mailbox(); + const auto& sk_image_mailbox = transferable_resource.mailbox_holder.mailbox; // Use the sync token generated after producing the mailbox. Waiting for this // before trying to use the mailbox with some other context will ensure it is // valid. We wouldn't need to wait for the consume done in this function // because the texture id it generated would only be valid for the // DrawingBuffer's context anyways. - const auto& sk_image_sync_token = texture_mailbox.sync_token(); + const auto& sk_image_sync_token = + transferable_resource.mailbox_holder.sync_token; // TODO(xidachen): Create a small pool of recycled textures from // ImageBitmapRenderingContext's transferFromImageBitmap, and try to use them @@ -621,9 +628,28 @@ if (gl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { // Need to try to restore the context again later. + DLOG(ERROR) << "Cannot initialize with lost context."; return false; } + // Specifying a half-float backbuffer requires and implicitly enables + // half-float backbuffer extensions. + if (use_half_float_storage_) { + const char* color_buffer_extension = webgl_version_ > kWebGL1 + ? "GL_EXT_color_buffer_float" + : "GL_EXT_color_buffer_half_float"; + if (!extensions_util_->EnsureExtensionEnabled(color_buffer_extension)) { + DLOG(ERROR) << "Half-float color buffer support is absent."; + return false; + } + // Support for RGB half-float renderbuffers is absent from ES3. Do not + // attempt to expose them. + if (!want_alpha_channel_) { + DLOG(ERROR) << "RGB half-float renderbuffers are not supported."; + return false; + } + } + gl_->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_); int max_sample_count = 0; @@ -703,8 +729,10 @@ gl_->BindFramebuffer(GL_FRAMEBUFFER, multisample_fbo_); gl_->GenRenderbuffers(1, &multisample_renderbuffer_); } - if (!ResizeFramebufferInternal(size)) + if (!ResizeFramebufferInternal(size)) { + DLOG(ERROR) << "Initialization failed to allocate backbuffer."; return false; + } if (depth_stencil_buffer_) { DCHECK(WantDepthOrStencil()); @@ -714,6 +742,7 @@ if (gl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { // It's possible that the drawing buffer allocation provokes a context loss, // so check again just in case. http://crbug.com/512302 + DLOG(ERROR) << "Context lost during initialization."; return false; } @@ -865,10 +894,14 @@ // Note that the multisample rendertarget will allocate an alpha channel // based on |have_alpha_channel_|, not |allocate_alpha_channel_|, since it // will resolve into the ColorBuffer. - gl_->RenderbufferStorageMultisampleCHROMIUM( - GL_RENDERBUFFER, sample_count_, - have_alpha_channel_ ? GL_RGBA8_OES : GL_RGB8_OES, size.Width(), - size.Height()); + GLenum internal_format = have_alpha_channel_ ? GL_RGBA8_OES : GL_RGB8_OES; + if (use_half_float_storage_) { + DCHECK(want_alpha_channel_); + internal_format = GL_RGBA16F_EXT; + } + gl_->RenderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, sample_count_, + internal_format, size.Width(), + size.Height()); if (gl_->GetError() == GL_OUT_OF_MEMORY) return false; @@ -1196,9 +1229,11 @@ gfx::BufferFormat buffer_format; GLenum gl_format = GL_NONE; if (allocate_alpha_channel_) { - buffer_format = gfx::BufferFormat::RGBA_8888; + buffer_format = use_half_float_storage_ ? gfx::BufferFormat::RGBA_F16 + : gfx::BufferFormat::RGBA_8888; gl_format = GL_RGBA; } else { + DCHECK(!use_half_float_storage_); buffer_format = gfx::BufferFormat::RGBX_8888; if (gpu::IsImageFromGpuMemoryBufferFormatSupported( gfx::BufferFormat::BGRX_8888, @@ -1238,12 +1273,28 @@ if (storage_texture_supported_) { GLenum internal_storage_format = allocate_alpha_channel_ ? GL_RGBA8 : GL_RGB8; + if (use_half_float_storage_) { + DCHECK(want_alpha_channel_); + internal_storage_format = GL_RGBA16F_EXT; + } gl_->TexStorage2DEXT(GL_TEXTURE_2D, 1, internal_storage_format, size.Width(), size.Height()); } else { - GLenum gl_format = allocate_alpha_channel_ ? GL_RGBA : GL_RGB; - gl_->TexImage2D(texture_target_, 0, gl_format, size.Width(), - size.Height(), 0, gl_format, GL_UNSIGNED_BYTE, nullptr); + GLenum internal_format = allocate_alpha_channel_ ? GL_RGBA : GL_RGB; + GLenum format = internal_format; + GLenum data_type = GL_UNSIGNED_BYTE; + if (use_half_float_storage_) { + DCHECK(want_alpha_channel_); + if (webgl_version_ > kWebGL1) { + internal_format = GL_RGBA16F; + data_type = GL_HALF_FLOAT; + } else { + internal_format = GL_RGBA; + data_type = GL_HALF_FLOAT_OES; + } + } + gl_->TexImage2D(texture_target_, 0, internal_format, size.Width(), + size.Height(), 0, format, data_type, nullptr); } }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h index 07710fc9..c5f8504 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
@@ -196,9 +196,9 @@ WebGraphicsContext3DProvider* ContextProvider(); // cc::TextureLayerClient implementation. - bool PrepareTextureMailbox(viz::TextureMailbox* out_mailbox, - std::unique_ptr<viz::SingleReleaseCallback>* - out_release_callback) override; + bool PrepareTransferableResource(viz::TransferableResource* out_resource, + std::unique_ptr<viz::SingleReleaseCallback>* + out_release_callback) override; // Returns a StaticBitmapImage backed by a texture containing the current // contents of the front buffer. This is done without any pixel copies. The @@ -361,21 +361,21 @@ // Resolves m_multisampleFBO into m_fbo, if multisampling. void ResolveIfNeeded(); - bool PrepareTextureMailboxInternal( - viz::TextureMailbox* out_mailbox, + bool PrepareTransferableResourceInternal( + viz::TransferableResource* out_resource, std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback, bool force_gpu_result); - // Helper functions to be called only by prepareTextureMailboxInternal. - bool FinishPrepareTextureMailboxGpu( - viz::TextureMailbox* out_mailbox, + // Helper functions to be called only by PrepareTransferableResourceInternal. + bool FinishPrepareTransferableResourceGpu( + viz::TransferableResource* out_resource, std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback); - bool FinishPrepareTextureMailboxSoftware( - viz::TextureMailbox* out_mailbox, + bool FinishPrepareTransferableResourceSoftware( + viz::TransferableResource* out_resource, std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback); // Callbacks for mailboxes given to the compositor from - // finishPrepareTextureMailboxGpu and finishPrepareTextureMailboxSoftware. + // FinishPrepareTransferableResource{Gpu,Software}. void MailboxReleasedGpu(scoped_refptr<ColorBuffer>, const gpu::SyncToken&, bool lost_resource); @@ -494,7 +494,7 @@ scoped_refptr<ColorBuffer> back_color_buffer_; // The ColorBuffer that was most recently presented to the compositor by - // prepareTextureMailboxInternal. + // PrepareTransferableResourceInternal. scoped_refptr<ColorBuffer> front_color_buffer_; // True if our contents have been modified since the last presentation of this @@ -524,6 +524,8 @@ AntialiasingMode anti_aliasing_mode_ = kNone; + bool use_half_float_storage_ = false; + int max_texture_size_ = 0; int sample_count_ = 0; bool destruction_in_progress_ = false;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp index 4708cac..9dd0920 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp
@@ -4,8 +4,8 @@ #include "platform/graphics/gpu/DrawingBuffer.h" -#include "components/viz/common/quads/texture_mailbox.h" #include "components/viz/common/resources/single_release_callback.h" +#include "components/viz/common/resources/transferable_resource.h" #include "gpu/command_buffer/client/gles2_interface_stub.h" #include "gpu/config/gpu_feature_info.h" #include "platform/graphics/gpu/DrawingBufferTestHelpers.h" @@ -41,7 +41,7 @@ }; TEST_F(DrawingBufferSoftwareCompositingTest, BitmapRecycling) { - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback1; std::unique_ptr<viz::SingleReleaseCallback> release_callback2; std::unique_ptr<viz::SingleReleaseCallback> release_callback3; @@ -50,16 +50,16 @@ drawing_buffer_->Resize(initial_size); drawing_buffer_->MarkContentsChanged(); - drawing_buffer_->PrepareTextureMailbox( - &texture_mailbox, &release_callback1); // create a bitmap. + drawing_buffer_->PrepareTransferableResource( + &resource, &release_callback1); // create a bitmap. EXPECT_EQ(0, drawing_buffer_->RecycledBitmapCount()); release_callback1->Run( gpu::SyncToken(), false /* lostResource */); // release bitmap to the recycling queue EXPECT_EQ(1, drawing_buffer_->RecycledBitmapCount()); drawing_buffer_->MarkContentsChanged(); - drawing_buffer_->PrepareTextureMailbox( - &texture_mailbox, &release_callback2); // recycle a bitmap. + drawing_buffer_->PrepareTransferableResource( + &resource, &release_callback2); // recycle a bitmap. EXPECT_EQ(0, drawing_buffer_->RecycledBitmapCount()); release_callback2->Run( gpu::SyncToken(), @@ -68,8 +68,8 @@ drawing_buffer_->Resize(alternate_size); drawing_buffer_->MarkContentsChanged(); // Regression test for crbug.com/647896 - Next line must not crash - drawing_buffer_->PrepareTextureMailbox( - &texture_mailbox, + drawing_buffer_->PrepareTransferableResource( + &resource, &release_callback3); // cause recycling queue to be purged due to resize EXPECT_EQ(0, drawing_buffer_->RecycledBitmapCount()); release_callback3->Run(gpu::SyncToken(), false /* lostResource */); @@ -80,7 +80,7 @@ TEST_F(DrawingBufferSoftwareCompositingTest, FramebufferBinding) { GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests(); - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; IntSize initial_size(kInitialWidth, kInitialHeight); GLint drawBinding = 0, readBinding = 0; @@ -92,7 +92,7 @@ gl_->SaveState(); drawing_buffer_->Resize(initial_size); drawing_buffer_->MarkContentsChanged(); - drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, &release_callback); + drawing_buffer_->PrepareTransferableResource(&resource, &release_callback); gl_->GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawBinding); gl_->GetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &readBinding); EXPECT_EQ(static_cast<GLint>(draw_framebuffer_binding), drawBinding);
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp index 33b9adb..a0f5423 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -32,8 +32,8 @@ #include <memory> #include "base/memory/scoped_refptr.h" -#include "components/viz/common/quads/texture_mailbox.h" #include "components/viz/common/resources/single_release_callback.h" +#include "components/viz/common/resources/transferable_resource.h" #include "components/viz/test/test_gpu_memory_buffer_manager.h" #include "gpu/command_buffer/client/gles2_interface_stub.h" #include "gpu/command_buffer/common/mailbox.h" @@ -156,19 +156,19 @@ drawing_buffer_->BeginDestruction(); } -TEST_F(DrawingBufferTest, verifyResizingProperlyAffectsMailboxes) { +TEST_F(DrawingBufferTest, VerifyResizingProperlyAffectsResources) { GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests(); VerifyStateWasRestored(); - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; IntSize initial_size(kInitialWidth, kInitialHeight); IntSize alternate_size(kInitialWidth, kAlternateHeight); - // Produce one mailbox at size 100x100. + // Produce one resource at size 100x100. EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, - &release_callback)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource, + &release_callback)); VerifyStateWasRestored(); EXPECT_EQ(initial_size, gl_->MostRecentlyProducedSize()); @@ -178,10 +178,10 @@ release_callback->Run(gpu::SyncToken(), false /* lostResource */); VerifyStateWasRestored(); - // Produce a mailbox at this size. + // Produce a resource at this size. EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, - &release_callback)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource, + &release_callback)); EXPECT_EQ(alternate_size, gl_->MostRecentlyProducedSize()); VerifyStateWasRestored(); @@ -192,53 +192,53 @@ release_callback->Run(gpu::SyncToken(), false /* lostResource */); VerifyStateWasRestored(); - // Prepare another mailbox and verify that it's the correct size. + // Prepare another resource and verify that it's the correct size. EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, - &release_callback)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource, + &release_callback)); EXPECT_EQ(initial_size, gl_->MostRecentlyProducedSize()); VerifyStateWasRestored(); - // Prepare one final mailbox and verify that it's the correct size. + // Prepare one final resource and verify that it's the correct size. release_callback->Run(gpu::SyncToken(), false /* lostResource */); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, - &release_callback)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource, + &release_callback)); VerifyStateWasRestored(); EXPECT_EQ(initial_size, gl_->MostRecentlyProducedSize()); release_callback->Run(gpu::SyncToken(), false /* lostResource */); drawing_buffer_->BeginDestruction(); } -TEST_F(DrawingBufferTest, verifyDestructionCompleteAfterAllMailboxesReleased) { +TEST_F(DrawingBufferTest, VerifyDestructionCompleteAfterAllResourceReleased) { bool live = true; drawing_buffer_->live_ = &live; - viz::TextureMailbox texture_mailbox1; + viz::TransferableResource resource1; std::unique_ptr<viz::SingleReleaseCallback> release_callback1; - viz::TextureMailbox texture_mailbox2; + viz::TransferableResource resource2; std::unique_ptr<viz::SingleReleaseCallback> release_callback2; - viz::TextureMailbox texture_mailbox3; + viz::TransferableResource resource3; std::unique_ptr<viz::SingleReleaseCallback> release_callback3; IntSize initial_size(kInitialWidth, kInitialHeight); - // Produce mailboxes. + // Produce resources. EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); drawing_buffer_->ClearFramebuffers(GL_STENCIL_BUFFER_BIT); VerifyStateWasRestored(); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox1, - &release_callback1)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource1, + &release_callback1)); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); drawing_buffer_->ClearFramebuffers(GL_DEPTH_BUFFER_BIT); VerifyStateWasRestored(); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox2, - &release_callback2)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource2, + &release_callback2)); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); drawing_buffer_->ClearFramebuffers(GL_COLOR_BUFFER_BIT); VerifyStateWasRestored(); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox3, - &release_callback3)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource3, + &release_callback3)); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); release_callback1->Run(gpu::SyncToken(), false /* lostResource */); @@ -263,24 +263,24 @@ bool live = true; drawing_buffer_->live_ = &live; - viz::TextureMailbox texture_mailbox1; + viz::TransferableResource resource1; std::unique_ptr<viz::SingleReleaseCallback> release_callback1; - viz::TextureMailbox texture_mailbox2; + viz::TransferableResource resource2; std::unique_ptr<viz::SingleReleaseCallback> release_callback2; - viz::TextureMailbox texture_mailbox3; + viz::TransferableResource resource3; std::unique_ptr<viz::SingleReleaseCallback> release_callback3; EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox1, - &release_callback1)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource1, + &release_callback1)); VerifyStateWasRestored(); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox2, - &release_callback2)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource2, + &release_callback2)); VerifyStateWasRestored(); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox3, - &release_callback3)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource3, + &release_callback3)); VerifyStateWasRestored(); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); @@ -303,26 +303,26 @@ EXPECT_EQ(live, false); } -TEST_F(DrawingBufferTest, verifyOnlyOneRecycledMailboxMustBeKept) { - viz::TextureMailbox texture_mailbox1; +TEST_F(DrawingBufferTest, VerifyOnlyOneRecycledResourceMustBeKept) { + viz::TransferableResource resource1; std::unique_ptr<viz::SingleReleaseCallback> release_callback1; - viz::TextureMailbox texture_mailbox2; + viz::TransferableResource resource2; std::unique_ptr<viz::SingleReleaseCallback> release_callback2; - viz::TextureMailbox texture_mailbox3; + viz::TransferableResource resource3; std::unique_ptr<viz::SingleReleaseCallback> release_callback3; - // Produce mailboxes. + // Produce resources. EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox1, - &release_callback1)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource1, + &release_callback1)); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox2, - &release_callback2)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource2, + &release_callback2)); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox3, - &release_callback3)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource3, + &release_callback3)); - // Release mailboxes by specific order; 1, 3, 2. + // Release resources by specific order; 1, 3, 2. EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); release_callback1->Run(gpu::SyncToken(), false /* lostResource */); EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); @@ -330,24 +330,28 @@ EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); release_callback2->Run(gpu::SyncToken(), false /* lostResource */); - // The first recycled mailbox must be 2. 1 and 3 were deleted by FIFO order - // because DrawingBuffer never keeps more than one mailbox. - viz::TextureMailbox recycled_texture_mailbox1; + // The first recycled resource must be 2. 1 and 3 were deleted by FIFO order + // because DrawingBuffer never keeps more than one resource. + viz::TransferableResource recycled_resource1; std::unique_ptr<viz::SingleReleaseCallback> recycled_release_callback1; EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox( - &recycled_texture_mailbox1, &recycled_release_callback1)); - EXPECT_EQ(texture_mailbox2.mailbox(), recycled_texture_mailbox1.mailbox()); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource( + &recycled_resource1, &recycled_release_callback1)); + EXPECT_EQ(resource2.mailbox_holder.mailbox, + recycled_resource1.mailbox_holder.mailbox); - // The second recycled mailbox must be a new mailbox. - viz::TextureMailbox recycled_texture_mailbox2; + // The second recycled resource must be a new resource. + viz::TransferableResource recycled_resource2; std::unique_ptr<viz::SingleReleaseCallback> recycled_release_callback2; EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox( - &recycled_texture_mailbox2, &recycled_release_callback2)); - EXPECT_NE(texture_mailbox1.mailbox(), recycled_texture_mailbox2.mailbox()); - EXPECT_NE(texture_mailbox2.mailbox(), recycled_texture_mailbox2.mailbox()); - EXPECT_NE(texture_mailbox3.mailbox(), recycled_texture_mailbox2.mailbox()); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource( + &recycled_resource2, &recycled_release_callback2)); + EXPECT_NE(resource1.mailbox_holder.mailbox, + recycled_resource2.mailbox_holder.mailbox); + EXPECT_NE(resource2.mailbox_holder.mailbox, + recycled_resource2.mailbox_holder.mailbox); + EXPECT_NE(resource3.mailbox_holder.mailbox, + recycled_resource2.mailbox_holder.mailbox); recycled_release_callback1->Run(gpu::SyncToken(), false /* lostResource */); recycled_release_callback2->Run(gpu::SyncToken(), false /* lostResource */); @@ -356,15 +360,15 @@ TEST_F(DrawingBufferTest, verifyInsertAndWaitSyncTokenCorrectly) { GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests(); - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; - // Produce mailboxes. + // Produce resources. EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); EXPECT_EQ(gpu::SyncToken(), gl_->MostRecentlyWaitedSyncToken()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, - &release_callback)); - // PrepareTextureMailbox() does not wait for any sync point. + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource, + &release_callback)); + // PrepareTransferableResource() does not wait for any sync point. EXPECT_EQ(gpu::SyncToken(), gl_->MostRecentlyWaitedSyncToken()); gpu::SyncToken wait_sync_token; @@ -375,10 +379,10 @@ EXPECT_EQ(gpu::SyncToken(), gl_->MostRecentlyWaitedSyncToken()); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, - &release_callback)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource, + &release_callback)); // m_drawingBuffer waits for the sync point when recycling in - // PrepareTextureMailbox(). + // PrepareTransferableResource(). EXPECT_EQ(wait_sync_token, gl_->MostRecentlyWaitedSyncToken()); drawing_buffer_->BeginDestruction(); @@ -424,9 +428,9 @@ std::unique_ptr<ScopedTestingPlatformSupport<FakePlatformSupport>> platform_; }; -TEST_F(DrawingBufferImageChromiumTest, verifyResizingReallocatesImages) { +TEST_F(DrawingBufferImageChromiumTest, VerifyResizingReallocatesImages) { GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests(); - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; IntSize initial_size(kInitialWidth, kInitialHeight); @@ -434,12 +438,13 @@ GLuint image_id1 = gl_->NextImageIdToBeCreated(); EXPECT_CALL(*gl_, BindTexImage2DMock(image_id1)).Times(1); - // Produce one mailbox at size 100x100. + // Produce one resource at size 100x100. EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, - &release_callback)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource, + &release_callback)); EXPECT_EQ(initial_size, gl_->MostRecentlyProducedSize()); - EXPECT_TRUE(texture_mailbox.is_overlay_candidate()); + EXPECT_TRUE(resource.is_overlay_candidate); + EXPECT_EQ(initial_size, resource.size); ::testing::Mock::VerifyAndClearExpectations(gl_); VerifyStateWasRestored(); @@ -458,12 +463,13 @@ GLuint image_id3 = gl_->NextImageIdToBeCreated(); EXPECT_CALL(*gl_, BindTexImage2DMock(image_id3)).Times(1); - // Produce a mailbox at this size. + // Produce a resource at this size. EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, - &release_callback)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource, + &release_callback)); EXPECT_EQ(alternate_size, gl_->MostRecentlyProducedSize()); - EXPECT_TRUE(texture_mailbox.is_overlay_candidate()); + EXPECT_TRUE(resource.is_overlay_candidate); + EXPECT_EQ(alternate_size, resource.size); ::testing::Mock::VerifyAndClearExpectations(gl_); GLuint image_id4 = gl_->NextImageIdToBeCreated(); @@ -481,21 +487,23 @@ GLuint image_id5 = gl_->NextImageIdToBeCreated(); EXPECT_CALL(*gl_, BindTexImage2DMock(image_id5)).Times(1); - // Prepare another mailbox and verify that it's the correct size. + // Prepare another resource and verify that it's the correct size. EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, - &release_callback)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource, + &release_callback)); EXPECT_EQ(initial_size, gl_->MostRecentlyProducedSize()); - EXPECT_TRUE(texture_mailbox.is_overlay_candidate()); + EXPECT_TRUE(resource.is_overlay_candidate); + EXPECT_EQ(initial_size, resource.size); ::testing::Mock::VerifyAndClearExpectations(gl_); - // Prepare one final mailbox and verify that it's the correct size. + // Prepare one final resource and verify that it's the correct size. release_callback->Run(gpu::SyncToken(), false /* lostResource */); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, - &release_callback)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource, + &release_callback)); EXPECT_EQ(initial_size, gl_->MostRecentlyProducedSize()); - EXPECT_TRUE(texture_mailbox.is_overlay_candidate()); + EXPECT_TRUE(resource.is_overlay_candidate); + EXPECT_EQ(initial_size, resource.size); release_callback->Run(gpu::SyncToken(), false /* lostResource */); EXPECT_CALL(*gl_, DestroyImageMock(image_id5)).Times(1); @@ -506,43 +514,43 @@ ::testing::Mock::VerifyAndClearExpectations(gl_); } -TEST_F(DrawingBufferImageChromiumTest, allocationFailure) { +TEST_F(DrawingBufferImageChromiumTest, AllocationFailure) { GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests(); - viz::TextureMailbox texture_mailbox1; + viz::TransferableResource resource1; std::unique_ptr<viz::SingleReleaseCallback> release_callback1; - viz::TextureMailbox texture_mailbox2; + viz::TransferableResource resource2; std::unique_ptr<viz::SingleReleaseCallback> release_callback2; - viz::TextureMailbox texture_mailbox3; + viz::TransferableResource resource3; std::unique_ptr<viz::SingleReleaseCallback> release_callback3; - // Request a mailbox. An image should already be created. Everything works + // Request a resource. An image should already be created. Everything works // as expected. EXPECT_CALL(*gl_, BindTexImage2DMock(_)).Times(1); IntSize initial_size(kInitialWidth, kInitialHeight); EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox1, - &release_callback1)); - EXPECT_TRUE(texture_mailbox1.is_overlay_candidate()); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource1, + &release_callback1)); + EXPECT_TRUE(resource1.is_overlay_candidate); ::testing::Mock::VerifyAndClearExpectations(gl_); VerifyStateWasRestored(); - // Force image CHROMIUM creation failure. Request another mailbox. It should + // Force image CHROMIUM creation failure. Request another resource. It should // still be provided, but this time with allowOverlay = false. gl_->SetCreateImageChromiumFail(true); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox2, - &release_callback2)); - EXPECT_FALSE(texture_mailbox2.is_overlay_candidate()); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource2, + &release_callback2)); + EXPECT_FALSE(resource2.is_overlay_candidate); VerifyStateWasRestored(); - // Check that if image CHROMIUM starts working again, mailboxes are + // Check that if image CHROMIUM starts working again, resources are // correctly created with allowOverlay = true. EXPECT_CALL(*gl_, BindTexImage2DMock(_)).Times(1); gl_->SetCreateImageChromiumFail(false); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox3, - &release_callback3)); - EXPECT_TRUE(texture_mailbox3.is_overlay_candidate()); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource3, + &release_callback3)); + EXPECT_TRUE(resource3.is_overlay_candidate); ::testing::Mock::VerifyAndClearExpectations(gl_); VerifyStateWasRestored(); @@ -705,22 +713,22 @@ } } -TEST_F(DrawingBufferTest, verifySetIsHiddenProperlyAffectsMailboxes) { +TEST_F(DrawingBufferTest, VerifySetIsHiddenProperlyAffectsMailboxes) { GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests(); - viz::TextureMailbox texture_mailbox; + viz::TransferableResource resource; std::unique_ptr<viz::SingleReleaseCallback> release_callback; - // Produce mailboxes. + // Produce resources. EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox, - &release_callback)); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(&resource, + &release_callback)); gpu::SyncToken wait_sync_token; gl_->GenSyncTokenCHROMIUM(gl_->InsertFenceSyncCHROMIUM(), wait_sync_token.GetData()); drawing_buffer_->SetIsHidden(true); release_callback->Run(wait_sync_token, false /* lostResource */); - // m_drawingBuffer deletes mailbox immediately when hidden. + // m_drawingBuffer deletes resource immediately when hidden. EXPECT_EQ(wait_sync_token, gl_->MostRecentlyWaitedSyncToken());
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp index 8744d50..fbef4715 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp
@@ -5,7 +5,7 @@ #include "platform/graphics/gpu/ImageLayerBridge.h" #include "components/viz/common/quads/shared_bitmap.h" -#include "components/viz/common/quads/texture_mailbox.h" +#include "components/viz/common/resources/transferable_resource.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "platform/graphics/AcceleratedStaticBitmapImage.h" #include "platform/graphics/ColorBehavior.h" @@ -47,9 +47,9 @@ image_->IsTextureBacked()) { // If the layer bridge is not presenting, the GrContext may not be getting // flushed regularly. The flush is normally triggered inside the - // m_image->ensureMailbox() call of - // ImageLayerBridge::PrepareTextureMailbox. To prevent a potential memory - // leak we must flush the GrContext here. + // m_image->EnsureMailbox() call of + // ImageLayerBridge::PrepareTransferableResource. To prevent a potential + // memory leak we must flush the GrContext here. image_->PaintImageForCurrentFrame().GetSkImage()->getTextureHandle( true); // GrContext flush. } @@ -66,8 +66,8 @@ disposed_ = true; } -bool ImageLayerBridge::PrepareTextureMailbox( - viz::TextureMailbox* out_mailbox, +bool ImageLayerBridge::PrepareTransferableResource( + viz::TransferableResource* out_resource, std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) { if (disposed_) return false; @@ -106,11 +106,13 @@ if (gpu_compositing) { image_for_compositor->EnsureMailbox(kUnverifiedSyncToken); - *out_mailbox = viz::TextureMailbox(image_for_compositor->GetMailbox(), - image_for_compositor->GetSyncToken(), - GL_TEXTURE_2D); + uint32_t filter = + filter_quality_ == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR; + *out_resource = viz::TransferableResource::MakeGL( + image_for_compositor->GetMailbox(), filter, GL_TEXTURE_2D, + image_for_compositor->GetSyncToken()); auto func = - WTF::Bind(&ImageLayerBridge::MailboxReleasedGpu, + WTF::Bind(&ImageLayerBridge::ResourceReleasedGpu, WrapWeakPersistent(this), std::move(image_for_compositor)); *out_release_callback = viz::SingleReleaseCallback::Create( ConvertToBaseCallback(std::move(func))); @@ -135,19 +137,19 @@ return false; } - *out_mailbox = viz::TextureMailbox( - bitmap.get(), gfx::Size(image_for_compositor->width(), - image_for_compositor->height())); - auto func = WTF::Bind(&ImageLayerBridge::MailboxReleasedSoftware, + *out_resource = viz::TransferableResource::MakeSoftware( + bitmap->id(), bitmap->sequence_number(), + gfx::Size(image_for_compositor->width(), + image_for_compositor->height())); + auto func = WTF::Bind(&ImageLayerBridge::ResourceReleasedSoftware, WrapWeakPersistent(this), base::Passed(&bitmap), image_for_compositor->Size()); *out_release_callback = viz::SingleReleaseCallback::Create( ConvertToBaseCallback(std::move(func))); } - out_mailbox->set_nearest_neighbor(filter_quality_ == kNone_SkFilterQuality); // TODO(junov): Figure out how to get the color space info. - // outMailbox->set_color_space(); + // out_resource->color_space = ...; return true; } @@ -168,7 +170,7 @@ return Platform::Current()->AllocateSharedBitmap(size); } -void ImageLayerBridge::MailboxReleasedGpu( +void ImageLayerBridge::ResourceReleasedGpu( scoped_refptr<StaticBitmapImage> image, const gpu::SyncToken& token, bool lost_resource) { @@ -183,7 +185,7 @@ // let 'image' go out of scope to release gpu resources. } -void ImageLayerBridge::MailboxReleasedSoftware( +void ImageLayerBridge::ResourceReleasedSoftware( std::unique_ptr<viz::SharedBitmap> bitmap, const IntSize& size, const gpu::SyncToken& sync_token,
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h index cf2ffa4..42f1876 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h +++ b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h
@@ -33,18 +33,18 @@ void Dispose(); // cc::TextureLayerClient implementation. - bool PrepareTextureMailbox(viz::TextureMailbox* out_mailbox, - std::unique_ptr<viz::SingleReleaseCallback>* - out_release_callback) override; + bool PrepareTransferableResource(viz::TransferableResource* out_resource, + std::unique_ptr<viz::SingleReleaseCallback>* + out_release_callback) override; - void MailboxReleasedGpu(scoped_refptr<StaticBitmapImage>, - const gpu::SyncToken&, - bool lost_resource); + void ResourceReleasedGpu(scoped_refptr<StaticBitmapImage>, + const gpu::SyncToken&, + bool lost_resource); - void MailboxReleasedSoftware(std::unique_ptr<viz::SharedBitmap>, - const IntSize&, - const gpu::SyncToken&, - bool lost_resource); + void ResourceReleasedSoftware(std::unique_ptr<viz::SharedBitmap>, + const IntSize&, + const gpu::SyncToken&, + bool lost_resource); scoped_refptr<StaticBitmapImage> GetImage() { return image_; }
diff --git a/third_party/WebKit/Source/platform/heap/HeapAllocator.h b/third_party/WebKit/Source/platform/heap/HeapAllocator.h index 5754990..491102307 100644 --- a/third_party/WebKit/Source/platform/heap/HeapAllocator.h +++ b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
@@ -12,6 +12,7 @@ #include "platform/wtf/Allocator.h" #include "platform/wtf/Assertions.h" #include "platform/wtf/Deque.h" +#include "platform/wtf/DoublyLinkedList.h" #include "platform/wtf/HashCountedSet.h" #include "platform/wtf/HashMap.h" #include "platform/wtf/HashSet.h" @@ -479,6 +480,23 @@ : Deque<T, inlineCapacity, HeapAllocator>(other) {} }; +template <typename T> +class HeapDoublyLinkedList : public DoublyLinkedList<T, Member<T>> { + IS_GARBAGE_COLLECTED_TYPE(); + DISALLOW_NEW(); + + public: + HeapDoublyLinkedList() { + static_assert(WTF::IsGarbageCollectedType<T>::value, + "This should only be used for garbage collected types."); + } + + void Trace(Visitor* visitor) { + visitor->Trace(this->head_); + visitor->Trace(this->tail_); + } +}; + } // namespace blink namespace WTF {
diff --git a/third_party/WebKit/Source/platform/heap/HeapTerminatedArray.h b/third_party/WebKit/Source/platform/heap/HeapTerminatedArray.h index 5cd2ec8..c422d31 100644 --- a/third_party/WebKit/Source/platform/heap/HeapTerminatedArray.h +++ b/third_party/WebKit/Source/platform/heap/HeapTerminatedArray.h
@@ -59,12 +59,6 @@ friend class WTF::TerminatedArrayBuilder; }; -template <typename T> -class TraceEagerlyTrait<HeapTerminatedArray<T>> { - public: - static const bool value = TraceEagerlyTrait<T>::value; -}; - } // namespace blink #endif // HeapTerminatedArray_h
diff --git a/third_party/WebKit/Source/platform/heap/HeapTest.cpp b/third_party/WebKit/Source/platform/heap/HeapTest.cpp index 99bf5dd8..d772ab8 100644 --- a/third_party/WebKit/Source/platform/heap/HeapTest.cpp +++ b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
@@ -6709,4 +6709,62 @@ EXPECT_TRUE(string.Impl()->HasOneRef()); } +class DoublyLinkedListNodeImpl + : public GarbageCollectedFinalized<DoublyLinkedListNodeImpl>, + public DoublyLinkedListNode<DoublyLinkedListNodeImpl> { + public: + DoublyLinkedListNodeImpl() {} + static DoublyLinkedListNodeImpl* Create() { + return new DoublyLinkedListNodeImpl(); + } + + static int destructor_calls_; + ~DoublyLinkedListNodeImpl() { ++destructor_calls_; } + + void Trace(Visitor* visitor) { + visitor->Trace(prev_); + visitor->Trace(next_); + } + + private: + friend class WTF::DoublyLinkedListNode<DoublyLinkedListNodeImpl>; + Member<DoublyLinkedListNodeImpl> prev_; + Member<DoublyLinkedListNodeImpl> next_; +}; + +int DoublyLinkedListNodeImpl::destructor_calls_ = 0; + +template <typename T> +class HeapDoublyLinkedListContainer + : public GarbageCollected<HeapDoublyLinkedListContainer<T>> { + public: + static HeapDoublyLinkedListContainer<T>* Create() { + return new HeapDoublyLinkedListContainer<T>(); + } + HeapDoublyLinkedListContainer<T>() {} + HeapDoublyLinkedList<T> list_; + void Trace(Visitor* visitor) { visitor->Trace(list_); } +}; + +TEST(HeapTest, HeapDoublyLinkedList) { + Persistent<HeapDoublyLinkedListContainer<DoublyLinkedListNodeImpl>> + container = + HeapDoublyLinkedListContainer<DoublyLinkedListNodeImpl>::Create(); + DoublyLinkedListNodeImpl::destructor_calls_ = 0; + + container->list_.Append(DoublyLinkedListNodeImpl::Create()); + container->list_.Append(DoublyLinkedListNodeImpl::Create()); + + PreciselyCollectGarbage(); + EXPECT_EQ(DoublyLinkedListNodeImpl::destructor_calls_, 0); + + container->list_.RemoveHead(); + PreciselyCollectGarbage(); + EXPECT_EQ(DoublyLinkedListNodeImpl::destructor_calls_, 1); + + container->list_.RemoveHead(); + PreciselyCollectGarbage(); + EXPECT_EQ(DoublyLinkedListNodeImpl::destructor_calls_, 2); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/heap/TraceTraits.h b/third_party/WebKit/Source/platform/heap/TraceTraits.h index 899966d..f2464fe 100644 --- a/third_party/WebKit/Source/platform/heap/TraceTraits.h +++ b/third_party/WebKit/Source/platform/heap/TraceTraits.h
@@ -27,6 +27,10 @@ template <typename T> class CrossThreadWeakPersistent; template <typename T> +class HeapDoublyLinkedList; +template <typename T> +class HeapTerminatedArray; +template <typename T> class Member; template <typename T> class TraceEagerlyTrait; @@ -434,6 +438,20 @@ static const bool value = TraceEagerlyTrait<T>::value; }; +template <typename T> +class TraceEagerlyTrait<HeapTerminatedArray<T>> { + public: + static const bool value = TraceEagerlyTrait<T>::value; +}; + +template <typename T> +class TraceEagerlyTrait<HeapDoublyLinkedList<T>> { + STATIC_ONLY(TraceEagerlyTrait); + + public: + static const bool value = TraceEagerlyTrait<T>::value; +}; + template <typename ValueArg, size_t inlineCapacity> class HeapListHashSetAllocator; template <typename T, size_t inlineCapacity>
diff --git a/third_party/WebKit/Source/platform/loader/BUILD.gn b/third_party/WebKit/Source/platform/loader/BUILD.gn index c4be3880..d01444f 100644 --- a/third_party/WebKit/Source/platform/loader/BUILD.gn +++ b/third_party/WebKit/Source/platform/loader/BUILD.gn
@@ -167,6 +167,7 @@ public_deps = [ "//net", "//skia", + "//third_party/WebKit/Source/platform", "//third_party/WebKit/Source/platform/blob:generator", "//third_party/icu", ]
diff --git a/third_party/WebKit/Source/platform/loader/LinkHeader.cpp b/third_party/WebKit/Source/platform/loader/LinkHeader.cpp index 3c86c93..1c5551e 100644 --- a/third_party/WebKit/Source/platform/loader/LinkHeader.cpp +++ b/third_party/WebKit/Source/platform/loader/LinkHeader.cpp
@@ -38,6 +38,8 @@ return LinkHeader::kLinkParameterAs; if (base::EqualsCaseInsensitiveASCII(name, "nonce")) return LinkHeader::kLinkParameterNonce; + if (base::EqualsCaseInsensitiveASCII(name, "integrity")) + return LinkHeader::kLinkParameterIntegrity; return LinkHeader::kLinkParameterUnknown; } @@ -56,6 +58,8 @@ media_ = value.DeprecatedLower(); else if (name == kLinkParameterNonce) nonce_ = value; + else if (name == kLinkParameterIntegrity) + integrity_ = value; } template <typename Iterator>
diff --git a/third_party/WebKit/Source/platform/loader/LinkHeader.h b/third_party/WebKit/Source/platform/loader/LinkHeader.h index b21bebd..a911164 100644 --- a/third_party/WebKit/Source/platform/loader/LinkHeader.h +++ b/third_party/WebKit/Source/platform/loader/LinkHeader.h
@@ -22,6 +22,7 @@ const String& Media() const { return media_; } const String& CrossOrigin() const { return cross_origin_; } const String& Nonce() const { return nonce_; } + const String& Integrity() const { return integrity_; } bool Valid() const { return is_valid_; } enum LinkParameterName { @@ -37,6 +38,7 @@ kLinkParameterCrossOrigin, kLinkParameterAs, kLinkParameterNonce, + kLinkParameterIntegrity, }; private: @@ -53,6 +55,7 @@ String media_; String cross_origin_; String nonce_; + String integrity_; bool is_valid_; };
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.h b/third_party/WebKit/Source/platform/loader/fetch/Resource.h index 11eb7e3c..b7cdf1f 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/Resource.h +++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.h
@@ -27,7 +27,6 @@ #include <memory> #include "platform/MemoryCoordinator.h" #include "platform/PlatformExport.h" -#include "platform/ScopedVirtualTimePauser.h" #include "platform/SharedBuffer.h" #include "platform/Timer.h" #include "platform/WebTaskRunner.h" @@ -52,6 +51,7 @@ #include "platform/wtf/text/WTFString.h" #include "public/platform/CORSStatus.h" #include "public/platform/WebDataConsumerHandle.h" +#include "public/platform/WebScopedVirtualTimePauser.h" namespace blink { @@ -346,7 +346,9 @@ : AutoReset(&resource->is_revalidation_start_forbidden_, true) {} }; - ScopedVirtualTimePauser& VirtualTimePauser() { return virtual_time_pauser_; } + WebScopedVirtualTimePauser& VirtualTimePauser() { + return virtual_time_pauser_; + } protected: Resource(const ResourceRequest&, Type, const ResourceLoaderOptions&); @@ -493,7 +495,7 @@ scoped_refptr<SharedBuffer> data_; - ScopedVirtualTimePauser virtual_time_pauser_; + WebScopedVirtualTimePauser virtual_time_pauser_; }; class ResourceFactory {
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp index ee821f5..9cb4bb28 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -1444,8 +1444,8 @@ resource->Options().initiator_info); if (Context().GetFrameScheduler()) { - ScopedVirtualTimePauser virtual_time_pauser = - Context().GetFrameScheduler()->CreateScopedVirtualTimePauser(); + WebScopedVirtualTimePauser virtual_time_pauser = + Context().GetFrameScheduler()->CreateWebScopedVirtualTimePauser(); virtual_time_pauser.PauseVirtualTime(true); resource->VirtualTimePauser() = std::move(virtual_time_pauser); }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp index dd29880..1efd365 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
@@ -375,8 +375,8 @@ Context().PrepareRequest(new_request, FetchContext::RedirectType::kForRedirect); if (Context().GetFrameScheduler()) { - ScopedVirtualTimePauser virtual_time_pauser = - Context().GetFrameScheduler()->CreateScopedVirtualTimePauser(); + WebScopedVirtualTimePauser virtual_time_pauser = + Context().GetFrameScheduler()->CreateWebScopedVirtualTimePauser(); virtual_time_pauser.PauseVirtualTime(true); resource_->VirtualTimePauser() = std::move(virtual_time_pauser); }
diff --git a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 b/third_party/WebKit/Source/platform/runtime_enabled_features.json5 index 623c1b5..dd5c94fd 100644 --- a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 +++ b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
@@ -598,10 +598,6 @@ name: "MediaEngagementBypassAutoplayPolicies", }, { - name: "MediaPlaybackRateOutOfRange", - status: "experimental", - }, - { name: "MediaQueryShape", status: "experimental", },
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc index 4195e74d0..087312a 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
@@ -2077,6 +2077,11 @@ main_thread_only().process_type = type; } +WebScopedVirtualTimePauser +RendererSchedulerImpl::CreateWebScopedVirtualTimePauser() { + return WebScopedVirtualTimePauser(this); +} + void RendererSchedulerImpl::RegisterTimeDomain(TimeDomain* time_domain) { helper_.RegisterTimeDomain(time_domain); }
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h index 6623ed6..c344cf992f 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h +++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
@@ -138,6 +138,7 @@ bool MainThreadSeemsUnresponsive( base::TimeDelta main_thread_responsiveness_threshold) override; void SetRendererProcessType(RendererProcessType type) override; + WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser() override; // AutoAdvancingVirtualTimeDomain::Observer implementation: void OnVirtualTimeAdvanced() override;
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/scoped_virtual_time_pauser.cc b/third_party/WebKit/Source/platform/scheduler/renderer/scoped_virtual_time_pauser.cc index d1dcd25..7dd7b51 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/scoped_virtual_time_pauser.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/scoped_virtual_time_pauser.cc
@@ -2,32 +2,33 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "platform/ScopedVirtualTimePauser.h" +#include "public/platform/WebScopedVirtualTimePauser.h" #include "platform/scheduler/renderer/renderer_scheduler_impl.h" namespace blink { -ScopedVirtualTimePauser::ScopedVirtualTimePauser() : scheduler_(nullptr) {} +WebScopedVirtualTimePauser::WebScopedVirtualTimePauser() + : scheduler_(nullptr) {} -ScopedVirtualTimePauser::ScopedVirtualTimePauser( +WebScopedVirtualTimePauser::WebScopedVirtualTimePauser( scheduler::RendererSchedulerImpl* scheduler) : scheduler_(scheduler) {} -ScopedVirtualTimePauser::~ScopedVirtualTimePauser() { +WebScopedVirtualTimePauser::~WebScopedVirtualTimePauser() { if (paused_ && scheduler_) scheduler_->DecrementVirtualTimePauseCount(); } -ScopedVirtualTimePauser::ScopedVirtualTimePauser( - ScopedVirtualTimePauser&& other) { +WebScopedVirtualTimePauser::WebScopedVirtualTimePauser( + WebScopedVirtualTimePauser&& other) { paused_ = other.paused_; scheduler_ = std::move(other.scheduler_); other.scheduler_ = nullptr; } -ScopedVirtualTimePauser& ScopedVirtualTimePauser::operator=( - ScopedVirtualTimePauser&& other) { +WebScopedVirtualTimePauser& WebScopedVirtualTimePauser::operator=( + WebScopedVirtualTimePauser&& other) { if (scheduler_ && paused_) scheduler_->DecrementVirtualTimePauseCount(); paused_ = other.paused_; @@ -36,7 +37,7 @@ return *this; } -void ScopedVirtualTimePauser::PauseVirtualTime(bool paused) { +void WebScopedVirtualTimePauser::PauseVirtualTime(bool paused) { if (paused == paused_ || !scheduler_) return;
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc index 0c1dd05c..30766abf 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
@@ -389,8 +389,9 @@ is_reload, is_main_frame); } -ScopedVirtualTimePauser WebFrameSchedulerImpl::CreateScopedVirtualTimePauser() { - return ScopedVirtualTimePauser(renderer_scheduler_); +WebScopedVirtualTimePauser +WebFrameSchedulerImpl::CreateWebScopedVirtualTimePauser() { + return WebScopedVirtualTimePauser(renderer_scheduler_); } void WebFrameSchedulerImpl::DidOpenActiveConnection() {
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.h index de5cd03c..a63b58a 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.h +++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.h
@@ -72,7 +72,7 @@ void DidCommitProvisionalLoad(bool is_web_history_inert_commit, bool is_reload, bool is_main_frame) override; - ScopedVirtualTimePauser CreateScopedVirtualTimePauser() override; + WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser() override; void OnFirstMeaningfulPaint() override; std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override; void AsValueInto(base::trace_event::TracedValue* state) const;
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc index 00c398a4..a4126a5 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc
@@ -520,7 +520,7 @@ } TEST_F(WebViewSchedulerImplTest, - ScopedVirtualTimePauser_DETERMINISTIC_LOADING) { + WebScopedVirtualTimePauser_DETERMINISTIC_LOADING) { web_view_scheduler_->SetVirtualTimePolicy( VirtualTimePolicy::kDeterministicLoading); @@ -529,8 +529,8 @@ nullptr, WebFrameScheduler::FrameType::kSubframe); { - ScopedVirtualTimePauser virtual_time_pauser = - web_frame_scheduler->CreateScopedVirtualTimePauser(); + WebScopedVirtualTimePauser virtual_time_pauser = + web_frame_scheduler->CreateWebScopedVirtualTimePauser(); EXPECT_TRUE(scheduler_->VirtualTimeAllowedToAdvance()); virtual_time_pauser.PauseVirtualTime(true); @@ -547,7 +547,7 @@ } TEST_F(WebViewSchedulerImplTest, - MultipleScopedVirtualTimePausers_DETERMINISTIC_LOADING) { + MultipleWebScopedVirtualTimePausers_DETERMINISTIC_LOADING) { web_view_scheduler_->SetVirtualTimePolicy( VirtualTimePolicy::kDeterministicLoading); @@ -555,10 +555,10 @@ web_view_scheduler_->CreateWebFrameSchedulerImpl( nullptr, WebFrameScheduler::FrameType::kSubframe); - ScopedVirtualTimePauser virtual_time_pauser1 = - web_frame_scheduler->CreateScopedVirtualTimePauser(); - ScopedVirtualTimePauser virtual_time_pauser2 = - web_frame_scheduler->CreateScopedVirtualTimePauser(); + WebScopedVirtualTimePauser virtual_time_pauser1 = + web_frame_scheduler->CreateWebScopedVirtualTimePauser(); + WebScopedVirtualTimePauser virtual_time_pauser2 = + web_frame_scheduler->CreateWebScopedVirtualTimePauser(); EXPECT_TRUE(scheduler_->VirtualTimeAllowedToAdvance());
diff --git a/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc b/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc index e874533f..15db601 100644 --- a/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc +++ b/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc
@@ -126,5 +126,10 @@ void FakeRendererScheduler::SetRendererProcessType(RendererProcessType type) {} +WebScopedVirtualTimePauser +FakeRendererScheduler::CreateWebScopedVirtualTimePauser() { + return WebScopedVirtualTimePauser(nullptr); +} + } // namespace scheduler } // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/test/fake_web_frame_scheduler.h b/third_party/WebKit/Source/platform/scheduler/test/fake_web_frame_scheduler.h index 066b578..ed1e2f4 100644 --- a/third_party/WebKit/Source/platform/scheduler/test/fake_web_frame_scheduler.h +++ b/third_party/WebKit/Source/platform/scheduler/test/fake_web_frame_scheduler.h
@@ -120,8 +120,8 @@ WebViewScheduler* GetWebViewScheduler() const override { return web_view_scheduler_; } - ScopedVirtualTimePauser CreateScopedVirtualTimePauser() { - return ScopedVirtualTimePauser(); + WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser() { + return WebScopedVirtualTimePauser(); } void DidStartProvisionalLoad(bool is_main_frame) override {} void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
diff --git a/third_party/WebKit/Source/platform/text/BidiCharacterRun.cpp b/third_party/WebKit/Source/platform/text/BidiCharacterRun.cpp index b7e3541..046b4a0 100644 --- a/third_party/WebKit/Source/platform/text/BidiCharacterRun.cpp +++ b/third_party/WebKit/Source/platform/text/BidiCharacterRun.cpp
@@ -27,8 +27,8 @@ namespace blink { void* BidiCharacterRun::operator new(size_t sz) { - return WTF::PartitionAlloc(WTF::Partitions::LayoutPartition(), sz, - WTF_HEAP_PROFILER_TYPE_NAME(BidiCharacterRun)); + return WTF::Partitions::LayoutPartition()->Alloc( + sz, WTF_HEAP_PROFILER_TYPE_NAME(BidiCharacterRun)); } void BidiCharacterRun::operator delete(void* ptr) {
diff --git a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp index e971477..e6a76de 100644 --- a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp +++ b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
@@ -243,15 +243,19 @@ } bool SchemeRegistry::ShouldTrackUsageMetricsForScheme(const String& scheme) { + // This SchemeRegistry is primarily used by Blink UseCounter, which aims to + // match the tracking policy of page_load_metrics (see + // pageTrackDecider::ShouldTrack() for more details). // The scheme represents content which likely cannot be easily updated. // Specifically this includes internal pages such as about, chrome-devtools, // etc. // "chrome-extension" is not included because they have a single deployment // point (the webstore) and are designed specifically for Chrome. // "data" is not included because real sites shouldn't be using it for - // top-level - // pages and Chrome does use it internally (eg. PluginPlaceholder). - return scheme == "http" || scheme == "https" || scheme == "file"; + // top-level pages and Chrome does use it internally (eg. PluginPlaceholder). + // "file" is not included because file:// navigations have different loading + // behaviors. + return scheme == "http" || scheme == "https"; } void SchemeRegistry::RegisterURLSchemeAsAllowingServiceWorkers(
diff --git a/third_party/WebKit/Source/platform/wtf/BUILD.gn b/third_party/WebKit/Source/platform/wtf/BUILD.gn index 5fe3b02..2c69acb 100644 --- a/third_party/WebKit/Source/platform/wtf/BUILD.gn +++ b/third_party/WebKit/Source/platform/wtf/BUILD.gn
@@ -104,7 +104,6 @@ "ProcessMetrics.h", "PtrUtil.h", "RefCounted.h", - "RefPtr.h", "RefVector.h", "RetainPtr.h", "SaturatedArithmetic.h",
diff --git a/third_party/WebKit/Source/platform/wtf/DoublyLinkedList.h b/third_party/WebKit/Source/platform/wtf/DoublyLinkedList.h index a5f809e..fabf4f2b1 100644 --- a/third_party/WebKit/Source/platform/wtf/DoublyLinkedList.h +++ b/third_party/WebKit/Source/platform/wtf/DoublyLinkedList.h
@@ -69,9 +69,10 @@ return static_cast<const T*>(this)->next_; } -template <typename T> +template <typename T, typename PointerType = T*> class DoublyLinkedList { USING_FAST_MALLOC(DoublyLinkedList); + WTF_MAKE_NONCOPYABLE(DoublyLinkedList); public: DoublyLinkedList(); @@ -89,81 +90,88 @@ void Append(T*); void Remove(T*); - private: - T* head_; - T* tail_; + protected: + PointerType head_; + PointerType tail_; }; -template <typename T> -inline DoublyLinkedList<T>::DoublyLinkedList() : head_(0), tail_(0) {} +template <typename T, typename PointerType> +inline DoublyLinkedList<T, PointerType>::DoublyLinkedList() + : head_(nullptr), tail_(nullptr) { + static_assert( + !IsGarbageCollectedType<T>::value || + !std::is_same<PointerType, T*>::value, + "Cannot use DoublyLinkedList<> with garbage collected types, use " + "HeapDoublyLinkedList<> instead."); +} -template <typename T> -inline bool DoublyLinkedList<T>::IsEmpty() const { +template <typename T, typename PointerType> +inline bool DoublyLinkedList<T, PointerType>::IsEmpty() const { return !head_; } -template <typename T> -inline size_t DoublyLinkedList<T>::size() const { +template <typename T, typename PointerType> +inline size_t DoublyLinkedList<T, PointerType>::size() const { size_t size = 0; for (T* node = head_; node; node = node->Next()) ++size; return size; } -template <typename T> -inline void DoublyLinkedList<T>::Clear() { - head_ = 0; - tail_ = 0; +template <typename T, typename PointerType> +inline void DoublyLinkedList<T, PointerType>::Clear() { + head_ = nullptr; + tail_ = nullptr; } -template <typename T> -inline T* DoublyLinkedList<T>::Head() const { +template <typename T, typename PointerType> +inline T* DoublyLinkedList<T, PointerType>::Head() const { return head_; } -template <typename T> -inline T* DoublyLinkedList<T>::Tail() const { +template <typename T, typename PointerType> +inline T* DoublyLinkedList<T, PointerType>::Tail() const { return tail_; } -template <typename T> -inline void DoublyLinkedList<T>::Push(T* node) { +template <typename T, typename PointerType> +inline void DoublyLinkedList<T, PointerType>::Push(T* node) { if (!head_) { DCHECK(!tail_); head_ = node; tail_ = node; - node->SetPrev(0); - node->SetNext(0); + node->SetPrev(nullptr); + node->SetNext(nullptr); return; } DCHECK(tail_); head_->SetPrev(node); node->SetNext(head_); - node->SetPrev(0); + node->SetPrev(nullptr); head_ = node; } -template <typename T> -inline void DoublyLinkedList<T>::Append(T* node) { +template <typename T, typename PointerType> +inline void DoublyLinkedList<T, PointerType>::Append(T* node) { if (!tail_) { DCHECK(!head_); head_ = node; tail_ = node; - node->SetPrev(0); - node->SetNext(0); + node->SetPrev(nullptr); + node->SetNext(nullptr); return; } DCHECK(head_); tail_->SetNext(node); node->SetPrev(tail_); - node->SetNext(0); + node->SetNext(nullptr); tail_ = node; } -template <typename T> -inline void DoublyLinkedList<T>::Remove(T* node) { +template <typename T, typename PointerType> +inline void DoublyLinkedList<T, PointerType>::Remove(T* node) { if (node->Prev()) { DCHECK_NE(node, head_); node->Prev()->SetNext(node->Next()); @@ -181,8 +189,8 @@ } } -template <typename T> -inline T* DoublyLinkedList<T>::RemoveHead() { +template <typename T, typename PointerType> +inline T* DoublyLinkedList<T, PointerType>::RemoveHead() { T* node = Head(); if (node) Remove(node);
diff --git a/third_party/WebKit/Source/platform/wtf/README.md b/third_party/WebKit/Source/platform/wtf/README.md index dda49e05..8e2ba35 100644 --- a/third_party/WebKit/Source/platform/wtf/README.md +++ b/third_party/WebKit/Source/platform/wtf/README.md
@@ -105,7 +105,6 @@ [StringBuilder]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/text/StringBuilder.h [CString]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/text/CString.h [RefCounted]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/RefCounted.h -[RefPtr]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/RefPtr.h [PtrUtil.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/PtrUtil.h [Allocator.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/Allocator.h [Functional.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/Functional.h
diff --git a/third_party/WebKit/Source/platform/wtf/RefPtr.h b/third_party/WebKit/Source/platform/wtf/RefPtr.h deleted file mode 100644 index a0f131d78..0000000 --- a/third_party/WebKit/Source/platform/wtf/RefPtr.h +++ /dev/null
@@ -1,27 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. - * All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_RefPtr_h -#define WTF_RefPtr_h - -#include "base/memory/scoped_refptr.h" - -#endif // WTF_RefPtr_h
diff --git a/third_party/WebKit/Source/platform/wtf/TypeTraits.h b/third_party/WebKit/Source/platform/wtf/TypeTraits.h index e287bec..2fe354a 100644 --- a/third_party/WebKit/Source/platform/wtf/TypeTraits.h +++ b/third_party/WebKit/Source/platform/wtf/TypeTraits.h
@@ -121,49 +121,6 @@ static const bool value = sizeof(SubclassCheck(t_)) == sizeof(YesType); }; -template <typename T, template <class V> class OuterTemplate> -struct RemoveTemplate { - typedef T Type; -}; - -template <typename T, template <class V> class OuterTemplate> -struct RemoveTemplate<OuterTemplate<T>, OuterTemplate> { - typedef T Type; -}; - -#if (defined(COMPILER_MSVC) || !GCC_VERSION_AT_LEAST(4, 9, 0)) && \ - !defined(__clang__) -// FIXME: MSVC bug workaround. Remove once MSVC STL is fixed. -// FIXME: GCC before 4.9.0 seems to have the same issue. -// C++ 2011 Spec (ISO/IEC 14882:2011(E)) 20.9.6.2 Table 51 states that -// the template parameters shall be a complete type if they are different types. -// However, MSVC checks for type completeness even if they are the same type. -// Here, we use a template specialization for same type case to allow incomplete -// types. - -template <typename T, typename U> -struct IsConvertible { - static const bool value = std::is_convertible<T, U>::value; -}; - -template <typename T> -struct IsConvertible<T, T> { - static const bool value = true; -}; - -#define EnsurePtrConvertibleArgDecl(From, To) \ - typename std::enable_if<WTF::IsConvertible<From*, To*>::value>::type* = \ - nullptr -#define EnsurePtrConvertibleArgDefn(From, To) \ - typename std::enable_if<WTF::IsConvertible<From*, To*>::value>::type* -#else -#define EnsurePtrConvertibleArgDecl(From, To) \ - typename std::enable_if<std::is_convertible<From*, To*>::value>::type* = \ - nullptr -#define EnsurePtrConvertibleArgDefn(From, To) \ - typename std::enable_if<std::is_convertible<From*, To*>::value>::type* -#endif - } // namespace WTF namespace blink {
diff --git a/third_party/WebKit/Source/platform/wtf/TypeTraitsTest.cpp b/third_party/WebKit/Source/platform/wtf/TypeTraitsTest.cpp index 3ff814db..cd72f5b 100644 --- a/third_party/WebKit/Source/platform/wtf/TypeTraitsTest.cpp +++ b/third_party/WebKit/Source/platform/wtf/TypeTraitsTest.cpp
@@ -220,6 +220,10 @@ static_assert(!IsTriviallyDestructible<DestructorDeleted>::value, "DestructorDeleted must not be trivially destructible."); +#define EnsurePtrConvertibleArgDecl(From, To) \ + typename std::enable_if<std::is_convertible<From*, To*>::value>::type* = \ + nullptr + template <typename T> class Wrapper { public:
diff --git a/third_party/WebKit/Source/platform/wtf/allocator/Partitions.cpp b/third_party/WebKit/Source/platform/wtf/allocator/Partitions.cpp index 9dfe873..e6ed2dd 100644 --- a/third_party/WebKit/Source/platform/wtf/allocator/Partitions.cpp +++ b/third_party/WebKit/Source/platform/wtf/allocator/Partitions.cpp
@@ -99,8 +99,7 @@ base::PartitionPurgeMemoryGeneric( FastMallocPartition(), base::PartitionPurgeDecommitEmptyPages | base::PartitionPurgeDiscardUnusedSystemPages); - base::PartitionPurgeMemory(LayoutPartition(), - base::PartitionPurgeDecommitEmptyPages | + LayoutPartition()->PurgeMemory(base::PartitionPurgeDecommitEmptyPages | base::PartitionPurgeDiscardUnusedSystemPages); } @@ -134,8 +133,7 @@ is_light_dump, partition_stats_dumper); PartitionDumpStatsGeneric(BufferPartition(), "buffer", is_light_dump, partition_stats_dumper); - PartitionDumpStats(LayoutPartition(), "layout", is_light_dump, - partition_stats_dumper); + LayoutPartition()->DumpStats("layout", is_light_dump, partition_stats_dumper); } namespace {
diff --git a/third_party/WebKit/Source/platform/wtf/allocator/Partitions.h b/third_party/WebKit/Source/platform/wtf/allocator/Partitions.h index 870d007..8813b81 100644 --- a/third_party/WebKit/Source/platform/wtf/allocator/Partitions.h +++ b/third_party/WebKit/Source/platform/wtf/allocator/Partitions.h
@@ -158,7 +158,6 @@ using base::AllocPages; using base::DecommitSystemPages; using base::DiscardSystemPages; -using base::PartitionAlloc; using base::PartitionFree; using base::FreePages; using base::GetAllocPageErrorCode;
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index 23598f6..bae06b1c 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -314,6 +314,7 @@ "platform/WebRemoteScrollProperties.h", "platform/WebRenderingStats.h", "platform/WebRuntimeFeatures.h", + "platform/WebScopedVirtualTimePauser.h", "platform/WebScreenInfo.h", "platform/WebScrollAnchorData.h", "platform/WebScrollBoundaryBehavior.h",
diff --git a/third_party/WebKit/public/platform/Platform.h b/third_party/WebKit/public/platform/Platform.h index 815cae9..09c2e15 100644 --- a/third_party/WebKit/public/platform/Platform.h +++ b/third_party/WebKit/public/platform/Platform.h
@@ -262,6 +262,10 @@ // Return a LocalStorage namespace virtual std::unique_ptr<WebStorageNamespace> CreateLocalStorageNamespace(); + // Return a SessionStorage namespace + virtual std::unique_ptr<WebStorageNamespace> CreateSessionStorageNamespace( + int64_t namespace_id); + // FileSystem ---------------------------------------------------------- // Must return non-null. @@ -691,7 +695,9 @@ // Web Notifications -------------------------------------------------- - virtual WebNotificationManager* GetNotificationManager() { return nullptr; } + virtual WebNotificationManager* GetWebNotificationManager() { + return nullptr; + } // Push API------------------------------------------------------------
diff --git a/third_party/WebKit/public/platform/WebApplicationCacheHost.h b/third_party/WebKit/public/platform/WebApplicationCacheHost.h index 09cc8ef..286ba2bc 100644 --- a/third_party/WebKit/public/platform/WebApplicationCacheHost.h +++ b/third_party/WebKit/public/platform/WebApplicationCacheHost.h
@@ -37,8 +37,8 @@ namespace blink { +class WebString; class WebURL; -class WebURLRequest; class WebURLResponse; // This interface is used by webkit to call out to the embedder. Webkit uses @@ -85,9 +85,9 @@ // Called for every request made within the context. virtual void WillStartMainResourceRequest( - WebURLRequest& r, + const WebURL& url, + const WebString& method, const WebApplicationCacheHost* spawning_host) {} - virtual void WillStartSubResourceRequest(WebURLRequest&) {} // One or the other selectCache methods is called after having parsed the // <html> tag. The latter returns false if the current document has been
diff --git a/third_party/WebKit/public/platform/WebCrypto.h b/third_party/WebKit/public/platform/WebCrypto.h index 062ecddbf..cf6a02fd 100644 --- a/third_party/WebKit/public/platform/WebCrypto.h +++ b/third_party/WebKit/public/platform/WebCrypto.h
@@ -41,8 +41,8 @@ #include <memory> #if INSIDE_BLINK +#include "base/memory/scoped_refptr.h" #include "platform/heap/Handle.h" -#include "platform/wtf/RefPtr.h" #endif namespace blink {
diff --git a/third_party/WebKit/public/platform/WebData.h b/third_party/WebKit/public/platform/WebData.h index b9a506ca..ddb5bed4 100644 --- a/third_party/WebKit/public/platform/WebData.h +++ b/third_party/WebKit/public/platform/WebData.h
@@ -35,7 +35,7 @@ #include "WebPrivatePtr.h" #if INSIDE_BLINK -#include "platform/wtf/RefPtr.h" +#include "base/memory/scoped_refptr.h" #endif namespace blink {
diff --git a/third_party/WebKit/public/platform/WebHTTPBody.h b/third_party/WebKit/public/platform/WebHTTPBody.h index fb32cdcc..f5da2b2 100644 --- a/third_party/WebKit/public/platform/WebHTTPBody.h +++ b/third_party/WebKit/public/platform/WebHTTPBody.h
@@ -38,7 +38,7 @@ #include "WebURL.h" #if INSIDE_BLINK -#include "platform/wtf/RefPtr.h" +#include "base/memory/scoped_refptr.h" #endif namespace blink {
diff --git a/third_party/WebKit/public/platform/WebImage.h b/third_party/WebKit/public/platform/WebImage.h index ad99748..90e7601c 100644 --- a/third_party/WebKit/public/platform/WebImage.h +++ b/third_party/WebKit/public/platform/WebImage.h
@@ -38,7 +38,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #if INSIDE_BLINK -#include "platform/wtf/RefPtr.h" +#include "base/memory/scoped_refptr.h" #endif namespace blink {
diff --git a/third_party/WebKit/public/platform/WebPrivatePtr.h b/third_party/WebKit/public/platform/WebPrivatePtr.h index 59c4318..576eefd9 100644 --- a/third_party/WebKit/public/platform/WebPrivatePtr.h +++ b/third_party/WebKit/public/platform/WebPrivatePtr.h
@@ -35,8 +35,8 @@ #include "base/logging.h" #if INSIDE_BLINK +#include "base/memory/scoped_refptr.h" #include "platform/heap/Handle.h" -#include "platform/wtf/RefPtr.h" #include "platform/wtf/TypeTraits.h" #endif
diff --git a/third_party/WebKit/public/platform/WebScopedVirtualTimePauser.h b/third_party/WebKit/public/platform/WebScopedVirtualTimePauser.h new file mode 100644 index 0000000..a720fe70 --- /dev/null +++ b/third_party/WebKit/public/platform/WebScopedVirtualTimePauser.h
@@ -0,0 +1,45 @@ +// 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 WebScopedVirtualTimePauser_h +#define WebScopedVirtualTimePauser_h + +#include "WebCommon.h" + +namespace blink { +namespace scheduler { +class RendererSchedulerImpl; +} // namespace scheduler + +// A move only RAII style helper which makes it easier for subsystems to pause +// virtual time while performing an asynchronous operation. +class BLINK_PLATFORM_EXPORT WebScopedVirtualTimePauser { + public: + // Note simply creating a WebScopedVirtualTimePauser doesn't cause VirtualTime + // to pause, instead you need to call PauseVirtualTime. + explicit WebScopedVirtualTimePauser(scheduler::RendererSchedulerImpl*); + + WebScopedVirtualTimePauser(); + ~WebScopedVirtualTimePauser(); + + WebScopedVirtualTimePauser(WebScopedVirtualTimePauser&& other); + WebScopedVirtualTimePauser& operator=(WebScopedVirtualTimePauser&& other); + + WebScopedVirtualTimePauser(const WebScopedVirtualTimePauser&) = delete; + WebScopedVirtualTimePauser& operator=(const WebScopedVirtualTimePauser&) = + delete; + + // Virtual time will be paused if any WebScopedVirtualTimePauser votes to + // pause it, and only unpaused only if all WebScopedVirtualTimePauser are + // either destroyed or vote to unpause. + void PauseVirtualTime(bool paused); + + private: + bool paused_ = false; + scheduler::RendererSchedulerImpl* scheduler_; // NOT OWNED +}; + +} // namespace blink + +#endif // WebScopedVirtualTimePauser_h
diff --git a/third_party/WebKit/public/platform/WebSecurityOrigin.h b/third_party/WebKit/public/platform/WebSecurityOrigin.h index 9c7bb51..4ac5b47 100644 --- a/third_party/WebKit/public/platform/WebSecurityOrigin.h +++ b/third_party/WebKit/public/platform/WebSecurityOrigin.h
@@ -37,7 +37,7 @@ #include "url/origin.h" #if INSIDE_BLINK -#include "platform/wtf/RefPtr.h" +#include "base/memory/scoped_refptr.h" #endif namespace blink {
diff --git a/third_party/WebKit/public/platform/WebSurfaceLayerBridge.h b/third_party/WebKit/public/platform/WebSurfaceLayerBridge.h index 14475d5..6e695eb 100644 --- a/third_party/WebKit/public/platform/WebSurfaceLayerBridge.h +++ b/third_party/WebKit/public/platform/WebSurfaceLayerBridge.h
@@ -18,7 +18,12 @@ // Listens for updates made on the WebLayer by the WebSurfaceLayerBridge. class BLINK_PLATFORM_EXPORT WebSurfaceLayerBridgeObserver { public: + // Triggered by resizing or surface layer creation. virtual void OnWebLayerUpdated() = 0; + + // Called when new a SurfaceLayer is created. + virtual void RegisterContentsLayer(WebLayer*) = 0; + virtual void UnregisterContentsLayer(WebLayer*) = 0; }; // Maintains and exposes the SurfaceLayer.
diff --git a/third_party/WebKit/public/platform/WebThreadSafeData.h b/third_party/WebKit/public/platform/WebThreadSafeData.h index fb3d62d..492e9c34 100644 --- a/third_party/WebKit/public/platform/WebThreadSafeData.h +++ b/third_party/WebKit/public/platform/WebThreadSafeData.h
@@ -35,7 +35,7 @@ #include "WebPrivatePtr.h" #if INSIDE_BLINK -#include "platform/wtf/RefPtr.h" +#include "base/memory/scoped_refptr.h" #else #include <string> #endif
diff --git a/third_party/WebKit/public/platform/WebURLLoadTiming.h b/third_party/WebKit/public/platform/WebURLLoadTiming.h index e4a288c3..5a382835 100644 --- a/third_party/WebKit/public/platform/WebURLLoadTiming.h +++ b/third_party/WebKit/public/platform/WebURLLoadTiming.h
@@ -35,7 +35,7 @@ #include "WebPrivatePtr.h" #if INSIDE_BLINK -#include "platform/wtf/RefPtr.h" +#include "base/memory/scoped_refptr.h" #endif namespace blink {
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom b/third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom index f904715..1279ae3 100644 --- a/third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom +++ b/third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom
@@ -9,7 +9,6 @@ import "third_party/WebKit/public/platform/modules/serviceworker/service_worker_object.mojom"; import "url/mojo/url.mojom"; -const int32 kInvalidServiceWorkerRegistrationHandleId = -1; const int64 kInvalidServiceWorkerRegistrationId = -1; // Represents ServiceWorkerUpdateViaCache enum for ServiceWorkerRegistrationOptions:
diff --git a/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h b/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h index 8f09af4..9ec9aca 100644 --- a/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h +++ b/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h
@@ -14,6 +14,7 @@ #include "build/build_config.h" #include "public/platform/WebCommon.h" #include "public/platform/WebInputEventResult.h" +#include "public/platform/WebScopedVirtualTimePauser.h" #include "public/platform/scheduler/child/child_scheduler.h" #include "public/platform/scheduler/child/single_thread_idle_task_runner.h" #include "public/platform/scheduler/renderer/render_widget_scheduling_state.h" @@ -204,6 +205,14 @@ // once. virtual void SetRendererProcessType(RendererProcessType type) = 0; + // Returns a WebScopedVirtualTimePauser which can be used to vote for pausing + // virtual time. Virtual time will be paused if any WebScopedVirtualTimePauser + // votes to pause it, and only unpaused only if all + // WebScopedVirtualTimePausers are either destroyed or vote to unpause. Note + // the WebScopedVirtualTimePauser returned by this method is initially + // unpaused. + virtual WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser() = 0; + protected: RendererScheduler(); DISALLOW_COPY_AND_ASSIGN(RendererScheduler);
diff --git a/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h b/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h index adfd693..ac139d0 100644 --- a/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h +++ b/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h
@@ -62,6 +62,7 @@ bool MainThreadSeemsUnresponsive( base::TimeDelta main_thread_responsiveness_threshold) override; void SetRendererProcessType(RendererProcessType type) override; + WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser() override; private: DISALLOW_COPY_AND_ASSIGN(FakeRendererScheduler);
diff --git a/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h b/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h index f61d53f..60577df 100644 --- a/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h +++ b/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h
@@ -67,6 +67,7 @@ MOCK_METHOD1(SetRAILModeObserver, void(RAILModeObserver*)); MOCK_METHOD1(MainThreadSeemsUnresponsive, bool(base::TimeDelta)); MOCK_METHOD1(SetRendererProcessType, void(RendererProcessType)); + MOCK_METHOD0(CreateWebScopedVirtualTimePauser, WebScopedVirtualTimePauser()); private: DISALLOW_COPY_AND_ASSIGN(MockRendererScheduler);
diff --git a/third_party/WebKit/public/platform/web_feature.mojom b/third_party/WebKit/public/platform/web_feature.mojom index ddc619b..6d71938 100644 --- a/third_party/WebKit/public/platform/web_feature.mojom +++ b/third_party/WebKit/public/platform/web_feature.mojom
@@ -1761,6 +1761,8 @@ kPerformanceMeasurePassedInObject = 2233, kPerformanceMeasurePassedInNavigationTiming = 2234, kHTMLFrameSetElementNonNullAnonymousNamedGetter = 2235, + kCSPWithUnsafeEval = 2236, + kWebAssemblyInstantiation = 2237, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/public/web/WebFrameClient.h b/third_party/WebKit/public/web/WebFrameClient.h index 2ca82a2..ed72e75 100644 --- a/third_party/WebKit/public/web/WebFrameClient.h +++ b/third_party/WebKit/public/web/WebFrameClient.h
@@ -658,9 +658,14 @@ // A performance timing event (e.g. first paint) occurred virtual void DidChangePerformanceTiming() {} + // UseCounter ---------------------------------------------------------- // Blink exhibited a certain loading behavior that the browser process will // use for segregated histograms. virtual void DidObserveLoadingBehavior(WebLoadingBehaviorFlag) {} + // Blink UseCounter should only track feature usage for non NTP activities. + // ShouldTrackUseCounter checks the url of a page's main frame is not a new + // tab page url. + virtual bool ShouldTrackUseCounter(const WebURL&) { return true; } // Blink hit the code path for a certain feature for the first time on this // frame. As a performance optimization, features already hit on other frames
diff --git a/third_party/WebKit/public/web/WebViewClient.h b/third_party/WebKit/public/web/WebViewClient.h index 4e8cbf1..5544343 100644 --- a/third_party/WebKit/public/web/WebViewClient.h +++ b/third_party/WebKit/public/web/WebViewClient.h
@@ -45,7 +45,6 @@ class WebFileChooserCompletion; class WebNode; class WebSpeechRecognizer; -class WebStorageNamespace; class WebURL; class WebURLRequest; class WebView; @@ -84,8 +83,8 @@ // Create a new popup WebWidget. virtual WebWidget* CreatePopupMenu(WebPopupType) { return 0; } - // Create a session storage namespace object associated with this WebView. - virtual WebStorageNamespace* CreateSessionStorageNamespace() { return 0; } + // Returns the session storage namespace id associated with this WebView. + virtual int64_t GetSessionStorageNamespaceId() { return 0; } // Misc ----------------------------------------------------------------
diff --git a/third_party/boringssl/BUILD.generated.gni b/third_party/boringssl/BUILD.generated.gni index dcf3bbe9..f59afac 100644 --- a/third_party/boringssl/BUILD.generated.gni +++ b/third_party/boringssl/BUILD.generated.gni
@@ -80,8 +80,6 @@ "src/crypto/cpu-intel.c", "src/crypto/cpu-ppc64le.c", "src/crypto/crypto.c", - "src/crypto/curve25519/curve25519.c", - "src/crypto/curve25519/internal.h", "src/crypto/curve25519/spake25519.c", "src/crypto/curve25519/x25519-x86_64.c", "src/crypto/dh/check.c", @@ -327,6 +325,8 @@ "src/include/openssl/x509.h", "src/include/openssl/x509_vfy.h", "src/include/openssl/x509v3.h", + "src/third_party/fiat/curve25519.c", + "src/third_party/fiat/internal.h", ] ssl_sources = [
diff --git a/third_party/boringssl/crypto_test_data.cc b/third_party/boringssl/crypto_test_data.cc index 46c7d25..f529221 100644 --- a/third_party/boringssl/crypto_test_data.cc +++ b/third_party/boringssl/crypto_test_data.cc
@@ -2490,78 +2490,78 @@ "b8a29a9a10c0d6a41cf32b5bc40edd7a1d97b295c63aa62c30498f15d70e427d5612ec3f6a2c1f2997fa9283f48018435fa6092269dc2e4ad524cc6da9689302f5c398d79e2b2d19470ea8240db9df0bc0bdc911c4d53f4f24a7ce44ec76378794d16d367434b4f8b6184c7651db77fcbebb8fcc5d3a51ee9739922cf20d4a8888139fe4669a164400\nA = -e3c4a10a64b7e67d786aeb81bb7ea14655637ce963f46cce59bc0cb6b5a9cb9c92afec3d527119db97bd2605d315cf28198992b4b2206e5616d3c560bc8163f56cb1f5626a7ac6d8427520\n\nSquare = 429e4283af7f895fe732ee88e4904348ed01bf579a93cffb7aa8e135d41cb9be218f8b9a9cb4f556124105cf042de51f34c8162fdc7a981de88e005a014149c955068e87214c174daa40fbc618c536a6e507ebd313763fba197059d68c69bd39933d614b2c32f235cc955e335c4a37b9e98cd7f98c7f26ea2da932c7f82ffd95be22a7741da423123f8908cb188abc26afaf4ba6d47b56e11\nA = 20a5e2a911627544219a1639c3321bbcd6192a32129b248cf62351f85b7a719cb275a4e44368a74f4d1a307ffd27ea2cae4d8584a57070609a30fb4e365564908f3d501b53c1a54f0e37745e9\n\nSquare = 9bcc8d423c3fdfaaaabe24a910e6ac3619eaa15e23b9f317c844d39d164c952fdf5c4bd270a83f3902e54d3817fd78c96018a706c1f652025dde0b98afe35597e0d8782deaeed23337ef6b3edc9317d54e3c8a57e4e7e2695f9d2681bf82927bab193ca1f135bd0e542696772f08520faab61fb4ea6ff0d15bb91f21e68bd7f084a6b8f24a47ecc30a779ee86610387b29a1de94de517f81318001\nA = -c7b60f4c355f2ca3937ba3c124eea2cd8d3536226a44afcaa3d17abe931c09ccaabf25a1986b172fcf46fb02a0fc36f2c163b6e42cee047c54ab05e9d30f03f6943b9fbab83aa6da12d7898c001\n\nSquare = 45df25540de94883dbc182009c29fec43627d3e5758e6a07cf40064e0befa0df184528a84757b445dd079c2b0feded48b651ab18b4bede2a81796be45caad0125c3692560d19cd9a6c8c0de8383fea0bc1ab46f6aca4e9c36b26575cff88fdf1eb1e13182308295457374968fe3a9ca34c6acd24c753fb84d41246614789dfe154faf34fc684cd15035dc9c1c6b0ea171e089e0f3236840e355bd123ac4\nA = -216f8a9a3e54d4afadf368c2693743efd3eaa4cbda7a87cd07f5b1a713eefd2548343e7f091ee4d9d6ed1d4343c06a0597db0eb5194b91bf2c858210557a8288c1aa7b0e0607a24dcff9de04146d8e\n\nSquare = 5cc707d97eb107c5c40c0f19fd432cbac9855f280082802dbe4deb45bfd193ac7a9149fd12c4ae6e9282411e2f1f2ca92135424f215b800634092ed4ff2859d16ab9fb8619ece41b50f8888d3e13773d38789e19158e18396096dd57fa5470f50b391c22378d980e59b4585f013e6db52c1e24c14ad83262fd37d42f52323896f7d4cb3e38868abea8a07e7ad3f90512eea001c5147645bf00396cb0e7a553f1\nA = 9a1d1b0beea76e7f32bde9f4f2c8bcff9094db2d32c04fb7ff43624b61033646e482aa0fadb9f8b4225b47121070b4ee5d6818d3606ed775aa631e0ed42da68c2a09dab26b6a4d09ac226cc09321fed9\n\nSquare = a32fd053eb90c365e77ff47573a24add3b25b4c301f4c662dfc1fa635af8e18e7947381989b37a9c9de2713ca438b9f85890b7b160fe251933aa7dad1c3839d502debb42ddc927fa0e9b40c80dc3d408889be567699a856b1c9cf3a393b3b818432e95feea825c17d0981b942236b3779f2acaaccaf9a5817ca47bd03045fc4de454d8f1d4377e218c5f7ece369aacc35369ab57a71652dd42621491834119afbe729\nA = 33190b787a2c3327b122d1f5823bdee5c93b19b586ce1bf79d801a19b2558aafc8f6274d0908bb7a8362f7f71d3fb52b8ffc87d458249caba7af3a516ce868e8a620e3126ad43d6aeffee11866fe77677b3\n\nSquare = 74215d33fa398e21c34034af6f9c7af6a3e01982320ec8cf23074a938f1a31543f80e6aece01de247668fe67f276cb4411db27666e1dc8fb2bfa4eb68cfd3563167d1ac4efa3361f920d8dd0fbb7f06362167f5ab5ecfb72956c20db934f67ff1c75aabb594c853fa61f43d219a3f5d0d45274005e3b167cfff5493b0f26d15f85d8e906a0a6e7645eac1f40c6dc637e6d1e061e5b9071a1227469cfb2c0f17ff983684100\nA = ac6c0b9c69785f35dbe244dc85a54313ef836ac67c853531ef5db45b28835ffe61dd258c5528b0acea50f5aa5c0f5d08dcb8d82ee19bc432fa8a45badadb50693fedc1cc79a17d63aa73fe9597f1d4ce8ddf0\n\nSquare = dce5cac967c47b8a58ed6f1bb1d1e6185e849400228afa2bfa05b9c2dd327b04a86f2a4da2d02ea102868ea0c4da0f3e5a40bd02c87a08aaa5cd8d9358b3a5ebd8c9fc2dbb1268c261f46d6717b0307b993deff0adc8190d32b4f2bf695eb2cc74a6a9a712c5a621c673219ff8a24ded0997508f8f9eb1ea872008c46e71fa97f55b839950e63130c38b49c0ce3ce724a0e8faa9738d2e28ce6e7fc7eab62b3561d2981f314f751\nA = -3b735400064b15fad81b08362b8557f8318c20656839ffb4d2513512015036ab0039442032f1cf515f8c10c9933afe4206a2f309e933d1561b06bc665af2f04f4d064e073eed2280053f56cbeb137a9482c0a077\n\nSquare = 6b619bcaf632f0d8b1d715e8850c0cbbd29ac6373a9a5e93dd1bbd2b82744a8a50a7446b48c6e215911ffafcda9ed7becaf5d26b7d6df7dc8798d53239f62a482f974bdb654750def1c941c49a24fcdfcfe73881b556a7b528d88daeeaea8d62b357211a1946c81cbf0819ad8d0188f60aaaab4ea2dfef7e9012ade7abeaaa4a23d7403c1248c36aa26b43b8e7de8a5aea639a0449f50359e9b4c1b125a548383af33703f8dfbc2528e4\nA = -a5ccc69663a8712c15f96e6fc746252af89a8c2a6317caef905dd2d8a6d4fe878ac7aa66cdb3c3721ba7dd36da310753dde9801b31d759339ac919a464ab52541bb2e0dc938752bf0f1ff7a9524eb98340d62576aa\n\nSquare = 77ea5b715823045afe13d10416dfd46a511141a7d1279ebd624f1de428cc04a4f246246e65c3f84344cebfa32864de9264b2e54d4b3010c4de9d3e6a27aae8f5f9e9d8e49fe26b73ac7e65bb216aa6a42db36ac03d749b5dc04192df819631593202a58264714628686507fc5655f169483b0ffecf45995cbc12faa105895564d287a9f4b220947d6c93786c85b2ee84a0a29183483f7c241d6a67fd0b1c38c7f74421355a14c6d9ed5720e24\nA = 2bcd67e6bde3f54c4ce0ea428418fc5c97272217c6c7de90549238ee322810dcc1bb9385967673aa3f9f5a5c05d987c6445135cf1efc26b3c17e55b93cc052761a77c9dcb5c22927b09e90a92e053ec1bc799bbe7597a\n\nSquare = 40d113460ca3e70545bf3613c2ba5de5d8485641ebf531a43b6b8bb76884ff4f348727ac6606e026981d2116ef1e60d4b37b44ed7e2003410d7d636b58aed2f92e962003f28342aa5f059d23b3d58a1ddfb47833ffe1d1deee0a7e78b8f7d9d6487f22376664f1ed9ddb5ee3d17f43afda296bead11680fd17576a122c2599fa9802ddd84a2115f9fda03aba898f66e303895f452077c920a322b6aaa0965f51fbb36f01b1d412c6ccf390da050d24\nA = -80d0699a46619db033461aa6060983def7deeb976d1a71f5c6ddb85e8b46dc70b7ddb1d254971d38ca87c7ee3905e63506c6db105dd683375f4239523cbf1874069266c2c0f4b37edcdd261c51088081d25813758bdbfc6\n\nSquare = ace99f98cba0d1dc1c758dc7211aa4078a2aeb6d3fff19bdfa6981ded0982b15bac792e6b542ae48a86f9b40c6de937e402e230fcfc390b10c3e60202dee1337ab39da7a342999487b8d8b0e494f2809cd1bfdb39209da5daa590f78ded211b6bbd3fca9013300b951d8906c9ce8d1c0dd9554d5d1d352f9784f822c928dd9700ef8a5fecf3771966abb1dc6a70b301461eb6b6087d6ab80a4b624205489584224cf6578f75acd8091fd621d02306504389\nA = -349936d60c9d77a0974dc8985930d8674976db6b3cbaa067554ca6b30b1de33f2d4e1c9564ce102ac6387755aabf42916f63632a375d995913f9d45ebda54bee3fdb7cedee46ebb5c8ae7764e4de323c17c797d3b529230cbd\n\nSquare = db6c73be2a59bdd35dd312240aef18dde4231c72aa28551bb370a87dded587accec2279bea24c930236f06f24d537fcf242497aafcbf72f085fd3ecf030cd750fb382efea0f82ad9d3195680324d73fa99d48802d085c150164aec0d29fdcc3262264bbe72311f89989cc71a4afdac6ab103ab4fbb6e973a42a1f8711bee463d198f727dc7bad848ff8fa77cd3b2f612d142ba46e95bd79a86a1fe4c2b8f9181be84825d05989695842113828a83b826e7d2c8c1\nA = ed01dd49d2e5d51fd30e9c578259cf107771b4ded6bf21f8b9b632fd360e34da740e0b1af6b5a67789fda5a44025af0f1547271ca8accc7a975d98ea7ec3d41c9697018d84ffb5d49b88d884ccdb011f715a199ddc44a4109261\n\nSquare = d6e38250ab89ffe11abaf8c5d07ba11e9053f1924ee1228f834111af16ed282389d04330cb0f47dbb186dee577aed82878ecb065b759312eaf167c4698eab5ed03a8657341bf5fb14a8e28e3b443a6b657c1f4379ff2549498a33922ea84f1fb19d10866fb0ad07ce1cc44c93cd4d9ec6bbb0e61c797750c6b5d7e8d55499655dde112f4747798f0e985fc2b937a44da9b04c2dc4b0816cfc57da1f80179db653c1ce287e786ed7eff7ad6d1383fc6de8c941d4af7bd1\nA = 3aa2e696ee570160b2a869c3f21c3f223959a185cda2274feea1c829af2234c70a504c959bcc49fe0313f4f5ffd27448e28aa0fc6ce24f36943d334c626459d7e6017339e787ab074879ebf697a93ad93835d69ab09294d007a0837\n\nSquare = fc39360cc0fe040b6f8340e0728c650e5e74cf1664f7b301e79986fe066f36e8df34d38d1a06b74a1bdc76867baeb3f39a9161acd200bc7532fa4aa0ea829377659646f073db82ee044279ae5fd797edd37d3261970819589853cb320887a085c4011c23d0da9b6d6f1b5911bb3399146c2912a967ab3b3f611f0bd52e00f418e6a6f0297fcf5c4a1f71c6bb8cc8e1c76694bb7301502d1d00c8b6c05bfabbf5d350590561abf3e2b1a82e98b56583e2e4e25cf707320a0e40\nA = fe1acf3d7b54e718c901c53f365894c22c8bb4182fee8a4c2558731e01e1519bfd1bf6e353483b8c4219453fa66f06063c6c99050068c15cd13cd1648ffc42b5badfc70f6fd4a0a5552fe637e54c4f92ca45c60cf9a0163978ac08d58\n\nSquare = 9abf1324ef65c726330f64643a024c466fad37604f4dd3dfc404d31c2a430fcfaa0c78283666c15a094d494b96d3c12de6e29a34d2c99f4f8cae8217bcd2a989d59807ac68c46d60600238a86155de499eeb35642d0f581045481b40e4f0a76905f9b6bc5b9585f77f8410b99333f7ea983c3f29f3fe66ca7b793b784a5a6a4f74512aa4385dd1e996832b1f41bb3af965be58c4ac5e867cdf8dc6a4f9d20a6f1e16e153fcbb45ae5fe8a798cb06a4ffe467d6b6aca2b31f335a344\nA = -31c243593ea611dffecc65d1439db345b2e89941113f9792c", "91a76b4890db6e4dbaf1482ee812e295d27956e48d07a14de38357f15b5931c5cc08d1d248df7bfee1cae5b5ce98984c5043a3e1a2b449ba1671bf1cfef91011e12bab94b6e\n\nSquare = 66aee3e4f43c672e0478c76e2092bef33e7c60afee5d4c7defbcc5c0c86d8fe956c90a740cebe604224cc3f518463b1208699b8ea2316315474991d0f120ae905a67028492cf46fff2ae244869db2a02d06aac6ac6eb054fb3c14c756d8a3e7ca64f06586e3e86e4477f185ed527a8aea6a3c741f3fd4b64a2ee77ff140190260c431cc53f411fb227377c02f85d0258a75bf6d44dccbb8bd04ebdafa115dd55b176b6eff5567e5b1bedcae15110826574053681fe25a695ac4540186e90\nA = -a221dfee30286adc076673cbcebd24a41a438a0a7a6a547c75d33149cb1a094a8425feaa5a23cc234a722db4cca8d5912fe1dfb6db4e92bd87c12f0d06b6d954fdb9b172955412b2eb5c9fa3b4df2933390384fd1f929a2b1a8dac479ec94c\n\nSquare = e880f8655b51739e34393c3e6d69d63e0256b1a887f7e69f40c78d21133b17e92277a136f5e37da2533ed599efad189975d22ad0340005ef58db0b471651d749dfbd48b3f7b3b8a42d4677048a855e99dae6c729d8bd7eef86911feca9f5490dd216b06d9e8d1ab695c1081e72449baad28dfe113744853382901e6bdab5413c67c52d6cbbb2e0bea711edbb3a219a4046e8739c04729cf8c8210028dbc4087737bc6c1d7e0c15ecf16774690168342b1372d3646d4d8696384bc932144c98529\nA = 3cfe075d4525a3c780d6d05f7bb708b2fdf7277a0f9967e0a209fee9d42136a0bbf98660d8ee8cb4720a8042da09f6271c45ad13db24eaac465f8207f78629e9085c1c890675f441c78efa38e5022b1b80afde5e3fd08e55648f2817631eb6cb3\n\nSquare = 8d6cf4eaf58099b1323fc598b7554b371f4afef5ab501dd162ab8429333d46916fe15dfc4ed6a99ca7fa7fc1aaa0cec3533b41e291fb7f69b560259507226eca87aabd07b1ae2eb93bb53f98fec508f051cc04db4a172901e06b74229c4fa3f550a81626c7a63fa99d41e46c2cf792287a5cf7bb68946971bd43c7c0356312cdc25e524665dd39a24b6464bbbe64fe8e87ee313b860639728a9143c3a6118bc8b150dde6c10a13bea637fa8873c393e6338319c506aec6ee973b4b52a272a74bb62084\nA = -be46a8072aa44b3bff0f90c81474dd576756fca624c15f55a17e1d0bd2842467ae000b04f79f561690c93ca7118ce17ecf830a8da3678c15436876d2a74324d9714dc8ad8181904be657d7f1da3313b78448cc06e32299a09ed59bfc1961e8bd722\n\nSquare = fbaa4fcf9800673fbd3a132305ed3e14f4889518fb56ab82aa5e9b3529b74d7f9a467626d68f4709a2030264aaebcf05c0a0edb511e81f357d85b79d925a24605f1bcd4645915bb75d363654b676266329df532cdb39152fb360df1b9500e0c296014289650ff77faa78a604397a82b34d16484e94a8de123fe720e514c88f11ec276725111563db91477480c3245542ec6bd0bb2f4aaec02c6c4eb1769030a31b05da3798c224c9117f7c38d3e98a343fca03ab584ec2d7e6db60fdc4273c3d8e23cc1ce09\nA = -3f74b25f2a9c4d8d977e69a4e067f9fcec281136a508e365b282e5fc3b1d097bc6a0f59f7827fb90d4890b08840a0a1919032c67448f8f1a771f785a0f125a4aa4137c154fdb489dc1099d57bfcfc75f4ca5e69f93f2bb87ed09cc0dc620d3e76ecd03\n\nSquare = 5135becca97d93dd4b16a5a1105ba3a3e3fe02bd6a7c3cd182186fc63ed4351641182a2727ab6715e9672458dfbc31aded4781fa345054eb4c317872e2af6d4ed64b2ca7e8c25e1e664b5349df937118632a64e4ce439ffc625a5ad3358270dc83fdfa73c7afba03406094fa36d87517e5e2e1fee5526fd2dc00d9210a0f6c3745b3d4bceee5f8b03d976d696c57a09d1e08e4ce780972eca4f2ed6500c23bf5782c31f13059e48246180fd09db693d2fb5d48d51846ece8beee45cef7efc87c003b44d7b137a900\nA = 902fbe2127354a7df5cb7fd057f3d080a7bebbdb83c86a50560b8c287a37a841bb9c8421c63d359078d2948b6b57559f98fad8f8014f93c912cb70a6701c4dc4fc5e88aa413fcfb685c32975a8b72424742eeff8262d28cebad00c5fcf88baeafe8f6730\n\nSquare = b5976cf6a6560412aefa6704b126e0d987dfcedbb4da436c08ce17b1bf1b6e0bab9f934abb5c4186a5415fa38724fb8fa341d381319e7d768209ab108c8debd99075d31deb3e03ff7d23957d4f3204d543b7d9079cf337be3037b1cb4908fd8c104d92e52f041b4cb27c045a741f4d64009980e8d27af75d9493920ed98c7234777592d6577f2d1b3a0eec645ab4cee2f28d9e4efd3e4514db6796487ba68a462fa0e316e1420d6604db2b901de46553546cab42976fd0d459afd81196275cd88ec4dd448ff331bb35499\nA = 35e700e034950bdd7318d5b3c17e90a4772ecdacdb055b9391b31538eb823fc8a4599f029e78e4fe5299ba1a423a449dc257a431d189dd5dca275c02cc1f12417e111c73b731631d8a1741b907dd8f24de226ddf9e3044cf4064e8e51ebd55be774be7ad2bb\n\nSquare = b7de0f73397893a97928e266bc56299cc8d43b16a251992662646072b58fa578ca80f7be1e12619012b130e9514be803dc166b12ddfd26f558d36c2053ee6209b01458379e49469753300ef20f6b3dcd5383b121861c76ab25debb28c448ec33a81250d05f7eff80a5a4133d522d270fab29f739b607395a77278609aa5e1a55ef58d1d48492b71ee30a24a6505aab1a3ac22b9d143c9d6781fae14bbb980fe3a99dfa9a1a406611d7d0304493342f53faf5fd79f9c96b9583a219a1b22aad02dd58f32ee98146b3a8cf054bf9\nA = d8f4d3bcfc7eebd7068b851858c3668ce062a834927e165679b49132d4f780ca682876c65c7cf2e7ce34ed10e43696477da6301d13f92abb8c76e2424c4bc28a6565f15e59563d607b852dc946652b68fbfda1c3200ecc2976400ce7296b96e75fb059a4c8eb5\n\nSquare = 5ec02661f49fb9807bb73debc3c6eccdac1df1735e0d61fa7e0eee07471068a5809796a2af490c46a77d61f618b44a3168dde67aae1cf9e530382411056958d55bd18f0e76fe2c31c98b00f87fcb7f5691ed5b65424f82204156dc361ef6dec5d44cf690582599b3994ee47ef42850d5d2370a4169c5f73942657f85422ca24f66943877f73af493c865fbeb29574cc1cc730e9bbb097b598574f6b90257748e950bff867bcc01bf62f8df67d7aee1b6dc1d5db88826e86a3f9fcd8663e09cf8393ee71a09c43d0d38ba6ef643f4ab1\nA = -26ef9b6708a80d00f4d01e0f0a5546ed217085ff23519819ee89af430580ea1f086beb0eb51982682c6d3b922a2c92752dce63657836223a9d94964bd584bc8e37c6e30fdcaffbdb128344d51a92705e1c9f94205ca36452c15a08f7e62e0e02479ecd48085de8c7\n\nSquare = f6364409467a829abc2b13c93979dec84984caa12154b7cda2f4c8d91bf24ad7c45a968ffaac8d6722cc26e6aaf52dd29ea2f09370ba46d79684b7a06faedcd17136f35a58e5b550f3a2caef7b195d8409914fedd3c3154101bd735155098e8b10fbbb1b2e13555d2ab5d5b52b203d4efb27e498b240f37178f2e89b413f94859b0e8b2ec10b926c8c0b6f2937ee2d0355445364841c7e0539f7073b88c7d568edf1b253f3c10627e22c2ed731b7d4d199449cb0b5e7a66109932fe2c9cd741d75170deb9f98469049549c10a7a622bf6e91\nA = -fb0eec3246e99212879e51b17ea6615275818ecc5ea3058b13dbaba2576ef90e1519e3629b09fdaeb02661091c395c862b848f6326b9f536f7af45718c4412f09f19261b537bca36742d3ec66f964343516aae2ac27e249a15beb545b447e37b4062180f6c82809429\n\nSquare = bc4193ecb5dac900191e02be06297106155c6840c4908fbf6e41e9aae137d53c3d4ffb87f334f49837dc4ab7a66299994e4f5c9bf6ea03e7db663bdef066e94c610580a8896a9ae9c8f6587eb83d789683f5d6391bbac3a1dc1de60b4108428e6f5fdeaed6cd3e74fa01f85c6368023b61a413b69b14276b66f22653491e4f25790985053d075387cb13c79dcf963b6d880d01174314921afe1cc700c02efd2979dcbc59c417a6316db9ac45a2d60d2a036571bfbd75f9f5e42048ca086cfb4b818a9beca4a6e0ed51afa320ef3549151fb39e100\nA = 36e1f16043b4c9b4a304496c39dd63459d6521d2ac92916d348daca3f972835973fc8d21b07b09d8f5e3197b39a8f3fd0011168b815d67c48143c413e169ffe0f56ff2cf8b6596bd0a3b5b7a6b9a14ffb797f350b7e6aa7020d84d1d1b8006850139795abe2c74f03b8f0\n\nSquare = 4cbb5bc1dd7112326e2c94581f19efc8fb25339a299fa9c007114c3a22b395e9d39a8ffe21134e97ad1b87b97e667ba48b2a40af61afc81fb1e20e8e38c7ba666b146016af4dff3faf5de306591e5ce6eddc1173fdda6fe241a9f2fc6e054c41e56d296f8954377df0d140096b9e9d6a5a23a231db4dfab0cabfb11190c7a0d1c55ae35203836d433da96ca7339682bac0a7edb8b5b4dc267c6e83ac9b67a0d0d564717ee3c20aaf52c0a750f3aad94a12537c6971ee009d0f82ff576e984b06c7f7b357f5c049454e31326b952af17aa62104780e9ca1\nA = -8c279ebe466de3115b8740f3ff9c1f605b4eaa75512d82fdc8ca5ce84e11a68688154fd603ae1d607807dbfcbb822a8dc259098842c6a7b7ec350be29a3daa20fd5b093a56692e9d42e7a389c4ad2122a74205f835e268c9742d09ad36238c34e143f6e2ec69c0f490d29d1\n\nSquare = 4f771ade09cbd1a033d2bfc6036fe46ae6c12acc6f2b9bd52e7781693fa6358cf93089f23d1f0ee6fca476a43093b9b52446f3a7abd72ed0ce9b562dc438822ffd84bcd898ef9d092f1b0b7ff89c4fdb33d8715dd4a0d68ec49ad41338fbb62ca87867d847a4d99310641a37ea78b04c85606069d0c0950484ddbeedac8ec6f95124e7fd83da4e942d40103bc14474f5cb125fa0b06cf167f076979948003dd8dc3711923f5af5beb5f56c0a48ac0c5240b62738c1cdb06b87ac3dfa17befbe938ddc7281f6c248c41a1c7b99b93f69fac83a46eb298a9fd8b9\nA = -23a845bf2007ba8480e3ece0a1bbaf8bfccba6bf061e3fe1d8bcbcd6c761e650891c0958bac68618a1f55b27d2bc6e1e1b50afc29f58e2e034bdda8405e5378cb5bff0d84efcb458c5428fc607597d89d589d85d90f3da4b89a64c9d1623b98b10518a6f2e7d2295c37527026b\n\nSquare = ab45d12a4e15a294830741f4b9d4a14cc7dbed1c3454612047f890211c749d92ae0418f11cd44acbf1585b1f7323b33ac9a4b13c44e1a7e31b0dcc1c6dd4eaa12a655b5de08f3b948270a152db7d9e04dc54677075797bfad6a9a0e3958458d40e3df5e15028954bae99518de4dd3adfb2ec4b38897a8a4e4807849e1416aa4040c95a0e49a8d2889f6fb0537875f87516c3723e8d3b46da8da855929c67c0eb83daad62ceced52b4f52d2bf1c4e34f26bf16aa7da3afe0f5df76c0858ed98f21e1fc3d01e1572715b774bd5c2faabec5fa3fa59a7a1f32565a4f1f9\nA = d164d875e1f766b4567e9228241213e69d6b6c58620600166fac56938c5d", "9643932d01f1f4a2263dca4b9ad26dca1548e4b5b7e27581a63375d0e624f4e4c99b7fb9aeb25307c61142760bc4771e48c7ce38f5eb2408def632096fe40b80d488fe17a455d80edfc1c23c429775b5\n\nSquare = 5ae4e7dc5727543af39ed3d5e9ac086d1a2220421231b82f6f41caee7b9815b4049aea0d43ff499c6c9e1f226f8641351d03f37731c64686d9a9ce68e9234d6a762efcffdecd42f81044111599963d9b6873cc20bf4c8284fae03d2e4f238a14a74df4388fdc80fad0375a5d0d974da7854ede5896ed2ab25d2b49a3c39093600f73120e4fd2faf75381854f6ae80f81b977f62fc72f1fd01c278d183544052b77bd753dd88ffdf5c01745521fb8474b5c23b0b7dc709bafeb91cee0863a0c23ad7192c43cf15fc181d629853cb9b8334082c915dd3d04e3a0a81511d2e84\nA = 2622a7bf45ccd3cd567c757f4c5796b5a0fbca555bd0ac2759c24083172d82d6a887dcf93d9788fde052cb20a8963cb6db22bf5eee6151600f9d1896a7606b11a1b100cbc0925bce037bcea57e361efcc560a9abc495d7f7f45831c6429ac8f979dedc08c304f4da9c0d4d687376d5e\n\nSquare = 473cc933f5a650a4ae358c7f486d325c0e20c83b54838fc08b6ac3ff010f7c4b6a609bdf472974dfc5abda0c6b33c5ec7dc4628d85cb4276108e2b0bc4e19cba135533b3d7bb6a94332aea3165dccb230860d2353166b9905635e606185b014730e9dcf2c433e18cba83859fb2eac4aabef68c8314ef86dec2d534a184ebc4cb193643add0897341690cbe18bc2e775327fd7d71ffc7ebc49bad83cd68394eb276b2e615ec430180303010a454ef73b6a8f02bc48a1fc8a32f8150ef1b733f07da752b8e808000329f4924976bc8b8573927f18ca7c88c210845de6dcd0dee2904\nA = 870b2c4b054076d0d02877b19fe1210a8fad3422b00905a6db748239b8e807716ed9fee0d8c25496593717917edceb5db57f9960bddc1956b6652868d6ace82827bbbada5ae8c15efa26fda22657126c6300906f90e8fabfd58ddf312ce0eee760e0090fac44f00378c676115cd0639be\n\nSquare = b151124402d2f04b0e6599222d380dcf67b9716ef50d2d9ded0b21521b34a7294171f71b41762511b7cca93d9f50e9e30083ef19144882928011dbb143807d1b88c55eea6b19f0c4180023be6da63a59b6bc027aff3f5abe2f65c73b2de1e71c5f4b248bc4547040764e83a860cb3f882bb8b5f7821f92802808fa37c50f2f94d8f56daca841f42d3362762ba843aedbd03d3cdda887f75ba92423965ab4256eb842ad755aa7a2af331b488186f891065b07f5a299c807dc24fc176e085a8024bbbf12f386ef49ccc91bd4ada0936b6de78088cf5952ae6c04f6916799378bc0ede0da4\nA = -35439da9e361700152a35ebdea253378a1febec5f288e5b2bb0bdf25b84751b47e4da5aad7453b70cfd6640d5832237d2115575c738482ac6036c5fc21a981c0a7f979c8d621a92c02166b777475618aa6362a0e225dd6138ead3b2766ed9785ee01e4950a863d2fa0b7f5cb4c9a108bb626\n\nSquare = 4ed7263ae5beb0069f24318b38afe951a5a058a2e960e67f086c9680d0cc6d713f943812070bf94152f7926bdab9e5908941261244542b832f458f05ed5dc048c8b9eb84c2a85efe717e257796b4ca816948a6c8ea209c0675efb2fb5af4622b44e36066593db01b17f4dee21d7c1337ff41436cd0e5a8d01e4030dcd3d49839e59996fbbf1d39bd205343a424f2395b4d3eacdeb9ed3235d8df0dd00a2573260af63db3116a7c65d1dc69684a05caebff34e3d2cba9d4869a953a7b1fce10ebd008cba021008ac3187bba846abd7b39a1b97c9c07d8080549e313dd58b716022de3c1920329\nA = -8e1141dcebae61d5c4d81697f001d792ee2e847c589816f923f0ed42bb4de0d8f911b8ca47ffe77f80b9da6896a9b42f0030a3276218868bbe1a3fa64fb0a577704339af5dd82e66780da6f58900da3f1d75ebfcc302f78ed66ea3c7a737898a29b1f2500686b43bae1e6571addd2842cdce4d\n\nSquare = b09f5e9472cbb75070a67d025957fd5ac3be89c41e4acbcd5f75780ca459562461082c3f19c5a4a416a668b0a55f31f74cf2ec44555ddc43fde64da0ba781adfac4520dd0f78d04d9d2fd33d8b49c72663a6bc845015523e2e4e7ccc69e5b748b8b891e4089420bf0a3f6032602824c7230b5ff95f85a688dcdcfc890af3384710a9fe32ecf9ad7c6cc5761f13079b19d7b2906c7e63c14b64fc88c6f4bd7c41c0356c777d35c3626d49db8cb2d1e89ce682c7fccc3a459b08c20c4e5fc3a8eced9b37d01bed5af6ce9baff0d2b435e6e62871fcb20cf9ec10d1897a5c76e73a441e07fbcc2d9f4e4\nA = 3528e6581de547de385c93ccf1086a17614f23356a918b25bc6d73656a2302b318963bb679c9a93357f4a4f614e74f2e5e88e9c8aed8a6fdd8434630f664ed15ebb6095cbff1593f188a12f4dd6087a85b202f6c24df68ac3b137406c88c5098faf47d1eeec0743b35baaec7dae29b5a44eb09daa\n\nSquare = 5d5dc40783411475a4aac7c1a1eb760f76fcc6ec68dfebb754251cf499870654cd309422935ec841e6be4f5a15078356235c2b8cbe1ae755cd6d814e811072bdb76156b83c7d2064a202ff90af1e0f88f5889e5729a3cffa9faf33c463b74d0ad21fbb4473d4d3ebfa8a52e9c209ded5ce5131b12b69747c365146fa17ee5810e0dbab992f9da28b6c323062484d62472232721d608cdb9b5a341a677e2d7a6e5a983247d9a4001e16687b489b10b18bbf205f982b7ceee27cc3e9c6641827ab7952373f15d36e5f177b82d7eebb3f5054e12cec82c5f520a2675afdec6cbf6235d358c2fe73344002e400\nA = -9a9a19fcdf11bba84b0395088c5d187d84d69b68b77bc6418f63c88bbd8dbbccfe02917d814f9e2241fa0709817a0c85bd554fe887babae7439d96248514c12d71587c906247b3e965e954cdd57f1e51f1979f73c3237509863169efdf281c1359488daad3d9eb990a50ecf4d3fd25d4820077832a0\n\nSquare = a4d69ed4c4c9c08116ec5cc49ad458f0fb2ca00f356aeb148f18037bc49621e14820f325af39f3954bddc9cf01de7ba1e443088545883a94c04ff41a7ed5f65676109c5b711b4115775489667e00aa1b77f6dee5ac5c1789bc71c9fc797abf41c7c5ae3e2c1cf82d5b49b6c0da25190dfa9360b99b2f63444d21ec6114038b8284bf598eed24a2ab2b9802d6edd5b0fdb52f60621a87a14612844ffc71ca98180ff0915cf75f47432f73d28dfd7a932a125095655f07f50722b1673df2cc4f7566a1c6035792ff3f02356b9b9d25e905121df768dc6a1884cf5483eeb813c1c009fe4ed043febd61800ba978a40\nA = -335b12e40bfe0b847ed6ec143490df33d2e64ef4363869cb78dec008cb5cd66ea671dba964a53e48267da288ef4040e06371e1209691b81df02f2c86a79cac85fdcbb6732a1e5309fbbdbcd899fdfed18518d47258c9e63ff7f116ef4a8f5c4867aedd907ccc7d222cf8087afebc108f2a0f197c717198\n\nSquare = 74dcdacc1a4f02a99e3642f54f9d917b117d2ae8d9c392f8b6dee53fac66ebe1680c8e8cc29f5330e0eed3f63d10980060799bc37b34c93dd7b384d4ba30a5b5d42a145acc412ae838d7b9b7137637546d1118f7cf3eadf88b785f0aa01da8638f027c56faa16aba8591b64b45dae6138c9a40309b2ad29c5029a867465f9c6de8fbc5fc4b0442c8a8946272667c7622454ed6f2a236103bed7697dba20db84b5154ff3fbc6b4b9eb67ee43bcaae741d87ee2093ee67defb8eebc4a4a22d97a4e2aa7d4c31a1c88abf4a440ba4e2a5e40c4d903ba5ee4d80b4e8dffb8864bcb9806e015c1ce16490068df87282393111\nA = acf70350e554732c1972903cce269b215e985ecb8d6eeaa67fd5398d0a1b57c0db63368c0f8c2288c3a0466e2b3db081106b90920c46462faf00b5bd654f7140a689b78ef656a26b82af8dd1988f166ea04e9aa777a094d892bc7da4bc7bcf0618526f496cddea6d67df7bb0de9e99a35a0b1b210ff07497\n\nSquare = 9668b9e40a8bdde3c93943a918ca71fa0009cb05a1f592b2bb2c6c6172b2950719bfd80cddaf45d044cbb6aa99715046088f40ec6812945885679231c07f4200023548ead086b834abd8c8f8294db28b203329553242fd2f778ef5cc5ed0b48c7356d8c2d782a01809ccdb6b012896617f11d963300e7bd38ff512829514d94343476818ddf9d712bc70cffe7f767a9fc75a5630e6250ed45e6831b4660eb49d47dd1b8b6a0dddf3fb3ff0e12834337f145f741f70a2aa43769af50f099e004269ac47fab79e060800dc74da88141adbc46c15c7330931e3a2bed9b958f78b30214f81a64d121f96fbcebf7569fec0cdc6b11\nA = 310e7a40667d9d5dc29744b123cdf6a663a1b995f62fa9d4d853cbae0dd23669f4778bb2040317ebf6a06ac6299b21067aece5c5c1afbe6e789d656745ad66464991cada0eb237c6ffe991cac4670bfc90eed5f8c75073f4f846ea244bca0e9502ff56f8e9bc9b6caf275aaef38e26566fef35329ca45392069\n\nSquare = 49e677c8b052b7db97542948542449af47e14248021f8d3d3f92b9af41c803072f71050f16dd848aebb270affc47e85427a7c73f227f0d63f140d0d293157af0d972eb5b38de494fbc78ad3a4c3d1ab40197bc4427752b6102d1ced6d6cbc9d7caa0d1bcc57e708535822180055ecc9d9667e0590274b778480a3720823e931ff6daef358b1a1a9092f1f05fbb5b10ad5707a124e8be63bc696f083eb74e5b4f0e3110de8f297ecd30dfd2bcb010dcad4e387520d3d00365fc51c2a3dfe064b1ac77a9295f66beffbe5dd4333e5cd823b0f36b0b94d66507b1d9381060980f62f38a62e38e5a75203233bb8d64089bfd100f3205f1\nA = 898b5f3655de74cec3b0fde2ab03fd18cdbcfc3eeea48ba39317d26917130c2b78e05237cb0454ece268f091cab699fbcd51ce341b53d6ec0cda5d0d5388bac25c6517214a39d03450ef8502e1675bfe8e57bb6086f10ce4cf8ce65eadc865b5bd8a00dc26394f3adb2ace609149e3582cf44246184b2adc0ffd9\n\nSquare = ad00f10fed55175159b2409dc80899f9113ba7c8099d0402ec0f520ab4aeeb46d36369494a4e6fa23675adb38148fd2efa082df5094c0acfb77a9ab6ba7a299298d69b04b58011c35325f46b765e580b5c05eca721904f1fcc355dbe39faa92af5c9a6dbc4ab80e62b815b45983d9506ebd52b9efa7a6b9da352d1e4fd6ffa81d3b4596a0c14fb825297da361461ff2240e4378340d2ae529932d78f3d9f6b3c6d65d717e66122e5f590c50ce0a5d81ad8e0f24e104c0913cd8d0eb2de4c8cf62a7535bab5502df3fba08bb4dfe73d89c8b00edaa7d5f3274be9959e7ab6b6dde54f2491728a1dc11fa8e1c6a95e67eb7617e9b7471ee40\nA = -349cc2a5658fdbe9ba5c350d3b25baa38b1ede01926694bd550d36883e53d8758e8f1ebe83e2f4560605510413a7d880929e2d9cbc2730b1736dc2689cf7bbcdc68a342b6398e547a9bd67cabe298796d76b98ed4c1dd9c22e36145892e8fcf2258529aed24252a70b6ca8fd2aad8a84becf7e1bf98b1e9bb024b8a8\n\nSquare = daa3835d3189ec9ade592e6076e76d441838077a9431273bdec02379b3a6ac38aecbbd57c3755ea58d", - "def8105ac28f2ecc8598ec0c4bfc9c1c80222fffc776722eb0621cdd8a0d55f08767fc2922282a76e529d81e4d6e21a2542b8c9a403709ed1132e3b52786b81e684591438fdddb5df2f0b72e6b39cd2db6c0cc55c759c2dc1b6ccc20a5cfd10c6fd345fc766035c7478570d4ac534db3fdb718e2bdad3d096b137bfc09a562043800957e2afe4fdcfe292881f6189edfce52370c0438c2822ce3b14d73b3eff32f7e5ca97e989326b4e3a8fa35544193f8590bbb0ddb1f914894ab87998090771a0be1fd23917cd792be86ea0b98e6eb24\nA = -ec953f1b7ba7d561edaaa23076987daf86f50e9a66c36f0993290549a9006dd9d424885c0fa77295cfe34fc81c5edce9e2371b3039ea18d8f998d1956196284e6d81eb1c62ecaa8cf3fcaca28ca7e64342803c8dc3c139080bdd4a1ff30d7288b085a579d9e90903bd363b48f2072bb6fbfbd9ba2cab30a8a63784d246\n\nSquare = b33f4f3ae453058f4e865ec78f0844bab7af66a97dc2f265ca73ae2232777474bfdda39e10652d7386c16f145272192af728893c3d8a8e92c60d77722b924c30269ff5a399a2449ce15e50320c528c22655ad06227ac4efe5a993179ec61c2fc9115f89d75b53961fd16f7797657f6fbf55662b019608a1d30f64a2c0838e0018b7526921fdd34fd462bfcb2462b7065e2bc7abd57d71371e45dfd8fcfcc00a71f7e45430820747c9a060b72e4f6d2919cbffd00beb0c31a2bdc32afe2cc540b38dd04a2b73ae5ba481a6e535f37a757bbd6aaa972986213afadfa47cb7a15a6f1d443f93cb0ed824a10b4b7d82cae524a096b65ccb39be3c37c07f59\nA = 358da59ef65f62f633675764e292e5a68879df24a4727eca1fc4d232b3a6d936976c92eeb11456b5e8c11319838c145c6529d2f3acc828e55b8274bfe9afb5db241b102715f8e8164e454ef39f13ff1b37cf367a5a66c4f743c750896b7c3c29026e448bb36c6c06b0d9a3d048086ef0c3cd922a02e794223f388b5d646db\n\nSquare = cd4246489f6f221f920acbd8bdcdd17f47d2b77268f72254de4190685c123e8c5eab8517fded1852e8316c9e549d3fa355142d91b2921a3c94aafd8862cd2235429340da38a2af131b8d002f17662354f5805f6a7af7afb6dbd2f641036600614cea42bd8b24d86a5109eed29c0865a5f30c5291b1d1ef3223f9b9826dee773d98ce972da92daa19e843f84ca5f1cd77925a3c1117242ab0fb509b94a83f8de4fc8d21f856f37a4d025b3024bd0dbb6d8acfda4ab2993fd6eb7a7448d4f66ec725d37f0eb14eb242c0ff3f0c4572ba6b98a4ce905fe1b7ca3daca56c225171428c56af938fb66b37e99e54139157bbf41f536989ef813af738837afcd62290\nA = -e53ad05c88568f09f616797f0b7f2756fb543d691ec2a5b645c1e5892a247302826419a35b1348cfd2c1c569c23c31b4c46d6c57d4a488c29ab5beb77904d4adfcd0a01ea0a26bb0cc8790441cc2c8c900f030d7315b4319f1a3cf5685a140e03abe6b94730ad79e8de1f4a0cded86a3d6cfe2db267fa7dc9b2bb32872a90cc\n\nSquare = eea8028b26e0df090504d54da714a6f5f2695202e53cff479c78aedd47a8dc676243ec586740fde53b3eca9ca02b91031ce766242184109503fbe25b1b6d318e3cd5970fabd16dfa22984dd2e9f1e0f14c189170fc69c031d66663703e6235a942d51a4545bd7b0769d01d302ce2b00b83f01568a1e378f61fd0ca6201b0490330580cd9de85719e174a71915d7efbf65cd73d8f4e66f27e0dd3144d58ec09ed0f7ed7d1238ee596922807100fb7a11127944ddcdec6a9ca3bbf6df7301e354f3f049bfb7c275b43c3d8cda5907a932fba507c9145ea3166081c1b48fcc710ee32cd931f936c796b14f8a78a592e67753a7c9e428a01719c8ba82652f3a89fae110\nA = -3dcb44be1e54c5a5d7db48055ca9afa1ebe2ae648aa6e16ac497502a7deee09ffa124720fad0ab163ce8b3ea6a90f110ea52b67dbc424d0cf1e8c9726dfd9e45bebcefaa5cd5706edeed27896525f31c6bbea3d67ee97badefabf3e2532470b66e3ae3100f66ddf50cf02fc3a8e3f44c304251d3b6a7ca3a6e4bd5d16a41bd97a4\n\n\n# Product tests.\n#\n# These test vectors satisfy A * B = Product.\n\nProduct = 5befab3320f8f90542f3120235abd926aac3805a19e343f690\nA = b057af553afb120db6b7764f8\nB = 857734c4c27a1d17f7cf59dee\n\nProduct = -ab1ce167f4b2945c55ae3f87df50ad07d4be87cf9f8aa07b0c\nA = ae7a6a87ea8981a567d0b3ecc\nB = -fb0fed5f8c737bcacef4d6cb1\n\nProduct = -c2606cd48e6b075c8da79eb4668e7157f1f175c2860fd4c475\nA = -c28dc31984d4583e9d45424c3\nB = ffc4581a5c3f885cf42767e67\n\nProduct = aa6805b5408aff7f914472756da07830dcad902834dbdd6944\nA = -ffa07ff9f503511954e5dd3f9\nB = -aaa7af472ad8957763f5a7c64\n\nProduct = 58ca2569173389df29b5ce4b784086055dee821a7243db7210\nA = af417d936f4690008811a1ae8\nB = 81b26b80b43aa65aa55ded52a\n\nProduct = -a043d31dfce8bd01724d31c863d0a64f1bf013509d77737c42\nA = fb5fae5edefb6997d44a1ecd6\nB = -a336e50c6f7845a1686cc88a3\n\nProduct = -b5d6a45ffce851b201239d938ba551bab7dcb59fc11fc35fce\nA = -f918faa58bb57a2ffb8b01f05\nB = bae08c3006fade695029a1df6\n\nProduct = 6f2fde7d1a18625d727c6345ed85e597d546d9228bf7f0564a\nA = -8d108d7a16f0696d4ceb24445\nB = -c9c764cae465207097ef8d2c2\n\nProduct = 93808b1140841dc9735cd61c6f855ddbbb83066689b0d7e1a0\nA = b386d08daf3fa2154e9c768d6\nB = d2557dceb2d02d04d9c578670\n\nProduct = -ad04212ca8cadb1f7861c5130ba3a747046a2a7e4a0c72b69a\nA = e4e5f7d1311e0c5f2e404d55b\nB = -c18057a328d8c7375afdfd4ee\n\nProduct = -685e75c232f2b4a0e455fe5ee8aea52f292ad8b8178320e692\nA = -a683312f132b2320632e74ef6\nB = a0758f12791453b4af354730b\n\nProduct = 6f588c53185c503dc5b0dc3002d3817ca2e7eb2370b3e9a647\nA = -d70c9b93170261091f0c53f27\nB = -848c86c51a186ac4c9080d3e1\n\nProduct = 5e3bc5a04e054a9a244bf7c86cae215072fdb70e9199989427\nA = 898b64ef09d7cf63966e1a3b5\nB = af638b12f26aa5d12e97439eb\n\nProduct = -8d8372b235b16108285203c03a8aef6fdd3c0e1a9fd31d4f68\nA = f6003dc83818c14fbe36c9998\nB = -9343f6cbcc81fa4c9399dce5f\n\nProduct = -5ee6509abeeb7af7fc5caef40d1822ad3150c8d74f522dc7c8\nA = -875ff6f56ca72cbdf614bb9ca\nB = b375a68a21dfb1f159c22fa14\n\nProduct = ada25be404a17385af5a330da799e5909da81bfa0715baa6f4\nA = -c9b8df392e76abc3eb7d5ce04\nB = -dc5ab818c70594dd917b4243d\n\nProduct = bb24422ee4656ddfcd50ec38201b15baf679d3b75e5cb878ca\nA = f8e12cf4defe388b78510f687\nB = c07ee817b4ae95c2915b88966\n\nProduct = -93da296ba164c7220a17330647aef0980c94eddd2cfa2a3b2d\nA = bc5dc74ddf7a1363d1c2b1f25\nB = -c8f069bad7f93cbfe6df51169\n\nProduct = -6b2e1d132c4e0b0dc9b7e7de7d424fda5180480cb5ff47c755\nA = -a8048acb66a8bb88df39266e7\nB = a34e0b265d71435ae8c92a463\n\nProduct = 6ccb2cd93783576a8602ae43f41c786008b6623a4cca0a010a\nA = -b071f1f54790c951c1dd2a1cf\nB = -9dd89bb4d9b546207e282e2d6\n\nProduct = 5c742ba47d0d64bd97509927ce957deedb855766cc24c60016\nA = b44f3f252c368096fa62747f2\nB = 83439b97dbac579fa4f7b7d23\n\nProduct = -7347ba65691c913286c2fb55e45b177f031c1d86ae0e9f654f\nA = 937cf0643ffa53cdea24d642f\nB = -c81881f78243dd5737a7d28e1\n\nProduct = -9bc0649a703674e59f83ff9b8a560e5cbf51f65ca310f80f95\nA = -b536f8d9769be6f62da941ae5\nB = dc0746fb101881ae0cacde6f1\n\nProduct = bf4992fc3a124de350f9fb90ea825cf663b1fa051282ef22e2\nA = -ff7eacc7de1bb01d668c693aa\nB = -bfaa6627f9fc7ba68ae41bb2d\n\nProduct = 7c8992d34cc0b63f1c953f68d4e12a99d3f3a34d16bd76caa9\nA = 9e0d5a850d078890a983c0ec9\nB = c9b72c118b3e1f1023a696ce1\n\nProduct = -a75840c95082b9a0ae0d6e0a4eb5e09288e4e2a66e9697d9cd\nA = b2b042a21045a74ef1a5091d9\nB = -efbf8b120b384e869692a1b15\n\nProduct = -a510b333bdb4ed7479c142e8fbe2b12f7671a42acbe16c0998\nA = -e7fd5e0bb5496b9d876c27f65\nB = b6262653b2be44501af1d85b8\n\nProduct = a1c1e90afc4684754155526e307fc6ed798746f347bae2c880\nA = -b84674832b26ded0a690a8ff0\nB = -e0b7bdf2fd05a038ed3640b78\n\nProduct = 5588e0c33bffbefcc5695ca0615abd383343f21a8a0d22b222\nA = 80cad81ad9a66ab6a1c2e5669\nB = aa0453a77c8af1584f54750d2\n\nProduct = -6460c2fcd6cf3304ab163ea883ac48e2031cd10f2e9014c0ab\nA = c49ad3d7c8848d4fbf913b10b\nB = -82b3dedbe3cc7cd532ad632e1\n\nProduct = -a18717330b711669e85abde8c4dce426529aa621ba3da2a477\nA = -cab4a9c0a331a5a5e826dda1f\nB = cbfee5041c13075dfe3399aa9\n\nProduct = 8ab6282ee892b53c083d319a9dcab48af97a1ac8493c0bfcad\nA = -f7d13e47f9aaac8c25f9bf75b\nB = -8f4aa95231c1e2336aa092297\n\nProduct = 8f2d1c23c78777ed371f13155445ca3c88cbc0a9b299bdf9d3\nA = 9d8248d00defce1ad081337c3\nB = e8b479295ecd9cef7301f24b1\n\nProduct = -86d5e0c5b581fe59819730b4b71e33d1f85f9ab504c7dbe2d6\nA = b21b45e88acff48562a19729a\nB = -c1cdfebccc763beeac394b997\n\nProduct = -484ca05aefa113bdfcb1bc623f730c9f9555b462a8ab4c9606\nA = -8c12b406c02c4417163c0956b\nB = 8422b15c80c1c087b17eedd92\n\nProduct = 614c3c91f60050c785fd229a3ad74674577a90cacb654e0a5c\nA = -93d45bce155a23a397506d96a\nB = -a87e339c3fd5aebede5fb1b36\n\nProduct = 9683285f194a7e4feeab196a36bdfc4f828035fd184b9cc692\nA = f196d8fe760fdcae7eb60e2f7\nB = 9f7d88a2163ad818bf3a6377e\n\nProduct = -988a64599c19cc64f3cadc1a83fea6550185f6cc3ab82af822\nA = d0584b2a306671e4d2c9d0c7b\nB = -bb6e7559df199c68d6df3a3c6\n\nProduct = -68456814cb0edd951196d04c853172afdd5787a5bd69a57876\nA = -cefce1b0a1fb22862418bb597\nB = 80f614139947aea5e76cd55fa\n\nProduct = b4b1cbf5d6566e7a57aee0cc5c9c8ec4ad885e8766aa7662a4\nA = -d68ed1bea046c6cad057e21db\nB = -d7988b9be54f6e332d019032c\n\nProduct = 6b09212675ff5257a1384371e17b37dcc268bbb141577902e4\nA = a8208053adc20a609d5d01404\nB = a2fa927c5458c4fe662d7a3b9\n\nProduct = -8361bc26f9bcf55f677e047d822d30", - "04027da0d0455b244d10\nA = e82b6410b29020c2d6810a977\nB = -90ddfe0e7f0d6b9cdc0815f70\n\nProduct = -f1b6da00923fd513a83e32040a515649fbd362f69ebc016d9f\nA = -f9b697d9ec774a8d1ee5ea905\nB = f7ccb46a8869cb028492bed53\n\nProduct = d06206963f2e150bacdb32c823c3a47f013d5a267c3c0d0c88\nA = -ea8e63afa99c719897ad7f2ab\nB = -e36f11f55b6148d1b4f46e598\n\nProduct = af774a5eae6084df5ca499ef005642730adabf6a4f9533e2fd\nA = e4c7af7eea3ec9cc2443b7319\nB = c457bc264c8461789931baf85\n\nProduct = -76350f428bfbb95e6c253ec0f457aa84cebe8c7cb1af2a2120\nA = 8fd1ff97465775d44dee58ae0\nB = -d268a7d328f44baf80e35119f\n\nProduct = -787ae3f114f9a8dd4d249d5d3f3b0897b02564b9469416cefe\nA = -bc0b398bd0ec045b0cf147b7e\nB = a4050955c234e473257d0c641\n\nProduct = 9d6320b3d4aabac097a079b9bd2aca7f1898bcab0f23409fd0\nA = -9d7a4ebac630cc0662b816fb5\nB = -ffda517d3eb3214986b04e290\n\nProduct = 80bab8bd800ac8c9dc3bb57dca306f10af6fd88c5d8314833c\nA = 834bc50140d6c6ab938dc58b6\nB = fafee47793cbc533b3c66af3a\n\nProduct = -b08920f5922226b1dec87151ae087d8a7e5c1aea8c9be148b6\nA = bfd5b1ad323c79428cb2db36a\nB = -eb956a10edebdd658e6810fcf\n\nProduct = -6d428e08e8350bb4b0fae3b662c82df2aef7beadaa17430dbb\nA = -a57da276998c548101f514e9f\nB = a9040c1909712e1149d295765\n\nProduct = a57da276998c548101f514e9f\nA = -a57da276998c548101f514e9f\nB = -1\n\nProduct = 14afb44ed3318a90203ea29d3e\nA = a57da276998c548101f514e9f\nB = 2\n\nProduct = -295f689da6631520407d453a7c\nA = a57da276998c548101f514e9f\nB = -4\n\nProduct = -867614005cc204a8d19720fe13\nA = -a57da276998c548101f514e9f\nB = d\n\nProduct = 12bf3b676f64e5929d38c35e803\nA = -a57da276998c548101f514e9f\nB = -1d\n\nProduct = 24d8f92c68303ed0b96f91a8167\nA = a57da276998c548101f514e9f\nB = 39\n\nProduct = -49b1f258d0607da172df23502ce\nA = a57da276998c548101f514e9f\nB = -72\n\nProduct = -6fd5e6ca25c3d51b2e529f22173\nA = -a57da276998c548101f514e9f\nB = ad\n\nProduct = 1276d4705b81b82da4c7e82559d7\nA = -a57da276998c548101f514e9f\nB = -1c9\n\nProduct = 1ddb9abfc5d4017f068a67b5f4fd\nA = a57da276998c548101f514e9f\nB = 2e3\n\nProduct = -3a8b41c914b1b4a4e341433601f7\nA = a57da276998c548101f514e9f\nB = -5a9\n\nProduct = -97c0f4ba414d6e7d4c8b7ced84d4\nA = -a57da276998c548101f514e9f\nB = eac\n\nProduct = 1198739e0c23639c176d46d13f7c8\nA = -a57da276998c548101f514e9f\nB = -1b38\n\nProduct = 159150954ee0dedf541e4dbac0ec3\nA = a57da276998c548101f514e9f\nB = 215d\n\nProduct = -441d4bc44c86f02ff12c3d91a1562\nA = a57da276998c548101f514e9f\nB = -695e\n\nProduct = -64726b76005ebee27592237ba5dde\nA = -a57da276998c548101f514e9f\nB = 9b62\n\nProduct = bbe4ec7cf7c5bbd198e0ea86bb658\nA = -a57da276998c548101f514e9f\nB = -122a8\n\nProduct = 21f717d05681fd2eb1796776a69ef7\nA = a57da276998c548101f514e9f\nB = 348a9\n\nProduct = -396ac788a1748bc6955f99be4d2c64\nA = a57da276998c548101f514e9f\nB = -58d1c\n\nProduct = -54a213eb083aed1a04f3d1b2da62e7\nA = -a57da276998c548101f514e9f\nB = 82eb9\n\nProduct = 1366fb9c20fb14b8b9a9be4b3e3dde1\nA = -a57da276998c548101f514e9f\nB = -1e037f\n\nProduct = 238d65fd26da4733e5d93ab2485d40b\nA = a57da276998c548101f514e9f\nB = 36ff15\n\nProduct = -38272a99be154d531e922be405aee9a\nA = a57da276998c548101f514e9f\nB = -56dd26\n\nProduct = -64651b62b6a454c08951632c7f2c398\nA = -a57da276998c548101f514e9f\nB = 9b4d68\n\nProduct = fb272e3597b816144f8b945ae6130e0\nA = -a57da276998c548101f514e9f\nB = -1848320\n\nProduct = 280d9f5ed7243712ecb9a7c6358bcb8b\nA = a57da276998c548101f514e9f\nB = 3df5795\n\nProduct = -2fbb6bb8e1ba78cefc47fbbc20e188ee\nA = a57da276998c548101f514e9f\nB = -49d6652\n\nProduct = -57f29c13691ffa1642d2860dab9d288e\nA = -a57da276998c548101f514e9f\nB = 880c2b2\n\nProduct = 139c19d7668e6aabf2d7206cb0723ed34\nA = -a57da276998c548101f514e9f\nB = -1e55aa4c\n\nProduct = 2950ce04bf0cf836d4fe94b88fb757d0a\nA = a57da276998c548101f514e9f\nB = 3fe968b6\n\nProduct = -5175239488dad05a58414251496d2a06c\nA = a57da276998c548101f514e9f\nB = -7e020414\n\nProduct = -945ff0ed38bc6020cf679cbd3e0758c6d\nA = -a57da276998c548101f514e9f\nB = e585e573\n\nProduct = 11c69ae98f6b27e95477986f796bc67c8c\nA = -a57da276998c548101f514e9f\nB = -1b7f653f4\n\nProduct = 209afe75e8fb5ac76d13c06b545f5d4d73\nA = a57da276998c548101f514e9f\nB = 3270154ad\n\nProduct = -386d64b215e41506514f4988ed237e4da2\nA = a57da276998c548101f514e9f\nB = -5749c891e\n\nProduct = -6c13cccdb1d140d0babd52707ea72fa278\nA = -a57da276998c548101f514e9f\nB = a72fb6288\n\nProduct = 136228a8a45540372b9b3cd7f82021f6546\nA = -a57da276998c548101f514e9f\nB = -1dfc08a2fa\n\nProduct = 1f0ad3babf9d132eaa08cf5cdb8f19dbf01\nA = a57da276998c548101f514e9f\nB = 30050f2e5f\n\nProduct = -50d615ce183258e95af77319b766fac81e2\nA = a57da276998c548101f514e9f\nB = -7d0bf92cde\n\nProduct = -817d358293b86a56a4e881e50257c549471\nA = -a57da276998c548101f514e9f\nB = c84efb12ef\n\nProduct = f09b9e80be251de474d726b16e25a6865fc\nA = -a57da276998c548101f514e9f\nB = -1743322a484\n\nProduct = 22996cb0f9c60e35dce49f3825f8a479db26\nA = a57da276998c548101f514e9f\nB = 3585acec11a\n\nProduct = -2b307a37c91791a61c0691858f5f783e4678\nA = a57da276998c548101f514e9f\nB = -42cf6be3e88\n\nProduct = -8826698fcba6c30d755fc523de1cc25301ae\nA = -a57da276998c548101f514e9f\nB = d29cc8af592\n\nProduct = ae37fc99fd419809310782714530d7428d77\nA = -a57da276998c548101f514e9f\nB = -10d8059d4a29\n\nProduct = 1d544a20f9bc7d95ab67d1f65743979f23bba\nA = a57da276998c548101f514e9f\nB = 2d5eadef1c06\n\nProduct = -367897184e9929a0294d320f10278889fbeb7\nA = a57da276998c548101f514e9f\nB = -54431582d0e9\n\nProduct = -943a509076a00060a2e7fa1cddb7468d734a1\nA = -a57da276998c548101f514e9f\nB = e54bb102f4bf\n\nProduct = fcce6e42879af5ad13545c0bcaab85b690cea\nA = -a57da276998c548101f514e9f\nB = -18711db522cd6\n\nProduct = 258c49f86d0cbb14ae9edbd3456be8cede2022\nA = a57da276998c548101f514e9f\nB = 3a1562c7c269e\n\nProduct = -4a8bbce59ad7daa51136d557f7fa16e9a2faad\nA = a57da276998c548101f514e9f\nB = -7350e780b0f33\n\nProduct = -82f53ec9333275d5cc271876a7db936db49280\nA = -a57da276998c548101f514e9f\nB = ca94ad312dd80\n\nProduct = 11daee4fcc713db5b2806e47fa5dff3b5b770eb\nA = -a57da276998c548101f514e9f\nB = -1b9ed6758f9635\n\nProduct = 17038cac4f0c94dc24985ea108ae6682e175752\nA = a57da276998c548101f514e9f\nB = 2399b8a9b1116e\n\nProduct = -37e5f14394bf347a3ed061769fe8e6424af4348\nA = a57da276998c548101f514e9f\nB = -567840a7569fb8\n\nProduct = -9253d4a32a88d8f725984514d969012ead7cc9a\nA = -a57da276998c548101f514e9f\nB = e25b246f733f26\n\nProduct = ace3648371c16a931d29004e79f5b9678391da5\nA = -a57da276998c548101f514e9f\nB = -10b717b27b6a13b\n\nProduct = 1faa5b45d04c143c339b09d3aad94d39b94ef960\nA = a57da276998c548101f514e9f\nB = 30fbd672e106aa0\n\nProduct = -3fdfe246d27aae0d08d63b2bc501461d2bff3b8d\nA = a57da276998c548101f514e9f\nB = -62cef5f078a8253\n\nProduct = -5b792bfaeff04ee3d948cb343a249d49eb344f57\nA = -a57da276998c548101f514e9f\nB = 8d805ac65649c49\n\nProduct = c5f824406161eec321da5a58e3e00d393b55abe9\nA = -a57da276998c548101f514e9f\nB = -1323dd41d2e1e077\n\nProduct = 2226dec8a57be8e84e42559007e2d101ccbe67f8d\nA = a57da276998c548101f514e9f\nB = 34d47842b5d0be53\n\nProduct = -340f50f812c7420b502000940788a700f6769788a\nA = a57da276998c548101f514e9f\nB = -508836d8e1193d36\n\nProduct = -a00f1d96e19c590479625c5329a87774b5964cc78\nA = -a57da276998c548101f514e9f\nB = f798fc858657f888\n\nProduct = cb94f830cba8997331912a6a31c34f1bef826d121\nA = -a57da276998c548101f514e9f\nB = -13aec7a5c52a0883f\n\nProduct = 16b45140b048d6dc0b9fc811df7ce7dd88357fff04\nA = a57da276998c548101f514e9f\nB = 231f27f3e347bd67c\n\nProduct = -2aa94179351b4e87de5849ab619d94f47450640199\nA = a57da276998c548101f514e9f\nB = -41fe3ec2189599cc7\n\nProduct = -5489401d3da93158d4284e557d74016c0a7cfd935a\nA = -a57da276998c548101f514e9f\nB = 82c5281df41bfc066\n\nProduct = ae04d5b212ecfc9a6d7df07794d565df52991fb70e\nA = -a57da276998c548101f514e9f\nB = -10d3139229f5d02432\n\nProduct = 27821bc811f45d63089790b41d307be978d4b19564c\nA = a57da276998c548101f514e9f\nB = 3d1da85cc012b3e234\n\nProduct = -3de3c9e9d7fa3020a578706339314890dccf63096c2\nA = a57da276998c548101f514e9f\nB = -5fbcfb28bfc9044bfe\n\nProduct = -627dcb299a6720044abcf11469bdfd3f951edbb5bf7\nA = -a57da276998c548101f514e9f\nB = 985b930517b78e6ba9\n\nProduct = cc0622441497a37fddf1856d5e2c99df52b99ea4573\nA = -a57da276998c548101f514e9f\nB = -13b9b88948fb7e95cad\n\nProduct = 1a5168e1a492210591ad1ed660adde9110390e4caf32\nA = a57da276998c548101f514e9f\nB = 28b631c6e04b6ab0d8e\n\nProduct = -4d8ec27b7460ce616421b9f5cae708c2ac241daa59b4\nA = a57da276998c548101f514e9f\nB = -77f99bdf1eb09da6dcc\n\nProduct = -55a", - "fd796db7bce822a00073fc8926d3bd0c79772f036\nA = -a57da276998c548101f514e9f\nB = 848cdd6212b9bb3620a\n\nProduct = dc494b0d73e8ec07cd2bb6dd8191d2b4d48e7700cc34\nA = -a57da276998c548101f514e9f\nB = -154c39567bd8be5f6b4c\n\nProduct = 240e9301b4345b914ecd91a49a0e651524dcecb6fdc6c\nA = a57da276998c548101f514e9f\nB = 37c6e7ee89cf87674814\n\nProduct = -39002ecfd6d96661b336157ccef6536756ad2e9219be3\nA = a57da276998c548101f514e9f\nB = -582cdab09915a652203d\n\nProduct = -695f49fc891d53f396f0593efae3973082b76d4f9e944\nA = -a57da276998c548101f514e9f\nB = a30074dbce2246af043c\n\nProduct = bba2b7b45b97cb0d7fb30fed95089870742ad69e7aed7\nA = -a57da276998c548101f514e9f\nB = -1224195afc7b394ae8cc9\n\nProduct = 1910edc278515ab7d4cc09b496dc3c06c32c75bc7368af\nA = a57da276998c548101f514e9f\nB = 26c6701c39334169e7bf1\n\nProduct = -3670b7f9b661aba35ce50984d83173c84c8fa60e04d100\nA = a57da276998c548101f514e9f\nB = -5436e84b4a29858a68f00\n\nProduct = -7fa0d3e0082b37475342b7e22e5dbad7b8d4cb5d64f871\nA = -a57da276998c548101f514e9f\nB = c56e0f44fc63bca242eef\n\nProduct = da7fe3367ce640fa5941c033ac1874312f10ba5950da75\nA = -a57da276998c548101f514e9f\nB = -15200043166ff309f0426b\n\nProduct = 1871d72481f66b1d413100edd6b339cbbaa67b3b2b3cd57\nA = a57da276998c548101f514e9f\nB = 25d057879db26fa29a5e49\n\nProduct = -3cf1dd1e2df3456757d72f35353c3c7a659b2ef844ad857\nA = a57da276998c548101f514e9f\nB = -5e46be70de21949df67349\n\nProduct = -5e861cbe47aefab2a7ea59292aab1258932b9a322f66e63\nA = -a57da276998c548101f514e9f\nB = 9238670897685a6c9cbdbd\n\nProduct = f623344788efb857db55c924e95a437effa4dc8bb2bcd24\nA = -a57da276998c548101f514e9f\nB = -17cc0ec84c228225a7cf45c\n\nProduct = 15514c916b0ae7cde6add16c629d3e19ba52a101d75dff72\nA = a57da276998c548101f514e9f\nB = 20f9f925b3ed307edbb154e\n\nProduct = -460cf5b14f9d0b547c3084bf44207bf881745c409b08d07f\nA = a57da276998c548101f514e9f\nB = -6c5cbfd29f3dae1dce99221\n\nProduct = -5ddf7fb91d765af97dfda5333d8779e80837c2b51cfb4f43\nA = -a57da276998c548101f514e9f\nB = 9136aa79080defd1bcf90dd\n\nProduct = 12c1a0edfb6ab6a0caae2553fb3743827e1470a8954e0a3fd\nA = -a57da276998c548101f514e9f\nB = -1d03b512470dc3052779f3e3\n\nProduct = 28388a244214abf046488a8d95308d95f021eae4b994a5a52\nA = a57da276998c548101f514e9f\nB = 3e37dce784274962ff862e6e\n\nProduct = -4da476e76119deef291c0f56934a912a0877278a19a561ee0\nA = a57da276998c548101f514e9f\nB = -781b2f2dc40094a7f8fed520\n\nProduct = -5792496d33dd45e225f9dfca17419a04e075ffc0c90b37b82\nA = -a57da276998c548101f514e9f\nB = 87772a4fb582acafd3e4ef3e\n\nProduct = dd3a3506a7d748de16fb43d666928a87de0354d8e8a1bcaaa\nA = -a57da276998c548101f514e9f\nB = -1563841bf7851ff158a395716\n\nProduct = 24e8fb09a9ab0808ff643122479dea5ed41060c6c5b74e8752\nA = a57da276998c548101f514e9f\nB = 3918c30b5568318a58e9be16e\n\nProduct = -366c125f96b38b58d01c939c27c4100af3377eabb792b5491a\nA = a57da276998c548101f514e9f\nB = -542fb814f45924aa09a16f2a6\n\n\n# Quotient tests.\n#\n# These test vectors satisfy Quotient = A / B, rounded towards zero, and\n# Remainder = A - B * Quotient.\n\nQuotient = 1\nRemainder = 0\nA = 8cdaaa7c422f3c2bb0ace2da7d7ff151e5bdefb23e6426cf3e6b21491e6e80e977bfa6c65931a8dee31fc7992c0c801d5d7c\nB = 8cdaaa7c422f3c2bb0ace2da7d7ff151e5bdefb23e6426cf3e6b21491e6e80e977bfa6c65931a8dee31fc7992c0c801d5d7c\n\nQuotient = -2\nRemainder = 1\nA = 107f0e6cebfe22ac11294a06fed2b994d01c9b3610d50bdd254adafd08c93be8ebdd1e85e1286fe9c9e682a90cbbd6351681b\nB = -83f873675ff11560894a5037f695cca680e4d9b086a85ee92a56d7e84649df475ee8f42f09437f4e4f34154865deb1a8b40d\n\nQuotient = -4\nRemainder = -2\nA = -3d8746ae2123c2d3f1d35910b42af1f86f5e81f8e98986cea20b2a1bdb8af6cf111f1258f112c837accdf4868463fe9eba536\nB = f61d1ab8848f0b4fc74d6442d0abc7e1bd7a07e3a6261b3a882ca86f6e2bdb3c447c4963c44b20deb337d21a118ffa7ae94d\n\nQuotient = 8\nRemainder = -3\nA = -5645d65662eaac73050de06f8f982a9b2ae680467712284be3e2b0e58ef4bf4d72b5be5e12ee1fd803b47f161759662ff5c4b\nB = -ac8bacacc5d558e60a1bc0df1f30553655cd008cee245097c7c561cb1de97e9ae56b7cbc25dc3fb00768fe2c2eb2cc5feb89\n\nQuotient = 10\nRemainder = 4\nA = 813bc46ee19ffeab364073a89f96913f340d43ee72129ea9edac1beb4ebe1336450d2eabc7b26e51c400cec60d6ee459033b4\nB = 813bc46ee19ffeab364073a89f96913f340d43ee72129ea9edac1beb4ebe1336450d2eabc7b26e51c400cec60d6ee459033b\n\nQuotient = -20\nRemainder = 5\nA = 12805392c55ffa0e27e85e15f2b339872793664e9ed3074cd2600aa52459a57197130d1ea46775ef43115c9413248cc7b34805\nB = -94029c962affd0713f42f0af9599cc393c9b3274f6983a669300552922cd2b8cb89868f5233baf7a188ae4a09924663d9a40\n\nQuotient = -40\nRemainder = -6\nA = -3579fc4d6083394c691b060cf9e20318fe17da0487337f76710bd11512578830ba94ac7b587a2d5ab7cb4afe611e349cdcfb86\nB = d5e7f135820ce531a46c1833e7880c63f85f68121ccdfdd9c42f4454495e20c2ea52b1ed61e8b56adf2d2bf98478d27373ee\n\nQuotient = 80\nRemainder = -7\nA = -74ebad4b39ebaaff82cd91082408c979527907c363d8f0f75db410523f8477c074c45ff85851b6275b1ebc5279029818e78d87\nB = -e9d75a9673d755ff059b2210481192f2a4f20f86c7b1e1eebb6820a47f08ef80e988bff0b0a36c4eb63d78a4f2053031cf1b\n\nQuotient = 100\nRemainder = 8\nA = d2d8a4419fb3b1c22bfca04ca08c2ee066ccbc9fce2f41861b5eef91efd3c13eeb7eae5abea0ef1849662cfdfef7bbff892c08\nB = d2d8a4419fb3b1c22bfca04ca08c2ee066ccbc9fce2f41861b5eef91efd3c13eeb7eae5abea0ef1849662cfdfef7bbff892c\n\nQuotient = -200\nRemainder = 9\nA = 1bf534da2f4365c96fc5dd4928e73ac24b157b5136ead90cf6596033ec387a2c14bca828000ae1725f3a5ace8ad67a8c07a0a09\nB = -dfa9a6d17a1b2e4b7e2eea494739d61258abda89b756c867b2cb019f61c3d160a5e5414000570b92f9d2d67456b3d4603d05\n\nQuotient = -400\nRemainder = -a\nA = -3a172cc9483774544311a1366659d9e61cc9fac7dc11c68e36aa991ef4d5e96becf5bac3e0967c904d926617ea11bb9551b980a\nB = e85cb32520ddd1510c4684d9996767987327eb1f70471a38daaa647bd357a5afb3d6eb0f8259f2413649985fa846ee5546e6\n\nQuotient = 800\nRemainder = -b\nA = -5ecff3a3e47fa615b6e3ce2dedfdeefbfe1d437c394631820968a9650b59dc3a2dd1c9a0b06537e4e5c408a59e580921503580b\nB = -bd9fe747c8ff4c2b6dc79c5bdbfbddf7fc3a86f8728c630412d152ca16b3b8745ba3934160ca6fc9cb88114b3cb01242a06b\n\nQuotient = 1000\nRemainder = c\nA = d3ef80fca0ab3ac3432b22e2b485131d816810c39d02a9c82dcc05ec5e6406bc216026de3abe53ab103ea3b2ddbc2ea377ae00c\nB = d3ef80fca0ab3ac3432b22e2b485131d816810c39d02a9c82dcc05ec5e6406bc216026de3abe53ab103ea3b2ddbc2ea377ae\n\nQuotient = -2000\nRemainder = d\nA = 163956bc32325f28f48d41d32bb08d2a9c4ccbb0d818368fb13941e82b27da21d04094f7e897ce79c2d0ff8470505f1ef63fc00d\nB = -b1cab5e19192f947a46a0e995d846954e2665d86c0c1b47d89ca0f41593ed10e8204a7bf44be73ce1687fc238282f8f7b1fe\n\nQuotient = -4000\nRemainder = -e\nA = -3763f8e43bd05e6ffeec6d509bbe6ff9a9022ced8cb191c9abaf5fd0e0b75a53e2ad581455e3af09e702a77b164ed3fb54ae000e\nB = dd8fe390ef4179bffbb1b5426ef9bfe6a408b3b632c64726aebd7f4382dd694f8ab56051578ebc279c0a9dec593b4fed52b8\n\nQuotient = 8000\nRemainder = -f\nA = -531dd44dfa9e79a5aec8fa7c84bd3b753c146770d22d2c14a6d2125f7ab95e9b320e84c31cf3e0d883e1295a220f2a546550800f\nB = -a63ba89bf53cf34b5d91f4f9097a76ea7828cee1a45a58294da424bef572bd36641d098639e7c1b107c252b4441e54a8caa1\n\nQuotient = 10000\nRemainder = 10\nA = 900996b61f58713f0755e68bbdfa4e0bb47f034bb0304f77829847923d14715def1771f43b526c41b9667438b434d2b966c20010\nB = 900996b61f58713f0755e68bbdfa4e0bb47f034bb0304f77829847923d14715def1771f43b526c41b9667438b434d2b966c2\n\nQuotient = -20000\nRemainder = 11\nA = 179d7ede3db0c105525286551331d5b9e1f97a7883f0c13cf250afe9765bb5aaa527af7945c19cdd4596565cbc8532a3cfa5c0011\nB = -bcebf6f1ed86082a929432a8998eadcf0fcbd3c41f8609e792857f4bb2ddad55293d7bca2e0ce6ea2cb2b2e5e429951e7d2e\n\nQuotient = -40000\nRemainder = -12\nA = -293dc443c294c6a6c53dd49e84f58305d59a432afb6c7ea2039cd02a513231239571ae07f29b5427e869b9faa485511ca45980012\nB = a4f7110f0a531a9b14f7527a13d60c1756690cabedb1fa880e7340a944c8c48e55c6b81fca6d509fa1a6e7ea921544729166\n\nQuotient = 80000\nRemainder = -13\nA = -5b637eb8aa51ef15a18d9b144031c9756527fc0fb96c84b6df03700e5079ae1b3e96940a2c1e07f3b47ad8a9b2b8ca99171a00013\nB = -b6c6fd7154a3de2b431b3628806392eaca4ff81f72d9096dbe06e01ca0f35c367d2d2814583c0fe768f5b153657195322e34\n\nQuotient = 100000\nRemainder = 14\nA = 87c846f5469d4c5819aed0c7e77797209b2c1b83a7a0e2be70280b9f30946b5db9bd0f25a06cf4bdba1c7183a1b9eb75c19400014\nB = 87c846f5469d4c5819aed0c7e77797209b2c1b83a7a0e2be70280b9f30946b5db9bd0f25a06cf4bdba1c7183a1b9eb75c194\n\nQuotient = -200000\nRemainder = 15\nA = 11c2a4509f419aa977c3d37fa446fcf21b4b3b9f983fbaddeba4f51c285ac40322", - "00711a54cc6edf24297b1f3d46ad020131a00015\nB = -8e152284fa0cd54bbe1e9bfd2237e790da59dcfcc1fdd6ef5d27a8e142d62019100388d2a66376f9214bd8f9ea356810098d\n\nQuotient = -400000\nRemainder = -16\nA = -39e37ae0edd92b957e84682358039f5e432c42492a44f3de01cdf74d643760260f2837946608663e12291e9b0695449c1153800016\nB = e78deb83b764ae55fa11a08d600e7d790cb10924a913cf780737dd3590dd80983ca0de51982198f848a47a6c1a551270454e\n\nQuotient = 800000\nRemainder = -17\nA = -72f725edd5a3dd6f20b5e9ca7da08a99f8ec9214c80588182c0d42e03bcff34b488b28c03cdf41813a6193c10672a8ee68f6000017\nB = -e5ee4bdbab47bade416bd394fb411533f1d92429900b1030581a85c0779fe6969116518079be830274c327820ce551dcd1ec\n\nQuotient = 1000000\nRemainder = 18\nA = 966df62c26acab2d3d1dbe729e48d0181c68e9f5eba45f6caefa38d60e34057d09fe620abb8640cec8cac755957aaad7c6fd000018\nB = 966df62c26acab2d3d1dbe729e48d0181c68e9f5eba45f6caefa38d60e34057d09fe620abb8640cec8cac755957aaad7c6fd\n\nQuotient = -2000000\nRemainder = 19\nA = 190790727c1514b4ef83a1c6aa07493c0af7087fbc8a675bfd9a1e97b8ef80ef684219d6c6f1a5fb5b919f105fd7717cdd5aa000019\nB = -c83c8393e0a8a5a77c1d0e35503a49e057b843fde4533adfecd0f4bdc77c077b4210ceb6378d2fdadc8cf882febb8be6ead5\n\nQuotient = -4000000\nRemainder = -1a\nA = -22d115ab02f8663d8c009960086a0275d301d358cd3b250bb9e7c16cc6ebed4a8fbe43bbced856d93be64a17377d95f5f9c8800001a\nB = 8b4456ac0be198f63002658021a809d74c074d6334ec942ee79f05b31bafb52a3ef90eef3b615b64ef99285cddf657d7e722\n\nQuotient = 8000000\nRemainder = -1b\nA = -41f2e708ba47494a13607223b08e6d99c0b4247436632961d873804e83446dc97139ffaef3e25969950bd4b5bb4ff73b1a25000001b\nB = -83e5ce11748e929426c0e447611cdb33816848e86cc652c3b0e7009d0688db92e273ff5de7c4b2d32a17a96b769fee76344a\n\nQuotient = 10000000\nRemainder = 1c\nA = e4b52f78179039499c2f6b500840f41103fbd60eac0d7082297236f25189c18a8301a92f533945047fbb83427dcade334336000001c\nB = e4b52f78179039499c2f6b500840f41103fbd60eac0d7082297236f25189c18a8301a92f533945047fbb83427dcade334336\n\nQuotient = -20000000\nRemainder = 1d\nA = 10888959278661bc36089519a215bda60f9ce24ff7c0ac1f543b6e652f94dbff1f32aa40cad2b4b4d676f16948551501c29f2000001d\nB = -84444ac93c330de1b044a8cd10aded307ce7127fbe0560faa1db73297ca6dff8f99552065695a5a6b3b78b4a42a8a80e14f9\n\nQuotient = -40000000\nRemainder = -1e\nA = -3ada453530a180fda58533ab8c62beb4f693a134f512e4d23e487dac3b575e5390c0a90992400e402bb47aac93d46ded55f54000001e\nB = eb6914d4c28603f69614ceae318afad3da4e84d3d44b9348f921f6b0ed5d794e4302a42649003900aed1eab24f51b7b557d5\n\nQuotient = 80000000\nRemainder = -1f\nA = -57879eb5d92d565daac3ac5173639bfe44b6ecc69ff770af57bd79c9b93841c5677042cb362b794f3d8b24b0d3b73ed1cba58000001f\nB = -af0f3d6bb25aacbb558758a2e6c737fc896dd98d3feee15eaf7af3937270838acee085966c56f29e7b164961a76e7da3974b\n\nQuotient = 100000000\nRemainder = 20\nA = 89a2f1792afc54467955839eddc9ef2e37d391ce7a1a4a205291220c1f49f59ee31fc7a7a7f7706c199bf5c8c951a0d0743d00000020\nB = 89a2f1792afc54467955839eddc9ef2e37d391ce7a1a4a205291220c1f49f59ee31fc7a7a7f7706c199bf5c8c951a0d0743d\n\nQuotient = -200000000\nRemainder = 21\nA = 1c267719338a4562e934bc57fabe6da86ca534a34244bd38c15032f01f47c2fd498c83f644b345c5c661ada0e586a096bb63000000021\nB = -e133b8c99c522b1749a5e2bfd5f36d436529a51a1225e9c60a819780fa3e17ea4c641fb2259a2e2e330d6d072c3504b5db18\n\nQuotient = -400000000\nRemainder = -22\nA = -250249f2185d4b428fa9534f03ef3cbed535bd31c56c0b273e6c3d35e0266f7777a6e59a99da5738b8e3af8ac60061d6716ac00000022\nB = 940927c861752d0a3ea54d3c0fbcf2fb54d6f4c715b02c9cf9b0f4d78099bdddde9b966a67695ce2e38ebe2b18018759c5ab\n\nQuotient = 800000000\nRemainder = -23\nA = -710b30c23c3c4e646ba90da33d2ce35af2ff181c40b02e3ffa607966730c6b6e274dd4c3c78e578e0b10f431f2d832274bf6800000023\nB = -e216618478789cc8d7521b467a59c6b5e5fe303881605c7ff4c0f2cce618d6dc4e9ba9878f1caf1c1621e863e5b0644e97ed\n\nQuotient = 1000000000\nRemainder = 24\nA = 877f1caf75e7166ef18484d0718947893fd1ec016984387debc55c19e378a487a5ddbb03a80a88316f6fca16ae148933e719000000024\nB = 877f1caf75e7166ef18484d0718947893fd1ec016984387debc55c19e378a487a5ddbb03a80a88316f6fca16ae148933e719\n\nQuotient = -2000000000\nRemainder = 25\nA = 1ed1b7d9e4cf3d44ee98ef69850e61a39f54cc407c6795c07c887374441fd9ec258c21193f8a8c55802fb8f8c579cf94cb0ce000000025\nB = -f68dbecf2679ea2774c77b4c28730d1cfaa66203e33cae03e4439ba220fecf612c6108c9fc5462ac017dc7c62bce7ca65867\n\nQuotient = -4000000000\nRemainder = -26\nA = -35d324ba37d2000f960ca1c9e1ab96e341a2ae6a5ea5cef014c73a39dde000d8ad9606b817ad67e4e4593cc5894d354854898000000026\nB = d74c92e8df48003e5832872786ae5b8d068ab9a97a973bc0531ce8e777800362b6581ae05eb59f939164f3162534d5215226\n\nQuotient = 8000000000\nRemainder = -27\nA = -7039477c3e0a6f415e25e9f9b1dab1edcd8a23f984e7e3bc149c206a3b756b1be001450af4049cd4535e4243d7032afcf6790000000027\nB = -e0728ef87c14de82bc4bd3f363b563db9b1447f309cfc778293840d476ead637c0028a15e80939a8a6bc8487ae0655f9ecf2\n\nQuotient = 10000000000\nRemainder = 28\nA = d6c59dd07409da98f7bbc7ee471b6e06c4d9e832e9f4d04ed9da63564d37d3072a950564cf549bb5d6e7dc85565d3cc8ba340000000028\nB = d6c59dd07409da98f7bbc7ee471b6e06c4d9e832e9f4d04ed9da63564d37d3072a950564cf549bb5d6e7dc85565d3cc8ba34\n\nQuotient = -20000000000\nRemainder = 29\nA = 14d27a16a9cf2fdbc85b88a604dd8f0e57b5b34a27089d75d805e05fbb367dfa61c085aa98b896e3e53b85ef774a3fa52417a0000000029\nB = -a693d0b54e797ede42dc453026ec7872bdad9a513844ebaec02f02fdd9b3efd30e042d54c5c4b71f29dc2f7bba51fd2920bd\n\nQuotient = -40000000000\nRemainder = -2a\nA = -3bd0119619fbb5b260c44050d61e6b1925a49713d754ceb06bafb1d730a93f199df654b153c40e75096ebbaf5a6ce3c801820000000002a\nB = ef40465867eed6c9831101435879ac6496925c4f5d533ac1aebec75cc2a4fc6677d952c54f1039d425baeebd69b38f200608\n\nQuotient = 80000000000\nRemainder = -2b\nA = -61a283fe41d965ee770704bb453f689cb82a81089422d6d904a91776a06d32857220286e6ef6327807b724062dda143b46890000000002b\nB = -c34507fc83b2cbdcee0e09768a7ed139705502112845adb209522eed40da650ae44050dcddec64f00f6e480c5bb428768d12\n\nQuotient = 100000000000\nRemainder = 2c\nA = 87bd03a64d9c56fe340137065ba36bd07b556119546dd1fc3ae087ead32bc79ca7efb5c7230ea7bfb00ad419096d9279fbe10000000002c\nB = 87bd03a64d9c56fe340137065ba36bd07b556119546dd1fc3ae087ead32bc79ca7efb5c7230ea7bfb00ad419096d9279fbe1\n\nQuotient = -200000000000\nRemainder = 2d\nA = 1eb7cfb197d19f56ad994eca52d1af6466fd09da07d68d63067602046b2d42d3063ef5eda6b58afd69fd92b0b727a0ecde1420000000002d\nB = -f5be7d8cbe8cfab56cca7652968d7b2337e84ed03eb46b1833b01023596a169831f7af6d35ac57eb4fec9585b93d0766f0a1\n\nQuotient = -400000000000\nRemainder = -2e\nA = -3ab858b3329e5bd0469118be52a867b2febbe2894d962cedeb3a5be1738db1cea106cd0710c9f6937348c2c63b109ae623d500000000002e\nB = eae162ccca796f411a4462f94aa19ecbfaef8a253658b3b7ace96f85ce36c73a841b341c4327da4dcd230b18ec426b988f54\n\nQuotient = 800000000000\nRemainder = -2f\nA = -6137bae6cf7573afcbb6fd5c066ba37648cba8db0ecafe9dbc66959b19deabf42f3083719a2268b7602bafa2140a1ee8ce7d80000000002f\nB = -c26f75cd9eeae75f976dfab80cd746ec919751b61d95fd3b78cd2b3633bd57e85e6106e33444d16ec0575f4428143dd19cfb\n\nQuotient = 1000000000000\nRemainder = 30\nA = d00fec043edadc093673e5f5abef0c6bacdf1f3faa49a831a645bf80db7539d657f69403b122a5c6f879eb8e63be54d35ed7000000000030\nB = d00fec043edadc093673e5f5abef0c6bacdf1f3faa49a831a645bf80db7539d657f69403b122a5c6f879eb8e63be54d35ed7\n\nQuotient = -2000000000000\nRemainder = 31\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -940693131e2ba7b2af531803794983337dd526f0d84d08d58723edf002a388d55c8502d88c2a2a6e78233a2a1b1c8d339a13\n\nQuotient = -611b743a0e2acb1043bb33de50a59eaa0405b37bf6b622075dd69291fe5b53305dbfcc377d1f3082319c153d0c1ffb3b3346\nRemainder = -16e346b6a4297\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 30c77f3380ccf\n\nQuotient = b9e34073d5e6e5b9e5d2d7250150f8ad86870faeb88d5aed5029fb25c176de216e2388e0f5d33f7c3b56102873eb40b06f2\nRemainder = -16ebc86eb88339\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -197b6f6ad5b75c\n\nQuotient = 141bc8752e846cd63743e6fce4a22efc3eb5f0ce46ba81b8f578c94c516288ec3610fc9923f45d4af2b94c0b0a20b48ed0a\nRemainder = 9bab19f12d81c3\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a67342", - "6000000000031\nB = eb90162ecae18b\n\nQuotient = -381bd85c951e1dd775b0d7fab344aadf06b1b592c643b5852fa44aa55159eedf3b3e47fe0d9f399ad92da85ab2bfd18240\nRemainder = 1e4f817a2f52b71\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -546c109fa8a9d7b\n\nQuotient = -5e385a83b56830626cf8306acc232f955178080e86384bbcf92eec3a8961360223c4cfc1d8d118022972e61866cbfc46b\nRemainder = -292e149300fdd1ad\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3246242094394c8c\n\nQuotient = 9af0246f4b49316df43f61ae3795a764fe9b1d071ce227982ebda7988a7a7a98129c94a76635c6913cb15e4f75ea1608\nRemainder = -dd3b3e32ddc79cb9\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1e928618913898b2f\n\nQuotient = 1fe40099811c648aa4e84e4fbb8cbc19706774a11391fc03a9667d8dc72dd0b26c4a46d0bae56ba90fe4bfac1517d241\nRemainder = 16e021603d30dde2\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 948887c1634f4b08f\n\nQuotient = -3f4fa4c179dab02ad461bbea8f890292c934496db560f72878323a4463d77ae261363f4dc8f53eab145fcc3815d3253\nRemainder = 407ccb4f0b814dc5c5\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -4ad17434071e1ce664\n\nQuotient = -4d17d19f7f6861189a520776339a1e425876808111c303e391118714370111151ef4ad2e6e84250f59b0fe09ab3293\nRemainder = -36f745b0f421d16db7\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3d71635bcc25183cdde\n\nQuotient = b976d544af44e711351c6618106d3a002c42ebbe22fe939a2457d24e8dcc35c95dde5c7c77af6b4545344a198be82\nRemainder = -107334ab98e5099fec5f\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -198a54e35fa0cfa328a9\n\nQuotient = 1307bb8e89aaff7466bc238d32672fbbde7be19d15423bcfa14f9a23fe85af9739b72807fd4bc420ad0b0fac37a42\nRemainder = 170ebe9b83d4c43b79ab\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = f8e923a8bbc0242eafe3\n\nQuotient = -3925a167c1c4d2fae265f277302b989466e309a7211e0b7173031cbbb91ab7fac8dfe43c9d832764e222e9d8581d\nRemainder = 4d404e93edb435dbd60af\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -52e36cee22274556059ea\n\nQuotient = -4d5a6ef346a872142b999ff9a5429198b3c2a97e968f55aa2c01583efe30e9687c57e2bca2372db4d3d443052b6\nRemainder = -3a2ea5f9d204dc31f21833\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3d3c79a115d9071b573d2d\n\nQuotient = a49dee54430f1737a04543d5f549efafab25f0f28f5e304f1bbca191f99521c2c4be1b9927bde19e1ec2060bb2\nRemainder = -17d02758f8fcadca911a95f\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1cc65a75211f2826c9d0811\n\nQuotient = 1808ab7c0ccac2ff8f7cb61248bf4624fb60352a356fdd1408904f8c6fb0cc52b7642ec59183bcaf5dd89ca0ac\nRemainder = 5c95323f3b8861261dc31ed\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = c516e6e3fa6e3dc52cf5933\n\nQuotient = -437e04d7076794850aada0cb4ca7a1055df103e74e00766be6a2fdb2631bf294cdbf2695d0a2f8f9eb5587aa5\nRemainder = 1fc63797594c56160536faa9\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -462ee529b488d1db2b6c60e8\n\nQuotient = -5dde5497accc4575a412e7232ce75bdf7905936e09e382d5c9f133faf82a05ad9dcc94ad858aed34cc14c714\nRemainder = -15e79293d5e055f906381a899\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 32765b0a34c88864d39bedaae\n\nQuotient = 11ac52a9287472e1d3b8577b3d50c95076e190714796761322b3ce869d96b44387e190e824849ee345d0a22b\nRemainder = -a158ccc7c055d64e7df3fbcf0\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -10c061a37f6cbd11bf0c327643\n\nQuotient = 1ff5cda1551867577c5ca72c86516a82fb8fc5f59ce967b73c6bcc1b85168389872c9a747ddf044d6dba174\nRemainder = 21e766a0020ba429b330a325d5\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 9435cd2dc2a92c950bb9e69b83\n\nQuotient = -2719c892fa3f4dbc9951b2095056a16159adaf32dff902e20a800a0cc2e858ccae408f2161aae25d3e1f6d\nRemainder = cafbe9caa1f83fd0dd3d5a6881\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -7924e4dcf8f96da61f54bf83870\n\nQuotient = -5080dc99dba295f4a2d9a474c2ddfa3b232a82fe629fe62177514988983eff8195b37d3fee3afa343b497\nRemainder = -94ae72f78982ac1ff83f300cfe8\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3ad70d4b6b9b5f5b2eb65da67e1f\n\nQuotient = e475eebcfc53d49ffad2e0c2a4ba48fe7ce02c42ff107e01ab3fe5b26eee45c83c4f58c181d77c259155\nRemainder = -c83ac7582a02b47ee734e0f24dc5\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -14bbcff5423a260b21895327b18bc\n\nQuotient = 201308a421b85291d23465d648ad2a8d6f3393efc16fb675a42ea7bbca635ddd8c2449b1b34e5db30a03\nRemainder = 8e07efb8ae4c9df39533042362081\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 93aebb72a81ba68e8881fd1a56a90\n\nQuotient = -2584cc534f88f091fe471c652ac66a695906a7cde1fc1cde9be3ee09026b690c1a899378ff31f6acb90\nRemainder = 794801d9d5770a60e312b99d6b9f91\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -7e408caf387a0ce9bbf4309c80755a\n\nQuotient = -63f7bfc0fe5a5421bc0a19fa6c87713a72eeb2a33e5eadee8c2f32c20d14f403ab8bdc424b9e8e0c68\nRemainder = -24227c242afedee2473c1a66a5cc29\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2f622c665af7f8126eabfd90df8e9c5\n\nQuotient = e557e6d2180aeeee5d2cef453fbdf38e84cc148f4608ade8836045498be2d318520ffadcea6319432\nRemainder = -dd290149e0e159f9ba6bb9f5a4b003d\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -14a7623d1d9dfc177e913d3119d0d30a\n\nQuotient = 1651d852316d472b41ba0460566e43fabb9257861859ad0fb6ea5a6433a4164299e078f4d50c58afb\nRemainder = fb60aff5fdd2a2b794b0d973ac4d92a\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = d439da27b5e70342aa5cb365ece15665\n\nQuotient = -3ae357761a8ff43d3b1bc53eb336260342a39d22f8fac44eeeac96c2f6de32580dd6a688faa9c515\nRemainder = 4fa6f7ee4faf2f6be99c5ce4b65cd642f\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -50700f9c0da59482165a47a3eda2bf07a\n\nQuotient = -543b4390e4e254226683aa0b83b2ca176ec27a373969fb88f766ac72adc9125ff83b2652e46afd3\nRemainder = -12ff398d9a7d9e97a7f63a0bb293c8fb0\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 383c5a4f1767e83fc382ad4f1c7c2b7ddb\n\nQuotient = ecb72c14c59d49287fb6b2cacdf04619ee617d5f3f0f1b2890fd4e79746a4fbd848613cf5eb437\nRemainder = -1035512a2717a89062d48f1bfd213333ed0\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1402b751a1e5f3fc46e22b43240d6ce9b27\n\nQuotient = 1e800ddc5d5126f322298383f32fd593623eb88a91b2d68c5d9f56e20c16ffe2cefabe873570ab\nRemainder = 72935d534bed5ba557b91ea023601f50b1d\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 9b4df766c608ff3efe5ea1f65cc850fa73c\n\nQuotient = -2c2dc2378abceb983904cdf6728f361d279b4c821710ae785724a7251", - "c43fe4f705f023afa7e2\nRemainder = 249f6433af4e8e224eb570fd438197af62f3\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -6b382f812816c77d65c94c0c660b31a69b8f\n\nQuotient = -5f3ced1e42fbd3c6b2c6f1e16953e0c1bb6efb4e49566f974a968f69a1a66a3d7558f5a802a8\nRemainder = -317a7fb1af65982fe4641fbb1e5837e6ea3e1\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 31bc97372d17038fd842b72eaba2abb26df62\n\nQuotient = af3fef8111c449b9e0858e7e53e1d00b764232f7a077d75043249c387ece30af351c8a40335\nRemainder = -a1493bcbf57a8480461d62796aa8f8541ece4\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1b076b2f7b78b4a0f0e24ba3a05d6c697efab9\n\nQuotient = 196734cefb08f09cb32ffefc07da8d9545d3451d5a08736757184bad94c73be71311cf1e01c\nRemainder = 273e33521f4d74840a96b3fffe169f79d32855\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = ba7746f4400f812919a3dc86b00642e1487691\n\nQuotient = -3c5989cf33145057a9c8e904435d12939db519cc6b9ca1c0a11934399cb139a73613950f2f\nRemainder = 456ebf56c636d54e37709b9e799e83b7a08cb93\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -4e7d4f389423f42e980eda55b4a6a45f6f4bdc2\n\nQuotient = -8432cf3338bce1d12586f83025aea50cff3864af3eb2103a36bbb0aba10b0ba4831641633\nRemainder = -4f62c678137df301c4bef216e6aa910104e76ff\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 23d4c57b5a8162aae8d937be12efbcfd7b96ec06\n\nQuotient = 9f94c4399eef16dfc65a1e015e0786c86470299865932c4d564b71c9b1551a9c0308af38\nRemainder = -168b74a6073b4a5b54fa14aacb5c3bb7897ed0fe1\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1daecf01ec633610373b79e04c22cd7499012bc66\n\nQuotient = 1d5b838dce6c0324f157ad125adefde6e1045dce9ff97cf8d1d39b79bce02128e3433ffe\nRemainder = 3aa816216d55fc3c910a030fd10fbda1e12f2ac2d\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = a1598a12a84e9cba42ea0e200e88d4599c9f615fe\n\nQuotient = -3edb182b53890ca8762f3039d2d71a8a27c36cc884d0879e0635e6326af0182bc47cad7\nRemainder = 4610b2b1305220bc0de584dd3f87d90109012a8077\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -4b5c2f1ba3a82047c9de61d47cbf1bec86b6ef90d6\n\nQuotient = -7571ed4c509630886483f6ca0923859e644063acb38cfb338bf3a681fe449501262516\nRemainder = -21c579846594fc3e5efc53ab01576a7b32d69faf41f\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 28550e1f7c6492f4cb682c37b105f92b049c13fc03b\n\nQuotient = 9ed8fb31327a110ef4377258681c5287de8ef9dbe62aa4fe84a7f2a94bb69607cbdb2\nRemainder = -1b7bb759dd0ebc346cbe216e56be8063f063490c17c5\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1dd1e61caed1efc07d21ce05d889de1ad65808cae026\n\nQuotient = 1aa716227d1ca6af68286062b2d6dafd7ade16abbd5d6fa4ada0365832fe18f73bf35\nRemainder = 32e714b0c4ecefb38735cb88cd5e07c21c81be858cae\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = b1b959a7b3262d7f4dff488315903aeaffd982b726d7\n\nQuotient = -2a9979a530046939e0b43a25edfbea6775784eb5cf346a9fc3a2d22e1aad473cdada\nRemainder = 4edeb91a2472e80068b1883cf2cc45d68ff9bbed1756b\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -6f31bbe097587a68fdf01d0bf93830bd03a23920ccc0f\n\nQuotient = -566ff76814e1c7d31ad53bfb9f3c0607ef1f7d1cf9bdee6e1cfb78b3ad7018f8bbd\nRemainder = -1eac095d6d84021c33aa9b219d191bd0637f20b5920eed\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 36ccf5bdece624b4f54c729a8cde13325d8dd764f44894\n\nQuotient = aee4f377611179d8b6315811dd94639aaaee63e99bddcfa8eee297ce1dc04daf8e\nRemainder = -59cb3ba7efa1637c46b21795872e8deaff90f13402cfaf\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1b157ad838684b45065aa77ca3238a4d8c5427f719cdfb7\n\nQuotient = 1c72d32cb83cf4a9043d3bb5002f61b03e29c34e44a9fc5cc4d613726f5e618546\nRemainder = 7312d11fb5828c7f1a0060a5152a7644fc1e6a59de28d03\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = a681444c4d47d829f7b629b561ffaa0c3be1232346c907d\n\nQuotient = -2702afc4095a0396215e3ca36e2a59725f743b30de0dd8d4ec4d943fef6c37162\nRemainder = 223dd3080ede3a64744b14df8742cedd71388b0df99073bd\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -796c9ea38ccf516a2054a1e584c18b64b996c9679960585a\n\nQuotient = -805585c6a7badc933bced6f8373ffdfe9796e963d3fc90e85b1a22c38f842062\nRemainder = -a6ebff3f651644915d5c466cc2915d104f0f85a44e08fd6f\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 24e8fb7a6a3057ddcafff92916c46f7e4038b98c3104ae831\n\nQuotient = 10383ff8feeb180d4fde925b534be97ec3d5f1f1dab5d8cd9ab5d8ea646cfcdf\nRemainder = -a7efdd0401c74a69cf74442fe3da907acf92e8edc51668828\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1240a71ed8d81e86fd9b16e1d64f438b35d6f8eff672494017\n\nQuotient = 195d95a520fd22317492117dc756ff97806c48c1aac67a41ae56fe503a60cec\nRemainder = 8b8692bee56f8a1ada9ffd8b3583eae33a0df9b73a7d8585f1\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = babe02063b61cb90634ac0493174073d2419e00728d46ad2b0\n\nQuotient = -37791adae674b866e4791c107a697363847dee4a58a37806391426ea48b8c9\nRemainder = 33986fc6a5f5c4f4e31458fc7de55e08a4e9320509d90299b93\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -5563bb852e7338c65aa21c516eecf47f498e5788c608ed46cae\n\nQuotient = -68a30494eceff55e4f54a556dd9b30025ccfa22c0952fd746adfd13d31d00\nRemainder = -1b511d0ab81d528d00a1058850bef48df2e9ae9357e779bb9231\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2d44e919fd27bb3fd2093062d11830c30fa77febafe0a2082cc6\n\nQuotient = bd30999592dbeabb8871b76aa04cc1c6c3794a83f0178c2ad505d8189485\nRemainder = -b0dbce286df5faccf0bdb40ca60f508d436f9410c5e49c3f1360\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1909930e2d16fc877c15895a3ec8b2125858bfa1c5a1b8776bedd\n\nQuotient = 2171694ef4a9d57b83b09357a511d4e11cecbab5e9387928b480d686a0e9\nRemainder = 29abc8898d5ef85f87323c2a6fa36ab6e1bdbcc0ca742b1a2347e\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 8da37bc9c7c9bdc62f49cadcd40e156e776b7f4c8f7ad543f463b\n\nQuotient = -267d470f32911150d9944e684c14e1834734b15475bee968748dd5f6502\nRemainder = 53a2ffef61709bd7143c4c876e021f20a99ba481f2b11abcd45da3\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -7b117ddccee97816c2ca2f1a612cc0d94ac67f5a79ed41744c8fc7\n\nQuotient = -5a21a3bdd3a3d4f1361a978706ba1cec409c296a5b3c369e91fc8317bb\nRemainder = -2cdc818f1e445fb3772d2a56833aefb2f5565a5fca80662e6fc1845\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 348dfba3c793f0018d7d3a70c4060c3148b4a3163ba60af9d6f8b04\n\nQuotient = b301b4050fdf4ede8f9c746b26d968110e1eb119ca42cd9c9bd8d4fab\nRemainder = -17993daf81711fe59204ec82e363d2b91971129af9206ff9506d3cb1\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b11", - "85454dcf046745436391a673426000000000031\nB = -1a76328184b9bea8770c91cfccf8ab98e75b2224d666af58022aca80\n\nQuotient = 19c401336dd43c221a61264f8b91791d250e6c99c61850efe6d1e3532\nRemainder = 6c9e547a77c98eaba1b021777dbd98ea88f7fd37c95a2b182f2b9067\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = b7d7b1f95f4fe2f267af88b81af88fbdf603e54ab6de73ccd000c32d\n\nQuotient = -38a77853de88a8db14612884b515e3cd7c673175779d4ab71ba58f83\nRemainder = 51851549cfa00dbfae388cc3b46fd4824268e00e12fba288acceab339\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -539c0171f48e4160e5c308ee9e74f35d8b6d032e946dbcf748b1335a8\n\nQuotient = -79a7eab82e5b65f4f6734e8803fa7c30852ea3ae56e801c5dd11778\nRemainder = -f89592eedcbcc68d5df80663b3cdc638d9d779707d4ae5a552d97d009\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 26efac15401a945ffd37066bc5af23191292765164a0f1e4fd537fd64b\n\nQuotient = d33afb58753a21581c5b2351a74f3d220599ed56ebeacf1d43eeb2\nRemainder = -f699437f44af44b3ddc080f5b74f753d35f70baf3866040ba3c64b30f\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -166cc6a3c60facfa0d8d318f26c6514c7eb9113f6b625c1de804ad379f9\n\nQuotient = 19e55bdaaa5a375c36e6869700f8677db563e5cf985be2a8d1b012\nRemainder = 7bccc3a653f29f3f45b52b8de2449c868c64d976666c01bff2dca03a8d\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = b6eae7a82b5dd1554795573cbf558d7cfed813eec270c326bf290adccc2\n\nQuotient = -297530094c3e4270ab5cf67e60fa5af6a32eb41b18b050fa6d46d\nRemainder = 62d8b502e172da7bce53fbb7c1ae376b6c21b3a3a47523aa0023406e353d\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -7241ae5f1aaee9340d437ad2dab94b70dd29fc6fff7fe31b100aa5001644\n\nQuotient = -640f3c38230962c6d6fca459afe0e46137525e8d62dd9b84da73\nRemainder = -16fcadd5155910764ecf0b4bd0afc3707e2ce49cedcbd5414f1c7d860e95c\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2f570d2da7a4e62097eb494ca43f7bde33e36525308dc864ffbaeb5d48f97\n\nQuotient = b3895ebba13c8f383ac0482be02e1f5518511420cb4513426bb\nRemainder = -21bc847fdfd48c7a4c36c778681ea20481081cbb7af6b281c8b8ebf2b2c3b\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1a6233954b3480af5f911a6bb8ad33967d5e0446c3e56f521e892c986b6b82\n\nQuotient = 243f3fbefbf842c79c5e96162fc42fe4f177a59d27681c54b3a\nRemainder = bbfaf15a90e744dc4a1caceda3cb339e5491e4507a1118613c5e9739f976b\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 82ae783b8a13e2e65d52dd3a6d6b057163347872f4d72245ff364dbf2421ff\n\nQuotient = -30f7cef2948c9ebed8fa3c5ea9a9bfa96ee4e9729c9b18e9d3\nRemainder = 1feb3fd887629cca60c664e385dddf538d9bf7fff2d34ca9e0e7614946d807f\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -60bba60d69093c0134fcb90aefdb9c190e7bf037ecc13dab3cc7915d7893046\n\nQuotient = -6b6f0183c1f598a68683ba7435c05d700d74681fe472669a1\nRemainder = -1f4d58f81a8c18523918d31791a00ea9aafbbb87792d90a5392273ec4e405da2\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2c17372a5128d7c403a3b94838072ecf9aff88d164764b12bfbf6261df957e2f\n\nQuotient = c4347fe42b2a7d9d5a650b72724369c5c1f59262a7be3fc2\nRemainder = -1103ec9c4a15373949cae4e34b7b42e242da41edbf5ad8362ce5e5426d3154a1b\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1824671758069b7660bad819f06c86fc76a9344ea38412058380363e5c5b4086b\n\nQuotient = 15e8c8d6847dfe974cefeef5fee93da9e58b74d640c6c413\nRemainder = 61dac240f2b39832903d5ecad9cfda5162bf8ebb0610545f259b75c3dc6ab8771\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = d83386fb9682576cc70cf84520c53169e391b414f5421cddca6e257bd77753c40\n\nQuotient = -3572711bf994e6ad48535cc4d65ac323ef1ccff530b4337\nRemainder = b5899d4cb879e37022c539962959339d055900cca16153da09b54c658753cf50e\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -58a05faf5c61f85ac5a090b6bb045c851ea17332d9bfad4309ce2b7a79ad3cc575\n\nQuotient = -6931ebfc6e34305e5d7cba5284829d088d1ec0abdde508\nRemainder = -1b09eafde481064bab3a5c7fd895edceca40b1e62a9cf953eae1061dfbe00936391\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2d0769f392ca9ec629ef1bfbdf08cd8cc9219330ffe3c05343df792dd94b1147714\n\nQuotient = 9a4800f0cb2bfbe8d234410deb510103b7da30cbac7d9\nRemainder = -971e4a529e439a1b96b942001631027ff2fbe40b8939e224adb7f2ed30faff64d1c\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1eb3d7971125a036c3a67d9f5ce580a4ef4c469a492be53a55bafd2eafd4032b5b9d\n\nQuotient = 23116704b7a1a86cfa2ee5707ee46268634db5d50dc0f\nRemainder = 467c6b64c8121e4f250492191ea36a27119a0a6d19af519bf7ccdc2436c885c99d85\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 87134e98f73470e23a96c6a9139af3d4d21574de8aa9ea1d720df8940bcbda343694\n\nQuotient = -3b7f72ecf4f55c02366c52f38a827f5773b7cdebb9ba\nRemainder = 194b334b2046a66be3ddd7c6df01c88967fcb11e97b8206d000bcf6043c6e9ccb13f5\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -4f9d0341cadfb1f0bc38184d93503faa196fb8170f8ba2b5d3b512c09d39b7f79a5b6\n\nQuotient = -6db1d69019dd4cb26fd65d5b88a31bb6413b30278a1\nRemainder = -2042a060391e181882dc0c8d91c3b03c1ea35e2eff01babb3ae876ba1e57a505d44856\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2b2e8f445c0c3aaef0285945e4ca37a700310e003086f34d02c891b94b117f3d3032fb\n\nQuotient = c0e5b9a5853bb21b5e2e37f469764579d5cb2bf984\nRemainder = -154669d4bce7914cdc8d79f2b8d1faa43e8cc3b20fb0767e1c9a47c9e1daed4b665cfdd\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -188e619dbb719381e701363de874fe168529c10f30d3ff184e4356991fdec1649f72235\n\nQuotient = 180054f8c36833d44cab9dd61e6d89d28605c564af\nRemainder = 59192ec5c6fbd9773b8b7dd7d8ab1800dfecc8eb01c29997d15ad75b79575d9e26e1fc9\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = c55b5eb165c63ac2794bfac21980ebacadb93f1e059309fd2b855621572e8d9b3f29018\n\nQuotient = -31412e97045c19ec38951b0e3884c66d1d7479437\nRemainder = 56f1425227bfc6eb1ecda7bfae0e5cb59e92a2cc5306b28465c8739e40893dc5c1e94cbc\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -602b8c25ded1ab3877f58cb048c733649c7dcadf87b2652e35c4e5544d2306107ebff7b3\n\nQuotient = -8da1489ccf7203ecead94c67a5750884122b6e75\nRemainder = -15162026586a1e55dda72785f31c9e6140d166a1fd34c87a7d8c78f8d8f87bbdcf8f75b1e\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2171ee4a6f7f67d5a33d0a08c367184d70ffe39da28562655e75f6b66c866b1c2ac93e467\n\nQuotient = e635f8bdbf80e99723aa5718d3fade4e573be2c\nRemainder = -ffbd73bfe05f95bc2b135f12682288c620215eac3d6d56503d93a90e06f236e597d1df975\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -149375d478a096e724b84faf795c589ef0d772c4623f5be38da99006cd833dc5b28363faed\n\nQuotient = 20f76f5c6d0c8284764a10f6936c22bfba5f851\nRemainder = 82e3fb3f7252dd87b5370d26d9e8b9e98c7d333701f0ce8a05c337054c7aeb343d04d7e342\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054", - "711aab90a05b1185454dcf046745436391a673426000000000031\nB = 8faf8c0a3ef94ab1069394998e5412a7d84f44aff97edf63abc46d96f897172c38faa0b13f\n\nQuotient = -382586dfe93872abbe3a504fc62a8973913f96\nRemainder = 4d407323ef56093eea2f3993334215950f4e1a85ba18cdcd77d819d92b8b292c3ec8edea425\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -545d81ed25602b158bc79aadf98a8f655fc399fb8652ae94333bf54c8c9ffaf8c6b3f2a9d52\n\nQuotient = -7d179efc493eaceaf46572a1f3a62bdfc4a38\nRemainder = -3de3d817a9cf7d529b5229a503e8ebbbd2c53215ac3c584c010947f780198dee16ffbf47791\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 25dddb00f65d6a1ba8caf7815a8063c5da656d775eae9e0108c68ce11dc925183810888dd04c\n\nQuotient = a9f7e5f235bae0e3e29393ac5c99d510b009\nRemainder = -150478b4a0df3eb20dcd1be8da283a00636c021c5c6337e7732aae9c4b49853b95f6d2475ea7\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1bde6cae7f5ced9006c0b1a61fb50982a433e4e2050aa486298f456556d8e909e96933e2ba3ba\n\nQuotient = 16de125df5936181981b4c2d0051a8b4d211\nRemainder = 29ac7c8a11f9beb9ad649257994216146b663bf4f237c561bf315d95778fcdb1010283475ebf1\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = cf24735a60ff5906410be5c4d98e3c9247919b57e404aeabc7eaefbf07bd64762bc61b96c9040\n\nQuotient = -268a52cd10ab4814268f66d9f44f71a98eb\nRemainder = 20293699f12fbfef2e391963866fc082a7884cd13b1c9bd8d5d203558feed2b889720be936451a\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -7ae7d548212830013b7d653072c33f0dd54a6ebd8792bf75809d29a8c798dbc67c3edd99a69b85\n\nQuotient = -8f051067ccb82b6a3dffedd0ff2ee97c46\nRemainder = -100dac0d3bf5aacc5fade281c071eb2399560a65349566567ce1c0c34e43f175a575ed1eeeb3b07\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 211ebb5dc59a051fdfa3b18ac491971e863f2086cdc099672c1215af4ec877e29950efa4f487be7\n\nQuotient = 9b7ee4c499386f922432fcb1a453ee2ec\nRemainder = -f410122a74386d724cdd45b2e548645ac5ee4a44cbfecb82aad34ae470526674da44ebbf557bb75\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1e76750814dec1ecbb1af0fa2281ab3185e94e47fc16a77fed312f23f261ad7709ad7c9f85862c1d\n\nQuotient = 23efb26228d7bcf281cd45f54572e2b3a\nRemainder = 65bf2ef1c2f8e94d98060aa305f85e6cb869c74eabad99877010d30654aa2e578ef6aa3c5f1122e3\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 83cfc25e90a61cf8686e3d5857b2f958674d478622c54cf8427275ca5e9312ed24e44ed4a1b5e413\n\nQuotient = -2cfcae0e922f2d884bfa0a3346dc9812\nRemainder = 14de2725b11a9c6784d9608c52770d29b9fbf824ecd4890bf28f3ec0dc6c52e4df9be540332b8882d\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -694b057ff381badb37c7c15c81e74cbd6774e8d61c9e7d450811c36262ea834fc1287fa59708ee072\n\nQuotient = -4c0238ff3c18d4d58e543f020002802\nRemainder = -2ddef796c50817e82ea6f64a02a8c6b30ab40070ff5401c2d39ca14b9c4d99de33834bfe566a0c2efb\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3e51c9ab14f522b55e8f9d3ba995c0846a864dfa2d568ea211b0cac1463ce6a1da72d0a15746fdcc9b\n\nQuotient = d41f9102a7785ce64f76b7d7b870b0\nRemainder = -106eaafdd518c658bd371164ee43ccd915a01b513fc7d220900039ff840ba36450e16ce9987e08e7141\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -16549c5d57b531528dd4d781f03cf275b66cb94eba038b782b739c3ab30b8631c8706abac06004a942d\n\nQuotient = 1616b432b3277e774aad92b0cf544c\nRemainder = 2c89373720b834d718ff3df985ae47c3a7cde0e0309f682f5fd48dc97a1ff3d69fa0dcaa1245e956445\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = d6721300e877a8145d05f4f3d8085697c2ca5f34a5357fed0bdb7169f83b6f8d855232eeea594846b79\n\nQuotient = -320fd6a7375a42a3961362ae196d1\nRemainder = 5336711bf81237ea3449f4e9f4e6358dc250f8ebd86082cab92a8079f2c8f835bc783082efb0ed7e3f66\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -5e9e8e1d446fdd314d487cac1226088696e33161d923acb67d3c75e87e428bdbc193e02f53200610fcdb\n\nQuotient = -4bd06daed3f30345d269f51e4381\nRemainder = -1f3513bdefa40662f0f50a04b418a833aa2f85522dc6c399298b1b147662ef2164ddbfb7247ba9511b8ec\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3e7ab7ffe5f63a6c1e109b95b83af470ff820cdedbb3c90c398ec42e44a45e1ca894870a7fa51f17ad5c5\n\nQuotient = d6fd01a0c5b55fbe36e58bbe77b\nRemainder = -c51af3e8b430870388357cb366ea888bd7b4ccde09ad3a1d2ee1426af060245c6d6b5980ae87fb66c4642\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -16086df3dd5e665f2631a294563c68931faa19ee67d6a2153d262940a648ae71bb3c1745daca5ea977331d\n\nQuotient = 18bd9a8f5678d28cefd955cf99d\nRemainder = e193f2fece67b7abe16373c3f84f18dfedcf654d951bf47585fccfaf67ee04f5037354d057c9f5eaa8eef\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = bf758acacd11f3f3e6665cd740517c9ab2384266f3c7ff9afd0888cdad2f6c9401c24d6c11fc3949aabbaa\n\nQuotient = -371239db55c79521206c9e60c0\nRemainder = 93773085af7582dd298b09d7098835787978d820289ea6850f27d0d77eecce8614785e32b228f46ca4b371\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -56033fd85be464301f10177b58d895fbb6df6154da5c2a2a7cfc3a24d83a96f5295fb17a08148a4e51dde91\n\nQuotient = 696d8e378d12221e2d970c53bf63a20ef381db8566701972c22fe067cdba99c57b68706a5c6e52f21bb3de861e49ed2141b3036f07d1fd0ee\nRemainder = 9f0e50ca76031b\nA = b2668f5fbcf4170820ed3fc9b12a61862acf8e3cb17175482efe23c5cfd3556e77634d407b6d1f98a73437a8d6066319a7a860afcab2338a1b1313037e30f4d9\nB = 1b1313037e30f4d9\n\nQuotient = babe271ea266bc7bc16d193097903037819f82366c7e9ff8f2cb14157b40433c6ee327038d5dcc44140b070d823befaefbee5e13419f6f17\nRemainder = 93d7c547a9ba0a4a\nA = 74b1a591f449377836f378e05d2902b29964df59c6926e5a9182cc09ce3111783cb7021a185340b4880d56635de268d6f3855c4d9997373b9ff8df899ee3b3f1\nB = 9ff8df899ee3b3f1\n\nQuotient = 890139fef28aa3b77814e1122b9c7f26e746ee3c507e6082b508fcbe380de83b06a01f735239c6847c30eae44749fc8c5e3bd97eb40ba297\nRemainder = 6c97aace900389d0\nA = 7e89adea82b4cb6feb41297b6dc8d948e72c3d5554a987900e7fae48cfb38fb5282b13d9a1f5793cf7cbf1ef551865041c3ffe0e287714a6ec7123556af55a48\nB = ec7123556af55a48\n\nQuotient = 1fdeead441e2d7a6ce3cce2389b2a22248ddca7970ae3f7e7d8453052fd08534ff7c46f6a4537fb6f28df6c5fc8a7d384336e679b74205315\nRemainder = 2903c7cc2651bfa8\nA = 9ca66de3d83f0a747fe986464522bde5e42aeac20e8ace1ea13fa6bc9514c58517479a4281d4128c6d775489b85dfd114ad184613f308f6c4ea484a22ab0ad1e\nB = 4ea484a22ab0ad1e\n\nQuotient = 12f16c8f9f898a08853982e2ac5a906d784c5ab8d74007ba3ab311e861d7c1ac115efe694cab7583f75a4a59ceff2887dab53b2f1022aa452\nRemainder = 4bdaf1f352e87aa5\nA = 6e6a97b358b591b78db43772378dc084a11836ddc9dd4607f263ce620714e8fdf6bf67387c163b6f2999f84270802b4bd5c0f0377e949fbd5d42fe145e66ffeb\nB = 5d42fe145e66ffeb\n\nQuotient = 14e0c06c8cff1f9f5dd8afb6fa6c340f0953a18ba7d2b26b22d8e7f946ef20fd5ac277ceb59cbd4ce3e8213803c3b5b0452ed449e22bf2c29\nRemainder = 55422f1caf4a9a00\nA = bc9c054ff568af73e301e0751bc1ee055e82826cdc53449f2d9f45feda2ba227bedd6df9b74fb58a85917d60b087bef04a156a571716e9bc908ae83784ee35c0\nB = 908ae83784ee35c0\n\nQuotient = a457ea94da3237c0dd15ee30e9c13e7b4ca1dc90fcd67951b873787206babaed837a3eb17e298d74cae92d1059636f9aefe11aef9ffa31053\nRemainder = 124768541b600598\nA = ea6dc82b1906c277526ed867fe8b0fbe32feecfb935dbab860aef59a7d72799fd4e952e70b4c9304c7b2a06af8badcd6cfa12d0b6c9db38d16d2c4a24099ca14\nB = 16d2c4a24099ca14\n\nQuotient = da0a37eece8972a0e2e8817c54e", - "67c4d9f92373340488539d5051984bce0ae3300ef6ca9d0902daa4d485dec3b4db6c8b1ffd2c5d08b18ae\nRemainder = 1ba15c46023500b9\nA = 36ca8763e20e6ebf07a55cdfdd83892bef0bab68ac092093bfdac1a49c1da015541196a24249bb2262e70f7ed53e0fbae61f02ebac4b61f740548136ce50f243\nB = 40548136ce50f243\n\nQuotient = 3d8c433daedfbf681b528f88d610204d33bbe74d0b13978c34a617ae94177e07a757519b5a8f1a93a73d0751c7b5b72b4bdf475a9708fecac\nRemainder = 4cdfd72349c6110\nA = e0dd7e73b2a64dc017da65992176e2535c43b6fc14f2f7b0a7d894d768bbc77507eac0112b2dc3ca83d70989a1b949ccf374be6a012d80a23a74bba39671fcd0\nB = 3a74bba39671fcd0\n\nQuotient = 39d084b444e39c32f2883e9968301151802da15141f65893f37b8b834eb01c074aa1e1a978c5c99732c87ae106bf8db09e1728c8bf2aae88\nRemainder = 2950443357cd7477\nA = 16df31dc290559c3b6a3d192cf15d825cfe79f8dbd5c9848eac7fa90eea5d87f8b430cccf9baab3e8e4dc33467a4234d8551ff25e33af175654686ff1368e96f\nB = 654686ff1368e96f\n\nQuotient = bbead8f70c8e61114f22d36e97861f16037efabe1347613e78c51d7f539065421a66c907faddaed13ad2a0f0b00f8fd594e917799cd937e5\nRemainder = 3013136f5f728b68\nA = ba5e688ab4f8ab5c25592bc4334b6dc2b7a06d491d0f919b716bf1cf109b62a30d9dd59dd4bdf870dd2687894edab303277a5f3e3a537cc8fde3ee3bb61767d6\nB = fde3ee3bb61767d6\n\nQuotient = 42aefe467ff2a5614efef1edce25a1acba9c476b3abbcd680140a3aecf8f51c1ebaab8912de217451bfaca2842c0bae717b8a030b6318c0\nRemainder = 1f130dd2ead0d35e\nA = 17bd50b5322c51ac883852ad2a4446c039dbc210ca3aa0313065fc88cce6819b324e93b036bd0c71be58586cd2b243d01a4a918c10ea0cc5b22f9d795df09de\nB = 5b22f9d795df09de\n\nQuotient = 13de73dcd72a3638fe2a907fd7f6574bbb228698fa60e4ecffb082911c5f09c74bb4f50564d3d4035d07eedea38b634a3e3acc26c8e9aeff8\nRemainder = acb8702f0113e0c4\nA = e0327b2e59236a3f91ccf960490cc69b2afc854de9299ad2edff9618f9fe24251886afc65f5c581a9bc86013f356d599e98b8b10f5236a51b48a6b29025983a4\nB = b48a6b29025983a4\n\nQuotient = 27d11481f00519b786eaee96220afd45bc51700f7366fb5e7da35bbc84891aac3d9d2b709dddae371a6b78439fef810c68eef586e1d68350d\nRemainder = 3d1890c5e1555d74\nA = f3504d5d96c9e27a1527725ced337f1cd0a183531642051e166507432c01e8d44c4e8918701c2a05eb8a9d7e26bf04993f9adeef2826ae4e61c602477f849121\nB = 61c602477f849121\n\nQuotient = 10bdeac209c67b023044186704735c7291423054bcddc24b731ad601b49372f4d5ce6e9d85002f8dddf0411efce943f81a5e42cee2d0c9fe5\nRemainder = a93a0c5bd51004e4\nA = fa29e37b0d0410d19fd180149b14f94ec2edccd347da65f6832850aa06a61b7b78c96faf64dcb347893c93c560b8043466419864a382c6f2ef1412873b2d8cbf\nB = ef1412873b2d8cbf\n\nQuotient = 1c9b6cffe44241292320c0660b89f2f77aaadc8d36e33f5ac3da0f12b3c114a156870a92079f7192d237f8bf49aeee6282531c929cc56d75\nRemainder = 1ce3e5eb13ac7958\nA = 144325a641463ed6bddfcbd73e50620a44c606d71fac38efb1c9d2747b4903f7b51fdedacfb66db022aea09b43c7c2ad7b851035165ebe59b552d4f7eee617b2\nB = b552d4f7eee617b2\n\nQuotient = 1b4ad18dc0e634053beb3cf840b53e35117ea06309ea8ca22e37123fd7e1d391c96c792e5125e322c27daa73301024080d73ba3491484b659\nRemainder = 3286bdce6dc3a828\nA = e3a2b90d3ef446f6bde30d3e726cf3e78212324054b40deb0b18fe00645568fb0a6234b6bded6240977373731bb30d1349e25cefd54b7a9985735e9b78002691\nB = 85735e9b78002691\n\nQuotient = 28f5e8da6733240cc2f18e3cf4d42a50d92816062af33a9e1871fa89bdb39a0d905c49faf51cc1c1378741bea34d25ac2c8e522881a6f6087\nRemainder = 135784870eb40c68\nA = 593206f9367b72f9cc59b3e37d2eb23b2061422859162ee53656899c2471017474f500c6e23efe1f6b1e57852cd4229329dc182ba01a257122d76a26aaf9b844\nB = 22d76a26aaf9b844\n\nQuotient = 1ab276448d16c533b6e90b5b5ca266e13ec27b5a58c80b7657df963ec2d1fe4eb1c1d24873eff6408bcb3d0cf97c31e85240eedf0efcc1e5a\nRemainder = 27b105741264f875\nA = d84fde3d851b52ed3b2a1268e9b765ec6c09c5768bba709b3b799802fadac30a6c3184185e6d57249b1c34619f3c9d2b90bc0c348b22537281a39fcadf738083\nB = 81a39fcadf738083\n\nQuotient = 84a87678485b3e60ee1cae3701ebdf0a29ee44115a492c34a0c8e84090e14070eb2ad0abfe2c339f26b5099327515104fe3d1c5546feea98ed\nRemainder = 95f7434941f9d8\nA = f79a0643bcd9c28cc22cc7b4178b3340e4685dd2672792516d6fc08567d2de2d3e25d43f100a58826edb146ac94acac4213bb09bdf8a258001ddd0ab110b89fe\nB = 1ddd0ab110b89fe\n\nQuotient = 516a2ac26e5b3afa502c7f3c6f15376f7a380e5842c229443343b5b74dc3de84db3ae99a0c57043e32a504ded19943c0310cababb3e92cf8\nRemainder = 327cf78eed336523\nA = 17c0d5814e1020d5d69674bdf6b9df193a16c0c8567a589d014e8eb7f6c9c36560791f7acbbbacee7c456eb51a4cdd7ca88011e9d8d9f2d64ab08ad74f7be5cb\nB = 4ab08ad74f7be5cb\n\nQuotient = f0da0beebcfaa716f494cf3fc81fe65117c90adde3b3942e8e66986fe8050fd5c9ebe1c88c5db04cea4c4c14779555d70cafb53870671f95\nRemainder = 3b2f844440d7be00\nA = ebba8c393c2a22b094d824ed95b4acf6875719fc165f73ee6d359e1134949169fdacbb42d5deb8cea96e11e3aac985635b5bcc6c02a6778cfa8e03d9ce6fc680\nB = fa8e03d9ce6fc680\n\nQuotient = 56527f07593774f0fa642241400985d0bb9b41d3dc9e025ca069130d93afc972d75e3fe0f798e127c3e1b4e925000459a3a5a83b15186e516\nRemainder = b620b7a3b752b78\nA = 5d6cad9e26267abb480b2b9ac5ea323bc4c3c53e0de8ce40c89c85accf0499aea5b11703a04296519047585ff12f8795f98da0546c20016a115100eddabfb468\nB = 115100eddabfb468\n\nQuotient = 294dca3b56ce9529aed2c132a9bd6c0c61de7a58ac50582f396b4fadcf7873b502bb869f801a9ab1f12384631cefee72b3e6050a7f69eba4\nRemainder = 53a0fcf5486c7a6f\nA = 24aa73803f270185d23310df2cf3ef67b18d7800bc41aad2ca13f372a27ef0a9217194f3f512e79f545a903895def195a5eb9a1a1b6b3f4de340e9da9b305d3b\nB = e340e9da9b305d3b\n\nQuotient = 16bf4dab1c29bd284c9b6649de65a4ee58f21d6a8b51627ca133fa817872b1a4a9956662db0aead5898ed0eda08511be7c47449638f2fab95d\nRemainder = e7751deb047d98\nA = 77b04d93272491322ed2fe651044e28cadb2ae7825f02b55aeb0f73b8b8a8b336802416fe08c718ab681581ac04d87116323f61f50bfd2180542fcd4a46dcff6\nB = 542fcd4a46dcff6\n\nQuotient = 388ae1c243bc9111e663c0c80495c36e8767bafe188b532b7ac84b5160d902af1b638aec6e4c66955d16bd8ce94ce6027a7bf95910f705ad0\nRemainder = 7c667ea307017c2\nA = 52f357e9a57722a867d8199242e100f06e8df810ee913d6992bfd9dc03ed78bcf44d692aaa7be806df0c9e0802851d7ae8405f76114e6322177907198f85cb62\nB = 177907198f85cb62\n\nQuotient = 33dc2fcceef7dce92e3a9df58566c6e28d03b58ff6ecbbb31e43936cda6380a56788285d37b5e8f11487afd78c39cb2150cc98d9d78a0c6cb\nRemainder = 429a380c9f8eeeba\nA = d99cf9a0bfc347c9631ae8c69defe1f1509c3ecaeeee5dbc61317bb73fa5cc6e704f64c865cf4d898f8a2f63214dbd511f61aa6e09856222432376698f8d2f67\nB = 432376698f8d2f67\n\nQuotient = 18ecac9e5539a014cffd8310ceb1170577cb23aa9cb3c523d57ad83069d1609ff743cd3c275b67097a038b85afcd7105ad21672f9ecbbc7df\nRemainder = 37924fea665f5c92\nA = f87aa8b6e62b09291e0e9b832ad71d8f85d60501a8d89d2638dccd4022e89bc4932c186a198557282527dfa86dfacc2f90fe0656695b61429f8220509f5106b9\nB = 9f8220509f5106b9\n\nQuotient = 37c0649a53c8cab91a7458702870bf64cb1de9fc1c6b9a3b92444119d368501b62d3a5138af72bdb7752eab8af6bf4e3bdb9e3beb1805b88\nRemainder = de179463e3e91ad\nA = 995c04c1f24c4efe88393bab7a7545e39193662d5db7c8e557d6c554ed4367f5af82c463d0ba6bc3148620481140add5677937989e03fb52c0323980d8841d5\nB = 2c0323980d8841d5\n\nQuotient = a6d193cfe7d8983768ff29908ee6e07fee99927a4bc4ef41d01f63f3b4a2e7029630b7d925d0979458cdaa903771286af672253cd99593b3\nRemainder = 6bf69921db298b3e\nA = 55c856daa8110599cc4fde0a44acbd69a68eb177e0438f7d843ba0fb74caab2a7e0c8a6f176f5555779e65c555e9157a16a1497edf36ccb583a458f0372a57c9\nB = 83a458f0372a57c9\n\nQuotient = 63f379bef9866b59f8bfd6bb0120a75dc03506b0034e7440764afc8ec14d8d735aa6f03a568ea98d0a74ab9bbe9c6e11b288467e5f79a2539\nRemainder = 11c077beb8667d88\nA = ff1fc3ea60fb37ff23e2f2f4e207a86e055cca41eebcc5bd6376904b51fb3d233cb04666fdc92be33239b5ee552870e45717890e35fdbe3728d6ff55d5662419\nB = 28d6ff55d5662419\n\nQuotient = 285ba8cdfbf00b112e496ce65cdba2271c82a273b3d30bed82ef2d360790c5deb97f3311bd5eb9876a61e33b3a37782d00c2d5ffbeec752ca\nRemainder = 1672a8aa119c3a1d\nA = d614352268930d301aa4046cd38e2eda4dcfcc52eac984943f2c863de5c4f8a44473a8ecebf12cb8f4da4722d305e5c9c3eddc0109d416e854df334dbfcfdd4b\nB = 54df334dbfcfdd4b\n\nQuotient = 358178128648fa9ea28dcfe68b4cecc7071e129e3ce4d113f5d1e387f7e5a412e9d2dfe5ff16d9987a544004d213ade9c134cc240eeb6871\nRemainder = 44c3fdb374bc0c30\nA = 18b973dd011969e29a1f4a5b8f118313f715c2e31dfebd9fe0957cf23cf36eded89c38637a8d3512bb23324ff2a3627d5b942300200c823d764b7a6c12d1c91b\nB = 764b7a6c12d1c91b\n\nQuotient = 19ea7212f6604d423b308fe3f2f4986f31aea9d6a117a3e207e38ce5bbd8d7a866285ac60433630de547fc84e364c451457fbf864a82c6613\nRemainder = 2718de2dd0796f08\nA = 83577f755a448d5586e19486b04de7836818223ea920465c4eee979a9ce5", - "696ad8e2fd5253b5d5dcfdf355465e8c0819658ccc5580fd29b351169b54c62b779c\nB = 51169b54c62b779c\n\nQuotient = 13e0c5b9905770b60a6f978d1c983cbc84dccfaed0f4222f534df80c7d3d129f5e8f74f19581332a7f6d383915424c71db4ca19bde2591fcd\nRemainder = abf5f6c8ab6ed4f4\nA = e2bf43c91cdbb244790eb165cc13feafea36f5187cc9bf8aa8cf202042efd5441e3822a1164992da5be750aaac0bb11f09375bdfbd4a39e3b682c7ee6ab5f5f1\nB = b682c7ee6ab5f5f1\n\nQuotient = 3919f31521e87f90df3a4463d0c83fa31e3f569449009d307962d26f07d854e8d3f0badbf55311c206bf34e6227949327a93b1a5ada7a930\nRemainder = 6c3802d44dd4668f\nA = 2546880cc6f97fb379afbc4a2664115ba7909414f35a5bf88be2ed5187bd1a24afaf82eeceb0b438d4999ebf9b7ec752236669425bd3cce6a71d9ad67ff2ff5f\nB = a71d9ad67ff2ff5f\n\nQuotient = 121d5ad4115c2768b962e51d09f426d61624e0f203ac6c923289b4e7964e165b34f3dc1ff938a7cf37478d407de251c64db71d3ee629c1035\nRemainder = 660a35e1c1245910\nA = a36d3250c123697adbbbdf489e6cb40be57febaff654ca951c9fa0b396b1714c55ed6e05e468153ac443dabca29de9b43cc0cc4e62cdf24690593662c86fb5ac\nB = 90593662c86fb5ac\n\nQuotient = ad81debaa02f6e60da58b46e76ce041fc4da64138634ea7b3c165b8fbda027eb64b6b5339e70babbb83430d60383c2cfe22029e617fd03a7\nRemainder = 2e4aeafa2ad76832\nA = 8992cd131757ba5cbe54aa58be115723ea3438ddc782a4d1996980b7b312fa76e4483584df744b10340e5fc9e468690cef538920a732a8f0cafb4e30846cad1d\nB = cafb4e30846cad1d\n\nQuotient = 67a71b9ebaec91121a8cf6bc2932b6be01af7954eca69c5202d771c2c2d13683cdf90ec942a3445771ccfe484f947f078de825ea88b3c05a\nRemainder = 8395953f744cfb31\nA = 4f8ada84096198175174896167405b85cbc03fe0642f6b263a70f9a22f19ad6c9aef38da8ac036d409e6fd925023c95312cebe04eb653e0ec473dc8dfed98967\nB = c473dc8dfed98967\n\nQuotient = 9416326e2347a541b777a0fa1b0c35d8fe76c940d24c6f6806d6ae8ac1e280c16e480786478bda3f780ee92f3f3c361574efc2ed5ca98e26\nRemainder = b8ff45f31bdb58d8\nA = 902f5e48b96b9b1fd16c3b21292ed495987ddac4e1d92b2ab10378f2966c4399d6a41eef622a4991ccd1f647531dcd145de4ac99b3036779f9414ed2f4ba7e08\nB = f9414ed2f4ba7e08\n\nQuotient = 403c651b4e571e8301c4158fc185396554bf61d900708d2af5c2bdf495b3cb539b0b9b5acd0d71654b3aa68024961d5a7bc9e2788e6c822b6\nRemainder = 7856ec047cec8dc\nA = bdd6d846983fbf140173a26d2b709b9f31b4fee1eac9d25fdf0ef3523be0e6afb372acab470cfe1806b36d84017ec99302eb9eb5eb2862222f4916d8b6201d14\nB = 2f4916d8b6201d14\n\nQuotient = 1b6d967173f9777cb6194c8f69289b91da731456fe5a1515a49e4463cd906c84f97381cabdf9f358d97fad5d3cb140e3a3de397e7f9f683157\nRemainder = 83649246ade8bb4\nA = e3da80658acd53ada7c2dc57178e697f2907c5b0c64f4a87a794ca7521105a0568a32874207646df3768ee60964b7d1d2e29ea6bf7fbaa7e084eabd4ea553a72\nB = 84eabd4ea553a72\n\nQuotient = 27b8f1e49e404455cc68217a20766590e749507976a3a6de25a7cf2c32593aaabb04d84deba1ec6bbe048a2959ffd747243c396dc53c9c811\nRemainder = 3daa032278ce53d0\nA = ff3ead7c7b27f607d16f1ef4ffa91b6cc28301b9256cfcb0c22b6818371ce648ae8812dc50a86e4bdc0d0b1e5b0d55c6ba07b240886a6d5766cfb3ed0937a543\nB = 66cfb3ed0937a543\n\nQuotient = bf987f58700508356fb6274f64a9f78d455e4c436fc6fcc980ec0800287ab3789b91c29a8a72b16645ecfeec926b6f8242f3c7dc3adb40cd\nRemainder = c007da44faa80584\nA = 971aa67c9af10f70977f600e10f9278b8e66d2471956da38e5f4b3fedce9a5fc7ff42b800bb4a78314c70bb59394d0880383f5182b6c1960c9e5b47ef8e63be5\nB = c9e5b47ef8e63be5\n\nQuotient = 7332104442474715d7c4cdac15fc1731240f8b4dd0e6ff3284a15a62a8f9a071dedb87f2220efcc5839cb7e6933a8f65d767819db26e134dd\nRemainder = ef65a7789f54174\nA = bcea2ae4b1edfebf905a5820f0481b6c58d76a69df9dbe84764add3f49496a5d7005d645eaee3754e0ed105c13a114e6a0eae5cc4efab6aa1a3d3a0050fa86f5\nB = 1a3d3a0050fa86f5\n\nQuotient = 3f6182804a7ff12fe7ed3c8521b55564559b1a47a78e1fd56597b9470e7e0f6e7e48c58bc8841c9d118718ccd5e0c0bf9a08d8e244ae60da5\nRemainder = 398e30aff5bd284\nA = 2b877181a960c5e29ab1b2672ee22539256a82369e8f6cb5bcfb69e5e4a41f782e89b58fc0ef6ca336469ff929729f8492b44f12199f0e1c0afd12b2c999e787\nB = afd12b2c999e787\n\nQuotient = 1a80a681d2c42edbcbde552323dac3a1c03b43251a99b5549da6cb39ec6947daa0d574f0df68512984fa8e269b0b27a5576b3aaccb76ebc23\nRemainder = 378e44fdc7a5ec4c\nA = d37e62f44de27a1418f348139eac5ab9fcc1ada21ea6d7695273daf638b4d7eee6745f54b99a9678cf742d304736ee356f66d16d874f8cc67fae9be5dfd41a3a\nB = 7fae9be5dfd41a3a\n\nQuotient = ee982a63816d56758c29d284c19b9b984908cf0a9ae3f1f926e162a2cae4f88703aa477c5c14042247635c103494d11593c2c3839baf4d93\nRemainder = 39afe3275c01aae6\nA = 9a0b0476cd33861d2fc3137df292728e1f636f6fcba5105f384533723231a3104e7c77df46f7f34a4bdc63d5c67b418cafcf106b26ad020ea547d34edac1d3a5\nB = a547d34edac1d3a5\n\nQuotient = fb3f4a39a661e5c31228a6b7b4c27e6e52d1954e8ce262b98b61650efffd762cf2a1aec228bec5d5787683cad6b2e6e49a0de91c15c81874\nRemainder = 63e5ed36ff73a42\nA = 4453712f56467328401a69d4d749a0771732734a760a74094e50a62a030cb604e735bfe0bf0641754edff94ac0e0549e8c10941255f0f21f459e52a6cfe4d9ca\nB = 459e52a6cfe4d9ca\n\nQuotient = 7af60a7c0f995178be76c070cf49eee311e6d1e3afaf50c8c93ff200c1b3fe742b23259b4fc0b9ed0947be4fc9a6c212d86de9a0f7dbb5279\nRemainder = 19657d8ce516a138\nA = c9c92a31ad0f3cfb56a294c42a26eaecb77edf33ed40a7e6797927a0c996a7c0a701b484741163df388bb082e3daebf4e1b7a99002632d6f1a41c1d517238557\nB = 1a41c1d517238557\n\nQuotient = c890c55a8e2a3105b9bf9344a57a9b9fab5fa1fd57083d52431b695553bfbe7a44a9b6cd1f83958224f351f8511b14215d1648e88e938573\nRemainder = 1bab5b03c372daee\nA = 88341550e470016c7ab600b9f6cb410071a77f907a58cb6da4ce3e955d1e859534c2c1098fcfd91b9fa66926e51896733c36a824c3a20844add94e27f30ca651\nB = add94e27f30ca651\n\nQuotient = 34c240c42da400317f66f5151630493a2f200ee418d5ca3300cab10dfb429c2acd7280bf066fe19115f86db83d8f5b93cda714533b16abfdc\nRemainder = 18cd326996ccebc1\nA = 7e96d7b90ff09b114dd4393e9bdfb13d8ff517681126c566e18dd6369d87d248734d94bd02a1f19cca90be7642822b636369c51dee441a9d2663ec896e1d6c6d\nB = 2663ec896e1d6c6d\n\nQuotient = 10d18159e75efa8204e325e6be830b4ee8d2c07419e8276edeac6cc286488fc0c888300db3ebb5f935aa82654d3b932540f0093d1880e1d6d\nRemainder = fe9b6b8ba7c30f8\nA = 731aa6e2fb2ad1e1f80d7668c7b0642203af24af382abd207a5ffb588209e8b5caf953e9a96b478f39ec03a397d1433998e3c95e382d93376d80cf0c957788e6\nB = 6d80cf0c957788e6\n\nQuotient = 450d1f4a105ff8d1a3efbb12165ca98c67ae70404472e4862db479e03313b08783ecc42104780c9d57df0ddf19c5b4547ee9ba52ea82dd0c7\nRemainder = 169e15b4d5aa180a\nA = 902bcb1904b80183656dcbd51879e2982e2b46a547c9ae3119ffc12c6a003e4321b519289b7f22fad19d16480182d1d797c3045b2d29dcc12167f9ce5e233d89\nB = 2167f9ce5e233d89\n\nQuotient = a426f71cb3d75365cd076a6c35c10765bbc3f4bd317fb83a70083b0f7dc43a4e0b95508e60dc1dedb780e9b485f4f7a8870960de669b73af2\nRemainder = da381ae5c97a506\nA = bd59dcdefcbaecd9292c4c3685fb87d3a94c0f0ed01e43e63e1f36fb65d6c5eab3b584f3d1f76d31458c9f6b4c69869d96e943c61df102771274c5b4d821469a\nB = 1274c5b4d821469a\n\nQuotient = 26ccd4b7be090af22221729b0ca51a5e66435c2d33f8d88f94405f6c0123ccbbbbc8080cd8448a977946019ccbf5d267ac3f151ebe686720\nRemainder = c41f9e7bf20b376c\nA = 212dbeff03f14b5825f0d7cf8a7501db21b60581a01a26d522ee44e7fe69545cfcaaac64dbc76c7e3027ac39ddc2d80af6f3fca1824c6ff6dae90967d9ab48ec\nB = dae90967d9ab48ec\n\nQuotient = 801df28f4fd987b4e980760f4f2625276a2a7191d453095c82aa98a2253324ad2873abae70cd98c28ef3ce102fdd53469b9f01889f3ba8b0\nRemainder = 8e435da582e59809\nA = 48341b28138dd04807e522e341f74ac46b0449fa45f96d7fc586997c056a21eb3c399752a6a6c023509f042cf9e879f397a34af9aa2ec2e8904674f2ea3ff739\nB = 904674f2ea3ff739\n\nQuotient = d3857b72b70adff9b5dec3cbc63de7c90ccd7aab6595339b2de39bd6b9789045141d224aa4e6bf9a06e017aa3edd00e716a771b3f5b97771\nRemainder = 14135c686d2e9f70\nA = c1cea45dd46409d5e24fb7ed7d849dbb079247af2d312e01083754ed07f65f090e4dd50d23a973488702ef00936c5d78af603ec0fdf03dceea8f939c922b1e7f\nB = ea8f939c922b1e7f\n\nQuotient = abe20c90896e261e7d31bf40e7f3136d36b0b78006d12225a4dbef6aaf2062b609379eefe7e5af5bcec17126286f196f1330da8477096763\nRemainder = 230307c44cd55896\nA = 19a637e4f3051be0f7c4d35513bca4a91ca9b8082fe3c73899b70b6805a7aa0458512495cb6ee1ade55ecd5851be1dba96d65202f06bc7122633a0d905017545\nB = 2633a0d905017545\n\nQuotient = 5ed3765c4a777a903e182f7c9ce39d19c01460f389b904c3ce1d3525edf25ffe7dc0f4d9e24f0bc8b7e01bef19c83e74f17884bd7bfabb2c\nRemainder = 40f5346f8775e20\nA = 546578393e914be30581e24508a33f6560a5805dfb1c675d1ff1d6f5eaa7ee638b9e0265f543413e04e3f1f3b0895dec271c9897a48d9ce9e3d7df32c15b75a0\nB = e3d7df32c15b75a0\n\nQuotient = ed73a67932746985465fb0606fb0e81595514f1647c911c303d4d31eb0306e3b2aece07320f6fe", - "a57a7071d73150591ab2a82a7d53968a81\nRemainder = 2e495a881876da00\nA = 8976445bc318921f7e12c8d4e8e50596849a1503b5efb65e939c291de136597c05a1fd16137f0bbbd7197df943cd612118d1e55a50ee097c94331c1cfb1e941c\nB = 94331c1cfb1e941c\n\nQuotient = 5dce24b7a16d847b0c43cf365ea20bee9679fa0e8732813e827cf6ef3c9bdb7fd8846b5689ce8b80a7dc0dd05721cb06d2700aeeb7ff04d6\nRemainder = d8ead1ae3126aded\nA = 59b99e5d028e6771d27004bc19830a5fcb347f7ae04c0ba7c49130bfb198c5b16821e425c979e6d2dddc14889ae58475bb52c6cdefecf2a8f4dd6e462bbc8f47\nB = f4dd6e462bbc8f47\n\nQuotient = 170e10b399a4c5fe354b536fe59d53602102f215d5107493680ab6e181f67d75ffd45bf49ffb23cf9269b856156b5ac6b1c5def4ab1abb18a\nRemainder = 57131776937c5df9\nA = aeb35966e2a616762768b7f63ce3aee5e81561080617bbabd7846b3ca03fafaaef83dd05b8d16cef40db0a56f3b0ef6eca5e236681cb57c8793dc0907d9aa30f\nB = 793dc0907d9aa30f\n\nQuotient = 1acdb88f047f9bf679c50ed67ba01dd24dca92103f8ea2677215b6142083b64f9fd2a365499dc8f2bc61e29fa176f7d76b55557fa58e34f9\nRemainder = 5065b726dc6b3758\nA = 15a6292c9fb66c6770a8dbc6fd431d2a4b57338581f78d0860fda90182cca563eb2272a79fb4f5a6fc72c90dc23e8a95713b65988b5b3f9bcec4f0466c1c47cb\nB = cec4f0466c1c47cb\n\nQuotient = add8127c0a27c961203ea0351aed5b3c75aa816e9c2684574e55f55c7140adcbf69d2cff843e5f53c157bd60b43c45c8b6658de72062fbba\nRemainder = 67f48d3584cf4fe5\nA = 4e8938c8cc46d34e3369c5d8536b18c963dbde56020678f77cebac5f8777e0afc62ca2ba4f533cf6cf7561bdce77b6f495bc1b05f1416d1173a6a288012c7c73\nB = 73a6a288012c7c73\n\nQuotient = 688ddf883a0bcc1ff9bd582119c2fea7c059e19aded8c048390a1d8fd7d769666987418bbe0d4cf4b67009a342958928769375c1c0d558acf\nRemainder = a5356d04b64ee12\nA = e0c9e32056977aeca72e229d83f0d320fbaf5cd8bf3e033289f46101c75ef59a854982f33bcbcfd200034e8ff439d669a03fa404e7dbfea822664967d67dd5f1\nB = 22664967d67dd5f1\n\nQuotient = 39d4d94587fd1445f31457c275fd6294fcb69ba155e7da3e6cfef38ed1272d6c95755bca49007ca62cc101b038d264876f18594b8fd4c329\nRemainder = a34980d5046e2ed0\nA = 2efcb12fb55c923f5c6ca7ae076765059e15d9e75240a6e5fc3db92de184143fab1934c7450c3a380a9851846c9f43d67bc199a314e82e72cffee795d695f82e\nB = cffee795d695f82e\n\nQuotient = 145ea82eff186b7db4b11fa1514674fb9d41c698efb33227eb1abbc4eb78bdb2a280c0c4c47adaf4e010a4336cbb5650becd1ef544e223e53\nRemainder = 36052bba2867f5f4\nA = f6a6c7e33fd4c664652d696c495df387b85b132cfdfe34bbd35759477b4a3c052f610df57e49e85720489e4bb8dc923696400a4a28dd000cc1bd491446a50b96\nB = c1bd491446a50b96\n\nQuotient = 35d0c9d870348b113868282aaba22b21ec87cf421519a23b288b150604729356f924090ba038d7400c0ccd4932836c65902b4d3c46a202a0\nRemainder = dc8c7d087bf24b0\nA = 22228c8a5966ebdec64007704a373b0596ae702d62e29e468653b21a890ace2f02c27f26b043f48495687ce8c2ca8092ead21aa250ce0f6ca26129615a2432b0\nB = a26129615a2432b0\n\nQuotient = 52fc995a486c4bfd17ed9722948e9ede1c4ac2fe80e6bd7482fc47944c4337a185a506a9ca473d49073e1b813ad742f19b13d57914888d5f\nRemainder = 75c703f654ad630a\nA = 3473041ae301dd2806da30dcf06b9c09600086d6873cf3ee9d5a0be638849afb56bce2664f797de4123f6f8fe3e12acd32e33a285bb7f493a1cc13a7108327f5\nB = a1cc13a7108327f5\n\nQuotient = 1744946730b2789977620f2e7439641125dd338d1b31fc50813b34dea70b83d209330bd17fd527db9a402ad9752c26b8823082ec9971f4ae65\nRemainder = 453a3d59303ec3c\nA = c0f592d83649bcafb7e2de1a8a71fa863c1f51b595bfa638c8fe30731c6fca36da975b6f19c657e3ca29efff6febfb311c003ec68189998c084afe4979b5bb19\nB = 84afe4979b5bb19\n\nQuotient = 468f3eece20aa9d6473f3c559760793e702758a3d9cc19d7817216392c7cc7c3968778cf2fe0c3f0c1424d7512cee19ac0717952f18aa287\nRemainder = 5904e71034e3a02\nA = 1f0c99a128c757d76ae6dfcd01012f0453c8f89b00476ec46321ecb872f99a48b4da29a4abffd0bbff2b727dfa182652ca85350b4ce100fb70a6a40ab6c41d95\nB = 70a6a40ab6c41d95\n\nQuotient = 12198913ef16c1cfc7c1be13f1cc5991a61ff74935e09f0c46d26456b7cf2825403b9851d07d27e0197c1fa2ac5e32e836979a184f14cd94a\nRemainder = 33431c3df719f946\nA = fbfbf5494a9c5384c7ae3df6c02a5e1f9f32dc31cd7f437832696bba164bae1a9d95daefb8bc08e0e8e637436fb747084460697b5ef5ac9ddec06757dbe61aea\nB = dec06757dbe61aea\n\nQuotient = 376c2f902566d83c21eb7c3aa3a6fa0482ed52c253f67f00d5b915d0183c2d9a2891c2ff837fcb426a4c990c48bda4f90e0bf69d13558696\nRemainder = 31540f5e05e8b4df\nA = 2527f8cafaf7e8319ca53104229199188ab1ca5fe592bde8ecf605e17ca6446414e06898a85e177d6985b5cc6d4eeabd6b222b5f44b4fc1baba050665c090b5d\nB = aba050665c090b5d\n\nQuotient = b8fdd5cd7b2d9295258bd99e2780921cb2ea70627a79088039fc3ab1c62bcfc6307e86db4a7803f18e5339f152063f9e41d370e97b1ba2f5\nRemainder = 4ed4f2d12e4f4ba0\nA = a25bd113c5a8c67ef65aa80f1512de43c9441fec0c41250048d29c406fbdae80912eb3970457d621c552e3af7ef2d6bc1b5448e7df5be724e0adf6f71df7eef8\nB = e0adf6f71df7eef8\n\nQuotient = 5421daac8cdeb6acc2b8b0dd85b592f255ee4fedb3a9e90f2a5bedfb0f9f033d7c562c96958346bcdda4664c67848b9d9fa7d3892bc4e9af\nRemainder = 7e5661558c345eea\nA = 490aef65c81b32f5df76dd58decdec3e3f73bc1fcbdb6aee0c93cd98725056153b572509e75d2cc4b042bbeb0a77d27fbca1e39efbc765adde41a7dfc5c3576d\nB = de41a7dfc5c3576d\n\nQuotient = 156a8a24e7804c5f576cd1757dba44cb4185bc13cb56603b54ee3b70fa35cd98db1992904d4f7d99a63b3a486e6fb31141a9d39cc0301f897\nRemainder = 29e9c1627537e5a4\nA = 5e4a10e772de8dd2c96acd714f7d3880ae8ab460095a01038f3aa9b8ac8165889403b42019a1e70e0e7f32e77fb388eae3579dbcb690729c4671868b0526aeca\nB = 4671868b0526aeca\n\nQuotient = 1b0eff2ff0aeb2c02ee3cc9e0bff808f4d616eb290293b13a6b58a84127972bb417d55e1d001a9720ec72562ef3ea688e64c4f32c7e26cc87\nRemainder = 664d57c57d4952e\nA = 806b8504abfbeec4d5923f83ddc071be88e11c4394168854448df96160b95adb1fd9c288852e2f3df3e36916ba5118815ca2e83a6a7d9e074bef9c961e2958e3\nB = 4bef9c961e2958e3\n\nQuotient = 2e363b13b0457a0e9effc2d7e297df78f35e5d24d0f8ad4525b573fb2f66f374871291ee8a8ee3d15a823b560156d474c678f79ee480bbe4\nRemainder = 5ba8f49e0ca36ab4\nA = 2e1bb261d98ec405dbb068daac5efeb0a51f08149181864e9dd6bf6cfcb617b76d8facaee2ef468807e0403bc550d58e8ad9e5cc0f094b02ff6d0277fe642f44\nB = ff6d0277fe642f44\n\nQuotient = 149a5b1a81b9e47ed36be76252055bb202dc25f8fe7beaa1ce59c279b32941cfbaf8fe4555867850b2fba43b10b74534db82398320f9786d25\nRemainder = 1ef621737e81780\nA = 63de892cf5df40c98de78c755c99e94e0e76cd5dc0b49b8856fe69dd0abcdc535bb1416f0d02b4eeb54e8a939cf7ad4edfb7de4dac87523e04d8ea8637e50920\nB = 4d8ea8637e50920\n\nQuotient = dea8a9211974758752d89965eeeb93cc616f88ce757ec2809f829cbb8d99b4ffdc3f0f643779fc5e0bb53b5273a5b15965f4a364863592f\nRemainder = 9ae7de3edb6c7edc\nA = acd5cebd069f7febc38c318867ba3a562bbf8ea9b19a6b33538ba107e49439f8ac6e880c6267c29b39141dbe2273d93062464de307efdb7c6b738c0bb282c3e\nB = c6b738c0bb282c3e\n\nQuotient = e9149b347cdea84d740be70060b239af000c4336ddf36fd5159083b795c4763588c87a959df0104212a04cc928baf60b0ea72e8cccc6d477\nRemainder = 3ef5c6ee67e6f5da\nA = 6ccf1b8b406e6a106160e73ac4122a04c0814ef5a47708a6776eb52002d52772d3fce3fc05398172bba191390aba925bb23aa1eee626410877822f27d1e3cb09\nB = 77822f27d1e3cb09\n\nQuotient = 1606c2fe44cd0b780ee474a9c7daf0b2bebf62db0ba8ef5a99fe22036019890a4c7dff73e678965bb0e2a6e61d00a74a1d33dc1106842115a\nRemainder = 7cf920ba2897f714\nA = ef9a3983f26237576311a871e4a3df0538593dd0cfda58ab90b889fdb35c700f7d158abafad127605057ca0532e846992c41ec06902ce58cae0c1fe238c726cc\nB = ae0c1fe238c726cc\n\nQuotient = 8ccf17de5068451fef1c2808c62e19997c7f920d5cc0fde1f5a247cc57c6d730df553cf33094b786597a343a0ce9e4bffef568247e904343\nRemainder = 2689c40a54df34bc\nA = 8435babd279b7a3833d01988c58005d4557f7689ea9b7168ef42ce2b31a1a3c32a982aff654f271a651085335496dd826ee4b3bc27f58920f05dc6676e51c662\nB = f05dc6676e51c662\n\nQuotient = a9e78c48c779140b1d15843089765ce9ece3855537ce88cad3eb7aa7bd6ec72df65adacba2bdf6c491066406bdc3dd3dd734a70e93eed958\nRemainder = 53da0b15ac079ccd\nA = 78550cb7b58b58d6878b615dfa25a5b90a1ff631740e631c7f8829962446903c686c810c46a1551b6c1f7a89ae898435bb8e36d1bae24a80b54edbf4bbc9af85\nB = b54edbf4bbc9af85\n\nQuotient = 1e3b41304ee07f6baf1ca061e0e28a3740991c6ca2749eba70d3ea1f9cba8adec45cb69a31cbff22784a9e056e884713c0812e8c7981e49328\nRemainder = 3d051148ec43a72\nA = 76b9453d315e7a9c592e1f2640f5b6b90a65e7f2ff8ac24b9b47e35abb76fa5d303be6d501b341a882bdd9d2a1c81a9280724673f87fbe9803ed5a2e7edaeec2\nB = 3ed5a2e7edaeec2\n\nQuotient = 1921410e1a538a71d33d9c5de95593fada116200c399fa7590ebc374282570477f5f4abdd5166784ccee9671a1a23b96378df62168049f6b8\nRemainder = 1a1f4aeb882d7546\nA = e4aa84f782a65d376b10e7789a7d56695885aae274db6cb37e0a34414397a57b4a5f76dced11376af5fd11d31828203e685861a6dea2397891", - "96fe73d0e46116\nB = 9196fe73d0e46116\n\nQuotient = ed2afbd2e63617a651911017d9d02224d521e99275ab642ad1a941827983b17ef0f2067b5405b20e8e97f2ae6099150a1989df94276aadee\nRemainder = 4578107045b9cb81\nA = b547cd987638ff7e3c30fec9b728bc10c3b8cf16e7040bfe0fe9a26e44d2898c4c4d28ef525cde2b4007b2ffb3aa80fc4514a99b9aa2e112c3acc56b72ddbe9b\nB = c3acc56b72ddbe9b\n\nQuotient = 56181509251931afca3bb9dca21eedd6ed4226be67497d8d1bd0ec052af146993e7358f132e842f9b6c4934cf1b4501f5d6c5912e65c8d3ce\nRemainder = 1b9861df51429a6\nA = 32988a4e0769a5aca200f6f6f1498512e13b4904a9a311cd8a962fdd688de0c6e50b04f42cdd2cf8bf9b0a6922657f9ad195773e1250f85509672452618da9c2\nB = 9672452618da9c2\n\nQuotient = 1fa45bb973dd1d2df0002772afba55284a1e41f6aa4b0d1a6c6a4beb8ae00b52e88a9889037b8bfa9b7ee38036c57b713b48af156c3f9e8d8\nRemainder = 2525d52ecdec8814\nA = bda657ddeabe24c82c883e85822941bf64448b7cbb368468078101289b6fca36680b3884e35edc1fce5a5cdbdfc11359a1ba8ac0785c09ba5fe5cdbd30726df4\nB = 5fe5cdbd30726df4\n\nQuotient = 63e21f5568d07976aa81a2690b9e81b76fc3291cdeb010d1693d0e80191186815c7b2f83551a5f1b172640425d4733f06f4df1b2c8a7e6ed7\nRemainder = 14781a368471ecae\nA = 9f3dad0b3b56de15ac46cde1d79aba6a2f3b34d685cc810e9fa3f2d865bea4afb480d58653630319a258e9e8ded9be93cda3bc52b80a9359198221221724cc3b\nB = 198221221724cc3b\n\nQuotient = aae37878db016dd758003b85ef52acc7288b7b74c4723e3876a710baed4751d3be2ae49123b248f2b2c55a5be702c4428b1dba9b8a6ae8a9\nRemainder = 6c754d5c167e1228\nA = 4b93a98eb7b92cea0a4f5c2223e77abdfbd332b39f295b4ac40f71625d88e4add7e482adf3010082d8dd8854cf714a54fba0887de87946e97137cf7eabda038f\nB = 7137cf7eabda038f\n\nQuotient = 9881f551c4b7e67611f37df29e77cbe4e2d9fd5e17b7da3d013d6f3d4312e53dd26dfe3a2a12525cfef1ef81e6ebeeb7ef8fb4f918bf15ee\nRemainder = b14595005716bfe3\nA = 7737f8e7337160c14cfa8411236ca0354d8aeabf389b9fc4b14bb2ec3bb68286f3d82eb394dbd8062862b955e9fc8e86eb646317d1315d09c81ef51b30288cf1\nB = c81ef51b30288cf1\n\nQuotient = 4c8519d4d85ccf845fc5b8f31c27c60f0893ffda29ba86e8a3fd5fe67de5d29cb29362679abde996039b8febda2ecf71f6b9e1c1874361464\nRemainder = 10fae644af084f8a\nA = 900f7846e927760d9986894de6489e53cbbcdd59f7707917e7581422508f2ce79b77bd2c56d964a41e60baa927ca679faedcd9cd8102dde91e1f583ae834b092\nB = 1e1f583ae834b092\n\nQuotient = 16ef17b40bb73063f3cd0929cfe2405ca0ff2d3d426ac05f8a8dfadc85659105f7f728e113baab59247c4c7936ab975c08d6f1c72c12c532\nRemainder = baff11e6961c72e3\nA = 130b212cb6f3d854e4f17524953fd8592f5e59dfe92fc7d955e2899d1dde1ae4aa20d749caa349ca8d1bda7eeec2310532a7af54660e2a1fd4929335a1623bad\nB = d4929335a1623bad\n\nQuotient = 1cdd7ee2eff733b83beda5b862673177e2f2151ee0fd9ac0bf0ec5b7e05516f1d1b59ea754b0483d0e4bfb7668bb99117907a58a8ceb78028\nRemainder = 29e33e0c2a515780\nA = b0131ec2c1ffe9a523591a9453d2fc740bf885e7efc1a0158905da1e646745ef1bbf39b406564cb3da2f842bee307b36219bdee5991c969d6199279c25d4e380\nB = 6199279c25d4e380\n\nQuotient = 20bfcd06f9c54c537ae563e33dab31047aa30a6bc4e7eb0902bfbab3bbb7e65df442c46625c39e08c88310116348e9ebca2450ab463727f90\nRemainder = 11d8f2f6d4c1f55c\nA = cefafbaa2990eaa88184162ecb118d20e5999e5a8fdd25ae7f6248650ea74a8cfb92c58efecdd5d31eceb618f1596d7a6bfd31d092cf86da651f629975faf91c\nB = 651f629975faf91c\n\nQuotient = 37204c5735e4ba5e47e845d8b652cfc2b1dc715abf21ea0ecf5b1c6c8b9e596591fd7a7f41787be1a028c147a721ebb891b0abe3bd079b589\nRemainder = 1ee700ffb0ea02d8\nA = ce22d36b3cb913b32bd0e25cc14c7270d3f7b8e600a9b6732377f846adafd7fbd8a09d12fb7011f2283d988fc29aa25948dd4a0f24512b4a3bd460ee19887d35\nB = 3bd460ee19887d35\n\nQuotient = 191051194e4362bb201f5471d4bfaf92f79b6fbd119ca3dc1afffba334869ed9f8acd14fc42a2d8f616d652610a483ad90f5140e9a5ca4172\nRemainder = 74785b6874d8fa37\nA = f3c79f9a6af1c5bec72218d969620149afe8bf068cf7a7aceda977076665bb5a2c30729ac3aa976c9be379c6a5458f1501db8802652ef69d9b9f4f097027ddd9\nB = 9b9f4f097027ddd9\n\nQuotient = 6c46c17fdb03d192f75d636e1e2ab4e858d55f0f205cffd75550c4347726b5cfe036c6c901782cbe5a04f1985d9fd1dd39d747d25a6a7a88\nRemainder = 9a836be71a24e72e\nA = 4f6cf6e357b4985442a25b5c84e2cc0a5e685e2f5ff71ceba439b81f4123e16db2296dd4333fff23eea92bdbb812daf1d27c721412fa9847bbc9a0bf08879b1e\nB = bbc9a0bf08879b1e\n\nQuotient = -4984390f93e11c9a77880cfbe157dc41d43fe901c8895ac5091c5367a77370b16d42e8cc260058adf4d3fc8ee8cc6c0099804f4c319f15561b0a2b1caa7d703db82a726c9eab569c\nRemainder = -19374dcf21822188d720d6ec892bda2c084e8af84f38012da7029a3c3660c7e813fd4f7644ca80373575ff98ab6d743e939269c51bf62e04f\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 330af318ce0ffdaa92448777ed117de9c104e0f975651322c8e01b1c470f3cfb7a78b11f7daeea57614cec37d18b89155f19babeda0016171\n\nQuotient = 1a56f7d6c06a316a9a466319cbd558a99f06843782673a54775d859768a61933de3fc410068d00d5f6ab13fafc9228fd40ad41434501f8827bd7461441140eb6977f18d102d446\nRemainder = -3c3d566cd48a909292be2ce30f88ebb68e9122a3359f52d1d7b0189c467b829a9f226c0b64845715020dee12d179913ddb7f17da2db86d854bd\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -8e770450768d07ce20ff8f5f6af464b1ee5f1d0e8faaf927a19d3ff801f6089378133e822b8e63cf29c4c9ed721adfc91d3355a3c7bbde77bdd\n\nQuotient = 42131cf8f52a6a3f189697ce402a8c9439bf05cb3dc1cf8bc49dc2f07cef15b3bf0102c941b5b3bde6440abc6eacfbf77ea8da06ce932fffb226b33dedf001e9657464b0f06\nRemainder = 4cd483574fce075404dd22072abe61200fc455c15b382c7f2962ffd82c38ec1e2c60f71267cbc35fcf77fe1f9301d6b5f884f1c416304aa9f4d4b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 38caa64e74b29a7e9bbf341edbab112a730b17103831a9ecb70ef077e9660b2dd1fbf71d7f6bb4cdae2ed7cdbe9070ec9fde996c91b9bca5b83450\n\nQuotient = -11d6883fcd705ac97cae5bb7f8a2929d6f636f4f232ae9a4af9769183dfce9a9296fa0714c3f4fa1eea467a5c96a484a59d0cdd87496b9398e7a818daf89a58add3a39e80\nRemainder = a6b7984fd80d719ffe2e6eb756e4e3bd7ab51f6088e04ac8fecdc744b0385294dd23b5007910109abf40cfca814c10addcb5330e422b6f5eab6efa2b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -d25d50f53c694cddd56aadda2654ae5888603b39cdbace93d19c117af5505750aa24e615f95446862bd693f5b444e2a876eb2cf49f6c7acd007eae02\n\nQuotient = -3fa898b02c621915f44b213ba4e80b8e85c7a2f4c78df2bda7d99494bbca3eb2d9354965d83e1c9001f10aad9b3f3ed837a630b329f5a4b28935158fbd9d291a120b08\nRemainder = -320d41a3875da2e83ea9a83947f5abb1a7026c84020e983381722bf7aa87d5987ab088cb2c37fc3781c82c81bef3263fec560023e236a747030618e9d2b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3af2721aad4b18db27842b5e539d8cada9dcd7ac4c5b885065dd2496a6f76fa73c8a51b239b5c068ea6feffda22d8ea806fb488ad5a94210264597edb40\n\nQuotient = 179307c3e14de14a744d082825ed723b996a4e15f156ac473960583138c43f4275b4436c50ef8f21a7b450a969819b81c15bc355fbc5fb55cdd8e124d931d142851a\nRemainder = -9c8eabd36a25e995c1811b79a2a0357f6aeef4477cac0ffdd130046cb2a647f928a34d91d9b489d394965719cd58604b957c693a93145328e5568d33d88a9\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -9f2d3da1da77914df66bc889a40847a0d705d4648a11f282e09173d170e96d84b5a45092d995318fe7a954b54b88b784423402519a38bb521e84a4f6c5485\n\nQuotient = 6c0f316406afb4cc2aebe34f7948422de0b612a02dc47f4ae59419c579fc465ceae1980a3e524fdfdbdfad4862f168a9851664688c9ba01a8", - "bc1ac156a6276643\nRemainder = bf52a2fb6493eac22fc8b334ccd8e8fa347620539d9189d535373f94503310a027c5423197c7279bb51ab8c459e27f548d57b55740320e80b753290d077aa7f\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 22b9e55639ad3ff4f071a49c8bba6bd9047e162fb31882421db8ec5ce46f28fbc35040bbc74ead5a948c47c43e9c7adc32fa52046b53f12b07b5224e0d8e93e4\n\nQuotient = -1008fcb6894d8c411905136fb3e05b38ec5d8df35db06379fc2d6d3e3579bcb34fa6e021b98b899d9d082c111b1a6ac8e50418fcd5968ade6aff8828d8e4777\nRemainder = 3d7dca387b00c677d855fc4af4d86d86331fe4309929039e828765f0937990bffa964d3ffc5d4f2f4b8bea978329e7cedb847c7cc341ee52217f903ddcf9446ce4\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -ea045323f406bd7ce25b3ab4993b5f6dd92ca80e3a02607a862deb13470ccef229fad67ae958cd87fecf4f08d9609595077d0d1360d9fe48c4566e237aa877e7b1\n\nQuotient = -42a50301031962754ebf9c4b1e125e6df3dd40ffbe09c044b1cf4b62ffb4f92d298b05933a450bcef65e86398da80740a610ba45928000a5c12d26e9f6a4\nRemainder = -c5485b82cfefb3f980e0fc7c6cd89b1345a8fb942299bdc36ed4ff8916016315a0da84ca0ee2824dce3c7e5ed49d517c45173c9c8e30b224940af6cf828c73db8db7\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 384e523d5a687bd1a90101e43334894b6a27e8c6809a8bf5bffabc34d558a8309997dd6f2a3b7c1a63100dcc0b6647b444ef7e5aa4a9c52c7caba1ebd096c3fae6f95\n\nQuotient = 1054439945ccb5bc5461fed04e364c7a36d5dd2c0428872676debe07654b2ce31e435a90c81f2bac1032143acb0c49ad101398feee8426bf270bdc0229\nRemainder = -7bf919e14b2559ab82b3c1bf428d083a4c851a7a1fea44718377e9e945caa5cf48e0b1ad727e251bbb330292402a75ecd96a56db4ad07146533a3ab5a717d0a25a3a7c9\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -e5cd83a644ec86b94f5e33d4dc307a2f14ee8653288145dabb2b5f894560c164470197fb9e37749656f47df343c245258627aeea17965fea10a57336bdc6b4a47443492\n\nQuotient = 62675274798218da426a54ed7158f8f737b7b3c328a9c351371f0cf61f41712f9b28741f187eb635ce45866762fb5fc5051776151d202e2556c5845\nRemainder = 1aeb5d1fde3c259917e430e6790b00484d0d9508391ba6ebab0f6299190d4b34f5f7d8ea2174974471a1e28ee2c15e05da645db971f699d5d0e80569b7eba7908ae579f5ed\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2622350611b486e6be7a7c1c073c230d604d782c2696038a3233ebcc3f01c6a711969094e47f49e294f2c5bcd04fb1b7c0934f19bf6e7aa519a8d4ec2c172ac59cc1a57b26\n\nQuotient = -12970cdd96b92c37787971cd8dd166999ff241be881eb9543ff29165a9c1a3beeb38b1910a5724ffe2b73ab95ac1ca88d3989aa531374d4ec6122\nRemainder = 627455cb555398150e5b4c1c53ee16dac8d80d9616ed1ef40031424287f8028a9cad1a10bdd8430f6f65368cfd00390c8d4355aa5ecdbd1ff0266a1ade235f33cb5309446961\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c9dac93cfb7abaa3fcde359e09a92ab0b5c06359bc09ae9bade3c6783064dba90b233b4c8d5c6236a13ef96c7a223e37bbdd931eae61e845e5a10088f75b3ff5f1158e833b15\n\nQuotient = -6742b3871dece5986d4e219bf5f43c101da8896f247521fa286fde696e0b71ffeb3b6a3e4f33710c9ab150b7a1f747cee76839c5e7f2509f62\nRemainder = -203b2d6eec9d485f7b439fe9d4c640bb31170af38418faf4daad577c30e44ca06efda55ceea4fbd959b3809fa2002b6e2cb891decb09334ed89ac66ff05502036b2155ff62f8aeb\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2457088096865cd052e9cd9349c6e5e34e46c89d6e860a36f8e2a0bb1e5d983e07d05e6f6b31edc67e4793cb4d40979c029c80a13e654b66c8acf6b894f615a3ac800bbd09ce020\n\nQuotient = 15eafc416460d757d0abbda8d094eb535262a71dd033c25e704a6df54265b6123247e5625da476e0c220ba88582a1ed94265135bf8bf1fb1\nRemainder = -64ccd9a0ae0b0abcb5507d51b2e6c8e52e67907474605c439796febda06eabd8a3185fdfc0bd088cc49fdf564b5b45890b07269c15b1aa2f993cd9872b97aa6cc37dea2f03444b3ed\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -ab34d3906d8a2b806b22c73d44948d703c1e05a9337f75cb0b5df5205c5e2d23f8a92d8381372f9398c9ac2f7b9302b83e48b26512ccd0b06e6b8ef1b930ec2678d71e2eddbf7349e\n\nQuotient = 3b22916d9fe3145fcc3b8872bebf5aee4e14235f618e0aed09199852c6bed80df39256d8407d334c06f4479f230913370b7d451fad99d\nRemainder = 1b02a7b97f9ac1f6306aa00fff0e59f55fce463ffdc640364a950df29474e08b67cdfcec0628e973d42fa1e4f98e988ec4c47e4915651a1731b71d5e36a10a0d1b3420427dbb79ba7d52\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3f74cafe9ab0c1b307cd7571fd442665fa3205fb2f45b3811b92d1d38b096a2025b8170663a29c52ca84da102e62048e583fba96a594c0b23952fec587814857c25221ff2cd0533cba6d\n\nQuotient = -12ffa4b6fc369404968911c17358012b993c18c2ff34122e06f450d3d441926b5f5638b40efb012d76d8bcd3c0012d0a0ce5d55c596\nRemainder = 64548684fd5f6c816bd296234740a4eed772570bd4a48852462f9cddf14f1350ce7c7c6a58aee8f66ad7df87927458db09e3af08eb5376de08444f35e5171cfa0992fb27f70b81574f6e8f\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c58383afca9e1c480ee75d3cb6b0b99ea42e827d39fc96bab6b0dddc97e3eaaaec02a74847f9f7d49937f5ade3580bfcd491990737d172d4079437067251ab403c36a9826e974b113e2d2a\n\nQuotient = -4964410c2b038573107b0151b36177cdd62495e0dbef536b59c8aacb8836bb45e7bb014e5022360621e8e82a273d0d462b8eb6fc\nRemainder = -1250c42f8c9b129a5c477be446b86356edd1b19409d362c3a5fb5d59c30f1c3fdc1424a88a0d6ce20bae885905d98c8a5a6495931f73edf4c60112ed78834e3bff6de3ed54c867fbf16a1cd53\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 33212ef4a8e80daf1049ac6f639f8e1990142ac32f7ebc97675ec90f8eb1a2814dfdd295ae67317253d0187ad33f3932a3a7efb056d0a3c87d28e64e23e9f1de751ee6f0f61c6f39d08d72f0a\n\nQuotient = 17f77efddeed52ef2e423bc2c10d2ae15c97384b766f4108474964c2a44789e61249103d9f5fe00b4d612772dc6ea12a42e395\nRemainder = -1ec95323b7b95169d5ec0667f3cbf683e98c15dd0fe44df4ed9de9586e43f1f69337e41a6d11d889452665dc0b03cf8d9ef2effe0b350eeb9f6468751b8a2c42608ba2a33192b770cb62381a966\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -9c91fdf2dd1827ed103a102db254630c278bf8b47bb12a342a92f081acbdd8ae5f5476ae194e24b187011ac25b19fd09e6e690777f9d3efb6b3a32c8f5905e1478a27fe4b1adf17a70abb4e7571\n\nQuotient", - " = 4f5dec525ffc737094f40d27446ca0be5b7a2aff02d51d99609165c4cea0dbbc1d92bc0a8680782b616c149bbef7f5ca912\nRemainder = 1bc84ce56a9a0c74962681c02ac927051c81f3824d9f3f0f91465df333ecdb449473d9c26ae3abb9509add5795e89ba5eba6ec7c89b114c86e6991ca0c185b34d6e66925a14fd82809dbc4936d273\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2f47be01e6dc6a86097676fbd472c2af0c83a2f743fcaa885e44fda7e9f350e9fb7a8cd07fda59ccb7963f1e95e6a1236f5f94939decdc85afc0e523c711b24641c844cd3113c17fe35ca988ba407c\n\nQuotient = -163cafed5bcfdeda88555f30bd4cc2da2cefe2bcec9a7c19c36ccd04a45121a5a0dc28d0bf6ab7fa4b78933c47a5d5286\nRemainder = 93f856077f5b2907cefcddc4d767ffeb0acb7af64bb9dd8a15dcfdda6c244c24fb8404ff9ea2fe1dc337faa05930d33cac4f61e171d0236e222374cb3da76396ae1329a407fb4ac652fcbdc568d0fafb\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -a8bfcac452a5e48fee9132b73bc2fef771450143ab80aabd8690ce54c9b52c2b5a669076a7a35fa6d926268077bec6d90b722b5d074f28ce3843fb0147e567c45f4e91a11416c082762e71b5c6129c08\n\nQuotient = -617dbaeb8c6f9d584e8eae923c872048f9f9bf039ec6b50cf8f09c061bf79acc3311b37c2502e560848c05ab316fe8\nRemainder = -1ab4613767c4f1f7d127e848f2bb7c72a3a9e1dd6173b63198b80d3bbebce6a31494f19b53ad9e3a77248e6f9b26fc59060e2759a20dcdbe785297bbd912da9a1819527fac550d64bfd20ed1f96450c30f3\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 267d9397138fd0374a7a58593d41627ba1203a646ec2c04997acf607e9d217b8f40183d2f9304447d6f7e727a476e636ded4697a5ff30a9ae3d249baf97969658209c1b32ddc0edf920b0b278e9b5464313\n\nQuotient = 10ad85703fd51870306c5e36b51512341d6d39e0bac47a03732787b2f62e49c76666f7f49b2596de6cb5c5b2f31b\nRemainder = -846b4479713bb19ebb8c1f1b75d2be0f39fc1095a3d2ca149b5565146bc19382b86e5ab0d098ab1fca1ce701d582400190fee34b602845c3c0c498925710f0b9e3af2412ed5ead1fe03d77e9b2b407ac83823\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -e0ffa4e120f2f46fd1430b6022fd03f71a22f9b120f8d40e901279be235b32d94760fb8c2403d23cdeb728ae73e2b16af7322d6ebd5f5673187668c99805e700f1e997423886bbcb851448dc1ed4cd66d6598\n\nQuotient = 41567bbf616ab41da51108d7edcb5a8a4877c5a8663b3aed7559421b1fcf4b535a54989efedfcc935b3917fcd\nRemainder = fc026e554a0821e0d36b796fe6a676fcd7383a55fd6158d78ace4edfc3d8aa87c65f0eb41baa2aafadc51218b0562ff4b5c9b17bbe84afc491d9e309217a5138ad48dd51e1b1a9aa51d69963b608ec47d63fcd3\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 396e9b45ce43d3f89386cfad8ddef4b483ecb5173234530c67447ab74629d246c18b9da09522c77f598957e3fd2a1c0c9417399912fd547fb1023ba6b90d63d223bcbf3e7ba155e51bba7e8635aa5c39d2b9dbb8\n\nQuotient = -18f1f395347ce8df530d9330c61c0e30ac9531b50a0af2ae7809db1258285c15ba7a436121287990fcdbda2\nRemainder = 51417b9e9995de34316a66a2f70c146df8e36952fe64124819607bd8691a465f4fde98e590dcd56f0faeb95d1b67751081c2393626713c27ec2a2123aec2a4ec3761e5ace4aaeb612d46e52e16d72a186d2ec8a7ff\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -966dfc779cbf9c388a84e947d1128e2392399ff45d9491259c7cb19589154f82f41e852e0c6bb5a728f6e87ff4ff95abcb9b2b57af1b6b7fc125497775ecc1338e4bbcb5315f7afde4e283347184b908545211afb6\n\nQuotient = -3fd962e88dc1d501fe9335fff8b6b2d50eea967c3035a3dcbcdc9599b81f9a445ed5a6ae7413b8865fd4\nRemainder = -97f06f6155f8d0ee6850728192e0b4fcf55fbd9ba982c5f1d598ddcbc4e1c4be0e209fefa6ab3b7eb2b4c645e4dc40217202285ab0a7270d085dd9d4fd24e5293faf6797b4c3c79bbf3ec63fd82942549f9e8f862297\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3ac566d6b2d18572360fbdc626ec488aa316a74f33d71a17a2d0e1d2bf26395623eb91dc4abebf2f944e9bc3d669fae2e4332088e9ff9d9f43927a7888b1390ef60f05efd6e63ec606ecb3e164ed6dbdc9d088586aa71\n\nQuotient = fb5ce21bcf28490afb64e6746a1a81792c90eae17407c0b4c5ebf2464eeea43e516be2c615f84901d\nRemainder = -3d255bf94c3d610c32266fd472d070c0f5e7dddb88d32723b2e1a20709aed2faf28701e0d0227c2b33ecfa9e708e5ac354a97be732b786210d86f1f05d191513386c580b1ad1f4ac6890f87fd0d4270f23cc5c2064502c6\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -eedb64a6e204ee3d6df508830704f1d5b2d2e627698d38a114c07458ea0befd593a80dfd2e08fcb1893adf57061ec4fbcd3130692de7c46f5ca51361e9b79bb7a91963618b8e5b7591392a5f0e3be954e8b9978c97f12e9\n\nQuotient = 6933a3123d0b32693351a834751345300c49324b861a663e8700bdb3b70ad996747b284a8ea5c02\nRemainder = 13849ef93cbc77460c3c496e8f31f7e01a98c21cdfcd6877547161f9601680665b394933d3a0824f0d32854508c89f0e4a0873280c779c7ca636cd89cf6ee5d42a917b4f382be3b9654039f623c11b43164827f870fa0f0781\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 23ab6042240a7709d43de7ee17332a9710bd0d913c42b3591341527bf48d5bc30abb962482292d45a15cb03c9457cc8d78d1e00aaa63358427b000e59e4260bfe1e2cc603e175d7fcf02bd9f61fae3740cb8e10a510ea3d1d5\n\nQuotient = -10e67cbb33dc6e24765893a047252766c2bfad8385150689dd4fec9ef495dff63ede1fdf78bb6\nRemainder = 9dabe2cbc734b910fa1bd25616daee5657d25b6e4dbc2cd93cf8549715c87974a8336fc5070d86c11f6b670d4b3bd5ee8ae3af2bb321fbb4f8fade3f5c6c2d6c366b4d800dd13ce897f13b0d3fb79f1d9ca525b4e7286c56ff29\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -de093dba98747499f2876c8b6b7a6b9587284835ae35f0716dd594c826cdf5b9179f2c6b08d800a77a6936602ff2b64ee0b7c94493bd5009633f5bbe423454b7f018ae96c21230510ab4bf5db394ff153b0e9eda3ef90eb4c253\n\nQuotient = -521f5e35300b9ec2742ff472cf61235dfe2e449772afa638b1adb812cccf269afd164b7602\nRemainder = -2ad10e8758e1d358d4744ad344ce319617027107c0b8db195d1b58c6e6035450c9b377f026fdf9e5737750af5615cff2ac3ccee623c060d779373136d48a735b353d64bcc5f2e6ea1e46083fd799b5f57dd5ad0ff3e6df9764af977\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2db1990ba1e353a1a62de1b914ccb691380b6ea937c13621a29f0a40ecef460cea52cfbc77d98706fb3c9939ceaaf962fb8003b0cfb40535e0dee22e8e7d04b5648fce2e58803242c199421cc4b26cae776d3603f2ce410ddd1e0da\n\nQuotient = 1d45aa6fe6837a1b7ac95efd55d1690b66487202949a286fc85da7ac0b50b860215e44fb\nRemainder = -7984639b596f1d4e6efea9d8b4719215588620ac959034b303584679a44fa84a4be0c89fd2e29f54e62959f9b7a858c06b0cc051176af82d4b85e7334555ba11c39e6cfa1829995c383ba81dbc220e527e90a1d440c1d0", - "69703cc1370\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -80316fdc405bb002990d3ef7d0e98defcd1f0e370d1e51db2d21ecbd96230baf69d00b168afcb7b8da9edc3ef7f6621ae5c5a0d7797e5c92283342e42468dba1036fcb2ffef1f493ff97826477364f6b5a41dc56d6389a01b83eee041\n\nQuotient = 3c0c3f7a777e611d1bd0d17d669a1ef7920b72ea8de06d4b415a73b836e37d6cf0780\nRemainder = d8c77134a75584ecd5ab29e97a909ec139464901f9cfcb1d3d9e29a63d204615b6845d466c8710873980f107c40ab54eca9f8933ef6d726f9bd0f3e9e97eade5eb1a9bcaa7b01b6ad51ff3ecf67d6e4d345f128e990494a2db434fcd3ab\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3e7dd961be36c0c286eb9e78bf3b33e6f9bdf2c2137a0c660f1d21dea31ac9a044e526bf47ec8190e137a60f1f55e947046b9cd04a2485679e48cac80a1bb064a915208889289d63a6e338cf7069ad799861c31ec6eafe02a4ef2c2641c9\n\nQuotient = -178d749de2dae3a2ea4898c59aaba98ad9f340762040f5aea13cad45a793f1256ef\nRemainder = 6c5d9b19aed9f099255b6e3d251aa50d1e534e6c86d82eebe097dc8dd0748201e48ac62eec070a999c21f5c7684e5a700212e9079b5fb731321dd1e16ca82ce80c1f5c17fd1720f1353bb90997f47f5fce335a43a6f59facff0b3724423393\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -9f52ead13916f9807d0cf0c6699578af52c54816828f22de62328fbd7b4fd6c3740ffc82af4e24892092c7ecac44b5e775944445e6615fce25610984030a345731f944128f5734e6e315a0ea97aafd7563105695d026880d065761687b75e8\n\nQuotient = -4fe43bfa9417839ee408b254603c3dd176653b6915a89de5b781b400162fbed6\nRemainder = -1c15816e03751a203ae23c48965c8541849b09996bc81d28e28d7871fa87d1c3b2d383c056d3084d7d01d853bebe270fe2c0839e71851e169d417c47caacab2aff8a8e05f65dfb20eb17ed8f67475702fa83087bd868246cbb885d52639797b85\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2ef8419306ebfd215d9079c7a2b959a53ca2f4553845e3cd32caab2635c0e77fee8c5c016c121e3cbedfac57f810c132486ba78df9e719a976e0112516893f14cf9b89f95a89aaabf31cce509ac8e7e62ec3833f0be4336afe6d7d73518141d39\n\nQuotient = 127e8c06e12943017f9dd57ca24dca0ead230092811d307386c81b6efe009c\nRemainder = -24f3431858d5aee412443feab243b465b849f5dc97e4de4db88c7adf774d9bdda65fa0a28cf6b18eac6078b00cbeed2ac406f8426aef868d4b59ab045825d4b0a18af6c9105e32abc72fadef55b221278d329ff6fb9019630411bec143c4156df7f\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -cae6399216401dec0f8ff5eaca884ab061469082ee3a18e49e0b4d5f9cfc98a598c373249a8ad2374e0b3de71370e93a98650684fbb931aa5d8b4482cb0be142492bb71743c251346df66896806f926a4a5dd4c16ca3294f01bb998835e6583d29d\n\nQuotient = 3f180694e59df85f48ac02b6d4faa26278af9641db18d79f198da5d802f\nRemainder = 36cf82dcf8c7ec783b4de68e0627a4a4b2a508637c176de09feef62dcf382bfa5d8b88539b5ca2cab6cbbdbbd0e54c092f00ee13f4a352cb570034cb0a012cc0fbdb6ed32967f3b81d146f352139bd3d9a5c27789468b7d79b84d6a8f6085f859532f7\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3b7983bfaf565c5ca444367654a07b8bc2bf7fdc04ef12128c392bef2f6b67d9475b4d2f0ce1c380913aa98616fbe1d74dc5c9d64df15f5c9b87a8bfbcadf335a6e8f863c7a01ac175a7d79645ababa5f961fad7d1b9926f7284e254fed33765339e0c\n\nQuotient = -11f635baf7b7d613e84dc38978a21ade2f4cd741d0c4f6ae592d93af9\nRemainder = 4317c686dfd56216bc4865f8dcb6a3446e13d8b33861e74d6c4a3223c387ffb8caeea0141049898609ed1abfc2adbd21756cf64a72272aab6c0b8f2177419abcbf9086635dfbea80a7b884181f2f2ec9a402cb0505e8208909fe062d5e6dc7094d66af62\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -d0ea50558197566f22704e66a70328cacd6f4b7ca9b00c16b7c4b4e7dcbd47c9b2526b3858ebb4de7a571ac570872f3b44ba1fec655c0778a8a87ca24851f6072c5c0b7591b5e67a8cdaca78fa46f201e02379fcb9a8470e4a4971acde36cf501d369751\n\nQuotient = -64a078497f85588d3402355bf3e83d25ca1f0ed2c24a395ef6de6b\nRemainder = -87fc31ac66a24ebd629a26209ccac1b2c85e52dc83c5240269ae5a27333f33d31152c9470efd41472af034e8536bbe94b0a49e892b1d23db3c13fd84b7395d7e3f19d7d4cb4a4c07dd1860826696cf7202483446452aed2b4980388e7eda0ccac792d77a33\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 254a85bf512d9159b00a70678239902ee7e15ac2790ce5747c4a4743c6a0851e6a179b64c75acf312dd37a7b82a729246f79196b8a399ff476c48a05f89c29fb106bb06ef0300c4b330a7b2bcd4ea1e82584c7a96b99ec2131c885c5851343cfa6ae4d384e8\n\nQuotient = 116a06b1d38067cef9f55875fee1254c8ce39b42c19fb232a287\nRemainder = -c15a797fed3810e4f536e9509564b2142ffbfc0c961ee5aa923d43a824765c05d2a99fef79bfcb6310c77a91d9bc6d0762bd687493865de270c99989e891fbf6da7ea5c7c7a1032449457eb73222a011bb755ff44e4bdce8e86f8aa9f687840c0832f7fd8ce48\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -d77c14100d19fbaff6334ca6aa504001a1d56f274632dc89d48e1d517935503c26b60c047cab9e186a55b72439761c884f63fdd2a38ca1acc653f6ccbb4b7262e6215e6d00c8829b448b7ac8716fe0bfdbf8088c8c61eee8f8db43b7b5551f6278081ac2eb1c5\n\nQuotient = 6fc9533f6d0e6c55494cb1b319ec47bde8e621aa92d91155e\nRemainder = a1a70f674cb141a896c4adace0dc58cdcbe2503fd0ad36ce348dc5b8afc96d0f2f8c65bbbadabf2920012798b7ccaedbe8d896dd2674082ad3cc75b54c5c190ad56ff34e8cb5dd29c031656497d48571295d6da396d5f4cdb652732d874a79a674d06a1d7b979f5\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 21917f48bb8e65646c618068fd9069c06e22ce8c679a845f9c4ec843849010abeee12e2d3c61fb963297abca30813c446f2ae82e909ca6ac7839fb58974fa65f3b5d91fb8b3f99d948519ed56653d50026d694060208cf48e3c757f64885b4ed4328c6f071e9f5d5\n\nQuotient = -1abc689fd19523d2e295f260d248041bd00ad3009cc7581\nRemainder = 1ab5af1478fe7373d012befb319b53ff9e36899c1749ea763fb74f7d24624e70ee78faf3115c2a423629528f45295e4adec7b122b993b5c29260558be4831df06468bb1c63e8afcfb1b9b533ec6acf754563d2ae25e2adb4cfe5ee3024611e03a156484a130ee01f3c\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -8c5a7b6bc8ed6ac015ec24efff607b0446c1b736dc8b409e2f433e69d0ca015d70c64b4c924175d0e0102ebc3e1dd96dd4d5bb01cccad229e699f9d8f9ad0e04339d70cd113e93d50c10c03083a81264396f5db2d979d272798ed30efa15d52289d0c72f42582ea56f\n\nQuotient = -4aa210fbc0457fa7366a8aa9a3acb3f9fce812303ec9\nRemainder = -737bc4fdd3d5496fc7f936ccf14bfc3d93f5b7caf4718c444db7a3228b41015c67aed304fec7704ea8238ba6cccb1e94cac3bcf4764a44bafb49e5fcb0339ae44c0114cc304b9c4370363657cd2bec09b", - "f962ccb21f6091b081e71d2bff8556600576e18d4f78fc68b12\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 324774e49bb429553c10156e8db122670d6dcaf6ef5291f515c517d7ffaee36ec5ec5ccb4d12dff71ae7a05bdfbb03ebaf4dc6c4e8bfdc165b77cae20153c27d53bf27d92ff25643b4888cb586e773955a1c02ecbf0fa6958a8ec0b832332eab2e449be6e72c48d2f1ad1\n\nQuotient = 1c8631a18d189f1fb689f896005f2dd2098e0dae9e\nRemainder = -1a1ac9612fc3354056a5378de5b315f12591ee71f0fa9d8a6b2ea2b1c4eca9947e5c4f5ed3d4b78e69ef7a1f5a9894b9c7d85f6e2244ae76881eb06584eaa98c78b60b46084b517f4882758691f91d9e2acfd580d5e901dae14ff4a4fd6b0d7c73450e4928fc6f02fb5463\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -838df2a27bbb033fa0e581073b879d6e8747fff38539801a1870f2e52d91bc84cf10f2560e93784650fba080304244dbfe9da679f207b6920be46b0214a1e490537e56d99beef3f58b30f311a12283501ad79a5407ff209d19a6efd0421aa144e0cd427380d89bfae5d1f5c\n\nQuotient = 4213d04b9f0b30026bd355404bee887b22b2cf9\nRemainder = c2bc097d1c20f050e88912f066b658446cacc7a4d510343a8d88ed007a8c0cfd5d44fe5f067a0e81536d121b39f2d0feb8dd053bb5632e3f9c04be5f6bf4091d646860cd38c96271cdba466ef8b7e2377a51d5669117e664269fe3c08a51b10e1e019ac063d670a3c7db12563\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 38ca0c2f03a5c56676a2f95cd7a69d4aa2085343af6b1d2a71e0d1c54157ec0e8f9125df2a499cdd484c04feb23b1e0042ca908db74744584036c79f21c25c40401d551a65afed0ef35f1ea000fa1a99cb29e6307f6ca0304145f7e483d008cf9efb028ebb654115a8c6b87a08\n\nQuotient = -134e043b3b88b31f89ff4bc709cfa1bd2c1a8\nRemainder = 99c1c846cbce5e9a26c5afcc0186bb1e43b2501ab3205d13fdf01dccb9b1a935bc1cf8adf74d58f1c316381577366b6d126da49991a0d5e02acaa678085f335ff8b8e975e5bf2e52a05488ebfc21a3e0d0bc5bbe67442f77bfc3c1f0c03b7f7ce42bd0fedd8a498f018d8cbea47b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c261a6c562fcdd56e67fbd2b91027f17c95da43175eaca6e4069c16d240ebbd240582dcde953eea739a4668fbfcdc6af8ff3ab58674c95de90fdb43f64a61108b030d644a44b0319b912bb563f61e520dca9c88f411b32e99c872cf00a01f5badad584636352913b7429b99ecfbe\n\nQuotient = -448c4922b7a7d5e1efec2c3f41d0264b76\nRemainder = -2599e928027d10d3a11056eb719768e5edb1a625fc0b8a1dd4439ebd30a82bfdf89e617ac7c71622058cc64ba32dc242d96fe3ecb856f1b146f831334af562cf88139a99410dcb869b9ad6ac4826563b400b59f55d8fff262dc920fe525b12b2fa167ec237028a098c9117cb77bc3f3\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 36be11eb72832f8ae7b6bdf689f794f62cc1c885e64706d14a77a11df9761c2e9cd81d8f6a0ad0cb1696c69afd80c8bb992cda5100cf1162d600515568b9dc9c81a518da9d240888d4984df65c129ac0b4c557b4e63ee5be79a27473ff5bca58e559cb04c4ac93b61545e7351bb6514\n\nQuotient = 152474a1a76700598c18d9301866ec00\nRemainder = -274a2f9e2bc5f9d75f9897b28f840b71bb10a3e4e7a35ee1dc1150be61130b4e0e987e8742c5edb75a1ce3158eb8bdb7d657b8ba39436d7c88fbff160c7488ddff2f13b3b95ffe149a3d0d2d406b1737a7671f69c0e5d7074a151cb2776b2d13ca24bec261662f2967fd22339ed6c3f2b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -b17c79a31d5085b49793b6a6d628109a6047e3b1afc947e5212d0a9ae32b1955cfd6fed07fc60634ad15f32a9e402d7d5f750fb6d1ad958211f9e8ecda8990689e5212cf72b24e9b51bd07a6e0477dd4c02381d0ab6c0ad3cac1f620f723ab004880800736804751349f6bb19d3db48da\n\nQuotient = 5665f53d5a7405c83a5ff382ec376\nRemainder = 252d055186ec896cb3142c9e4e49c441e2ddad365b86ad21ae4ef1c522d3306c2834d6993a5e1f8c64a1ed582bad8ab746f7e773fc004b1c47814f73560db72f7237ef6e2f671d3b19a8777be2e4c662a76db87ea64f32c48ea371b1ffb15df26726854a417e18afcf49054c6d2e0e337e71\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2b6eb2caa3ca650be02fa199e9ea6c48646a76434e268713753a547e49571f9817ad396f2cb7b16d307801fc8892f0af3e7f93ce08f7955a8acfbc0b56add4b4c7ef7351f60e402b9a8ef7fe02ccdcb4b00b7ffe78c7009268dbcf1d606c3a1b5307d9a8ee6121c6a635a742b8bf36b56cc7\n\nQuotient = -eeda035247bb13860f228d8f2c\nRemainder = 3976edf710ab42bf069e5829de7e16962d1b765f6ae6ad0ffabe723e21ab01cb9f3f5f4edb1d8c13cafc0556c0aa93d72dbcff754ae9260abd294647b71785bb049bbb865a26bba22defc458a14af019a796e942e77d03484028aac2b3798fa730ae0193d89728bf80a8728715a0807b3c497b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -fb5e55f261aa96f54983869d58b3e9f0757d363b9c43aca5580b7c0380096f396ec79d1b30037702c19be5889fc6376793cad51975100f33ebf43e0897dfabcb9adf3adf8d845aa7589ba1f6d155b25f73dae3b2f835595ad6050401fd4e6392012d06194af415b810b0c10a53bc56350bfcc4\n\nQuotient = -5b37eb0c3e3f8f8d9ac6f4e4\nRemainder = -28fde388257b9a11441c592580cd38caf2d69e2ba57d43151c77d26535226e05e08a9e6d8ed470d4354e9f46b7626e5f2b22b652a2d78f817bb51598c727a765941fba63510b58fb3dd5f30717f237da43b42d20bc260b06d488c9c912bfcea1e7808544c58960a3e1355c50c889cefe75d4d9937\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 29232a3fb059242cae6e0b419ff13c479048cfe46a9063188706c6a3842674b16a1aeaf771c5b0ef401d2dc8a57f6fb4fe1b3c7bb545c18ae763e39421e6a07c4469d234f9fc737ac21ca67a5553c7ed693eede4325dbd132dbd9889d815c02f426801eff1f46e7a52f72845234acc6c153f34065\n\nQuotient = 1c7ac058af2e7bfbda9484\nRemainder = -54d7aa6dace87e61e24d87053b9d094bd160916b720d7cf4f740a4fc5a7f03909773d0456c530ea0204427146fd44d3ecec51d8627b5768de1494bf42081a8a4fa97163b0b93b59e70e533f3257723e441cafa4aab471ec4086601021c4462e1f74bebf298ef45fec98fa8e6ea97415f84c93c12633\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -83c2cdca7577b32c20e9e20fb498a2bceb7174ea9aca09d4dd2fc7a1d3b922797b4e9640c7eb9dbdb4d93c7fb9daadd680c1c7645d8102d77e9c877a9f65b13239f9a650dceefc1fd41ea9bd2b38a622bbec99cfddbc6e88f377cd51cc29fd17a27f3d0d970403a2aeeac6ff9fd69c3bbc5c2b0fe7e\n\nQuotient = 472df5f4393f33cc382\nRemainder = 16579a289cc776a47611353e158c43dadf0a78833396f8419fcbbe47d90c7e840e2c90e73e563e6c505bfcf691120ab0f1e9ef9c31db608cade70eb8e487b1113a46e2b5c7f4a172ad99b502eacdc0f91c295fe608389e61d030607a94d09d349fe1a0cc46d1e07c8db533cedebcb4a3b89afd8b924993\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 34b7f6780620246f5a0a92a768072185f02e57a52db1d865c21c952f4386ddb7e2dc1df076316cb4f2f394397cbcde1af0197fcf33e6428e6f5d42a9ccf623f7", - "5fae5940873097d4591d9b1a4cbd00074d134272700ab06d901742da695c3ca9d4f917a808113336f883e769fa8051cdcb0cad7cabd1cc\n\nQuotient = -12b4e74d76bd306d9\nRemainder = 8768fbe8ddbf60b548938d8b4a74c4a326ef335257e5f513e65a7d2cfbe9d456425ceb719407bde3cbc74c9c978970597b5663a0ec61962e77eb351adaee2d2d37f1fb55b5d2ceccf282ea3a0d398be1dd1b166d55dce04a39ef434fa392893618003adcfa61401276ce4e599051ad93152e3477ff524f0c\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c898a753745f0fc178227a7004d917557cf3dcae2e85e95aee51e137b29c895755853ce2d61f214b80070174cad8ebc2795a7d070790acd335b383f9dc88c01227eeab85f1f29d76c1136ffcc7b9fdc073a3a03d8812c7c561b32d8e69754fff64acfd64994b7e9574d2a7cae6bfd5a6fd61dee7ee993bb7\n\nQuotient = -548c97fd02eca7\nRemainder = -939e90e281f97a433eb1c6510668d0fc448f03d737d92693b6362c692167add7e4442105d60ff3db29c03ed06c3121aa4a53c4625906519a4092e4821c918d2264ed0cf088b7da43a222877f3ad9a9fe8ec06fc66b9cfbb44e0fdca1dbe4e461dda9b85231b5b9733e0c78852da83bae557755de3680ab61d4\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2c61dce04200e725ab0ecc5016f66044218391bdf650bc0bd31f3749ac06c24707e79526ee459ccfd4bc22834f8d23f391f2e99135f92b5abd0b04079ab75a263c0e98e46edfb440cd865269ed7872e8c1ada312df1bfd6a5fcd2ebf548d7b7d1d75bc36f62e5e9d15262bb8652a8041e5c8f4d673eecb777d1\n\nQuotient = 14622572f311\nRemainder = -6d197a84d2ed486327790059adb5c073218c56345f48c15caf6892734fff0aa7af4782738bebf24d984bc8adb3056f67e57f9960001a67fa462afd8c57ac9d60ae6517d58ffb4773b637ebe6bf2473a5490511fcdc576a4c40ed03b3afcb2fd27c57b66a26f6d3f9b2bb101502b1117ba3ce7214c9db6302fe20b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -b818674faf69bc92085b7230d9335d7bead0413f2905539a54e8d1233843ef13f07cb5538e0787097cb24f152cf54a92e62ef143e31cfbbaf3c09650b14229a4f61a783eead26430949c88a87f1618788abab9728aa52dd8419f5d568e6a109f278b2afdea91cdedca43e562d4bb8fb7f1b7aef13992fa7edc320\n\nQuotient = 5cdbb03ee\nRemainder = 1cfa68d5da7a600a7ac598b9ca1a0759f972fd9a46ba62e5e96d8f6f00fbccd0ab26ca03d14470b43793411ea9803c9409908625fd74ef8f9b2d7c2064b2e3439adcb684e6f01432a1feb0f492fcdd2b8b5a6cdbd0bf460272218bcf763974be8784e5306c219ee535baf5541b8580952e3690b585fd99f77c46d69f\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2869338cd16322409d3efbd328b27e2ba53cbf71816ff5c093849b1d866b8cdecbd6bd8ffea0b7787251acb760f85c277ded21e56acef05d29bc728cf44f55be87cb4c8913408a01a1ad53461058a1cf94538f05ec14a6d3eba804264df957de7eb1a61b794a1141218966463dd42402c260c229241ec46afdb5a06a\n\nQuotient = -f16da1\nRemainder = d8b66b622b5a54963c2c84aa186bfde5b67a3562e07a23a5f6843bdb615a3c5d4f007ad8b275ad7e4c5b1436252efe35699cff2e0546e6dd8c7230d6ad560c51cd54db6d312be32ae4c708e9047c3a25c211e2566c58d6b9291de31612006d4e847c6916702be99b3f7ce40e1ac842908acb7f03dc120aa8998c60737\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -f8af8fb7002a9d2218dcd0f0c139b8e3dbbd48e25a5c910f6d0b6684bca224f62768b64955580306bac6bfd45b99ad77483563fc7dbe015edc06bee3ff93b0afa8f5866c23c7a7570b366550490c97ad84062c2495cff30717aaa965a8e15e270b504dbd4fa943be4f97a7fd1f3b589bc9fcf4f907a7690d99c978a374\n\nQuotient = -71bc\nRemainder = -13316e9b053a06520526f579718c326402d2a9686d51a340375cb53d7cebba99c8d1ae93388db0a41cf55d5753dd1174014ff3305fcdbd5b02de9e90c45ec0d2900ebf6ef847c2a045eab7f80f07f01c81b9fff093a779a280ae42239df79de8d2ec4bff6723788c86786fe276ae6a4dc1472442b552258e1e5b597305187\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 20fe256859a2e4c4f77db6adef78b2aa4758b29ad0787ce7e277bc68391d5949bb4dd07a9b1a79fe890c8a760871d81adfd3858e27d1bd6de33fd31b8aa6131fef9130a50f995c3be1d615d1bfb9878804b7f6494237d8ad78ac219488f17335ae54b494532f03a3fc8e9576cab6facd90c662658878fec86db66bacda3a7\n\nQuotient = 10\nRemainder = -23e09736f469c83f280052ff01071b1bdb52b7e2b061e8a1a8c6a4e091fcd7ca0b33ade885d928a11a3375599aedfe554d1c2289795daba08f07327a19a8adfc219592bcdf9fc5aee5961a48b3b1b5fc380eff5ed2ba7d7e564462397fb6c6187254ee41c74602b141d7adba99205d2e0b35da57efa96397b3a5d112751cf7b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -e849bc0bfd9560cb90e42c8e4e88df175133c14466e530716d89ad0326b660b0e617b4efe8df6b000f517d3cc24d9dd4cafa2773dafd4c6bace0aba54e43c17e8e3ff9497a97ed83e6408aa0aee0e6485dd1d89d52520d1acf4d587422b0c5cd2d5e7e81fdcf842d6331779e800f96628206e8be020ad4021789008a641f67b\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 22004040a65f9b6f120bb7243c638cf3a4cf6fc58c230da932c79568f68e31af7a7b8569aae77af671f8335ae68d6dc1698baa9d6ba9cd633a662101b45bde51d55098b50fabde8546f317ecc2ae7a39521bc075942e3751a349f51ca3c371f3b8a6cbbea3e11a334d677c07612bcdca767194c07fca78ea8a06cc3b0dc6dcb8ba\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -cad46f410062dc33ad4d712c3b743ae2b7613576b2bd7c346a8479ed679a08e3644c7ee4f23b95f1cc9111905714b170abc37ee1003956f64f0a7e876b38d524fbb2436ed56069479d8d2e4029770f7801a7278fff99b3dc76280f35c7d43ee594073f725554a92eaf4f785c18a7cf6669dce5adb0995233241f3294cfb5bd8f4741\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2fef69f9745646aa13e0c38d77951161a1f881a7ceef032698da3fce00764959f11140bec7d7f53d6777c3622453d4525fb068da48047609d18d463a8fbacde1d21035963b668ca11d5b9ae66db13de7a7a5b66a40608dfb56d9f9f0c8880426641083a05b5ff9e6ba0d6da3a04af1af01dc218e9b4f6ad7b1d3a4d1d26a5c906093b2c\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90", - "ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c50a24e5ddafb768f64677233c5cf09da1b4f06894bd68e194b23feb5c5d6844320a12a02d13ad012f13b1438eedd6313bac9c1f9bb4548fcd314988d8fe0ce6458306735307afe08a96a0c2bcd9cf126f529e48b7ff4b8266caa28c40b5c3d2a473ab8805c860d27d7ee9c032423148d96fad019490ea019d40679de7a2a3323e80979f9\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3a8682d0e5a4efa985dfa8bbddc2c0d72a4400b8b070a8cf7450aa8f831d8a91c9ae3542641b7a4ad793e232a0d301b82664fe2c7f20bd9bf8275828a2a20027d6056b211638b9b0220fa4252d058bb485dd3c4622b1eac97d54b9634b558ff1bd5bd11085d4f3d288f7965af52beaa922b23ac0207d5763c24c085076128e0ef7370eeaa19d\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -f00fb238bc9383079c7ecad9b9f6efc622d58a76f2d5d40ec7cd7c3c083c459fbcf3d128df4d20ead5f585505515aab11c36584ca622d28e0cf037419a649d598346063a07e29c61b7a8e76d1949dbce3720d45576763aa0d391b39dd6b694c7cc60a1b4f4f107d87130402985695e1847e82cce39b8d0fb5c88bcf3b37d6dbb90baf5a8553c3a\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2b809f6baacecf61198856d9edbb768ca2df2abe9b7b8ce1669fd9259732c8569c0cafde2e32d253094480ed281a8db230f84e780c6e8bbf3657c0b0baaf19ea973fd8daa2870c9d79f3695d78e063f9130fe07ce806a088ca267fd2820f10dac34b5b32aebec20e4362dce26eee0c29d2fedc1e020d452bc2499234d07a2a6e54314e3fd6dd85fe5\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -90ed75629073df816ec1d6dfedd1cdbed9239661e362db706288dc4d774d806bfacfd4b32c3013ec67d8c2af133b46989f12f809fe202d33d5ba53659bd2a9a85d3fa542de4a5c656aacbbf8899aa66ba816b809f2629f37b0444cd3a6dfc99103bcf2a5ee87790b8401be806b5d7fb7064ff0a6fc8ec769d0ccbddbc3d35f7dc4d388d8d28021c95b6\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3f60052c9dfe0bac797a674ca7f11377a24c28a1396ffa0f46acab7909543086aee1995cf51852ea4a21ff4bbf6e7309cba9848a7b2e3b33dbe660bdc58d513d16bc709f1f2253648b46daa7aa037332552db1da81b4ab9850ac4ec66621648fc856a71eee3cedc6617071600ecbc5ac8636233f288ec249b7ae0bac942a5fd539d03990c4fb28a46653aa\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c12fc156d9345cdfcff94bdd324429530ad8caf8afaaa1a82297eb3a8aecf2ac021384036749e489fae05e8776da0deca7e4325436bc8f383bed579c2d67a456c4e23871489780d760d63d0bc0d1d0ab41f06a091b44f602bcdc0bd4e817202e39ca6a934c0c9405adb5a14d24da895c58a81d1c7ce52734183e00d80a414ddd8869998822364e029b3f42cc\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 205dc6227dbd3adf8ee49dffd43f835882822b1c94f92cf38f5efc62f943075d80b33588973a0e0a8ff5e800ede21d394736ba98d4eedc53a9122f8c262cd09fe9e91cedfd0237003b0124d757797ee13cd03e7a3a257bd8df756940a4d22face9287edca00ca23e7d5e629966ef710b07e54241dbace041aa6d9f82687c3ecba818203adb376ec0b201894a500\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -82c30a9ef6a83d81b77825c71ddc563939b8508f1b7e44c725ae0f61006646ba9b86507ec9a4dfd3755ecd8bfb451c2d43a61599732b8aaeedff7a304ce0a9327e2333f75e9a010556ecbc3abaed02214f25e1c8373bfafc2c288ea36b8d5f848b76295a141d8f633609a6656c07f3d98177f5fa83833476dcd111aad179001f81d6013ca3a54cddcd8dc0ce7eb24\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 33aeafda3cfc20710f0b4a3d9ace4817eed80ca57ce6c82dc2e7946058a40983c9204ac95a1399fa633bc96cb10af3ddeee3ad2337c64391a42dc7794fca629e3e1e4e03a2ae24a000e7113b91c1b6230cce9592e45b6ee7984680b45aa0aabd7f56cab1a64ec310cefe5211821a75deef2e0c8e43eb467dea79dc8c03d2d523734498d079d5493", - "c904a2ebfd8a3a9bd\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -b897bc87a40211ef8f93645b1f6c981fa00ab3b12e117a89375400ab5f4c64bfbba01d265c7bc6f5e3a8e26de5de9df3b8f70f4a39c0eba577db5e4b7a68f751b4a69ff4a38915983cbf70dd7e066779405d572f5bbe0719c978b6865ea1a72d90d3ec8a8c146f20d98595036b3de88a7500d7b476644913e4b63e85c4e2632048e9600d553e560759770a902cca680b17\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 20604e080549e1c503049ebf4a56cf9447d90fe699a9773915b0a65588890e15bd58f55ad7b52bd7b7992a8b24704f1dfd5fd07c70aae4ccba5646405ff8a9cbf542dc334cc0c27a790c05420b552539fbf0a155861bec0e4d9e3fbf045720ea3aed58307d5738b64252a963f3fd5ecd0587cb4d7e159b4980dcb112e26c9c34f10a192e090ade157eac1d7a6f970871eaa69\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -f11fc9682601cab97c25533b2599f50edb1ac65d46f1969bd9c3cb3717461627621c8cd401a0a0b91f3645b8804e095aecab31c1bab0c26df556adafdd7e7f4f0510e0bceefa3619e26b8c9a1bc613db03857f53e9eb5d4b8f75a8cd1429feb81edc705e5a779d5f95373d2243368ce17ef22da79a6a2672496bdf629171b7973fc4659c8eae9ae867cf38d6d7617029bf59d2e\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3cb0ffbd9ad21d0e86e4e4dab4d237e2a17d97356bdd305fda772fdd99acefcfb8309d813643c852f66e1c6c7fa41ffd44f8335ef7333b2b3e846139fa9be2c4ea762afba4e11263c0b5fab18c5efff2a18d83ee89844f5f4db2c1325f0f55e066a9e01030c07a85e2c9bbd37b5e767ebcc9b95f474ecff24df9ae52a19edeb66546a3a28980f616eb5a351cd399e5f8436f17faf6\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -b8aaffe779855c6ae51807f8cba780aa64bc22e8fa5e33f7f1dcb084fc476791565bc33eb37b4f791ef5cf46d64576f48b5fadc9f096f20c798355861ce5d24a7be1450bb871f9821099f98213d74a5e5cf83b895ae65e0e0fd096698463906a112e6e169a1cc0769df7a5ba6812300fdd33611761b6339385e1a70f8f8b2be7679ca216f5b183140e69586a27aaa9f2fac118118875\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2b7ee3ee34347dd89ba4a81415aa1269d0390346597b07444f0febb71d490a01b6fee174634bd88e8aa180409549b2726d044b4690353de2fb2294c8f69c612485aa066f68fdb89466760a85901cbc7312bfe5a6f656e67dfd2d4ee099ff97694b01d6d5b8626ab1650eac5267be53f5f3ced5dda1aa86bf42ae132a28fddb94902a515da40e0fd0586dc8b17a34af8eb03d06f70ab89df\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -bf8213944ba785e01b8d37a12de77b2ce1492f34bf6f67406cb51da89675b4f70f4d4f314f30ca8d65cbc48ee2fa1f0a3e4ac0de3a87d2c4c589b6812e850623d78ef2e46fbb555f6d3c69b211892c11a4a2dc3d8a9a19e96a07952602ed5ffc0232c140c3e828acf990e5425d8dd9ce0c1107ad1c6f96c8fbc90ffa457abab0d843094dca3c8a45ddad81b7850190625613a4851485f38fd\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3083421e375f0722b9397e156de47f77635d62ba1d51794469371b473b71c02e3722841bca2ca06b5d1cf1492bbacfa0abfe394dfdaa7bb8787550ddbd953540e9c97631d9a1efe0c8f8e14f395c82d20245cec6d8021f8564b4d66e7779c3245734c56fb74481172f4e349d9a113cd0ee5263c69ebf746c5285cd4c0fa91d9531f769fea3610c2972ccfe9a22c00aa62ebf52b3a4c6135f3069\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -d736bce537f47ae4797faad797af8cfeaf8a4fd42df1f7e61febf8ebf6e47dabc48252ff7948f3dbf8cc369b6952dc58f64cf09b4c53447d135c7a753c21b6052a9726a47a61e13628edf0f2bdb357f2e780ac1ae1f28f211296c8961c2955b773d7dc2904dfea96780b2877af133c9591a0dd54cb20884f014f363862478ee7ec45236bfdcf0321af0692e68f744af28fbcca827ebdc7b210da38\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba4", - "66381056a3b92c35d9b8b71372b\nB = 2cf1708f1e675ba688c0d19eb61a05d2c8642528ea6b1512375faa732acc59ec04ea0aa55e0049144be09eae1292b6cba6db7a9823f1e912df6a5032bb9674f4f26c0c8244ea0dde7acfda566574956cdc33e4a27bcdea25fe255c19f218cc4316ae8428ea61d1bf865197a066b959c5fcbd7c9596207997d05fc38e32322aa189ea06cf5139522571661745c0d72b740dc6d842f1dd8481e318b5792\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -a9180e44a284b5bbe72fff46e55869f749b626ac33c8cb17be1fc260d7c6f460f24a89e1367112e00d0da4d213a821d09f103f35bc4eade5605bef23c5d048b1cfb45dace8b9c637af626a85fc773cf51e6602a7a5999a030030cf114ed6a4ed7583465b9303a72e7f60824c12329517c6763b0f64abd8ba2b9b26cebe882a51f05ef8076e527d53a213db910a5f42be5fb78729a3dcd08d69a709920a2\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2f26e156b3b1117f7cec542b20fcc06ca66cec03a19b6f5eeebf22b4c0fc265df5ff06fc9dcac569735135bdc142b526b295225711efb71577b10aacda2fa446f5208487c725407c2188b3185237740c813e4455a6f1dde4f62916237f23164a3471aac0fcfe24ad1ce1dd81a6144f5861ad0cf22dc337abe10fc4a88b36116dc4929602ab48eb971fdd7a5ff747d6b9e0b2bff75c59621550991966a0a19f\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -9fe18ae697576dd36ebdb621d14cac1cfdfd1f5cbb7cfa8962c5a7dace96f9f54fb4f4cf2e650dbec5d1ba89ba53d251ecef7dcc1cab8c2ff3d77903f5fb5f29a4e8e3a2a3c05c105d5733b5132f2f8d88f99d17de86ca1191c32ad8ed469bb649ef188306f69f183bd0fcc32759e4f855170f88c0a3f6745aa98f6225536821bfa056a42b37535a622f42b009859c974cabf2e14f75c749d0fe5a01fb3ab0c0\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 33ab185854b20a8126884eed85181b14e75d4ee452958cc1043b099bc16c24b9c2f3e0b792744f230013907844496e600389800e45fd55133fff0cf19c9c152b9d031039eb90da568f9c5212a3ba283f4d1353ff8ff9dd04d292c265bdcb77c3e411716f471930bccbb8ddb819ebb0e0036dc1a18457cd97f4f5909a725baabbd15e8ce33875895aa8dce77a4dbedeb0271a2a4a17f77f5920c3776caa4a75ac650\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -e7ca0c037bf8bad5f8d9c5a2737e044d9f7284c616156d142612a53eb217f57f4aa00b6daa424e6c0d9163939e1ad0510a1cd64fbd576f3e54c59d7aa6228fb3caaba7cdcc951e00ed141ac3a68abb9780bf46bf544fe0e347f677288e962fb69782741df49b27cbbe8720c6f8f2e769147d89df6e17e3c592bede2e696d384b9f01b99b31c505d67eb6193a8844f8c4cdadc9fe45dd446a0dc572c9da6e58ed303f2\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 22b76d6973e37aff4a09216e57662f186c0a0748c4375d6bed370ea61d1f6fac2d9bbe04487a629118b6b0b0c8cc4179fff7bedcf048cc529498bbd9cc81ef3a103d6cac49d58bc41c83f961b6df7f00c7171fb7d9359e03c76e4364cffae5f67321ce646e9b05f9c04aa16ea65389e940022eda6dc740ddc070bfc7e589b86fd1559dc320701c39de20d54d0483fdeef6c4fd012850630b982c2e243ac1ff918377ceb4\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -e6e4d69a82b83e26ef8ac0f4c3a211153ea6655b7ca12840e7b866510d114693049c5b8b22c3a097eac832bbd1986e60564298e54dba3316807ad64bd6c18903a0f22660c9e8d5dac180f57cbb90b176b842d5b58d6dd9f47499a037833a92a18f397238a8bcdc4afd129382fd6d200d3d267ca1e6bcc2cc65950831cb8e30bcc01665c8149b874c9f11168153c187341afdc43e4d8652ce4fbed9f9eac75db40d64344ade\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 319a81f052db21ee213c536db2cb8a71e0dcd0a9b2ce780a9588c38b717c5e487a337f82b5223f638fb552e92b826192e6a1c27771d1e86584bc6c7cbc5d9a6ce6edf2ea2ccf6939485959ccbf3183b40e410768c4665adf90a0ae2792fb4b5d8aaa06c6294e31893620decc3bc72fb4eb68f1e56b48e39c59abe869d07509b7564268d0b7f178ef09ef5dcde6e7dbd2a20fd1d4fcd707943dd63adf590a117ead1ad10ff85cb\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -eced809145e696ceaa0ee8f831eca67049509b31a1b15e7fc86cdd97a73a2ca05bfea5f4b283d287e49906463ef36f2f8ea23c2aa12d5534c08e9769055e04822be0f8ac85f404f5c025a6833b4115f78da9470451c852ba0f24062397d20385f58c5aca10f3f09072b2592e5672ffb989a390abf86cbce74268aef1f4ffde730b3b962df1088bf8745105a7462379ce142f819c253", - "8d9bba99e094ffbc4478625bc54df16c5e1a\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2c1ffbbb30e71d5fa77b5473392f95297b489c85f83013262abbe948842473154e00c86b2e354278844083f960fd746a3b7cb9baecb9c66932774b3a28f678d50dd8fe52fbeead43d8c8adad7c0fcdbe5e02664b0feb0ce214c5fa007c5fa2d08c5fe96787b95639311cc4b7eb2a7217c9c38c6d93444fa60c1f52ddae9bb2ec1a49a593e210e47377d3623cd2c4994ad9343863443911062e12233176f4a65ec715b3c9731c4a0cec\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c3bf056b905c0392a7b5fa57446ed350f325eb67d59f1784c744b04c7f4d8f5397db913407aa8a7f1dd0225c1a9673828db0d8bf3d4908ef53307131bf5b5c4c6068ad73b874aab98e8db33b0a758532172acd8b2c830d0679a8226537090166317b8eea91e8ee4a7282c0ab0ab6f2b7b63d728d22b534fdc88294c376a8d036ba9a644c2489bcc84f6aec83afbac08067a7b93f3897f8dadfb68c327b751841927a728faba47dc44ec4\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 23fcf9510caa531a304eee8d0b2d49050fca83abbf287b6b6dea06501c5afc6d87d2924df1d45b1bf6c4bf77b563a3013cfb4ad9094f8ee9892d33f6ee1c70131cd5721c5af804a9da7654510e8591aa185ee723f8caa78046d9e6fbb891e6024d2ec70110ae61c3969995e35941d2c7f3779d5bb71ce5b693bc9ce4b087068adbb554acc4ab23624e060f7cea169ab512a06ff3d2a36c2b6e3bd9a75f1a9ad30a6a16b0256c42eaff2c3f4\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c32d5e643b12db6616554116299c1da672efff1eee394378c5e9e5f702ea4ad64f0dac8904bd2751d2cef91adcb283599f6c661967dbab27059e94dd50025489cf74c6897a22e95013669aa3063fcdd4b73aa6a9a1ba5cad3956bb26346e22df6741cd0ba1c0ab87fbe74035618a394383823216df47b910cae495b8fe7ac5feb3b2cf0d0ef6c75db477160b75324db8eeac48a0fce72b9abbd7079ce6f529a89025a03a3777cc7d1deaf3e4a\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2a8f2c530342bb6ce683a760540e956a1155c0fe065476e400caec59861ca97ca71e51a11b3213b2baea1a41a29449998778e0f533fcc181698d293f05e28bff2750ef4095170de98a19a36ddcf59a65f3789a3808ead51680245070262c9544e446f23652eba47065a2bc4701c55378bd49733619ed2c213f8ed12a4a317c465f37efe07ff2df8e88fc33d3eb42cde9408dda28215702bfa607030839285a8bbf89b5e8842fa7d7f50d83fd4ab5\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -bcd2b2362aa146cd120b729e81c98ae598804006d046a7ed0f9782baa10a85e37c7c22288dc61c24830a1b42b123d63779e88d7555028292fed5ada1793264b35e961b608bdd7398e421c5474c33a65059ef13787e0cedf4f8f032beac48c4b5e5a67417109142a43b198ab617d1de1a38d6fb4922c6ef70a5aad3faf6f8d5da3af9679c94cf61ee760ba792d2972376425e2ec9c4109e969e3d9c3dd90cdbaeaeb7382cb7bd024b75a1fd6d621c13\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3940430ace4b5b87bf4baa2673582db3d27307ca4cd8e55e976ea3e10da72b6deb7de932253bc9228c85cd4ae7766cd0264004c658a66d81e60bb9bf4dd66e2afe11057b7f7b53a1ec222510748be53a93970fb056e8082631b2b77413fccb6e61cdc6f224b7903d75345afed8a4f194b4bcedfee1f16dc256c2bb9f4a129fab6a9fe752895a93937a3d087ab7ca212991ff34f1bf1c55987a574674af43986312bbc3bad3280bbddf4ab0217440f851b\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -f0dc20b88450f45381791e85d080e4f2cf38837391e16e608b8cb5e0ac0ca75e9f72cc04bf2f56f130d46aff31efbabc0ab14f0c0ad680d6899797297152be85ac012644c8d0927b5b6c70dc3e5a8d79ef92a0873ec22af3d9683bb5db1ffd5ebfb698c5ea64cbe2b6a8b9f14d4c18624be1b78b19eca14942ae9542012692cd0d5289ebf75fcf5486596f92659143e9f952af3622137e633376fb95e628055e0fb1ba3a37ccdf0af69a4c0d6b0793078e0\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2f2135850715f623909e41a745eaf7b37593567fa8be2d1ccf76d10b93a096e244b91d8700cca37a2ec1bff7c3d21cc3211ea8b03a3594921dec32faa185e7f3d9d17e98cbf8d881fd2abb944181659242ede21df7e5e8784f541cad678df1ef6ca4a5fa91f7856c62fe593c4d24436810cf4fbd11125bcb571f6975d82afeb81bd0c7700e053fc175fb5fc7b329c438479a863b8d5fbe6b4436b67355c51d0306e8847a27a30c9e61f0e08232673cdf0ba4e0\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4e", - "fb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -cf429f101a2e19a65af1e238f6745215cf476ff2609c846f10289f1ef21b89af2aec53def3f4ec07ea42041f8b5862dc37fd03b2df12adaa8c9f1933cc69b526d47797b40f49545fd093b8ceddee3c55721d1fa19b336218de0cac56d410cc6cff4e620578cf820f5cdaadc367dc4d6372aab1e0ae3831a6d153c14920b1dcf09e7629b7442a06385420d79742e409677e3b82ec58bcbfa668ca072e981e20728a983d84a432605389c855a6668e0ee0d2b67449\n\n\n# ModMul tests.\n#\n# These test vectors satisfy A * B = ModMul (mod M) and 0 <= ModMul < M.\n\nModMul = ae2ca2ce7addaee2e2b7752e286b2bb6a58b51cfbed5c924f00398e59ec36fe6341cd83da43a33a12410f45f6228079c4aeb3912be87e2e81fa1799151bfa0fea29873097475b2c3efa312145d0bf7e51b2a7c9bc961a4f4dcf0c883ff90b919b87c21099fba40257645be31f95a3a277\nA = 6b18497fed9befdf22a01d988d34213f6687d8a96e86c188dea4172e7c6095a0d18d3c86c0f5a1af9c6e3aaeb6baac2a510930b3ed06ec78ec2e12b\nB = 1a058d99397db0d209f01212dd4023ae01b15da04fe62d1f76f21622b2695558c67d706c535ca7f19b36f8ef2d508ffd6cf6fcf25e5\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c462c7cdd79b7604246a0cd97b40ea5a9a77408f13cbb548b56ee713c690dac0507fd988bf28e77462832f4307b08564a51510d4a951c1ad7564316dbead2b53540090827a8ade8092a6133af0e5fac7310f787dc1472836178ed6992b9f71224da3e884bef8e8379a58e6d4be0fbaf59bc520f786631857213305e23fd5ca65\nA = 16c92f77c139706430f396f72ec7adb045745cd9f5899b0074d9955bd32de66f57c05c7929b575312a7f1c04f19e724d64744bff7b31ad0e6171437763\nB = -8734c4a2361fc530f60b28a5f1c7e93136c5ff6bfc7553965eaca54c61e6befb3c0f8cef4280e780cc5940d21a740debba31f863ded75\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c462c7cdd79b76042469eb41a7a83115eb84103da4ba438c3e33227631dc185054ba4e607141d1e60990d8aad4e0bb0ceb645ce9ccdfe72d4738cbe1f6a73ed3e070194fa4feca6001c4a853940a227d15c1f1cc153d8c96e90e24805929fb11e0665e0c41c77d5a97fc5903a8b215360e26f6a19922d650f460f7056274ee92\nA = -6715098ab2ba3ea1e6341e89936e3ae913cdd450dc831c8534071f3c362841e47d88f2cd29c0d1239aa0949f3685f12f8519625bbf10b2c7a515e6d00942\nB = 536d4b3e4815ae5ed55bae6950f5a8a61d52439d2800ef1b5ba2285b85ed0f6ec4af9fa0e364a6b14f6f6b8bebce9200467804e787f9f3e9\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 309b3e30f74c58beca8b2c23f64fe1203830db8a7e306e1fa2e2022f0d6d422851da509d1b2936f088f0e35effe12a7463f47ca369bee2f2980bc48dd8e696b2d8c6f35cf55fb8baafc2e613b4c684de26129cf196741aab873f81e498b1e03018a539b5eadffeb5953029f31f8579df7ec0ff3f752491910\nA = -11fec955948e007b59fc50e729941ee9d43d552b9411510b73f6b4faafc0465f261f8381d96f647267f72175883172918b5c866cf1f1ffc43c55f3c96a60c01\nB = -2b3792f39499767e0a8b7a6a406e470a78f97ebb36765beab5fe52e95abf7582736db72a2ebfdb2405e3954c968b350a459ff84ef815dbc5910\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9143ec3e9f74a8eec476cab17ad8636eaa7c60e108e89ae0702dbdb2b255a217ba2530c6fd52658cd931b962054a9c20c8713976ef3b7989c40611cd25b0a9ad0635d61f6dc95dba6e0c4a7d53ff539b623b97ba3d66344fa324f905abb861c6b1e830c4b0fd5f6a4b01f09c8e1408941291b2285c4625267a108c\nA = 7713413d87f1e50840255927ff27bad79e5de5898725a876e4647913158cda9f5fa031dd7fc11d2e8130a0ba99e8706341c1a98d5fee3218763ceb1d131e9cdcc\nB = 1384e60753dd4bc20cdabf398525e7c4aa40065255c5058cae0b2ec90a3821bea8de672a712431aef5864eab719ba621cbbd8b46fe86fb31286091\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c462b3b4a0432890d141c0f46a28190a2e30ebb2e4ba90ed132169cd72316b290dbf5c261984d98e63eea6525fa890bf52185ad7f164cf49f67ca91c2f35511f3bef6eb7f3da31a602a78e4752e326d79dea729f4ca6438f2aa65eff44bc60979b42e44f6a301cb5de8fb42abb47bce5633c6ae9479d39c9e8b507d96161e0fc\nA = 17d806d7c76aa8acb051fd9c0c782443f1b1b6387455f7cfb737c41658d0459bda5d13587055eafb87ad8d209bccac1fdc392aeca0774ea48799511c1fb9141cad2f\nB = -d7c9b6574354e131de4b8643d766641e98554a03238ebfce1112c3da5f049d6c410a7f05758571aa2625f7190b936a214797570539317b32fb94cfd8\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 16c84ed15ec6352a8ce6d5c2bdc0d9f13b333072fc7041146e944a29391f83e346b8ac0bee6dde98a420ba4f8852801d7c5bea6f1177a6cbf799edf2146f8297013e0e796917cc967786788ff12d9c1d07d9ce4b897bd22a1b8a391d3b4ecaa5b5c85d0a03aea5145db6350c42a964a41ee5f83e7d35e14cf442e5d99ccd0ac8\nA = -6d84cdf18a2f53fe496248fafef183914d55c42267af3dd42a39515e80cf29211fd58454986f5fb6afb56170dd9865d3158249090270bb9af341c830522a4dcabfd494\nB = 6f6f3f74187b7d74dee92f79be864d0a2c56d4bca3283742e9cdf15112c8f4208e3ac8ecc98b44b4ad74b0671afa4aa9e48dc31d34224a1f66bb2b4658a\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 8fb782e4883ccf3aaa2d3e020b08993d580c69ec8fe66ecac152c5babc8aeffafe406736cea492450fe6adc25dfa2e12723a3f9baeb02fc0f785b3db760ed28048e1710a78a2ae0c96b67c109c5034375a512b6fc7906847253f66316baa0ef90facc9ab992235153684d49d6939ab9e91086529494d7386f604ed69aca2f53\nA = -1f745c8f0c8fe6ce3f893d77fb274c61b72b2d9f9c5a2eb2467bc00d1f496d0ad469d76bce318bd64ff1107ee5fcad4469f84d658586a5789c068b0cb9b866d8fdcbcac5f\nB = -3a2347b491813252e8ebef1bd181534b074a368d076b8c80bde2e54ec3b4ec99001f43080c7857427e069d99b1b65cff998a141ca6963aa5fad1ee632986ad\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 7c0c1c05ae1d6420bd93596a01aa0153000ecce660a8a14d6fde7d4740719cc495fe6681a9a08163b2dfd51659b3ae7db0fbe09504370bfc695457d7b32665a4df53e879ac817bf715d5bd6ca0e242b1ebacb1ffd6698ec90c442910a92b35ec103b345f9a9e5c7b005f8028da4dde80f36f6f6e5675040d19e46aef06040eb3\nA = 4c09264420a9452c6f0b55baee42c076aae5a73697cc6bbb88b7c922f236ee4c18e477f88e2c40cee03f0bbe87d3ac8dffd75f635315f856a3881c6373e8b9a286c813325d3\nB = 10474ece7ddae5c53c4df5b594439124370932dd94aa5d5b4ddaa233b1a55634fb7d72e33bf1b02965fa9d1538f97e1cdb5ec0477cec8ebaf202aff8533211169\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 481543f1556df756ae2e422ffe35aae020c9bde9e9b1f760b43043a4654de363dc67f381c0df1c3c1b90edb4343c47ffb8345a1aaf5dae56f446fee08a0b9ee8c42fff57143e10846610a9925be96418c4c957b4e92af734b96fd6f21974877dba52a0db1fec4aa97640e357434f95ba74b6b8323cbe", - "17118dc489552844602c\nA = 11bccd165d9fa2d8b01a48c0ec549a6e600396cd2023f0240056193ad27e971c604eda8aaed6ff6be8be1001f3dbdc8655f1ae84eceb963938ae7bf428eb5c968f584798c1bd8b\nB = -cfb6629ddfc98a242e3290959f4d0726c0b1770b52393bc7488a471a90f7f0951362c03e67f443c9ecf4987f5303a789bf65e0fd59cc5eeb9f5d4f40d3e4a14080c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2a770ccfbcb2bad207d0e2dfaeed04b6e7509daef00a1df88e57509451739a8a0f15106ce8b53d280a4b4e09900420714cb6961ebb0e00e88567c5df50d2f2908b4bf8e0a9a5a8b3c6120503c14f16a99297459543c467dcb67915e0a10e19f72ed5b6891a6121b66abaa602818801d3306630bb04ea57e6b31b2c05e368d398\nA = -442c80289bfbf00db06eafbf06109b55f99786a323fc2c6db5686f99094cc24aef50475841243ec3ade2a1e0ff28b4032fd8afb8bb5e28f3b2863bdb9fc8f033adbaeb5f2ab16fe9\nB = 6d43e3c46f4a55d49e78f40d34033a7f5fcbe50873930e7c5452b6b3b176534e6e70033868c85b4d63052964093214dfd0bda6a84e893b1aae3cc72aa83d039e51c014\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = ba0e8c91a86af1001b13deb115c77609a1e7a3736a6b807255aee898e3100f469ef6222be532dedb1b8d3db4b3b55aa4b5da5629c83e9b2bde76bf2f2a4119a5378b5cde000980b3e58595d988ff776f0388fe025625ccf368e20914fa90dc771c826e4a836b2890e82ac2274471d586b4de5dab3278f0e70207562ac6e6493b\nA = -14be403d28c8451cac4dc83fbf895a9d2b74f730c39b0fcb33d7258f99211dde31a78f182ad1d27a559031d67d6f2f94a741f141bab80fc692afb452ee2d502099ebd5760ccec7f7ebf\nB = -2742dfd02134594edc6d3025aba5ca4a34dfeb43821ad84164510b43be4fb95748f8d0eed7bbcbeca14efe843fb676882784bb36c889be29bdad9270e0956286552119561\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 20c691d6544912fadfd9894cbfd42745991f39a29cbe3a1cdd302bd0487bf70c0179b9579b77f8481bee13ddbe42f32d734b6118af92884c946ea8576f6dec867c1c251c73777cad7c7c76e90da00ae07f96c8d6a751e5b18157dac4468c05d32eb86e74e0e8312bef85905af8193a3f5c799c5875badbc9eb7ead1258e56d7c\nA = 7ae9b4d5151b11bb7bd4d1569a6f4804f3b4d77948e0c6300e4f28d51c9a0afed2ae7503e53489edca5359e2b3d0c82a9cef316cd7e1c1275c31fc9c51a8c1e5fdf23935484e467d6460d\nB = 1f46f88d39fbedffa8501fa1268bdf3460aa98e12b629da59676e61852a4d3f8c59f72a2fd717fe2faa09639bc651ba516cd39297e0cac67444ec57c0db47c2a4e250033d02c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = bf21b3cd55c0df8d4d568d00f757b10ef3de782ae71b289cb2b59d36df1341382bdc1825ba13199f2cf279a72968b3bbf5f7e3d13ea9adeb96d81132788231fd988eef04828119dcca21ec1fe844998909cc95a8d01720e883df27f07ef4dc3f09081015dbbdf019b96707c18b0b1db6e689e8f86466a2afea4a9cafc576e10c\nA = 1243b14aa3d16a55935f6f8ca49295e35e7f75b03de7192e1e8a479abc0a430e0d340acc05eb9a61a5dcbfe3ce3a4c5c940699f5043e924f282bd21e341edf8b7a6741c6ac72d7587a9e7a60\nB = -bcf08b2153e8ca911096189e35dbdb21b77ce89685484f574c89f1747612f39340bf1b204a23530abb36b2c5e195940b86ef1252d6729393c25d4c73dd434b6dbc3057b05d3f15\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 460539d96c07e72acba5b59c88fe904bf7f1e1648612908444b0b08172d05968b31b43456918b4287dbe01afc3cb4860d9c2fe549a580c989b6507094f6c241eadff910d2603f747f8e289e7a8176ca4a978bba89288a4cf875bf3e03939af966c54e77c28119a39d34a2b7055465f58ef2efe7c82ac547fb675653198e4b504\nA = -5a44cb669c055ba7c28d49f84bf8d12179aa30bbb9db2a48d7a6b09e44dc0e0f7471e3629cd2fb51e5a53346ae025fb49f9591ed1d71bc79daeb3f1254342d8a2b091ae07a758c1555efe59e78\nB = 646cc0f766346aaecbc5147a4488ce157a6d844045b80884eaee9d419087285fa71108b5ab4a05689aacc8d2e3dd0e6714c55eb8f77487a3fc5e56c3c2df0c4acf28a457051118560\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 79b536f4f30f9f7483f90e65e6456ef8072d9a7430405cf8c9377ceea2c676afc338837643436d55ac6af2326ebb362684bccc5092367209822581700d641cb8d331432b761e4c6e22639a27335f45a25ec019d180fc53dfb53d69216d7cfaeaa07db8288adc35b7bbccf2829631c1eebb821e4d3299015c3d462dc17aee5024\nA = -167529b1e8668938ec02a68bf4d76c22dd018c41e19be25e2f821f63c2046085d0af30d8b4212ea0f3f9943be1c14fb2d2a944551107cd2bbf8dda5bf258957325f06277036282977db4575b0deaa\nB = -378e1be10a57e03b197bc2b1287d643ba6d89da4bf6a6170816691fb6529c602eced237863ee39659be3729825f032a57eb5de0a87b0894d1a1244523e85b6f50a3d9976dbb038490e46\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 658169197ddd0bfae101c10c3e6a2b10dbb456048e81160b47b197fef439b1e0ed710399cfc80ead8e436f1c0399064f92da50afc335847515686e055fc7bcc0ca721184435955b896b0af4f4d96672ebed2f154538d49fa507b945c0a6ae926793751231980274213c80046666c28ada213a2f87509d1466b8d1b2122e93f8\nA = 49136d37ae8f3da71a6114327833e8aaf3dc8b5a9a27e9d04c953988456e525263f86ba94397321c2093803b789f8db3ed7cdba19c4b796500b979e02952e1625246f8e977e01fccc133f94cb22832c\nB = 1dca005663385fc00b4fd58c73adc7589d15ddbcb8cb2fba03a737a320c447a2b21e576ceda73811a31d8277883fd31e22f776bff3261a098ecf8f40f2855b0c723d1265eeafb43f85323e3\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = a49fc8084f3e780537b4038bb769b8db3653a3315298a99c2ede6739a1732a636e9787f2e8b09d0b9bea08fac43cccca71a315e6f4a7d6417d171b4693dbdbee8cd9f95be0847ffd40ff027267125d67b89737e1d0365bef6c4429504d13cd8ddc7810f456d6293c0c57c14a307b94010d79d5c13b92a907f923966fd3c5c8ea\nA = 1e7d8de2061cca59d1cc19b356a8fcdf2ccf917e0d81598f014167c5a8de027ccfc8f2cb8c37c396ebaac83ba862c146bb2d551d10ce03de9528f97725804e8a6de57b9d9da811200604c2a032462b6ac1\nB = -e38592f3acd75b575f64ced439d5ef2377d21c61bc70625639b01bf755fa2c6de803ce155744993493debcd4de40860bbfcee86d0b117d7f8c3f8ace68b67cb6fe7a81a145535553896424f7a\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5a99c8a6afaa97d8e7d84f4899803c7786b1bfd2ecabdbfbb3bbb92247ff91ac213a72f6d23c24699d60babe91a7d9cea751e686c027fa1c954474fa5680f0059118426c71299462b11de5f2817d190599cc4b352df4d2e80605f9ad1e32eb13712d3027a2b6a19d52151e37e7fa057d8fe59dfc8a943a42a1756a38f103a75c\nA = -7df29221e6a102e32757c18f87927cdc90ecb012ab0557e0ab855daba832d76ddf595b9c5a62988ca968b64fd5bba2a147a5991810c17cae7edfde38bdbb7e13a1fe5206724c05a9fc9276c8d4e503a860c7\nB = 5c586d1aff7dafea3b8ee42e0e8854712c95385374b5bd1fc8ec41a72b296e070940c4160509a4a1699a678533ff3d12299338fc441b0f01e29a48677bfc5aebc644555285756e97c74e1af6aaa8\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 21fd2d881b6a52332dceea42664aeae1ca110512c13bb33e25ba4ec0f39f80eb73b1fa08", - "34c998c23a2453dbff971eadb183c51a30ba78d593f23be9cb6b2b33a554ef31e4a36e0314fc2ec889f18debb956b89d1bf8172553271bd56d89ed0b30abb70e68abaa2c76f73cd5a3de93433747d09c845b5f8843f9fdf9f6c975c8\nA = -19fe3bdddcf08190a037768b77666de803ca4f7f0d7dbe6aaaf334a486dd0da7ca024d1b3df11e0406b0326595a171be30b04574c1a7d04f4d2ccd334663690fd20e4fd168386280510a00a70c1a11e99483048\nB = -33b2400173c057980b0e0cfabbda1a5cb5b83b7ae80708c199f28142237f04b071c6eeb63d42e80eec04b76152250c9e4d4c4f19a048cb9815dce6e66710fad1d27494db5c31d9af37d2aa779d12d7f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 1c45cfacf30682a876cfe253f05b393a2cd4dc065ce73126508ce897a99a723cf5145187643ee62d746f6edf70269ddce3c348a1432316286a648ee9ac31ef87feb14f25c42f2dfc2e84bb5bdb4ec0124e249c526c55ff2cd0ae938555c5f86d856eb181572ed01dc045f1ababa52d249e56aba0ecccda905d7d1e64bf89bfe8\nA = 6a40d948eac2fe5bf6db15d7f6b89fdc0712e32d39a881c21859e8f7722391ce05973efc7c40e2c0d7f56c217d8a986bfdb08bf87bc0435873cfe4d01967c46f7d39464bec411d0369f6f5d1d83f42596fa47451d\nB = 12529775e8253ba220d890d4912fb95f91e4edb59610e889431208b6bb42b089cf2aaa12ff9ff98c2482e7f4cbf35b22d15fa28aa288217bf766e937a706fe1e600143087b0a67f668cb7b762c9b9f38c0\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 3b3b08e8eda8be3918bf648227eb0d569dd898729d9cd54deb32b1a1dc69cf7b2c4184c8ae9641f0f75950df263a5e236f428ca86244e617b14a04edd0f31c02bd4d84f25bacfcd4a2786825f0361251475eb6c7e99020dfee4298a1f1bc260d4e364a332bc6f651dde7ce5026dbeb0e5aa75ee98874da54c7930108ad28e3a0\nA = 149d36918fffa682cf90c4d3f3d48e6408e7ddcbeb44e78b9cc7fbb08108f65215761a61d79f37ec8f67cc51e0a9b4bcb3834b0ebcf6734985153f29a2778473b80147eddc813b4fbeb98843f5c1ae6cea68f88dbb4c\nB = -ca87f66182e271a69c0964eda92a009d438078b584c3eede28ce1a501838c5f497186d305c09922f32ba858fb55f2a0dbfc9cd0f93b789c1f800cf092726d6d33db19e4f26c7dfca69b83925db14544ebfe2\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = b199655160d88b6b4157ada0e5675f82b33b5592408bb57c46e2f7d8791bfccaa51436dc3b772b83e907c20ce7edc2835ce96595b78c0647d244e9bad6f4184e0003eb0899e7a47ba0be888b9bf795eba95e5073a85c4d20416fcd4a8d4e1e16b403deb38845fb8bf9e9264d68807acf02d579e8cd104cf2bd555e6cf73d0450\nA = -70ccbb73e33a7cec30ef2071f3b1f2e008e70fd6d00fe8b7aa4b9146fc6d0549c57d984cd014c7e0a4ed6d33376998b7c2c9778fb9580d8ca4ba795c88612721c153c186740c58df3fa63b6cf7a4de76e049217218c05c\nB = 6cf4168d44a8da8e8446b4420466fefbdeeaf9623a40e10b77547687b25f36916f2c18cf6060c03b3b40e0959479f6aad5e44dcff0ba799262ef53e280f4a7f667d262d472b2e573265774deb5ff8f25dc1822b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6ff91af444c61d2e2fe8ad73bdc5377d5becd55074eb60f0f98eca3d8f4be8c02f196b3afea12c36f78b78ae6a5ab677ffb7d9c0bd58987cca816affe468c7fb4b56055f5d2326532d6ed1c00ca2d052ecd103994e8929bce04e067082b4ded7e1973566f99c514b4e0d95b9a8a931ef4f6355066940990fead70208a63841f8\nA = -1c924bea12ad6f8b65abd1796e381fee2cfbec15138191bc22d57165928794bb080c83878fa5fd19a5d657b2fa91165459966f50aabf19440f7d75f027b32e999ff4d3f7a7ce878fe0f33a847d644d86ca19713ca9968d97c\nB = -3abd4b281b8f25f5957d1f2fde904457d49a3a7eeceada26b454ceb4ae0e879135d376571f08b5038b7b3d73a9a9fecbe265b72375756a715a523ba66737085e5ef7a4ad988155adc93eadd5d95a0faea56914983b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = b9076229b1a1241e8b4da3fe143ac31d060785be6ac1e841c2fa9683d2bacff2e2b5dbac33f58b0b1718ad2053c37ee55ea54a9d258ddd8930d2784852844d85db24e4721762839a5c73cfe588efedc8932ccfa585e1b5975083919be9e32a86dbdf5cef84d3d4b2ccaf7a006c0cadca1e35fff2da9da7d7e779494d8f85bf4c\nA = 75eb0fe6c07559c2b0c7b2acd7d29b5798f6c4cda64a504ebabdf54bdc773ab28b218f0defc040016178958d5561796230b71edf49bbdcbd3f14494859843c8ca7a0f777cb05827f2839f3982832f4f3e3c5e50af17ecebbbc3\nB = 1b8aa718d61447003fdbaa748a9d86befdd2675a677cf34a1be7c81e4577f665d71135a8a243976a4f6ffa1636695567bde522f8fb1948033a7e0941f833d827e957781cb4349a08c6be418befc8959960fd5fc1b288c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9df82b7c34ca97a3a5d4efa28d5ed4f35484914dd73af9090c4bb31ea3496ece8ec650f4e7b07dc779c97e597e76e43cdadbfc6e72b61ea718c073be1cd204f8ad2bad0df1e530e75705f3d3dc285e9d793c8d42f04dc20773d3fcda8ef3ac1cb10d33d20a91add0358ab8658f49d2fe51d0d2d72684e31c0eef85e5695bb4b4\nA = 1fc2a171445ee6add5c2e4d29e50b91d83338f8d63c111e4d3e95f16d2a33be02bef24dcc3d6ce6bb8f1ef980dbf8fed409a0232c0566153014eef840aff58ed8c33e8d463d408f93e2f5381a26fdea63676c4e5397eba1d39f928\nB = -bdac7a177c77451104852bb99004ce8e617036906667258d85adcbe8cda21ab7d03aa7dcf62cb210a9db8fc750c7e1ad290b35473be0fd607fcdc686de0b78fd9f258f5b25e2ed43c2ad1a38859f882b9f6b293dc258659\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = bd9f3d2e8a1086b177698f87a9860e3a5f030e04a0bf4ee9436ac55e005bda01ff4ac662cb85d39e98a41c723ae542a83a936c3bd0280c6801ffda080ec0aa4230b45dcd0bc5eb41cfcf272028bce3572847637a92d1543bb2b8408e880f5b776e1cf14fa28d15cfb584f025596ff10c9f091c837a3aa622d9e5c856db8ac207\nA = -7fd5357cbee7c5e31fb62ad03bd47b705b574d915200fc7f1013d836b9cb683db020b152ae9464de6aeb8baf14999ac7025dde6173fae6ade325c60ec310eff6dc4130a8efffb15ddae90d760cb7f76a27d0368175d4a44a22f7f223\nB = 5894a0223e4aafe4efd4572752fbde4952c8b09cdfc35137e7e6ed650f8fdcfce9de673853dbf73730b159b2656047e69377d7c5025a6b346fb08831e64bc8bc34b75765012460d8135a4f7a0f41d768fb85abf17f5e2f5c3f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2c61867bca70e8662c7e5435a5aec020faae86fb079b992bf49d8497fc5f96abbd38a6f04f6ca8510e0160e546b3f68b7baef4ef0f404e881771cc12ec5ed3e3787c2d2ad6bb957cc59f8d56f0afb4bea49cb671cb42f4e8a0ee1dfadb6fa14f84a5b3269dd33e20d658ea4cc39499c7a39a4b5650ad7018d32f97954610f676\nA = -1bf5ae15f24c7c14eb59605136a3f679f303cd5b81e4a27465281d17715afdc2c231d7ccbc59f80ad176f4e0326eb757b52e3695e27c6776d7936da47e3a8a904f735b151422029535045ef489e61ec93f02e6d588491c8dad1cc311f52\nB = -3238dcafb85ce557036d19e42e7e7e473de9f9da6f920e18845dd010546868d2652decc94596cd2c36bd16b02c02559892b9f573bf21ab18c3c75591413d046b385d08aa66d849ab8adc9fbf788e837b047a7ce2b9c63f7fbd263\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c1d04b831b712d0619db462c3f3fb5973f5984e9a48493ff273a5abe17a548e185d751628899e2851e425a7d4b2c72d4d908dc813cd122b8f497e08e299dca9166f19752ff8cd9840a70155ed9e8c063a3840838b3679f96f1cd5f1cbf0e037d222029e02769dce7fdaea0bbb5417f85497d77c76a387c6b970eac15dcd128ba\nA = 7aeb60c134e84f289e419b74f99a5ce", - "5b4aed5fc630d5d591ac7643251ad32d6ca7f052fdf8857f67138262d221de644140e9018f7b84879d74883f8f251303f65e06bb52246ec6a912772cb698b47de41c1826ddd065359f6b9f1ccb0cdf\nB = 17f81e53d9fa6201e4d3eeebb32267929cd5258d10f053e7c021c4afd17094f8ecf433b1ca752f8740f6d6bd84f801b1b9fd64bc4787b9ae5e5aba0b4318a63dfe27e92d5a3ade192af7563c74c9d6006ae7701240efdd6021a83cf6\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = aef89874854ed34deae1b77286f9cb0e3017e3ae77fe050bb244acf4f30dc03504c73c1a4d44b769709bdb53811a5d0f8a76a08e6a66fc2cc4e98537ad6a8049f02494305b89a49a55e71fcc3f5fc42d6b478456ada9b19ec0a03f5ccfac5538c0040092771660312be5e51996073ff1a506d7460c57d54e10dc2991c028606a\nA = 18d3af14bbffbfcabdaabe44074b407d69abdd80a6eaa5954f0e45fac85af7ced1715c78da872f7a8fabaad3207e31f12b7195cdb25abef0a1e54d3b13349d997f207fe130d7985e2033cfec899a0af310c9827749cd22bd062eb0b1faa254de\nB = -85a7d9f08a60031e689b0e611d7f7f46e1178eaa2e6459602e738990c77f4d3783ac43fc04d53504cf67fccbeb02f9846756f8e32fa4a9316b6d3b45f644254077bef096a72bcff17ffa17070a4355121cc5daa2f782fc0d0bb48101db\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 14a85edc6297763547702c212b1a8274b8f85d53ef35cd1b01ed51039bbe030d0a1b9626ae2f571a43f1224d723847a1c6708f2238f6f6fd75db6656e6c703a5acb57f69717efe8ed58a3713ba2720d8c001d026d83de0ce5e24b67c41daacedaadfe404aaa9b672f00562e6901fbd0710c4303fec41ee3338100beb36c9b1ed\nA = -44414ec207060d105f599b9a66aafecc5b232b55214c1a5e1922f6b59439b3ff77cd3a327bce4f7406871196b90350e6dca9aae147ce03027dc4de7563c734f111d95171f489105de5ca80047cfa43f7e932917b816ba7d41fb95b4106745d700f\nB = 45f2cea1b9b75880ac3ec206740cfe0ecceb488c9155cfacf5885a8cb49be78af8cf221ff8de2328f4880479c031f830a3c9eaebfd83f7de501b7c5cde03c4720c56a676d331b2a13c4689a2e34a43fc11f62825b8776e75d31225ca7ff65\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 7670c1e2e141d8f8f5466de8ae2e0ba2eb3eb7634699eab8415d3a37f8df291d00def88361e9fb64a2f116433dac3ac2764fd62f3201dce4e48a3b7019e5465f82241ffda29d5eb0462fde74dea3168f8993ccd4d090b9c31a5a6cd7e05f725bbc89479836b89379b422250ab049f31c860110df5ed69089716877fb0ad7b0dc\nA = -15b4a2f808a85a5bd466a342c4853c04ac0ab73f8e53a4a0477f73dfeb8d7a911ab2eb5d3d192b9b084d0e38db491148947c66f838aa5f460c37341b129137614259efa531c0e6ffdf163ec6851737037a5299060418d96da035e6f583e6ba79d0414\nB = -3e94fdf22004384f7881875b1d8f58019ed8afb1b6a31f5d591e77b0998f3100b34174d6f3466da44b4c7fc8b92ccc5679c26c146b704198a65a88554d24291adcf897bd758a035361f671a82972b5962002c6a828792980f86a64547165327f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 35b49beccd8d2010a8d777c1ff69e28e01a1bb78c6466e717f0a934bb62f9bbcec5ed29f9cd2c14d240a6c33b28c986eb9c8912a4927605532483dcfd31a50876e1819f3d7a0f49bd276ced5c4110470244fca52d2611ed7e31cd8b73e749aa70743b39e92810b3b52320342a65cad3180f6e2966059d15f79e5574348f5f66c\nA = 6fd078e3cbcda6a71a710e99204da640edc71a65974fc765999a74ab50a0e4b090d57ed0ee869c8da2cf694b6fab56e87c4af62fbe73eb8890bc066ec3460beba04dac3b8fae7e4f316e8f954c6e8d934e946dfdc9f4cde0f26bb3d40d5c444b03bfc65\nB = 14d8041a3b83468d2f44f150ad8d8d0a1a22035d630f2a17b70d5c3d557d3abc7e4d753e1ebfb3a3ba465520b84746073d211a67e079ec7f47c2cff9c06da69bb5cbafcb6cabe7e0018867c42e07931d6797d4499463e3cf786c6d5d6c8cbd600d8\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2f6e0fed8a9720fbd83ce950d7545d2c6d5b271582194570424f90309227a51777cac974bca0ad3c1289ceb91cf75af73b0645cc20d71e7789144876b8c1bdd550328d9907accc316189e8ad81310848cddd2dbe362c9398d814a048f93f9368fdbec0f19ab87ad2a59d4066d738c3da3cb71d4716f2cd2336ad35ea1438276c\nA = 14bda9e4aac85b0ab7abece728f61450b7779d3b5fb83be813758e742d2ad76597f132aed91e20a75c554f0d61ec4dd118eb733d04942b2548b1efdb4dd22fdb543d9bc1e4bf0574ae2cb2c46fb98cc4835b6a074d6df1a3bc5443beabdc784d542e3349ad\nB = -efd765f8ffd72d041ac3244078b8dc4482233e9411b289cbc2cfc26fed2cf28e286835010438ddc9e7021ceb098b10c68bcc4732608ec1f4052df9362176ee14812bbf09ccf7c2882714ecbbf92bbff61c06e9dc35a368208a05dde949fa2cd091ce0\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 1f0c436379f6dff55a59093ff2a0626a9b959e3e3e59365afc33c7a7893f04bca863ec910c446957baa8de4e35a1f4e9c4a776ef41b053f03b775f327eb7e5fbe68bbb478aa4339ae703ee4b573d6931e47e09271d40239d527fe77098a7fbe519f5eda1f26dd6a7d0ee6833efe37187d8a85844690fecf9fdc3a4d80b921130\nA = -51eb34de29ba24d2b1fbeb0a1c324f4ebc69cda2dff971a315c0c2775d988b03ca29891ed0790f3dd507a1d26ead461dade9284613e45df338dd83aebfb66050465d8aee554970b43f7d4e0428e1512289fa1f9b23867b67095c455b66d536b91207b749189c\nB = 55259a1122eb7eb611a69118d3d42c2f05dd228d71c0e1e42ae3a8d3d180a95b74150d844e916ac85105805126e4b995f2ed1cd3fcdf28e1fd241dbe3125dfb3e4d90556256eb513a2f7c9b596719c83b26931d92bfd3573560e8bf054138f5d6b9cde72\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = ac321a272d2206df4dcd6ed8ca194a1049c1e3a20bf325fa44809d302170f850721c077bb5d792f86f7ab03ca259567397cc2fa1429771190bb632ac2c92d3fccf6e05e13cd33149994cda5f9c57da155439663f6a13c66f9da553f5038fb92fdba186ed9ca04b8ec87cba4c5a68c8edeedb94e38a6dbe293340dee1a4ecc768\nA = -19ac99d7d51456b00a193b3b04693c7e5436e05763f0154768db078ea5111cfe9eda3451091af213b9c8cc649d341de66c12ab2803ea39655d3d7de182a77355ca444c5d2778f791d39952a7a11839e497f5dfd8a703df49ec4d7628bfc25a992e94a6477e6be39\nB = -286d1d436f113308be594f0f43d7a05120639152b7e2f93058cf602cbdbc016512bfd23f7aa937fb358b7b602d15998ecc150f2b9224c58527c0c1267739e065e24236771e2c683957871637468181e6e896b513569bd004b9845f0f0e4c26a5ca123365e1c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 3466804a1b7d1af8b6060aa93a4c325d9cadb33ebcc8bd991f9e44cc2cca8918411efeed0f005790d649382ec40278c8cff903cf3db177d24466c58cf6a56ffc14e595c36bfefaa2327d37f616b1466eb702f5c49170598bc361d892e18051b8233dbc5b3fd6832befd9a995bcef3b0f3beda6efaf09f7306ec203172e78264f\nA = 6710c19330d3f974fc377e28039e0c0ee0a558621fd67fe724c326537c18c66dc5eec60980e07d401ad5556a05688d2dbe7b271f9d5eda3032bf7cb7c420e7b5d65a195bc037090b6fe83064ac3731624ce2baaaa62a6eb07156ca12ee51d4321988026cff573ede9\nB = 137ca18f47a151363a3e8c52dcf024262ba525ec8852e8e406f460fffc2cf88f1999b17a5821849317fcd84d09c88ebb6eb0340120f113d7ca5fbd91c6a40cd790bce7b422552cc0cfd2a6417add2501db1667f2802e5d0f4df824adbd033a90a155cebfbe0b53\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6f248a70b2cddd9627b32fbd130f05a604866799365f94d97f1eb582b28192959692a870be7c2614536a8de84", - "cd8c1364a75a3927ef9dddbb8c6c87dbf526f2d3a7916384f2daed96002831173fa4a51863c28b4378f99b1b201010581d5eabd66ad1e328cc4e647bf5e0588bb775e130b4a4d029eeeeb5852c5742862ddbc3e\nA = 1f014cdd87cb33ffee623cf454edf2c476e91df279b4f0879637eb6e8e5ccab305186de67585595d34ebc195fb150408c4620cf6c7a0b0d9695ba0e0e1d7552ca7d0be3dd678b1cce2beedd11939891a6804770f1c843e16dc2ea6aa8e4043940c37fd3d950caa122845\nB = -8d8d9dedc80994fc5db04d8c935301e47054250fea9020bde8d5fef01f2307cbf458d5afef5210a369c396287c5eb453637a2d721085af3de0d75a5dfb5dfd22fde3b229d438439af7b296b9e68ffc982efc6c825556c52a735f8be12a214a06c4270824d5268fb6\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = a35ff7e232f047e575b200b9fc4c9253de6ac04c612b8a82c275a951075eace5e7d6664fe8f78301d554cebe7b996c1f4ec3ca59d8d12d7196eb3909223de94c220f0445d24233534af1c93433b05c5924799d2c781fdb88c4537bb8d442e6bf76b2d966827bfb4f40378a3f135103513da056bc0d375b1339561700d15a0227\nA = -58346cc8a9a1e5b8babaed8e7f59415388e0db654ea7cd465d96781c57faae7a8af8e7578e46f3a8de7bd1027188e1cc32fd1c0d60be24fa3289a12cd822a6c9a77dcf8799624856c27ba88fbdb047473274e651760581b44457ed048cf76c166d38bb9b2afd3416ac7e45\nB = 61951a16dc6466a9fabae99df29b7229f1ab96b476092dca1e4f8fc8e7404e2fba56ee66486d1f27f89bb3f86f271307228d7d6cbcff943961e177300b6acec1eeb46af1c5725f745a2d2af0fd9642f57a09c9ce6742114be0aa6e939e638bd5c7a92a7c206b2d36e35\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 90b441d8277eb1ed454964acf567067925881b5db0b446a7d554dc61ae87ff979bfb0e58ca1706123453e62ce31284a5a2db1228d259e27abc7fb5cc5848dbeb9a6808fa1b4afa844ab39b652abc41423c2833e1209a1674db518b6df7ebae315dd7f416df54e73088762ef64cc2cd0a08b1cb01c49d9299d149cbe84145a55c\nA = -1ebb693ea7d18e0ff4a9a51124ebb78bfa3a4635b75a6387e9fc745a2325409f927324d1289be8a4f5cf2d5c04adc7ead20564f97e453287f03e5ab59a6133584f970446652d05a131d7d382c47b7cb97580ef6710a532dd4f5a0369dd3db500ae5a3c5efb587cf0cd2638382\nB = -3916ebc4653e7d6e0a4f1e234d765d41e9e948b5acd7ebc73cb595559c1b20b037a3c8da0a7aebfa5fd327bdcc922551cdb8db3fb0a581fa0620ca2d2559ccde3ebc44542b4d80926d061e2a35c08c09547e0cd587c396ff2959ee93ea64b1e6b7e2b624cdf445988e1f42\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 3ac61c3a028f4a2df6645acbd36818a2f76a3229d229ce22471760807585a909727411e8b68bfa4e76adc459409a101a1ce83900d46918e8d0903a163de87c07bbafbd60c7f536a62c59370ea53b6cea4384345343146bbf529334b4201ebdc7585b6e5eee42696400c9be9f496406a4eb51d2fd1b40466224f1752b181774ad\nA = 5a16d5fb9047949684b80805e5d962bdb939d0d0368b48517a2a826679c37ee0ded4fa83e657192d9ae84294e450f7e2f2773d1f13395169582cbf95860891b9fdf8f3240a16aadd1198e884f22b2718219d478e2410fd4bb98ea534a3626201959af099fa55488f5390791bcc7\nB = 1f67066dd06ed4a49cb556dc2fce22814754885a7cf6c13915d974b46b0e6269c0fafd688f45ed2deeb026a7cbb772c080dfd577d21ed2c81e50e7537a70dd550eb94fcdf626500040da88c43dabce13c82a93769a9e0ef66a471661292dfd3b3af07169e2dc909e43678400b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 7087dd62eed6ccffc7e1370cca9444dccc4ff160458941aa9f49dec1a2e9ecce4cf50ac2daf06994c5010cf225cc92238cd60e1aed9edb2befb0fb354ffdde94ef5e8ad0415bc95851d59095a5c4850ec52a74c78eab58309f395d3078dc481feb9d30bcd9f113af7a01611b94d085e32193dec738a64c5fe9bdfbf5dbc98cda\nA = 13596eeefbf06e9ead8d883113d8ae6cc3da8b6fa13ab66681db5a9c083ef9e49d905ec19c39b149cc09452eea0446b29cc92d4e865e6f681827336945282fa6b276ef552363229a976c503b822e6e4a9862d3fb30dd0c3627ccb97a7046a6a679050a39166388a9daad5ec5555dbf\nB = -a4e574363f2e5982cc087b38110d257019962fc166c2d6e6d396220bb308a8a0dc7d90c5cb2ab85faa19b07ed7dc11eae9bf2abde0a5fed279e77a717b43d35e70fec4e18445e37741262d0b0c20dc4375371d87d839d39934f1dc41122e815f3f37352d04d0cf514738b351f02\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 8495eeee238164082240ae1db1e3c1e36fb6621e6b714c9de914f9de8a587d7106b8dc5214f7c60c0ee231d7441e03cc26462e71adf8e29772ac95d0395722d2756f9f64daa8ed41d7ce824a572d7f9fd419112ae823b5b48b8aaae09fe093e9ed05918c4ec88ab159890910837ad0691849b44be95993682b2da2b124de39ec\nA = -403f21e1a7911806747bb78a4f20c4e6572d49c6c4ce071db0c8c91ee985e68a16e60093e4628414b2673d25c9f13c4c43600633af95017e3846512197c9515aaf9953570ce5861620716b3d80eae7de0f033772fba82652484cb3ce7cc189d1fafb14e044e07a88da302547f2e623d8\nB = 689d1b4a968b7c00082ae3a29c8571f826c4630c947a7767fe4a71af43a5de84db9b5baec0980eafd0019e09de1b5c56173ede68c9a6acf260bef3d9a03f4c83a33106c94ca7e1a8615b3553088d1d05a62ddab0f1e5a126df5d960f67e3b92981022e1f0358c7970bb2fd5dce7a7c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 397df584bcd3b2e1ec7ed89de624e9d104bd6812901e38c5740755ce91bd54155c0b624c590ded199590be5d98bd1ad4acee56a62d05d6b5fdd1ade12f7db8e3eb08c4a5996450cc1204be7ba61b768af0efd563ea478033324731e24fedada1ad6e564238c891494e85ded4feb2165fda22f75bf120856034a9206511885fd5\nA = -19cc480d1e07523bac502872a971d78bb26955c5453386f5d51767150e229daad3ab2dc85e0fa0cf6e72389391fe627fd2d9f263f105508642eae5a095ec4d88545dc9d0a2c436907460e1ea7db174673000eb2e0b60d57163ced261bd0f6cd8ce54133cfa10591f1fd27996353110060cf\nB = -39c45512fc7c9620194fb7ad22abea8f6dbff4a137dc4523115ad7e262934143cf1f320892f8c097a400d4099e787ea7041d0d69b6269d191fcdc8ea28340ecacab71058cb39a9c7362c848826b35ab560c27113fe53c497ca452397891c81365b6e7f07f916d47961e50b8c7c5cab38f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 263ab04c98efac12210beb66b13fec7c260c5b1cbc20cd732a511fb3786b917a617d6622847f4eed70f25982ef5d0b0d13848c62dcf447e3a1d491f4c80e69cec03cd318f6f93134d582210bfa81c1790562053a71091333348c6624d4d793fd6ef971d284a4ebf0be0771efad302015abfaf3edba017907f10ea14a46d9fdc4\nA = 7a354753e39b9ad1c0ad6b65575fc7247487f3ea320fa82d1d333ba8dd5d0ff925331994a6961c9c603be5775ef1842159551f0bfb34920b93d90ca60e6abd514650f77ee8ffff2bac0eecd0fe8ea0fffc6ed0285c9f3c3cfaacf338043975457d62f9c8dda8cce1e99f34529435016fe2ed4\nB = 1a4384f9620567c698ced05870b4dae983d8f0df6aec888353f9dd6ac8ad54340c3ba8346bfa47bac38897f3963fce972f6d55f3407ae03f5c7637be1a34e483e50dcc27148b76ef079f117104162beb191d146ec828ad5c5bde5ee1683a031d554c276d837bf1f2f622cd11baabce10212e\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 91cf4d1899e170bf75dda0d51a6481f79eb94c333b876382c9d04681073e949191223926523f6531f0a45765d7f382221eaa080d7bd05a3c19220ebe18802b15d8009714e8e4e9872223049622ca02040eb041707c7e525f698cc361847c66fe3673a72e4d701466bc374f55fa5437216eb59375c0e2c4f7020149d0118ea72a\nA = 12f35c48024e8271e8f9a60a48b5a214bfb6595a837c041b230e6ac87a4c1d4b3f93a2d3a193c750c9857c8627d0f7c454d6c4f224dbf14a865eb83e990b1d9b8bfb729b8d3dedbbe9c95032e4d60676c2baa2aabafa698392590add3b83b521a7a5e7d6", - "f8af207e44ebecd735374acd01ef5822\nB = -8fc18f92c0613d085cf3ee6f586b39b99ecca864bcbe60fffc63c585e5613df68f3534ad46e244916b1f9188507a3692526c9e403b8e93480b0a5a6297f65215f1a5d8e20631a9d559fa1acc15a98c9397761ce18903f393b10444ba51bc92ac44df90d4cf0852da9d75902230c6de6f26dfdb\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9af562a7b61c6c84c91bf979f32ba5d246d2ee2050f07ec2dd5cb3f9496bd37c3922ecb2b5b17085a13e93ab2dac6022077cc18c621cce3a2d2247e5e89de8692a36f596e5dc7a6969a4f3ff0d1580eed380e6550c6218c1938caa2b7ab401ae6f520063c811088504d60a19da3b5018d640ab8d340f35d1337a2ede8bc64bf0\nA = -63bc10b8fbcb391dea305fe61b404d3bebd035514a812d0e1d38daa3d67f9f1bb8f02d2979270cb9147aa51d66ca73d4b5787e472456a13fbe0d568e92b622439d33ad3c357a56dd26806ebda7b3bb592385ca5dba7e5eb5d85eed0a1746441e8d56e22decdbf8f4296e30d222da5af17c427e832b\nB = 57a602bbdefcdd00f42ed1e2cbde2ba858d171804da56b0ac87081424ad1569df1308fee7c9ed349eb496d5409c4c46921f09ff0830bc9f57e920e17df16523598fd90314141955ddb84a1522ff3ebfa812cfeb6670525123476a739f64ebe6a5f1fc805a880f8e5a71b908c483a121b38d05cc2c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = b395c9f264172a3653af6637e72c4c8e564d1ce68032a5d761bf546e0c4b51b33cb026bb4256fa639ae98e54e5ff7d8921ae411497272b53d97c2c44b5b9ecc5aba43dde201f64f1d033056f19ceb0cbd04decb486a1d07ab1c64fd213d7eb6db9cd11efd743462e137f368acc4ca0b49a7f85587bbb5ede4be1616889e2699d\nA = -1e71df5f04001f6468c3a192086bda948aedd19c5da9a5286856f30524238d95b0ae71940f2af123315ab5d2fc61964d3e970d5858b7c1a78d0f2cfd10cba7ba4830a8c19a09b59794ca5d7da32cd8376b5ab06079b51cd9819c0021ea41a9e43aee147befdbb17a92cac7c7767705fdd908bcd291fbb\nB = -394c187308320ba1b14d91d75b8ff993dfd57f9c84e8185f12bf9924e046629ffcd7174879f9925bb643988259cbe9dc9277fa83a25012f91159b012f1964aefddd5a94ac6c2a55a22bbae93085dee079f84cea1d53dc4771901db9a3db5a14eb17c25aaf5377e2beaff6276cbce7cee97a9b8f32737\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6602ce0fb5002eca37e85b60cc871b7b2eed13d38c20a37a6e0886ee4814f3ce2515f8714c67ad81e8c3abf6a00464e6a51b15e55b6c11296ada43cf459e15915026d3260cce8fb796241fc2b0bdd2b65ec04bee3b7ab6626e10597f3b13b43d16c34afd5b43a219917626c88b24c6f8392bde1b2e65a50b7f1a8dc5eb096702\nA = 4855ce75a3d7dbb72a257f6291e9f6ccc158647aeb2f8beb3e8fb32f6f59af1a46617b77440798562d6f58bfe826d3ea7dd28daee8f5162d7d24ae6c24c2deb2669b15898689ca789e2005903f3a94e991e7d3c8f3ae6181029d959bb15e71d7ba94d2dfd3ddd10f6fc49a65798b5f6ffd64682c78b5d91\nB = 15b3e9992aa3f042fd58ff97a8c04aaebf46b75fdc38caa9224394a1805cc26e4311bfb498d5a04d19396e98d11c8810620979362df82b23a115fc1711b57c7a56b8408e2682a2edca36cf9311addfedd2d0889a78cc1ab170d1379245de6f1f6f4db815fea9130463dfe5283f195e6e81486a1d39634aa\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6a81ccd82f00d829bac186fb38b85097d52afa3ca83a026856bb83f94d6af6f6c6f3141d433f8fc159d11397df8d2f44c769f255cf8148249d8e9fc4f59ec3bc8e804d7d5189e71e20b8d0e540b59a2854ddd7feeebda5a95f17605e8bd5f311a63cc2e4ce23a51229d0a49ca04982c1bff79c201de6cc6150b690c98106a39c\nA = 1f1589c9b5ad9d878631cb03c23ea7e94680220856285668838452a63b726e01709588b38e578da8a4845aa5cc2e4723beafa4f81a1a2e463f67d9a3e432de7064ba8bfcb943cd9efb0e5a136649cdcf5e85a667917075804991b997f318752304f4946d69abf161625ed0c03bf9abeb4ef28034f818e2a643\nB = -909dc7fcbd27d0bf7d6a3d0e2937ce725b5cca0acf78c103d633206cb431e2e2c785aea4bfe2042df32417143de76b71d21587112f36d067f878e556b94ef63d59a07d19647593efdba7f3f5324d64c55f93a283a0dafe080167f6576053f9beb326994f4a1d53e18e3f3e770e69450bb70f276d128e48ecc\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 69139f2e10726f83300505d15dcbad5b5f284d1c06789181683b7b8caf35dff063dfa4968c35facf32a3628dcfc19b3fa4c30ba0e030b06773832a2631529fe0c0c402e05a0c4e9446a8b6c22754c70ef540f90d903d83a2e3592169ce6b5edf939ac5ff25b8bd48aa2425321602a9571661a1109e275a3b3039ff0c2f430b18\nA = -5d02cf3969bff8789850ac898c00fcb3ff1fc49a22cb243ad18703bb8fae25f83502bcdd885417fe46e8237fd0b444712c4fdb8f4972dbf9278a83eb305efc7a8210ce55167c069d1c4136a9b66d0c4dfadbf036c079d12aa082fbb42bfb0098006136a61f3da43aba3d3bcf2f5ac2d7884caddd0cfc28681d33\nB = 50b369234d993721288662d83298d99b9052a0a66336a5a31b76dfb20ec2b5be3aa76f78b2c17c63d78402a15aacb585be5c8d2e7083145e316e71e111fd34f5c79363c4591c247b1a94b20ee042d840c42a3001d6c8dc7cc1e1348e0e3ea8c6551f9d24af2dc2d0c38a54ef065ff048b148ce4f11ed2b549c50\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 87de406a6c957e85c759f8ff684023a0f98e93ad4ffcbc6fb0038c7a7ceed2486f15f36555d286338aab3283aef677118f7cc3f88a7ff0ac9fed31da6786ce895c3c08d3edb652bbc9ac2b44c4cd24ad281ca3a8e8e6e4d730f4f0c25487cfc1b2afe222934eca8b1e1572780dcc149422a88eeb1bf31065c929685a0a97ac3a\nA = -1878e0497aa1c2942a2e6956957c876dac73c4bdbf42bc92498f29a006bc92f788c24a4624b87324a7c8aedc6b2c0c8a1a442aa91557aed9bf2c02b6664979e8a9a21330dd839f4ba8f84515fa6f7db9287f7c20f31732b98fc09ee7796dc524870dc35851814bc57e1a8ac49d8935fea04bb08b8760df33a98149b\nB = -32f4e94bd073cf3f70810d9af7a873996a0510109bc6fdebb855f27dcd012c59507491152d30849d75f95dd868992c6fbbf29b1d899cfd401e9e7f4e0436732cb4cc9e6a6d6b0cb63fb0bee21e422b7f7b7b14dc5d2b6d10447fc4add390fd3c8e7b06f1d9b181adfa8d04459ed051bbdc9666623b00e3871e597be\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = b456ccf9d066dcf4247a21c7f3820e324ac9cf004cecf8dd1f6c3aa40c2a33e24c423e97190fc71bb9fec21d36c5a687065a7877237a2a05e64cabfb3b20bfff0b1f5ef2e9adb7edcd7140d1047b0919a2c770579ab44a08e5ad9f63a06f90ec7d5885b91de5e524b2e187937609b4b81d40a0b33e31a48d7b9868add75286a6\nA = 6c484e3c6b530dcd3644b19fee66c41c7c2c1dbcde574d87ee13cabef9dccbe5b41e25c32c6a56df23f2e87176afd28249e5fcb918723707fca94d7e2c9623a3493d395db802a1b49d550f52c29666f785652fe81afcab00a60a5b50cbf523cd13dfa06d5a5b0809c68ff7264a2cb35b8d52284172c62ee658e8417e6\nB = 1b4fc753d0530bd07094bae09a02b1ea684fb4e8519086b1e2ed9d59af011f61d1b94ffca6f354a5b428417b328bb1e8af3f6c7ac9121dae58de9f1dcbaa9c73a357f408b870e62b0c7db1a72c4c440f2e6fe90b199b9dab29fc23927190d3f2bf8a7ee926a152e64474283695614ad696c85ea547f5f51d02d1b823e3\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5e7c63276f350f04816a6ed9f98507a78314f1d99081fcd906affa3b8395fb58d029ec657af82e77ef45611bc988095bba9c26f25f8fd404432fecd02398e69635f3315a824d6a98b33eaf6a91f12957a5e80cb48d5b086c795eb3b1e04da5432a7e8be3d683addc586a44b6243ffbb7a979bf9664cc7ec41e75f267d58a7127\nA = 18efe267d4c62576294f4ba44c67a058cdc0bb44c48f4035682b2d6b8a63106081af43d99098ce133f8d7f9cd04d4dd7414f704e32871d43d6e5d73fa9f447873168b43b32d6ad19378d74a967f92ec7629a690d29a62a5a6e734e9ccf5b84857a00d97b9db846b057004b03d88b827dde717fc30e6a", - "5246c752d65dd625\nB = -ebaa580d3eef5361547c692e107439c8391ac0a2d1cec0cd275d0be69133eba8a94bd186ff9a129af3f5a015d5ebd30215643554d7064635dc11ec7a8ed2200fd637b099e534237f0495d2b629abd4c8f84aa1d925d53e98490d02f9fe51bdda08b043f67f0903c0195fcb886c04397d3612e4501ab8c7b7db69f781e169\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 76fcb39f94dd2756e8266c025cebe8e801524a757b976e35ed45e3da3db720061cee9037fdb34776c704ad2059ad8920e400bfbf10eca9bb157eca7750cc31fda06473bd22d4def80189c47ba32e2824c721425f225563df2a2ea1edd090e01c0bf980677db5a5dcad37d21a68e2832d1012586f506480e929b2fd9bb4aaddf0\nA = -75f903ed9bb0b6db8e3be16e797258f6c18f6cb7b16f835f04e3045f7e4974d7a86a63f2ec351c88fadc0635b6dc83a797cdcb5cce1a1674f89e44190991e0930575b19e2aa1512bbbf2ef6f8c3e707b17516756fadb635d8c6bf9caddeba14834b5950a4d1e98bca79a4d15e5fa5fa3c1727d7a49b33d481d32fb14ae4164\nB = 4ccc582c8460f7def2d26167b68788a681c41bdf6dc805dca83127a18bff6f5ebea6db75cd959beb859637b200ccb5c7644d571f436e46a357d027edc9769da226278f7ab947963f7caed1e7e70e572980e960e9764a40c6db67bb526694b084976142471270b2331da563a10427cbbb38e76203d7da5d67487eff701d75188\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5adef30c67aefea4da3884b8a1d0ce6724492bc76b477f1053621e7d19f3cac15448e9401d34e05ac4b508b9d1db9a8d323cf43722e0af6e3c3b6d463c6007449c3bc3236d156cdf988dfc308a1b4911554ecace52938a7b10f463d14f917ec3d9fddcf6d33081745009c59b58aa22bcd7dd8c3bbd489997d4e0bff5473ab9d5\nA = -174e8e057a1d66e22eff88de26f43fde1c8efe5611f6ba4f318f027f5a5818df02ec3f014dfedcdfc8c143c5005c3c5098d409710967c93474f5854c1113fe4030e6682bd56d389ca8b9a4587b8b9262d146bc92fcd81d75c3bfa4281898f394f45d5dd11cd4c7344ee7a933ee346bdaeb6f5188967c388b919a0ce6730c0bbdb\nB = -22702bcc4f9d5bc6f803af6af8072780ff7de7a346d6b9293ca751d6ee3a81493fa86738c44cf2b7be4bf14a55a4f8179c35c09dcb1485f4c08ec5e9f9b1efa91f4b5f15a31a46e1ed71cd934ba6bd271bb22bb5703aa468d297f360ecbb48f9fd6c572683e83ebc3d432203347dc62e19fa06f93e087283347950829d4256bf5f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5c2f67b1607776c10fe2c30b112e541c4d8229f5f99f615fa02cf715d3f20556a28eff5c233c58994e9c6c1fcc37b3416b0875b9a62fa5a09a4b8f9e216487203b387ff97fad1f39f674ab19c5e34cb2f162e6b0b0b0084f0618e64928423b73b189c744e3de9fa50d66f45975f68b14866cc16c8c6c722a54420adf027880aa\nA = 67056e93b69e8a7b789f1f8b835d9c6ecb7762f844d656b26df9844a60bfbe0d55684f61debeed31a24ef4246485e8a1d43d49eaf97ed9e7b9f2d2916a8d85b8c9e8ad5575cf5a3fea42392e5d1dfb23f7ad41a7b56a4f21e2828aab38a602d560c99783a4f807120292ceae366b1fbfb4be8e5d4561bc8944e7f17ebbcb0fb6296\nB = 1f874f244ed6cff9f910ba9a58db0dc0a7435e8d99ba6412e976b8f64d4106d3c5c57ba079384fced1c261aaa538e131734451fe84fd3cc5cc8b3ab46b2031f888d95084cd3a35a61092672a9118eee4ed1a0df0409e3613b3ef45a8b16b71ec892755dc3f83c5492b67fb9a143ee6102d053078f4875636b20b536d5cf851768cf73\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 7850019c6712f18eab877faa8489daba23cf34b512a3193852508185b13cd5a2e9f503fe8d61b74b5d3930021a5b8c38322aae9b9b1b4814fa4c2c5bc409b58f11fc8fd7854b17baa94a6bff5f234832f9468d90d148fa2bfed774ac03f2dab6a506a70db4ce363f932adcae202f04fdcae968f632dd674416c23d4e21345ef2\nA = 1e378a0f27e6259763890d29e112e3d8d2bdeb9994c49fb67ab680b6e71a52fa0a7db886d3baf52f36d943b5430ae8bcd82e229f4197239c35678eed254c5816722b995e9c311be942f8124e2f80c1e59658433a57f346adfcdb83202e55457308161d2f928b60efc39538a6469f90f1a868cf6077568c8241623896ddc2705cf04e4f\nB = -f4ee37e39d4cadb692bab5483ceaf0258b068f2c0354c540438803780c983469ea28324ce7e209c3bf55b91f0a2f4544bf318585e4514333eafb9b8c2f02170c620e9b5280a828ce1d8dfc64ae9c28577e15071825a85a59656c5b47d9a382af6b78a5b3dab1078dd647e0b473174b8415d401543d30a4018cc3eddbfa546d0fad9cbb2\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 4c8f8b671443a3af5ef5749885ce5de8e2afeadef9051bc49c0d7e72922d049b1accdb79d82288e472b07578e8b6d2176d6cbdd7f0caab593dc0fd9224a94920235410501fddd6001b62a7f7d8eceaa7a8e4c0de52029fae68656e8120972b5cc1c2e909c2742e836f2fecfa51e12e4f8a2ec7e69eab061c81785374ac607fbe\nA = -5769eae759dd6bf94468eae94189d3396886d4569b0ce264c22d39b623be3abb01bd5008b9fc86701a3373f7764118becadcc69481cbb134c20f669cefeb376dfc489dd4ee91cb333d06afa391dd322abe2b3b715d11ee372666473a473e29dd90fcc97e939049b455be52b3f288db306999019c1177ab5820d94859a9d2f050b7ee1d4a\nB = 44adcaf1e2afbfddae19b23cfc0f0ba1f940d32945d0b541db23f3a0a9d06fb1f67ade9a8e620bd96f4005ced99430c7a55eb7e93a701c829fd5b9e55dbb4d3833afbcaa0d9c946916b1a86af4a6393b1155c6439b8b82260e09ccf0ce5d1c4856f4d524983e4b0fa123267694a1c6118beb8be26113a02721a02d7b0ccb01ec6e9c0f9e19\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 51e25767b8d4d7b2b0c2652d9ca6bfdbfea06acba543b1bc8d3d25b2fe5f2998febe1a6e742abc3f482b4267854c2223a5918a9b5c84e0864278283bcb5bace0c046db1d0240443404fb62d70ebff3ccc655e5f5977958df4c878d9859a69731744f3d33978ac31551487270bb4fb56ccbf59402ef9fee42cbc329420180de08\nA = -1966812979042198f70b3f1238c93ac5c6e5749f1108c2bba869b1dac7680f910e56318c9b59be9212e713a348767ba6e75917fb599e929ea2144880d18d4fbda4f4663c7abb49b02245169f385e09098a4e01b56dadfca8c803acb7cc244f3c98bc17440ab2afce318476b80e1d0b4ed9a8d6f2a0be64633f8faad5eb48de2681a38a633ec\nB = -2e4f5eb92fc34c753c61dcc826abab6fc4f427c6ac7e73ffdf65b1037464b2a9a0b0290e713d81ab57c0e1dc30e76fdf96046fe10a34cc4511398319ee34bcaf73763a9042fcacf59a100c43d3333ffb3743048e8df0dc61fd0da3f935fadf882ffdfa9f0f42980c1af6edfdf161c4b16087e2b14277f655abe54582de79c51193e13169b55e6\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 33539b5f38a9943b15801d449adabe02da6e21651d96acd9aa40e866bf65015fa40178399254e8af6bb082d021e2a05da0f45b699d193b70112e114f0d25287476dc0c733c5cf9df57667ad0d3ffc4ea2f85b43cd10459cdca9465b0974e578c00a6e275e0b97ef2a4c9886aab7b5947b78a88f84a3f1d8c5f26bd07bcc59886\nA = 531b891fe9e8db322cec59a2115574c7a304c423e6b11516906b840542b2c608785e2c18033262ab9cf68f63edb40ad4f073ce8841db602cf8fae0a6771d741c6392976c9b333ecfcd0c8e9997da40616ae2a9e0c6be93fdc7af0dc0668ded1e42a9f729c70f74500ee76a91d3d993c075c2f645b35792a20edf17c157459e35c0a48da6c4c6f\nB = 1a6fdbfed1054a0c5758f92f72db7e5737b0740c4d8c3ae4713366ef6709b21eaecb6b74c92541a9a0c99ae18ac6ef7de79d4c84ce39ad59cea9c203734a99bbb895916275e8778cfcf7fbb7b7d081a677769e4ab96bc7bcf23303100e629fa8e07f5b8fc2e39c7b5724c72907eaad09d3088783b3118e57c9c8ad1799b43a13f73864c5602c478a\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2eab6018361f557ab06725ad90f6886d4b468ab1a193f8fdcfb4ad15fff781c8681329a27aeb5f03a81d7c404b8017b12fe23165e941ea767c733513a07e921aedf20596763f6f977316e37bed70f6a617e5c2757c229c59b3d7b1fe8755b5f65f7f4", - "07f13634aca7c8a267e661ae2f77fc5a95f56cd6c8458119df587478b1b\nA = 1cc779145b2b7bf9ef4c9692845e162329940f96eb43e04db8728bfe736698082aae6b6a1b3c32867c293b08547a0941cf4059d2d567840ab6ea526e3724ad59e715a3782ca656cbb739dfdf0c113a18f0dd62423d4edb60057fcaedbb852178d38f1b5a232842b4fc645cbfd97a8cac0b094b870064302dcdf23df2c9e9f736d93409cbb8ce9ab3\nB = -cbba16086b51bd83d3460e51cf193ebc79b826e4f30978274eac3b2dcb04e9d7b56a1449b7cb128bbfeff5c4720bae45271fcc64085d3ee501f0f21fe73cb7db5f275d88be55c339f9180ea21a8cf3755a875331931b75d23f57c2030c89c6f9c1ead431cb4dbd4480564c83f8470610e5673c7eb6c0fe7351ffd7ee460df5db7872c67041aff0227f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 96fd93535728b961b4167be8b304e570cc34e787c12a9a5d76e099b336ed6b837cfc246c5bceb04b0f4744c5da7071fc01d70e342509473e5bd7c60d6046c9b4f21c5ee71c4e678447f837db3a7694fc3936ca733efdb7d387f0f6e263b3ac0b89054a826da9716691c9d580ad38d701d08ca090b6c59be466e1b9833e75d820\nA = -6791fd686f46c3773fc8d7f4753d178a93f6fa4941f4305d9689c2a305bc67840bbef80ff05c7bc6de3a595f73846609327d28540cd705f5aa94a3ae5915ef55304c37c4c43a4b46906889331ee16585629bb303673d439de9c0236f708fd19a977e6e1032e0576a921853f7dd328979ad1f1aa945905dae93a82b3af9451a541f544c18ed2546b66e\nB = 6ae062b39c77bebc2fef05743e6d35e14a31c6fe1fdc42d8de2db94ce70a6d60d66263c7414b1081ef2fa6ab511b361b8baa9c71ec628dba5bfd772c440baefc2fbed68d40897878232d9715c4b7e7c9bdd41cfe7b6986d825f68be8cc16d04afb0cf593f3028f3dcd91bc94923f3d7211aa5f0f12d3270e8df8bc191808f0e266c4fce2af97ac7ce06b0\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 949ea5f645ffe5d0d03359d51a663c7dd6e6013812a47be309575e036503126f48677c68c4ef6e7b3f72d76657fa282ad5881263e649b5297da82e24298300d032af3f5e8309ac7eb597b16e257a6f7af3476a264415aa7783433e83be57ffb3fdb404a9ddc3527d6a9c297f8cb7b6674961b3af837ebb65f218147a46c39cba\nA = -10f59ba073126d92a201529a5374500612bc59a9e66322c6706b422d35a4f82d97e668b268f5527b4641c6099c80bcea504234f3c1e3fd29eba0f161da97c50aea542becba499f29d4ba5571873d4dd9eb3f48cb26fa6c929a704fe8e49791b2ca3293c2428d9cb453263935c9c90a4a2b39d23a0baa12535845f907d42b729033a0a1e74d18da30a88ed\nB = -34fdf9ae6760d4f434d09ce2a7760ca2dda14bc256015809745524dc49d841b07102aefe5a1d0182e3e09d4d45b415e46f653185742b9b8ea6960160752080e5c9577a12182ccf1a293407b534ea8ddd33ad16cd19ba537d8db5b542f86a2a292423d452bf18d82361240a7efa831518184572c5a8b73b108a81d5036b3b530d98bd47c7fb2123418f12e05e\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9ab739ddae55a0d71b39974628d4601122ba6c5035c3ad0439691317f23dc33c0014f3e870a105e4dc1432ec79693bac658433b21cfc218ed411e003990b94ebfa87767f3614ec19f5bc30704adcaf85a9d3d15ea764c8f0bbd52ff388659637746d39859398c79016ace8c6f97d3a5616711a235b85f334fb889b9280ccbea1\nA = 76b15a0aa0f59ec804a5e9a627e1fed524320b29120b6789f8e71b1ac4e00a9a8c826919035b84f87d291e2f35460bee181342136dd9eaeb99ed00c6328b8e44c49ede3921d6275f6e7f03de179fb2374ae2fa6c58852fbb2649e214691daef945ead6c8bd5a53ad2b130e9eab6ad046ddd6b80874ca6515322bc171ee32749333669de0d9c883058423579\nB = 1fe2171056ed4585a143b6b2bb5f44047664f64d710dfc05c18be5840ef9426ef05b6e92e4ecb5544ee4622e9030153dd9827f2f01ef38e62b88ecd6c46b4457d16644ef6d863c226acfd6928a40de614a5853137124fe69127a7f05463eaa49bc742d8f7be300d06b302dfb0ba86801119bcdc01b516afa360aa8b22b7c6c1839cff859ca1bf26e3f7e030512d\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5631048ffdb2767aa04d59d8a5750016b38b983a2d53743ba4de5d93bcfc8ec30183a84bb1e290ef9c72c7ad357728acecfc613a6f9b3d712456d545ed54a337930937f4589fe41e66ee930db3dc10a4fe41481008c69eced65b9d1c46b8574c5ac8f7d94025d8fff00ced17a5e17508527681bf94c2dedd51502a2c4652538c\nA = 1aca12b1933f25ea081e12ff4a4f6f9ce379f96d976da2ff7b8eb8ad791fabe31c1148fdec22dfd67828e540c955a1e13f40c5b125e1c7e6bd839bfa84e5bfb58bfed76058c6db77af7a34ffd25fabd60e19f65e1faeeea6371d7785f2e5bddc8650a7492e06691d61f997483661eeff54a30656f1daacf31182486bc40647975151fc05d2f64b50e632f5d5c4\nB = -88ed894287043e7e5cd2eda3c1e5c97f85809f7a246b0c20891fa9a024f3aba4ec1f3d112580fe6ba6b0bdcaa1325ac7ec9508aa88c187af08e4f37631eb6cc97e4481b18f747ce6d35ff355e425a4833834ffb8d34a818bdb015fb818ac9f58feb87020234243aff912da5590ea3f6cba74f1a9fc3ffa2b4aeea25479c55a3b572621e75d86d8c8f6ee4f587e0f5\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6ce341aa4a571cd5bc110dd436acaa09f409661967de0bd096c77c60db58b2b0ec95cda50acd7fa20ea4266b2c579eeb6ac214a75d40abbb70845db74c4d6c93f8c545add269d45fb15d985e7e630d0425565d06dad4a3ff9835411e51fdd9780c24f466dbf29244cd1b8c3445af181d0928db399bbc8632f7ebcb9d48c0b754\nA = -52c53999b02a92d6254557203cb31a21dcb896495d1f29f3277d19129ee43e521ab9d5a297204a844a9537d63b74686eceba72ea2e7b98ee8895513395cf7c44c99348f5c4eb657874a8115f0027d6a416b8a04a1ec0e6809b7701ee7d41e99996e307bee9c295ab3df1faf674e0067d0ab3bec4da998580203e33760870ae472a3045bbd66e352b8f4d284efc00\nB = 4329d110504caeb71ce0453b0706ff675f646e70a6bd9575791a38f672eff226f4958f8b1fe4123c0001d8f8595d8030d0e9798232942725a9b9d654ecf50546adfba7103fed796b455ffbb4c153e70f941bef7953c8a210d6f2f4ddf5d9a79d9938503ae8f24d69d5d7df1c988630ed960e12dd877bb80a1ab0bcf6db67e0c0578fc0c40408f72b19052534da8d31ed\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 4b9fc1e0eb4be199427c48bbe1b53948d0135bc1965b8aa5421a4ec704b13cf934c650405ba02ad611b0f29d46d82d4a1fc5a84651a29364524e37be2fc7001cbd3c792aa477802999841ff19620cf66dd2453c9b05aac349b9094d43b40e358f32805d87cea3cfa98e05240ff95ec57d88e0a12917628ebd34946eb1ad6799a\nA = -15a223b691d8b3696306b0ccdb52c1d62c7c2d1ac71e5f07cd8fba960417b42fb5ebed5eb9469be67f231b5254bb0fcfadf5ac5d2906769e8bf8292f0442986cabd88805a162c0c1f60f9ff0bcc2029ce33452d05f754375c0bd147fba745bf8a0008792d4f90d0e0f2cf391f2d7865705544f4a220ded44732321473c0ae7870394d4e625df11bd0923340cb70b995\nB = -340e5ccd644849d982bdd455ddb3b9a23ca14e168bb87256bcc370ffb6b7fe78fd062b3bcc1ad3c8c3b8cb549f2baaf1b7f0f6522aba02fd35b651f7de52b3aa2e0e40352bfd6ed0f84a2bbc3b3a396dc8512ca1db01cc69611925f1037794c82a418f10e0d994f458d1f19051e8bea32b90ce744d46718f42e711c094ad0a1ee96c88920188078f1b044ccf307e4cad7de\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 31c090e5160faff9a136a7a482b42a43ae3c7d00c215cbdad28804be0e7b12b0b3af820c1350b1622a22c8875f24d48ff16231c826d1a946c66f70aef92d4e6582e3ce9213d907267251ac74fa3cca9f1c8fd53fe9898aec19936a2b797fc345d68f0791cc740199be39c05053d5591d874b415e62653b04a3f41e263d00f230\nA = 5419e87e50b28b6d24927934b541d8de548a8f4ec7e9b00aadb6d23f2d33406177d3fc72d29ad2c2e141ab2916adfd30ec4791c626af61d8d192276d632aaf3b54e2ffe83b44f6f1ac441e6823b6b58cc08fd7a0af945a02eabb5aebb2c7ff0622a17b38077cd0cba906ce23e71ac7f4da40ef6066565b4cb3a62ebda28f3629eaa251dbd9979b123a5447ea20331723e\nB = 184782ba4daf429cbd13ac13fe93fe5833f09915cbbc707feca3293e505ce9cf0b4b12ffc8b178e0a4617f809be53d4895a4182e7a8a65043361e654befe8b0", - "1429ba4b7420193d1d7d90930ee19cee0316f33a5795335f5fa517e1ffbc99b95101b0f936353afd3bcfec34851ebff1ef02fea991a01b587d28640c935ec91496d1aa3ab8d38a6ac75b3a4198ed27b9019bb3e\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5eb9f3ca660de481968a3c7321281f22fb9273b16fc10d8eff1fe34842364dabcfaee4993c1c8ddb7c8d6e509a8d2afc005075d5fd3c4471f0622753c7797aea900e785ceef905e2606f64f34e47239c40b74f07e2ca70bd5a18cb0a88780489f3e98232221f65ac9c5ce703a256b7b75eb1dd38778d8bc05a37ac9ad8d36b35\nA = 1c73d8e3d5db127a81477a5c4c6d61ac62af446981773ca15a9a01fd5175a2826a8763f91d68df28ee606e8ffc203305875a238d2095345556f12f3b5e10c5bb6ce3f90342ac74b9ac057195c863c4b9d28ca1d958a98649c7f8897bc6abbc39becae963f61b33bab4fd20d9d0e5464f21c2cdf06d00f597dfde45dc5919f5124f26888b12d72cbd2f57de3f2de7c014f891\nB = -e406fb60e35f0abdd313b8431f4cc89fbb034daf71fae0cc727e9a93cdfde53566fc74e48f4cc2111fad158c63293bca0b21b98416381b81d2443d0e91647679481cd6b6869b37112d3b6e575eea7fbb5bdea422558d817b49ac36a829926553202cf9dcef09423c085d26176a89be741ae20a434ea461def090dbffaf2e2ef97bbd4ec779041ed69ec07d125c7b85a2d215bb0f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = acf9d363fc9b76ecf7e61c33270031340e66595e559dd1c9dd4d2243819b660183521a4124558fd4b216dcf5c52c4127fe517c48cef428b9ee0f1bebabab487c968a80b9815e82c12e807c096974ea3893a8d5597f745365c352a6bc6ce92479176092f02907538c5e784bf26dcde7672338f402753b08de8aa21b9480df6955\nA = -7c03ba6e3939ebbeabd35cca277eecaec31f326ab75f1a29e05af50c4e62e0175d4d6a57acab87cf1fa3a51791e9a2b2d4d5db570ec3941263902b0c74544c323c106557cd5139d2a25f3c3ef81ca009d4e3c16f1abf6e2b5196df1b30def46d61eccdcb3741a6dfc8e8c5e6db68ec29c82b0adf6e35ce7aacef8da806b3b58bfa489d319869b20768f8eebb604a9624d048f9\nB = 4e021959da96ebeaad17f9896ed53010d80ed3fd4c3a826a266e82b80ad81b3032303e7c0e58034a652b8aac00c08d42a530039de60d74ad349438f5ecca1256342ded6f30e3bd2aad5bf2b49124cb27f45f697e157550dbbb37f5aef0f04839aaf1ba43bf1e77a1529818d0fa91d940904eda6b748e5c86cd1b37592542c43b7b4afe2b8926fef6dc01784fa431d43900edef27f8b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 24124c69aaabec7a7b4e7a82245f6cb14b199852a8b314a7b8d9049cb66096d5ac93ac75eb58a2004de8b0fc8375638c0878fb6a45be8bfbcc292e3571df1bb8d6e346d5595fa395fef983a365e4e868154fb3e337d47771419e7f1dd5e4220900c564d7cbe8e7792ab288f99d265aeb296c5ebfdaf08b88d9b30ac660cc3ff8\nA = -167c959417e9566c93e7e05d2a410f4850e3a313e516ec958c3d2fbdecbf58072d05691c68981e176a867d7467091dfeca11f695f750c8c44ebc4d08e39e679d96c4791ceb1ea3b89fa3ce26f7ef214c5368c03ba694f7ae592bcd8ae53a66cb3eb1e0cd3c105faae6eb7e7a8fbc88248be722406f2d35e46c751b5ceabd992091eeba15191ccf6dd61a7ee0c624d43b188c42b6a\nB = -343940f3b2a5f73a51d6f609e8af306f44ce7b5c2e79edf6f4dfc07866dc5c4b2e0ba48099b5503af87762a44ae451d166f8914ba25b3cc41a766583bf73d27e40784064582fd9fe952fc00e9aa2d4e4f1ef35818978e725e69c1bcf267fda4d635d1d292d54d3ad10bae9763dc5d7f7226f371184465695f2d384d749fe07967a1bb64df22f294ed88b13600c7068d881f713cb8e3ce6\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 50cac148215963e58cf6d2ebc36fa518c63a0ab8fb136ab84c9657fee459043ee9f42aafec89e8ba5fd1cc5c4495a41e80590ce197e12c087ff7e6ea88ed798735f55a1634562b82f8514488ada526e5dc10700058980885000e266cad55948d1e080f6343f84b12a3698d9ad5427fad4017d931df77ed2e45e2fb8380b7fa39\nA = 6a9833d768a22ea46aab1a1619f30283a1ec254a2de5652981d73146aabe31041ed04d271c6f2e5e2d090cd615518a06563a94ee2b12cf9f142de3f15599998a712974d0ce9b122a2aa65bf8750f54c6324f12e321a888154330f0f9e1e5b7999acd70d4e6da95c2df1da2d19544b7abd2bd3041e3228c7cdba44f7d1cbfbcf968f8fe87fab523eede0485efaf5cc9e56095cec8983\nB = 11e782e2b3f469b1e3d14ccd1b8301ffcde7e371f6e9afc99af5809110c6d70e1cca5c0bbfeb95fc3ef8352581c11ba75c0f8c445ce2aea903769a24289581c95ae5ebd9553fee61a30d155bf6011278807833eb2ce7ee2a98fececa23fabaaa259409e88e3c4f4eb1e04176d44878ad3f6961e0615ade2fe86b6eb02adeaa7c9019d63231a28f84b7dcc8bb0e71e2a717db09301e1dca20f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 7cd49d72bcf5ff4fa2c686f21e1f0146c4f24b9ad2e900dca1c0a5d2fac5047509064e65ac582946b251a3f04850c9abd8b80c92af0fb11ac13debdae8b94927f1de0e4bb217e78f5d04897c6a0762667d3d883cb754dc610442c9dbd44228a7ae4f14fca145550d813655befe3bfeb52f1c76f989ea8a1dd9c10fbc7e9d6574\nA = 109fe33568598972063279b71ba0efdc2e03f770cdec331428fb8ca084c9b20d0fdb5cf9ad7ce90c8cb8f0fef10d219d7dfcc6b4599440db8cff9971da7852880bf004266886eced8763b3569720df3a1fb0dde2717ce0183f2250034871146628430f206c12f5fd87574c206b203d90c0f2c705cad3484c73da8bf4e9f7e1bd433a6f7fd27df63079d30c490aed7161bc594eefad4bc0\nB = -b95da952cabdebe0194b7fba519768e1b56149353cd12023b97397b59e0d7f4dd1d27b65b833948f58e66d3f6928cc3140cced835dbd612cc82a7e9fae1621986f71ddb6707ad57926b03e87e165d30fb145795a70627975bbf9d9ac9bce07492de5227c666663cc28b3e70b19dbaba7f16849535ce5fd61e91cd2875e0a534a10c60d21f919d566a3469d108a35ec3f023210efd5d318c7210\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 98a89cb3c9602fe503c32c44609bd4487b6c8323737b3376dafacc3eff96efcce7a31f1b61ee6799dc9561e77ac058fe5195cc013e72a2864f7e492d9f35244b321d46270a582f6f14f15fa8203d392e81b183a1d64d48b51d70e38d49c93869ffb9d7509f15ccde547d2d9c4dccd50eba49190b6e831a9f4f9000a95dc83f3c\nA = -67d7fc8f1766c40bd476cdb65d4dd161c3d4c2c5860a0c559f0e87ada213c9ed33308c36bb1c7d615fa69ec53656bbae6b57181a0134af23ea2a75f8fed3290a2f483392a3745fb57adf2121738c84f6d34325121a702c8ccac0090ea27fe9a5ebb6ba9d4f397e4a7e3151850b3d7d25643398bd3e4c1da081471389799245d986cab825a2e6ca72b38ff978a2753c835299ab4597bc65fc\nB = 676ddc4d18960817ff8fd2adffaa68c87d234d62d445d6ba3847ded849356d929d9e4ff01f517d7b1c0778bf90f475923517d855956f17ece1e032e2fd474d2133d6b8a591995454d8b587cb4f6fdd0fa29305f146d340cbe6b6efd28a926c73735621be0c5decb792083b3f063a43dd9f635e03f78c1bb56389a5cc993c8f36134d755a324d4fccc2ac3bafa270df67db0a4ee6ea4497aa33b5a8\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 76c31404854006a7d55554762094df6e11e0393f5b0451d85de2e5b104432df72023a35f44da10dbde01cebf77b8f9d3ad582373c5d32232564729af0d03c5450e439045d96a2f0a38871c922af2bd38c545d219adce0ec80fccd121d6a733bac09253604a8a0b1ecf0f24e44b818ab9e9974181cef10e9eb17684c57d72257c\nA = -134e8784878a8f3cf49ccb952075f9f9bcd24a20f8883955f262867045c11a9c566abee00638927e5de924872fb98f6376e321ebf3f567db6cfeede62e04f839617d78b7c9d3487b60a0d3897b3fa49b14c12511d04854bde4a9dbe5f31424a3d05cb75d23b46f6c0819536020880afa5a2c173f6881754b56f82a2864c99c820156f96b5cc4665d603597331d98d90a52f4a30c6215ee5eaa2\nB = -3c5c0d35de5fb21c84d2db228829f43b31132b582556b92b495f59df502a6d00584bb5bacd9b8c1a8c7eab91db0ea24b40f07e62a712842d5c2e1d208a6412a068cd5c6394d715260b67fbc03e3ae7eb4862f74f4d7484f747774fff03830c65fe022d579adb6737f6dfe297db750e6a58d1004e7e2716838befc2ea97179ecd53b7f36e3540e1c3a0f3e044bfe2d0efa9b89d2d308cbd0bd88ab3706\nM = c462c7cdd79b7604246", - "a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5b704b3181e5d0494937b4d6aa8172eea82919fd1d884493197a6a85ff047a7bcd5dcf072bdcef0287be20d4ac49918d1df550d184f86d7220f0a84fc4da3ad05e131c443fb529df01fec9fe4fa6fa2f36e791f9e16b4092759016d2f9b1ae7c3d071c57edf26386aaead767a3109c12a5004c7b9fa595e6d592daaa2dd1df04\nA = 48a0ccd2d14e14e2aa862d306501efe5de239e8ef36ff6251c861a0aee9f739411f402491bd99aebacdc26c4f30306f9137ffe4579c2f13efa81b979ddfffcd23675ac6307c0aa3ba8ee77a2e3a3c8e241bd2ade6484e6ead32ce8d752fb3584d14688f223758c5cb8705cea9c56136b219d87f9904bb56be2ea1c9a035df33455206e6b7972cba32ca4c3db41991117d88da3521780fe65c4023\nB = 160120a35ae3edac3edbede9ff1c6f317d95481227d87785b7ee46cfb80fac9973e418244884caca3211a3f6cd3bb419cf70fbc22d82ba5ab98ad80e1f6c2cda753aaf7be78613ef25577107a47ad1ee3c3645db85c4d29bd77900e99e1f439cb23c6c68662c05322f94feffcd9e37d8665cde984387093a043447de590e7874e6acfa37ed302040df4d5c3dcdf9fed91b3d17ab5c141d4494d0f301b508\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 448c3a64958b82ccaaed3c74706ce0a48c5e059c3610cc03a6b5a03a7de5d4f1d1e4b08a31478fa8edd58401f0171697f0662146ce2b371e335d695f9e4a671255f29fc0b9b7d1b2eca4cc7f8357aa0920b5942e31bcfae84e909828fbe5d02251ddf10dbe4c15351f675e96e2eae6d044da1f0858ce8ba9b7aa146850b85d93\nA = 1b2a52aefe44170376df29d17ae2dc1501c9c296f72f271c21f53db71247e72c3eb2b780190c45343bcc8f548507559ced3bd4a6fb13f9174dbddf965b9c4a56c3d88727736d78be9db2268cd02382e50c6fa28ddaf8eab9f44ad45d5882a5100b3027c150a7f3bb36f29d24a76e40f3820ba116d645800459f06c20679321cf5be72450879462f0eac99ab6ff8d26b464cd0e6d78621c9263394c15\nB = -b7d9bd08d7d8e0e9596851b7e03c78973a502afcc7b5fe5b0db6034ebb8a11df1ef7ed0ae1371eb4111cefd61c61935d768be3e3755e481daced219874cdf0d07a76e7144be626cf1fc21c8a0e9db4389ee213193775e95d4d86741d8d8fc820c239b7a90937000dc3e89b2fcd61b44e1c38c655bb3d31aa7e422b4406c9e4a88e6a2c18ec7c048f4a6b5b270c90d9fb378f64be3b5b351621db48a6c18625\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2192157490ae044a26c23eea6da51d3a3dd08c7fb67a9beb76d37ee24ac0089863aa7f00849b81bab8259f3a0e1bc744d841e07aa413c286e4bef2ff3356bdbecee756026915894584b4fcef7e49da4012cd9fcb5dbe3f3b867cb6a7ee959a328b0fd56a9eac1f4e40a22bf0a30073cd2d48f99245ac03c373810c54eaf3306c\nA = -598eef47b40d1fa1ce260edc561bd1c1ab286a7e068af412ec2baaecd07c5b9cd596505ea1bf0370ea961c4ceeb9be76baec74e6952cb846f20e5da406bd01368b85d59569b403b7a305cd7448f331f10a34def43c738fd633df9a3eb194c32d53aeb567889927271d71d3929d43fb9338248b64f7d23cd1b053239e09cc2ccf5fe9c9ce240f1a10fb151a8583e4b4cbc70ec3082dd20a9962d564544e\nB = 559fc917de34bd7dd7a23a432142ed79e3ac4a6caa357eea21e423eb9af7fd94f1eca735d2588ec4c2ff013520c3a0e209627217cc69bd5a07ca46a43ec1f1bdbee5f09ceb1b2c18bd388d3852e51070943f16152a73da624be680c671057677356c6f281a4ba1f7c60609125d7fd9086c907ca5c191820d80e483886b70c1074e2963c49996ee92577334881edafd88270bb967da795aa4fefb739e4367390ae\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 3488bf00f67b852592922fbae64fa56d2e4e7081678e789bbb3b4f48df62576d537da2e99c9bdd721c725b9a828194662bbd51ee20ba73d4ed5562482540880686d9fb1e8ae62d08e39fdbbab1d18e399ebf07b3a6559dda8b043fc25a8152858d39b10ff64776e00a839950e7a9ed5ea95b594b6e9e9d4348ceae08071ec5d9\nA = -1b135d8cec9969561be396323e2f8be0c60903ca59b6c418cb19876e9e3cdcb9ce4f5251eadea11fd6e785476c70822aebdc94617063d161ebe55584a8a774ab230b8228a2b65bd5a6c873bb6b261429eefdc7d0c64c7e78133e739efe57f835ad03ef8f84601e1a2310659db5e0ee706f23e3c5c38c9f8c36e5b15b654d1cc528f1dd392f1b08921af8be6fe4e4e6db774392441883ef867bc729338943b\nB = -34fb63435c90018e5843098e379c76ef3ba0615b6b500854b3dda3e77fc5646228fcf3a6e1cd87a506e4959ab05e24474990ad98ad0865942737734c03dc289307f1b1f424b9a8c2264350943449b3d2b0f71f989039131e23095d122ae98c0089a184dc530669e804140134e5b602861a5e61c030fc3d3b3eef0a59f8c0579fc9b0afceaf16698de3fa07c43231312254c04ab11ad7a29efc4597780c2cd1b64b43\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 8ea5fcf7fd41803606c95729d2d910941e43b222f9b0c93a1a803b197fababbd653a92ee34e805906fde29b307a962a294aa4dabebf0d181c046653ad0fe6da1295eef817f3289dcc6579cee8869198c39a9f79992cf6894162d35d812df327a64470c935994aca4985d0e6a783b853ad762338dabd575ca71034e29d768d014\nA = 6858d029a62b0f75e4c59f3ec067e3990b2304c90a097daccaf554abec49a9d297ca14648471dba08f22ebbf8e238c89ea06f188203599aba56611eb3d4df09ea795a7e28f91f4a9a582c6b949c6ffc584a076de653446aff9b24e87202037974aede37aa9a121b5b70a3e9b5ca376c9056c2c91f5d5484baebb64cccb6a09b4f40529afad1ed64b4cc4aca586892693fb5f92edb6b4d5f678f7a2441e51410\nB = 197d6deff7adc30b025e7e418cca0a641e1a1b35f78fb56b9d8847f0690313475e6fbc6f73c3a718b10bf37434dd9fb1eca33a99bbba674195b20d35e3b34ba9d7c8438eede24ebb48e6d39eecd93fcd7dac44235ad32f208919f57b261da70ca378f9b03ae5e5a733f97f0b3f4102d971272015bf50b6f3e50c7b36cdaa14a8a580366c9cb0118ceec6e627827b0b8f614656292675ddb66e1c55355d5a1d78e69ed31\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = a25db977e7a8fa4578fc530995335411432ced67e131fee2cd7ff56970df64a6f0f4a7d225d2f4ccec8e98273ec9a0f1aef01dc0b866e425d64e09cafb9ebe3f80bc0ad71c769f1ecd5efdb4a990ebd3a94303f52f4a97e3a1d615918f8b2df5321c4aa9339b4453d7a710a803106dd0ab49c6cd9aea431f97fea9fcae0bbd90\nA = 13f97ba15ce46ae32147a0aa4c1639b6b555f4d8a1af15ede4f1103f7a0b06b4625bf456d667720adca0c4e26e858f008b012fae63cd89322b33fe51e87714519e7dc3cceea27d968b46ebc04024d063b17901a7ae978591ca6ca41afffd81769f04b714134cfaa6700cf23bfda6ce67313988bba5fd3782bc62f76cf551d140c978dc002a779ae37400d34cbea013a5d1338b203ff267861edd88ab8ee1e4c4d8\nB = -88d8a4c8c680fb01f493f73753c70ee753951d4734627da14962e36449db5490b8c575729fafbd203a125b500b96364e6799d9cfcf0efb4ec877e86865eea5e99e2fe5e7655c1ee0eac641e73b71c66d7a72c2934d1ccfefcf59781035b2c7b89e5de3f7d1e9128cac57947d22e7577832ba374492a2f53be37e17733d8bc625fa77fa5cf093975049a5c477f792fe75e85da26cceec820c8b255df0292824b4c3a8ed455\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c1f2165a402fe9becea284dae60453965ce327f540bb8969562485fd1bb60372b8689d9c9c97c91bcfd699dc370117ea8b704f06cae3d972dc6e5eaac971597c69d4dc24a68b256f97229e643706aa6d2d844078a5fee2d08270820055ea58155d7bc754f09d0c6f804e55ebe53e3ec418747d4130cec68533f6f0c2f8fd2409\nA = -626a1580e52ba52a877cdcd62b34cbc7f949148671d4a61201e03e98985d704b2975b9a2d9c4557deae065becd662ce8448171ac582894bfa2c59d4ed20c6d0471fcad1d0fed1291df5e4556aba72f3645486580c8bfd0e3c8f6cb34fe17ccdd75fad4d4a2db4e00bb8c2a23ed17a31e95631320590f40416c153efdaf897e3b278a1faf1917554d9292f90c4edd5992748b58492289eecde1af34976ea8ff507fb9\nB = 44c336d7739118340048939d6c198f73f90e13030b69be286ef920902391d87a58df3632091d0ef25340eab395203e8dcf3389e95debb7432165147e145735d2e3226637b4b8cb7d85d68308be07f217f57fe439b31fddf3fd469869a20f1f852e1645b0d4903432ecd1fb6397db4c11f6b6b9c0fd25778b0ff00bab9ff576b16538a6b7da40f01fa7b987af8ead41ecb66b", - "8940c0e8a1208d0026773e711153d99348e92303\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 98eaf476f11168bb63fddf7dbf3347e619f9b580ea6804ab893214e94ebc089cb652e307f1f37ea7ab9052a352e260ff7d1e8c17461bae68c52a8a8f1a57a84c79b2c8fcc2d504ac4f553d2534f2a776ca129ec1942d83c8ae24c772f6a8429bd61949ca1aa714cc3881ed731497b84415c88ad4b9be34197a549737edcfeac8\nA = -15897a5a986641fc2cda42d185d72aa1552eb92f788bb71cc74c0e424bd038e02c620d0686ff88ebdf0bc1632093c0d89e724e7d5b526b0ddc4c7e145aa90b36be0d8574901fdf286df84a6b52674a78cf21ae4865618b4347bd905461d878537b33cc41710ddb290964c48e44d4d2ce2ed82847de75938d23ed418bb9ff1caa03b5c1ac5d65692dd1defbc6013b3270c4314a45dc67883762fda5509b915e8277c1924\nB = -3a7141f54a0bcef68cbc3006166f7e15a5c2394892a428fa417a485981316a537cb3ec757d4a2473fdec2cd61010a9ff865852af8f43afc79a97d394bb6c58643858e2b4dc5cb958c33781b5c35aced7882e8b8d7b4e4249c2b82150adfb0c8f2bbb1cff3d2ea27ed24eae030ef468ae4d6b7462f0b072cd2a2f02426b3290b87b14d14b34e91a94c5bd69e9eda53335cdfa7df90a57f97f3d023ff85537fe0a8bc5d8fd7901722\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 34464b7a50713d17b01b5940b5acfaa7006aa6b9b083bc17e0535b08783761391eaca8703af2edbe13dd0fe9036d38aecfd9faae08c0861042ea1a25b41fa8a15b7721909783de3aca127e955e177987518dd010306a795bb66466fccd55bd9e2bde17470cbd36b1e8f8b63805229754387a5fb40f3ee9a8afb2e51e25c8bea\nA = 701ae8c5bafab7f41c999e492f04a7626b2b1054e6dce1b83002b2d3de46717225b018733b0fa8fe3f973202da8a090ae3fd14f48b27097513ecd4ceb1b9729e7783c17fee9be5221fce4ed3860275b3b36b7416594d2b65e198ff564e82301cae23756c878494e57b5ea8fd22ad800a582cae32fbc985d122cbc6e0eac77c1000d3ede45ae7aa087534adfdea8e9f924efa1b19c43dfd3b7bc83d7c40df7c6578a320a19\nB = 18e0256543619a750384d30b6a7afbbcbdcd9a2ce644dbfc97a8ff699e118032558f706502c9b956695cb25a46d7526596b3d0b67b69611009265838bec533a9488d24583e7d7f2284e23c3cc4ccc5920fc57e24f60da0d479d41f5b9c6ad9152903a4f37842176c6257fb1e3e0681d6d583e704c1d1b24cf616fe638106638fe9d79a0c74f0df67cb2df9d99185324ebb037d01ba0066ba947d5345cd3201b19769d438c43292f572\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = bc57cbb3e1051d3a3035f77c2e375c7e3221dd472edb1a5ccaa7521849fc0ccc7568238aea9335a733d839e89ace6f2b66ef238267e0050c065c3d9553cf50cc5cd93d34fb43c3ea1c31b8ebf0b751f595a7e5e3e860b366229de4286b9d3f0267f78c6888ab3f208c55d9292079116ea0eb9f4ec2934c97149aa132c03336ea\nA = 1ffb0aac11f6d1d257ef7aa997a030e2a12b0615fb11ff04f344f6ecd550e8e77e9883c246e009af33a51204e4066ed4249950e022a61337848dae17c88317e15ade5b5499c0d7597a69a02b6c18db0f975c19c16d2167c583571e947676ae9c15be60e69d76e78329aed5fa57dc5e616795b5487f3d52bfe74b54bbf93ceda093c2e14104a6d2f017f0d200a9fc89deaa283e04b0bd9015ec67598425312868eeefeae9c996\nB = -9de2d82e25b449b8ca4b02b2d2fc0a023fc5804ea553aa84674a815bd74193a2e549070e2cfa0b90a53070646875282fdf855940905f834f5a07f073093c658cd1813fc5cd7092af592092d789ab5481bfb14b6683139646cff8eb1c5dcdb6a33113d1c97d4b587f15f972c06046730b7e712a8e3dd5f4bfd07cfae289047de31776f222d11510ab6b70a200ceeb6802d6c33f913c509b31b96e2b8dba9e25b0d2250c3b102d814683f1\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9f7f4e010370ec1d76fa83f73c80825c3b71521855fca5db06d7ed830c910d0430375bf319671f6a83bf6b57d9d53cfaaed5bc5d615c5690df0067b18791c33cb9f0ac9fa5f0473e4f4eb7840b0b660962097606b3de5744089ffb37d9c0df1123a91a5896d4deeab8aebec469b099a3a9a4f6d822030ec2fc4d11636706fd0d\nA = -7f56093243ec2399548ed95df79363e6ff09de211dfffc314b7cee526535def0f9a8eb9aa6f1736528ee7aae8be55c06645708d576111766ea33e0564c12103edd61ede3128a7a642f968eefd0d7f3768b1325c2dd910d459b15e54145a234225fd29932234e59d3ff5099ec4d5b5c6075f56382ade1101115c7b94e1e2a7bf075dec210fdaf2357c735416dd5d616335002d1cde6056bf7c478f810b78c661a3dbe6e54084bc9\nB = 4df1a6296428d06f51f31a1b0f66d0b77a04db3bb8e1b80d64da649899a1a55d4041bf0bb47d3e3936ee0f3740e1e8c2b235e1b8944d28c7d617d1f968abcde9dce10d6e3c27b2e3607d8df815f5a39da9b5569e95eee1fe5532c0a80011e7415800d8a9ec175fb1d13dad959becf04964b70dabde6d37072dc9f6d914309b850cda33a565515dd6c0181fc48bc7033b314ae0bd5872480e02ffc08dac4e3030d83b33488cf149e19b0021b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6da5fcea305cc6eb47fb17190889e6a39c339da1bea2d7c95e997fc538b4aeec8b0edf7c109faad7fb6c656420f4afa104ada7a0d3d14d3ef0fc6774b59aa2687c0b4efe7c3fc83194a89c832f7168346cadc2b1fa6fa9a23a67c91ad731b4cfb9943738c7f9951945b2eabb3743473d9c0444ade756291f53fc7641501597a2\nA = -19dfb98f9f7d20fd331ea749d2019d8367935fb75ecde45d6dabc815ab9e593e51178a72816f85aa678304e6ff3a2c24079a59aca253d76c4ac633fea1070753ce770765bce47428f8f5ae40c26a3ac91ddb551b3d575bad9a3b6fc7954acc93aad2131b78fd212fb0db7cca4195b41651a5311bbd4d8c64f1c93e6520eef8e6308e98caa1cd0d3c9b4041182cbfa131c4948257f1200b1c5351bee77ac8bc8e44680ce64ed0648f3\nB = -2736d5038c60553927f389c0650bb1355b0ce745a7dc5f52c9909039465344af910a5f6a9cc4ec130b9877c1cbb52fc08b20d672e42b853d26a02bc07eabb9e3f91399db8465b6a8b1c9f4a4b9eeeec6e9b6180f1a770c139c8f29ceced61cc7ba182884ae01d14dd85bc924391333e8ef039b586b6a0ae18db3570aa560c2b0226d5e23e7e753873637c25aeb19e74997da4f5d0755571785bebbc7dade57446e0df4cdb8df23c1003533f60a\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c0265805aa8ab52da5aec06ef7cad2026fa0b18edb27b4903e3c068ca6464465e34d3f3bdb4bcc10a19441040deaf5569645f7e09b36c56631b3a6144d6206d39c9bcac53b54210db6d484cd6a2780bc68c07272de03a9bba7e51c9d86cc8883cd2e1864a2ed711d505930143c883c57545e9c40851c6df8b3314a8c9a0d201c\nA = 5622f906b077d243521325be82a43fce321412bdab1f15e4ff0c11a7066a288b7939afc01d30243c8a4150e74286611ac1ca4daf457aa23508a7af869d2d55f54f2746afaec477cd7df0d5711dd636802ae7f673b3f730236ac3899330f89cb71d48c2838322fe856d9d8b4053d9c1e66acdb5e43614ecff954dbe37c5269d7ffe00b34e682c0be3d7cf653ef212daa3d55dff92b329126636e440b0bab55f4810a2849f77c39ebb93e\nB = 1ebe0d1800b1fcfb67d7d54568e45dc604450c1dbe103ee21d48dda300c1d9b9415dcd9f5a56cf12c2ede3c862e895efb83621435377387b29b882b2acac78386895c7daa90810092bd3062a3a4867f92d54622d7f0b89b40fabc4709fd507d4002ca80de231596630c234fa418611ede0ae4a9616d570232c1b03329bad02220ef64e455c164aadc16190ce35b78060a6b117b4b0641fa64dd8e8cddb5914e7657573804e63dc7b216b1a9aa175c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 606d2b6f756548568013bdaba6e811dbae88fb01f5f36d30d15dc1e099d86bdca9fc1eb3a785034ea14cb7f4776586327d57ca5a52ea1b30f26e2a76140bbb0e930c7780673770fe22c5ed443c349510e1494ebe402f2621b1e6bde39b8691edbe5c7242efaa6634553e6af146dd40666edf4a3db5d1e7f9347fa1189c1e5168\nA = 14ea5e6fd612945c71fdb17ec44d95015773edc908a85a6645a8eb823d11226545d05b81791401cefc81ce9765eacea7a619cb482f29d38988d355ce731bc9009969b7487a3acca2d2065c1faadc5d6dd8ca1dcd3f3d4ff61d0a75ef75272e62193618f6b802f70795041de26d6ce367ba996dfb91167cb1fa16c8977f982e1718de7d60275a7f66e4ad72ee55ea06267cc4e8b08f488579825cc674b0bdfd34a01bed08b62004fda", - "15b7c\nB = -8a542280f6c8bf4d9fbc96d5bfa6ee0d16a09dffdcbfeaa2dfa1097a760dec7bc540a0b5b2020bab1eaa594117a40a9bb99c3f16fc340c262b29909608740b8e77fe4706a88dc0fc3bcd47998e88fa02f617062393978ac1bfe14235d43f3d5edbdfb9f140412f4fc2dfc05a700f47b1f0f90da7ae07ae781d9ccdbb951f19a8b8a9a7dd8a65942842cf207f3baed3a0b2f08a06ad0d9ab7ad0110346293d51ec53ff8165b925c0e7906be8b7303252\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 512220042f151479a6a8b7c743ba83366cb7733caf37164e9c823422ccbf78b0b83f426a7230f559d50bb0ed3d9486c6a6e25f4cf96c4fdcb2c861566c6a73215b6d08995a14569710cf9e54abded1d77fc7722d06fda4557a3a99862e5ce963e1be25336fb42a4629391cde3aacd47ea5f5426e7185c5df27d9136a6df26f54\nA = -4d108217b778694931088bc255d1f69cf8f5a14252156163f948ae58d58f2ed54f518177d668e795474952c930052c1bcfcae11bcd15af168ec2e881e6ddc8de257d0cff90ff3ad409bb3a080d30fdfda99078cc3ad8302a4bdd77de66ac082b40fddb3cb36c75a86bacaf60984a74a0fd575d751ed2830650d85844aba9e3f781b2dc6b515bdb8d9459b083e1aa653ef177de76282e86c99e97dae9c0b050c9e6456a051e7d99adad7be4e4\nB = 7b9079504c635655a588ac360955fceb10cdea5f3de548ca2db681da38c17a70df5798f72cf18691d14a5f400ac69fbb47e64115cf071466c54bc7077a228249209542683ba57791352ef3409f6a947865d8f234ea9d39491b5c001685487b32130bce9aeade97d9537afe3f2f87e8f3315619ef7f215a73cb724f1adca99b90912aeecdc81485c0d00a74387ea99c965118fc6a9af1163e60d1ee6a1eeb12d7c2bb9a54f747a415beb5873d616fa0eafa\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = e36899d83a143c82e19e11494ba18478c0a9497fc89fd83df38adcb6b33918645a416626409a156899c6583ab9a4426438d9c32cac54b78df579cb7b6b1feb3f39ca4a6183743a4b823082896a89f9f1722be842cb2d2ceb605f84a9f9b61cdc7e184593fc2f9ff2994fe6cc4860d255809d04ab47e154eaec9ecc807ceb298\nA = -1422272d9e91a14b38b3e81cbd9411a0cafca23addf4f33c94a1bca70603db879dd8a9c0b95f5986bcb447731219c4f9b32a1e3253b027b7963ce40279dbf4008e526adc0bd7bcb2b533392a105c6e8e1bddfdd2bde7dfa0d2e3b1c6ffa07fea07ecdb9fc828283e93b0ce4861945562478b1a56de32251b7d31f9a2309488f7cbdcc38cd6b1c951570675ef0d61e1df69fed78979dc755f160d93ab5a3e65dc2944d3333cb85aaf87a153a90fa\nB = -2424fc1e71286ce3be684a10dd885e4891b52e9009c3021d90ebcaf68b6db81130bdbb74869cbf142e0f44ae72684fc12c85abb5157987428c7812889beecfd7bb43fcac2eb6298ebf1dbcd2e70e4274841c2703b8685df18f6e5bbaa1422004797defc6ba843e77f891bbb46699a863bc1d77c5e3cab809c247e2975e8170da00fd9c8b232abc3fc6b16951ac4e6c96f9503c1ff2d6832ff9c35b2c8aa408645849c577d2b8599ef520da57fe2a9eccfcba6\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 4e8a59476d47ee2cd0217bae2981cf25a2c38e5f5d5c30c2d8bf95856a6e8f42429e565f1836365e550d85207246514624e7ed932d6f5802a50ff9f15d500dd84b27729c1717a3df0f2d6dfd40f0094208445193ba6500ba03fa3f4bdeaf9251aace8729b32ec3215bcfa170575e26265fe523cf44a071470e3b1547901e9227\nA = 452cfc78cb9597e67aacd4ec83e5b473ab8b7a1dcb6097fab37e25d5a6e25c69c73a6c20de0e2a744375bbfe7f612036e69c7a503255d9e17c6ec1dc6cc6f634d4c79bed4764496e5c7c026fdf9408242d3b234195e67a5681e7d7b861f58eb631ddb9aeeb0e5b3ff7a7657a7fde5975b8a9e1f643893bac47debf7918c7ef8f6d7439320dccaf63b80ec9761559078baa8e35d98fb9dc242ba83536eef7ba9901395ef02b19990d8312203df7dc1\nB = 1dc222e7a737e6d97a703fa232defc6c0a4fb2bafd247c8e547b9c474421cacb7692ec98f94be19a5e40269e1f5713d06a6d081a943dbc667bc867e481b99c55e437061cd44c4482649faf870d9347e0252ba9dbe116fb4992dc2c2a0583c1351e9e01e71e9324f5fa942322485bca93c2d95cf304028e68224fed446966073ec7326c93ae326a7a533a36e053437910418bf1761abd9c4c5ab7e6f538e9bf963903e6c80f21a0a38a683e8166e4626a8d8b743f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = a4d5e9fb7f0d75ce41ffecacd2ee1e4d15f82dfd4decf5ab1bee75fb97792d0d574fee60a30b15af80bd38e6a25b1821e61628dbe456e39fea3f8a9ee6ef3d2332412be1500fada0c1728a1457656eb3e9d94c64fb2d0ac89f10f2b9ff57d73207274ae7e8c7538936cb7241615b830cc9011d4363ef88f51c7b3ed503c25179\nA = 13eeef030b3110451fcb1a258434aeb51d3dc805b38c72ef7c79d4b0e18d600e5dd28b552b59f3dda1898367ec7da5dc6d9089a585cf52002eaf8f9ec64b8d3ec50d0bef7dc3faf203c48583ec89757cfeaf888ec4a91470a6b8ec9f26a6b07f3311b4fe972cac2f2ffe47f5c11d2dca87c62680e2229120cba4de9cfce9f7f5c33af8398c07ffabac1675de1845e05a32536329647214e54e5d9216fc0cbf2730898eae19e425688bf184d16bd1d655\nB = -ea324da99252edb03f40100e528d9a5080c43be97fe4b7e03d9563ba48040d328e57d0defd4b7ffa9bef3ca0d2682aefd2a0ffca8566e755b11f2e3c6c1b707f1b9465592aba6181e583babd5c70588e7123361a8ae77d8c398e33f894ee288babea1d7eb63e2f3de469e502b5048417043c5a9a9a3eb921cea1533162e3ce9c79e6caf62bbe7e17b180b72c59b9ef5fe1a001b733d909a8278029fb4a63077ef9b3545f1159ad73dd75030aad599ea4884677e01f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2f096fb8fe2156c41ab695956f13f0fd9a084f87ea5f5b1acb6b60c62617b8d7079f4b072223ba18cde474af3942599fe070ddb0ac1a99f42b9506a2648e1b8f6106015aba0bf7a824842403bd3f4ac8b6fc4a9861bf0e8ac59be0322f0495e4b515fd579dfef273160ddf96e453f4ab663e703609c709fb1f016ca919fb26c\nA = -4212bf679cc00adb2ca502604b71dd5dab99cdfaf55ae92aee6bcf8b3b6354a384656c09eec6175a95c8cb4591ce118e783d6344525c25e5b356e45802ea3ce1fe764833132e6b7bec434e4481c9cc2986904988bd8da7dc2e31cdc481fd0e359674bbff524124bab1ba4379885a6cfc1b73d953e6d1aa1b938129d74fac9dc597c31383f2f7e02fd995f7065290a9812ba8e205316ad5bac6fc65c6c7310f1a6b033503ebfe85bf6d3851bea1b65b9c15\nB = 7ad83f97f40d5be508cb394c128764532f0aee9a108eb02840ca1c635860b6d751d5f676e8670e2f61466397e1bc68f97ea52d64b335d07aed22f20bb1ed19e3e42e4205d650e6d37714c2f80d39b111577725e3bc7ce75bd7ed5e44f8377d5fc2b97f05c3c1ed5ca1ec90ba3ff7935a25a8acbcb15fe1fc7aeaa1e444cc2f06c1e6711721d24b8969d465e4958cb87924b3e0fe99ccb371009b5b15747bf6dd5d0fb73b8fdf58d955c8773a55424a34c741406f6f904\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 909626a69c803e9acdca97c56781eb672d6fb31430a53b853f467ca26d4ae96c182d71c0212894b776c88e773acbe9602e3ca56584c39b5947724290def7dbf04c6853a108c1282def95dbd5bdc015b68daeea0ee959b35bc5af98a4ae4cc7486e627bc9432bd009b21ee9af3085f074a3ae1bca879e321018e991e7898f2897\nA = -14eb8e28dd04a159c576eb10578c24fad9eedd3d8b7560b681002a54a4bce2167de05cd061338f63c50b86327a79595a2dbfc1d3f4e76aabaf88cfedb69faf5148c61f8cfb2130511a3bf4a17d846ededd4c08f3b635182dff1854e8c4c48007af028e06f01235fc2becdb32adcb9e2058dcf8f8655624bed9915faa06be972282cfbf8530bc0cf2de5b2057df32e4a6cbc3c772feea0a511cfe3408a6dab0e2714fc4cf15602ba0da03bf0016f1f3f5ddfe1\nB = -388da160568aef9f82fc16f48a22e8d7aeac99121cfac9b748c815e5d3a823b673ddcd20c1168f98ba204df5e52535f61b224fc0374092f8c834321949fa0a812b5e65c492fd9fe8246b74143a943bcdbeba16024e311d673357a3dd3eaef9ae3a72bb06e03e34e091cbe5b6a9eb9fa3d7f36c03baa5c3e242f2c186b58db5dddbd73f6aa54aae027529b8f8f0a536b9b283ab08247b9977a2ac2d0d9f162ad03a2fe247d2c589b1a2d14b5f90d5b9c0a95918ea956e261b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 128e8844a2f04704a4a60cd33e85cb7ad373ff683abd167894a35a1d", - "af947f504c0abd7a614e293ce10797a5330147c88c4d5e1dad1bdbeaf74095e3f5a515f2af68b7bc11ee1f53b493133905b654318dcfe73118ef1931eac47deb6c4958406b704ce027d9b027803eb8e639b52d5983094b8ff4b54e86a7dc6ea169ff1af4\nA = 75e6b045aa44dd9b8f4b434dd4bb1346fcf558a5e96b00fef9b6cfaca72fe8b1672edc2a64beee8b959683b1861138b297629b44a0caec6bad2ac05665728379cffaf66a129f0ba40aab7c6b1c3fbdabaabc87ed3dd580ba80ec7ee765e9a8fbe845c0d207eee7a1a3a0c39650c75ccb6bcdae2e0d5149991dc3bf899ae9b7626a2baa17b168b260d82fba84a12f10e09234035e08b730cfc230f0d2651c03e34d4952fca6409b5c6ea5d8791c90466bdc4adf2\nB = 102fc193633b0e60a48dcc17aa76f3e52cbbd1012f179736a0ba7a102f8dfadaf434063b0ed1b1528a018b349eaf192fe62f868b538cddd7e8e6fd98b93147727d58561517b2836e4a373bb31fc8d5e42d16126ed80b880c1a37940c138fc1f7255ee0b7fd39b1b799c34e5178580cdc076ef3fbff65fdff7497398fb1cac75e5c09cc7df1168a20f88a16e7b3ac78091a90f1169bccd48c0d06b4707ab79b741a168deae5ced5d48bb5f5dd3f465e43c82b9db7edab24569b2\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9aa9699d1e5d2c6acb21e31890c1899f30a925b834adb5b8bc8cce83a1718944a2c90faa71b34379a21340457478c0c43121dbd65d62e290eda2ba6230bce4e6f18555a1380c7c95c1700793157f7c1cbabeb09460ca28dc596bb17851ab2ba6dc6bf311ea69bdb7fa8eb78df74adf171d4677a154b8536f8104d919bdd58648\nA = 157fb9e1b38f288db78a1a0e22fdd9f48a59779487a9ada2774a094d34536b85993e7b9ab6e24f081c4cdfb64a82271100a054169e4f1c24e3957ae9aa8300e85eb2a45a6d5987eed4f0fba6fe8557cbf6128e018c5f9df028131bbba6c544b2c6312aeddc71405f0e4ce648fbab9e5d51685949408e4ccbe06fe501a36fc13ee65c31f062313135054b7679eef45964c77f5a1556ac09b11c496d0ba8c6057e283bdaebb4e6d9e5c557d975745f9f98a288d5bbe4\nB = -82cb6334479bd997c771e894cac1ead87dcbaf8f5006be5c70ad48ef94303137bdc45f261af91a201b276a17d884a56ff27af7dc06cc5b7b9c94f7c4d4a36f68f8d309c477b4969a6e7cd1b2afab9deec06555cb753d8a0eb00965359ef865a84bfa87b815a42b2050e1635d5ae5e3743c007bd79e820aa37a968702a960fafbddecebe63f022553cadd7a4d4fb27b4dcb981e8b490e80bbbf13af8c4412d158775db71f5fbc9986e7b8a8f9299574abf7bdf9ce7544e8c4e85bc\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 46e401989fbcde9d830dc6e3c42768999f153d44d270d4805c5beefb470bc1e82706aa7173b359763c5e15d146eca91a32a36f0a80802871933cc7f2ed15a5472988849a2d2f57543345b531538db57ab9bcbfbe787efb0a82e61baa505aad628df5f9e881dababb35bc2decff267eaed3d3671757ae1764ec5163b792b4db3a\nA = -590c16ea2cf7fa7f63b5cf74804333f22fd2d0e1da7d226da8425abad2b39a4672fcebcf5cc15d220b0ecfeec09665e682fff0140f16889f7a6ade9ec11aae3fa3a369b3fc133babe52e42b7a8bb9a24777521f4d9e0efe7d7977dced9e40784c24d2c6056b3b668ada7856da71af73d2dd33d2e481ddf40999d86a6e236d0d73f31a67c52cc8b38203bb2840c0b92c2612ffe5fdb6be87f9a787d70b3dd506f9a63d144db3417495f0a48523c812d14a89710d95bc6\nB = 5a2865cf2254710a1a51ee3056b0c1f6c5f77d22d7aa8f939e6f48ecec529a169e630c554bbe682a8c4de9ce4daca77a278d7e752cb678141ddefa75ba42e661885a82ab55d699414ffeb75802cb8f4e7583bec8a7ab58803b378bb60fd46f476ea490c9aaba568ec17f3a6afdd6f20ec54a512f7aaf62d2f941e35b4b72dea77095e863dcb38bcaf8777707c1dd437ef2ac6b6a8b2b832f80ad2a6d6f279c053d02058b1a657a1cf5b6b269e15d29087b0cfc0c2d4c3fbf32a167a3\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 1c9649f4540556ae82ffd71b2c71ea8588aeb845c50dab595db9f8faa01a26c809d30d8433b6c0add465e164cda2b6723c942ee87241eb7baf9944cae08babd8e22a0eaf35c09e9efdfb9f8bfa65d53ee6eb23fcbe1d12a66ae05e7592ed788b231b000f895d098a24febcfa4372d249575926a5faf966072f29a62a401ec51c\nA = -1bc9ae5fc2f6a3f1274584bac1e145f02c5e8c4779f4df15e98dd34344c988c1437ee4428485a09090d81b18606a6ea5c1b9136872ab5b37373fbffbb5b3fa8fbeca1e112b9f1643658c2f38b9548cd8f0f271779ce0acad403177057ea0a2af2e7435109879941fbf463488a2522b831b95c1cff21d2d816d70c25156369dbcf04a0e28e1d746afb8a77713703fefa512816fe73e203bb4c3428efe09b946b750199bd7a03d30feb90230c219a103ad4528cbe0de1e5f6\nB = -39cae179d955049f830867d4115d3bae25127c945b1fa0c16fa850e8fd77c1b3b9b7916b9983c1659b7cee77b7dc72abfff1c56681b7931c5e58cfe4f1bf0168ae32df0df8f652223885717a98f858a497b1a4be62a2215c39316c34451b0d957791f49139921d9ac8041899b8fdd5d3d443547a26ddf5748147e4c3e93f5043ede42f38a9baa628df65d3d6148ac2ce182056700f0f94029be05d3ea3a218b40f65a87b4baf097fce107c080de24880259f1046175db1297016af76d94\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9fcf6a47addfa336557749821a88ccd2573a5ce2c3094a17d9a29b33e043bea165499e89fd2c939f17a670694aff05e9af46836b62c96e597c83681092d63ab9d6e22751aa8fd4b9ea94a90a373876ef0f6514304a495edb5ca1795c9ade7965c70f9aa92f8ea460ccb670e9a62c81e9c\nA = 71b93fbad39b1c2755f2051ff7d532d59c985756410d58aed3947d6ae737ace5aadc35e7e0d29c684b9d4bec9c0fa277996bb30230f70431cb7b905\nB = 167be8381a3392dd4df62e150025e13b388bf366922ba8632614928922cc290772135857d1b5234d51c27862cb1a055c1b86260b6ec\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8e2ba940fc5165c6c5f7f4cb55cd89d1d5f59e90e78730bd66fb120a814514784879dc43ad4f355030ddb3486a59bc34b601474978a94ddbceafdc0ee23cb18708bdbd824d37cc32577802ac6057fef29a71f168e816309fc80cc46f251e7289c6a57fd222d5868263360af63dd73e7c8b1dd6b3f3b6939849580b9231940a4d\nA = 1220ac4bde4feca135268550ddc79d8b05ff72f483b39f77436f348c4f5360c22c598f7dfb76697bf6d2ae86c68e90748b8b729b25f932b2e5fd33f3b5\nB = -bfee56cd412318cd62e7b6cc49217345d3a94e7fbf6fa19053fa685efbc0f8b320b7e43883189396781c49371dffe7d126c032d1ae4b6\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8e2ba940fc5165c6c5f7bcac0e449b64801e75134a390f120acc58cbee43888f50d07f7aa6dc2b33643c025cf745434d20eb1aeda8fcee5fa3fa5baf10d67c21390297857aa50bbcc4a29a6b10885f97fea60f1b88fc72512c111b938142ee8d67545efe386622162e8fd50418b09769b8c22efe54fdacd652580d609f0528bf\nA = -7bc53f6f2e78628678ebc8e35ae4905caeec61acca5c64fdf595689cf005bde2265cd43172802fc133dafd933d7b48def44256868d202727a4aa6c0cde66\nB = 74147c93e729707111d0d531b1c135453f3e59f63a7e082b43dceb8b16cc5debdb6d7c0ce0c00ec9b5ca51e7673e411c3cab34938124db6a\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 43c47d7e319c32a758360dd726a1d91e2cf5c57f73cdf9ad2040e61a9c282a2962d96d300e04288461eb1ed37df19e6b88f104a250f9885898740f6487b081515314e0a217df2d4345d3cf81eabb2bfb346b634b9c251624748f6e9407cb677aff4c53fcf42cc027de267e6ec011e14bc7f3bc6666f693d21\nA = -1e6ce0b44105047d0da0eca7b936980267db41d41319dd5315889fe8fa2329023d7cf54f71ee179b5bfedf442cdad1920d311966f7175cbb953bb42ee105393\nB = -23a330c7e06cdef4b6b121d15a9c0bc774eb5e432e72d04c5f03a0c588e55e010b61f57c03c51edb1211685d8dfd2a35393091fd0e3ad2304fb\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 768293c84c431b9c8dc6e538ca3f856c60ae5e1aaf42325865418b7bed16c7fc2589968319cf41cb370657c8edc7b969", - "de10e0566b64ec796470b630e22477e7aafb38e99b6012f100c9d23d5517d486e3cab1fc60c1568c0228c9b55d2d77d23b1351fe37ad4fbf9c07f29330a539de4a32709d043dfc9e21aa1a\nA = 6bbaeec78b6a41818b7eec42fa3be7d639dfd86fbace2bc14e0369dba6dd3f04ede8b808743d809f43f70f1146dfdb1d649546441919e27f1f7a9760da4a3b152\nB = 1199dc2f52868a0cf440f6666b576541c7aec1e9cee14c1d22010ab0f53fe8bbf3029c639ff78d89dce82de85fd8eda4e67395d435df60158623c5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8e2b90afbdafa02ce68d537ae807b4e7f3e05a66b20b84cff309941fc3150f99d083841ddaf6f19f5a76886ad5d853c73051a0457e95eeb0fe3776a084a027ee77d14f3825713a59622ea163a679cff904db33bf6ab23b06eb4b31f4e34fb122c8c170321164439db783e7bec1c265eed33f33bd9cb6d1611c00aa18a9b4b90d\nA = 1c4821515167f7073d4b7cfa318ead1da1131499c12497447846caa84176a9d4af576fe549fd8b0f77bf8dbebf6c395f84dffd40400101bf28b1dda0bbdcc5da255e\nB = -de60cd639044e863c6a49c73213dbc2ca84e4225aefa5f880e829f2d9cb48ae92e3f2680c462ac697dc34da38f65fcdc1b4d8c3c99e8cbe29660b539\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 33e8e8e193b4b99d8bb382c29c1fc5403190d7654f43cd77e28d1bf77bc3a728dde9de9a89c6522ebc7222d25f46833fd1753a44275b04485c77b675d816090280b3541ca61bfa33921a79f7286830131d6eba13acc46cc2c449b3a359f1cb49d67a4d0cc1245f3f8b59b1684aa0c3ff1c928b8e880a3375ed811dffc991fd1d\nA = -50ff3e00feeb2efc6df6387d6409a622b7a8297a717b8d94d0dc41c6ec6f29a8455c3580019349660b31dea1e4f66b74147de93535e671c853b604ba06a9b62d34646c\nB = 49ff858c7081392defc3ba12ea8869fd61188ff15d9339be72657b00530b851de53b1fcbe16034816e73251fe1ec97bcecd8bccc470373974287ca328af\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2c88dc40414969e8b614bf8db05fbc38fb2b7ce144d7e707f9f8eca40ae2309c1fc67e713a8da5fbb20e808ad20aeb369cb72a77fd285e38a7895ec0fc795ade4ef1f1680f3a3b3cee4569cc9d5e699984daab3385815d2e515ba5d67d21dd1defc12ca81bc8ea645f8f8d103b4a0a9cdc92eb50690c07a037df274bbd5217e4\nA = -167ee0fa8e5d8b569d7848b068df06f6baed80f6fa6a442f9d11d9712622b512249b92c7ccb821ac751fe4ec0a7a47e04ea5571c7cb45a7985749ecdd87f0c0faea01d232\nB = -2207fd8dbf2b8e9a5e3cc515479cde241dd3671803f9fbf7859459ac66705be055fa759c85631ed2a61139657eee7eb08fd963b49e33666e60b7e75dd26b5d\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 674885ca3ef617a53eaedb9564cf96bcde131760ac541a81f4b25c174a6fe1444c2c206f7171e343e1bb43f81610162994c497419e75aaa25b664c122ed2b27640b45bf646fc5da1703fbf1cc66e10a3c306eb69ae5f937081a1a18dfc8db376ea18f4c1c499109b0cf8806eb32cb1f28985da790047bd7b32c1f67bffb9761\nA = 413cbcbbb5851a4ae12555801f7f80ccd888bb82ef1b5c31b99e1901d7e0ab91ee489c84044bc21fa2010f11aac21d0531fac09feb482fda579cb9f224c3149dd6249b0225a\nB = 1b6bfea70f1d80350eeb45f9a5cebda954d72cf5cd27a299ef5a42e1ed0b50a541d1657b70e50b0cab69b22e31d0944fd735957b1ff764865d9385af302bb802b\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8d74ba5fdc67733ced4d468f6eb6ec4c1ebd79c97682c1d4daa06105788ed9c5144992e555d903804d7ed0dd9b29ef2648568ab7ff462a03e0bceb5482485afc3b91448fcfeba435dc587db6f3a022428d37fa0e85392d0e48e7d4ed6b21253084e653da8175587b3b709e28426cddfec8d9dc582d4ac2f3d540305c0fe17327\nA = 17c0b7f0e2cdf316e4d32f040e26d41dbde1e6689d98f0652da1c380daf5dfeb6a511b72d82f1b32d3852e9aa2f594be10776a8fc89a8a35c160e8e41b42a06a342fa1c309fd82\nB = -d7b7701340c5a358455ca5fa314ad83860d9f765978ff652d7f542de2e123bb976930b8fe84b9608648324450d8ed2bac4e44f2fc71711ae813cd8793af8d3796e8\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 57e60f79b4e156ccec4c253e70df8d86e4aef326150d612a5ac4dc285761e88ede412d28d9dfa5a6f5c073d3c91a65ba9c86067d81f296935f0d0ebd2af82e7f6b5b336422429cc3b8427fd8d3f5a6fe936f4208362632093bdd3cec1aa8f4b176d260f605caf4a12cc011f3d1b76135ac2507346674e41673eb16c0f55d8010\nA = -4f1568c207a9ec970b5c26f068f3cc8019e8cb483525d251cd2919b368d072ac8f40017a19fc7437cf88e927c9e7d6f539ee84865f0af24be0d6d98fb33d74e3e0d28020c00bcd61\nB = 723db98a78f42aa45496f31cf78695583526d25e167da48ec310e447ad3540be2636813a2c2f7b8c622795ac451992e91bb8e43e5737f0dd95623282e729d815b08ed8\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 237eb5726e2c628a515104bafd44348dbf099569815784eca5d6a415d3c12421c8c70fee23d6d82f7b5b136b70ffed3b6d9e98cb47854e79239d96c26f2ec955e4ea8dabc29a1b0765c9b7af6ef09ca673d1ee21c680e4b8cfebf47bbc74c993d017ead6cb6f3319ce4de9e9765cdb3ed8fcc57a1b153327e1a6a965e5dfa89\nA = -1fd1f634685eb1470dd9080529a891253a28a0b31e15c662733e20d43fc4cd71f4cfe83c3774adf8293a0fc3bd806d0b31b61c6ed0b4414ccdb91e2994e22797e5771c63defcc0887f1\nB = -3ec0478afdf54c949a097ca411be41f931acb750ef4f0ce97d0f0fc77cf15970cfbe24b170aa332de04836b7a0e6c5d456814182d27c8310d5fb662a818bc421587d95fc5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2f1d500443fc4f4b86e7ec93e4d0dfd3faabda35a6dd31445021928373be14c37fec369ce80ebcb77aff2151b7ea94d21592da1823ebfa0af196f286d7a69ea54799573bdcd4d09ca4f33b8a3a93b35de5ff7f65099d59367914f1c79440b471ced6773b0802bd8ca99cf531b62892eb1e78d67f8210592208859b0aa1754b14\nA = 572de2984fe2ed0d5ebb5bc3f62b197fd592795d91cb16b48a0c898991ee3e884e5870b92405f248036ef9b3898c5ee6100a09ede5a48bf7edf3a067e4fc77e7e6bf6a6e3d4f538e3d66f\nB = 12c379402b18a34dc8b80c0dcd25be16c99d6f76d5d64b6050b90910cce594bc022794640735710c7ded857ebd44fe5b2e51574a2296f7d7a61b59c0123051bf2ba4a168cf8f\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 4001c734e1391a88640007893f167eb79ef61e4717d5eb14b8d80c25ed59c753be63fc8e54bdaded22c9c7d3e49753eb49efa010439807dba0d90ec4f9b498aa97f109af542bb41922936223213ddedac4d0fad8f1446498f4228b758aafdf1d9692f59029c76ca2832125ba50e811cb95f2b982a7a4d87b4726e6dd8b1963fe\nA = 16792909716b581a936287d0a8550a1f3e840935f0f3ddca75aa32e3489269b078fd19a16f8d6b2326eebaf46da76e90890c0ead3b35689bfda8c1ead17a4f672588f982cfd3da2c2b9bdad9\nB = -95ab2c47f85001aa852d6999f29644a6a55f9e4e12bf905f911f90d29cd1e4fa4fc9d1a2aa6c215bcb5c5643561499aab8f2678fdc5fa9c6ec138aeb2d62f635c45f239e46b0fa\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 1bfad44b58d3f8bc987116d4cc7ac98f89f838a8712d81d726189e9e1469cf46fe04675dc0b82e6e556b02c350ef4e30ec6203c7f1df937ea80f435af7c10f48538fe7755ba78993f304e64ca0d783b0f46f61bd14fd3fd30768f233c59018ce911a94b495f58e", - "b96438e416ca3c7eba5b1bca9dea5a770c1d2d9f2f62f821e5\nA = -78a6a6ef40e443c52036e75f0b35938d632bd45aebf45a1fff5c2e1b6f601a57382b9a82c3e8b2984e643eb1570cd83f3a6be6daac567ddf9f37bd96785662bc3cfee6f47503d239c77781a8df\nB = 4920f870cf9f371050e64a419ebe07ac92dd3525b41e8ecf6939a267e1ba853d54862dfc95dd21b3526eb0a0a7a7f8fb67df2e9472dbec81e15cb13266257177c5f2b92fced4cea5d\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6b0b84505907a5ca37abeff9a5ba169975792c69b5751d9845c0f09dea833fb679c8dfbf3895bc470529e0cc736c9b4a0d08b75d709a1d04525ae583c5ba082d3bca1355055c7bb674aa1b92689cfdec4dbac84a96e81c855280e417f60e7e4931ef4f428420c0b85d2cd11c1030a47788d6ee6af0a76b5364fcf23b270e9d4f\nA = -143d843e3b12431fa0d873815a757a214cf731c298db61ab13cb87fe78b0a6184bd1fdcfec0c7661b10775b4ee2c815dede0ed497977c9ec5154f7b24a8a786501ddb8dd257bea51b9fd9401ff760\nB = -25d4da7b64f439987eacbde66abadf0da7c1653c1c1c6d9b2092351fbc714a20d2d7ad8093209da371150b69b3602480595533ecc1f3c5005a8ead10732272246d8cdfbab87c49e65223\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6bce40524278ce242b0b5292d27751a3dc414f962d9c1cacb45fa3ee693ac6890d2ff1647abe578c40ea8d4b326a2e0e2fa7cdec28fe2da089338b5fed91c4277cc5be37537eec2f17edbf48a45fbe38f15c58c3e733d408d001262dbd40c9d246c323e7978df4fb7207aa9270a12921743cee2a483e7e71b221b09a6b2c667a\nA = 402671b0cfe14655bc650bd35dd0c36ce7f65de274a0cc4b708c6f6c3e84c2125ab2430e702421904950b29aa8a03b049910305127890457cd0cc97a3e05df67f29d28b0452969986959df02f59d207\nB = 1648c29205f19fe4c646eb62e8ae9b65260c2cb8424a526423c6bc04ed55870cefef9b8ba808f8ed2e1ab170e2e411f68b934abb1a22776969f79f9420f8bcbef28417582942e26646af60a\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 40db38dcdc201648da555f1062bbbb92c632c29b66902eabf90d98dec69ab3f3b28e60cad1571e7246f4c9e6aa62ad26a6d0bc08598c7a8571fa830cae4c2875c5c95a59f3295f998681edba7749b7e38cbece8887a7823b4752165e1a897e638836d408f439f009d0fb6c196e83e83ca3289d2bd0f0eb36b721331e4f9f80fd\nA = 14361ace8ec5223bf0165b78913b77ef921b7089bb5e28891d120bd3db6513ddc90404a4e6cd027f9b51fbc02e80d376d59e1f2b043954199ef8218bf26cacdc5e749f668ad3b4ab35cd796f94c06307e6\nB = -851a39d8b0101fdb22ea9e367286e572dd132b8a77a6a14dd0e995131467aee898230f37dc6224e35bed2eaf459aae579181a161450bd7ebe6b62ea7154a8a0ab590ca4a6c2f05531c4e24650\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 4b085796665458b798f824d1c1a88c23ecca456fb88713b433228ca8735141a616633ccec4bc53ea4f6e0c74e4aab6fece2e4cc4c4efb479638cf54caf55d4addf75908076f5fb487ed00d540e5b984acb8f81cae3ef51db926a06382a288092b352793de721c23c371fd0ce7a789486b2e8b867d35f47b5daac2d339d22dbde\nA = -511565611538828ff7dbc45c273fe46f4f5105d41ccf5dd343b41e9dc579429e56a9cefc54657ef0422960d1375b72411a5cc93ffa323455e006e242580358d6cfb641f46b9c36fa777a613b17dd4a187454\nB = 4f22597947638b9a9e9b9b7c2a8d37f77259f1bb1c7db65003b6e1a1c807469c84c89a75b80bbe0324fc3aeefaedc6ad9c0d9e470dac9c30bc48f6abbbdce9547ad7624f0ce9ff3cb6be23e47bc7\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2b90a57349ea94ea818207fe15c164f9d3530c7cdffcae178557274552f79c4ab56acd78033a570bd6c3e45789704ef0b0ef586594fe4cae3ccfbf9ceef46e769589b084adcee3ef8345375b7103232465b991273df724964248737d5eccbac558e35e4190112571d3e7c291baa7aa8b1800121bd573b8419f627c0091e1bba8\nA = -170cc62ad57094d307ce1b317ae5e825c2f2e317ad6060437afa105501caea00dc9a86af8729e2f3c3a854387dc3ba368c0a84aab1a527ab34fe27b0a69bc71c728cca87be728457c65eea7d7538ef3aa282615\nB = -3d9da1377a88f647de57ade46dc7caf71b4f42bbfaa5e77f16cfcc90f00b5d3e9e9d82355104c7cd0db4c1dac0496be3aa35706cfc0a30a1329755faa439694e8e9b41fba8f1ebb46140818c7008e27\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 4cd4da762c7576d582572d3427abc4b4297f740705fc14a32b46347541b152d0d1e3a11f27213badcea1e2009e34a63350c7a59e4d43654b28298d2757d6b54c4d82f580e98de4230cd119ba350416452cd4b8adff29b9f35ae0c533f666cfed716838e2b91941dfbea8d6a978a369d5f27554ef411f15e5a89850655d7f3f5a\nA = 4f4a28af27b926d8ac347503d6ac0bfec388a6c0b38a577501c3ca4aa709c69601824ddeb5eba4d9e437a97f3e4477e1487d5ce7b4a35b90fb863657a5b2d901bb8c3c838db40b89b495ee9875e8eee607d7b8013\nB = 13ca192603bc8b2da29dae67159e4f8d32f351a503434ed9e4e24f74abb5908ef7da80781c71b1a5ce64fefd13a16cc1eab05a370bfba2a97e6cf90cfe98d3a487ba72dde0762c36c10e1da175f1c1b5fc\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3812e9e835ae355fdf328b29ed8b86dc3f6895e379b8b5d65a5de41eab5fb20ad3e2290c8ca69f9500248ff883d9715f59d0db6257d13c5cd612211bb1fb99867161daffc77968bdffc1fe48bcde0fcce02ca93975b3cd9e93b56974ab4beb59582c3d0ef2a65957f701549f8bf858de0c5bc98af3e5722f1450de391876a2d9\nA = 14ca6101af00d67139b985ac9f149accc260336237dd2dee802b5cc6e506e217b74c1a007ec10c20012f071ddad34e7407012669109ec1f385566ff04cf1a1ab7562353c0af1ba1be0baaef920a188c60db27970f64d\nB = -94b683326e9de19e414f653aeb2cb4bd7b17e76a23de6a4d91c43d717a35e08f2155b444a9549dfd01a8aec4dc901ea9f629f16bafd2c84828b12d2f63dc154323eb2d54938895ec4c9efbcaaede274fd4ab\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 5ad7411cef0581b2e675d03b0ecb9969102a283eba5e779bdcbb7646d94e843083a07269c932d18b973b57abe54eaaad0aa76cf7b61f30505a263bc95aa063efb264ae829eb1d1d5f7d380a0b4db59839de9ae6230ba51901e71b3e3d59e8c34a79678e751c8b7ab139123bdb2f04d90a18ed81d2046ae86da1a73c8dae4fc4f\nA = -469f61cbff01f0e4124ba69a860ec6dbc75cd758dd8ac7cbfed97645b16488a329adee62d1a66e90ee4212569d56d58b61676262f49dcb68296bbe5d8e23853e3fefe8a304710cea568ca65c183531a992ec5b4d82e226\nB = 4a0d48e31cb8c24a3b2c9c95fd19edbe46823032ef4c97fe65d0a30d5c2cad7a4fbbe89e0ebc9940ed9f9ccb8ab18bac269759a9740a7985809d0f38259e680f0703febe7fa012d1ded47f0cace4a133f59a721\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2b2953981db406ebc544c39dfeb08a8b089064533221536c7fa2bf2a7a0d3a1192859b7dc0ea5036eeab5aa371e3e0070c3980433adb3e3a5202ff257bb546bcb9550423201a35501fd717ed4c0016eb3a675ed399340bac7f058a04e69c1774590fe747ffb9c27e78ba50fcee30ce533a1659fc49dc080a60f21357a6265d24\nA = -122621d97f42b65b060c84df3f0c0da097b5e240731b77a37bb9471e7e398b242db6f1b5e25062a9bed702860ccf6aaf386c1d6fcf60fc31b8c190d3486949c5772b9e621b863a7cbf29449ddd68b7e0c21e669492e58e94a\nB = -33978406dd30ec2b192c416e422428683deac210017cac9e4355e8446d6969295b0fbaa8cabc92c1fc0068da70efa047f938a419bac160ed6f794a9f69f53a88648c9725610d5f309b652f5462bd3011cf68ea859b\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099", - "c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2104dfef151526e072c09a4a277eb981a035379de3b1a55a88cb060681706f26131c388f5572c5646826b119c85ed450207f32733487e3c4e1e9d701a65058c4b4ef0cd1db090495643038229ed177b54695ac32110619038f1c1cece14faa693d88476e3d70329b0084d0ba5d547bbaa5b59ba1ce1fad5aa2f1c11a75bc7c0\nA = 7b79e6f1330fefffaf8521089c3348593e40ab7e8d4da3d4346571b43b12740958336580afd13619be3dc2d42eefd9e30599405da3e32e7f3a5655ece8b77a367059668021aa092460de75e627526da08e6206b0f8f539ef40e\nB = 156e234931907c0c0970c1fe6bd4b24225ed94d5f5b1be4693c8e141e9a6032425b4a47b6eac6265afbeb9d796eb230efa707d5ac4a73808225181cf814b319142e9d175ac461c75e6d479bb6bea53954bb981062eb16\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2a392c5fc96c29df2f5ae9eaf76e7d981dc1e2f3b47b43a98eaf556a9465ae8727c622188123c64658053ec50c25e54ac5c6c8bc279b134d326e911f14c873357647866eccb4f9038ed0cef5082c2058ebd71e1619f7c8f8f2fb80871ebbca3fbfb7845bd855d307d2efd853f1bfd467fbe030862f165e53a9cfa633d0d3fa23\nA = 1e0430e7cf15173d00592037e83e717c90d7dab4f54a5b2f0f5772762fb5f56bc0b2a53ec1bc3b960afc35e7b043f9d85d0af6c29288486af3e186e52bae6300b58917647231b40a12648cc8c020a797683a9bd7ff34eb6d41b928\nB = -e08372fc766eba6e0ef55a9149d700b503e2e3f978c8a397912e2735d5bcff69c461561ac0822c44160c7c1bbf722df421b74beada57462ac54a9bdcdb42d6a27b86413036ed2282abf62800fb2518a32a4a135bc948053\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2608f68632ef14dc3979725c8cf1a0db10a1651f17d91247edfae9935b53f6364d233b030eb99871a87b7bd876ab2cfd5a643387a7af9d337e81770db04a14f4f8dbda2cff604838c9af9a31e8dccf9277d453176589ba33abf77855b9501e63370b2e6cd22831e1e70ff1815302c0a026c70042957d08e74dfaff940a91a7b9\nA = -5d3568858c05a15bc9777af949eb01d33dfdba58439fb3f7af2ba792efe8e78b16d7fbc2a303a4c4c4be7c9d43f57405e88be54d6ab55268a4739945ef582921d2877019659dadbc76e0939f4b2cfbc91e5356ba2ed531526ed5b9b3\nB = 47f81f65ea1af04f702757c02a175a299b23cd8ad551fdb67020c50cbb4110b5371dc5790b12484e9ce647eeb24c0220a5e62aaec3461a9dcdaf1a22814b6f22d66372cc5ee31944bef33469f905458c172ec7871d9dc9c301\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 5735109bd21d31b5f54e9221bbed78c54cf387e39c13d31557e8173e173f786b2d2f1acf3966c3bf4552fe9bc802d0868a5a7632404cb91609a7a45fe0fb83fea8d83b0319666c1b0ac520169c15be708343359447f2fd37960c1e96d32799ac9394e839b391f59dd347acfb79bcc4e34e76490880d163ac97ee69e3a0a6e68f\nA = -175011349a0a1ceba11756bd528f2bd631c106e709aab223032d08d52d7d6724e8c5b055b6f97b48261f4860eae297badc1214cdae9b2500a7a47b4b777dd7b8f1006757754ff1143b637d2a3adc555f38eafbd5478cde0b04e5f46d3f0\nB = -2aa7f75d6801b04ea9f690aa0c5448906595fd28b53775059c01efe54b463f1d87c9fb4b39cb038e770f99bb995a2118b86ff8d004bd964e958c2af82becf362fb0b927c671cc3bd7185990419d26a827a2d81bbc0126e1029556\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3b4ad19b75e1301d19b57ba9b68e0666c28c7c5c99df1d5fbbe0685dc1d3489ff39c919222719c5d8b7ce2d7ff967730d776a02b36a86064ed66a02011bab82eb575390f85f0104715f6e4954a1bb28518450182a8ef58af35d00e2fe417f07ba25dd9c85e00c3451082becd22e3aa0c9bcedaa96e6423c7df6c375b4c799c65\nA = 58e1ce4a9b512eb0632b02cf1207936d6707b802140540fbcbbdd712e5ac1426b4f36e74a9a9ddc812e572855d4fe4fca8a0de6644226f5698fb46a5f2a479dfc8b588aa8e02ddb15acdc79ed3d17143e290f1317274f425b869df54a4807\nB = 14e341cbb5f5a7f3b4dd864172b82ceed2887fcf20aae7d0598b3d8afafd2f10c27bc7456c1488abb570be3df04f43d892dc6a8dbe7621f55bccb0ee3acb1ade989a510b4e0cbe29b6b93968f323f0016d87944c908824d249769f8b\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 7fe0bbbccad6032069b1a335b3f2dac16089051cd9321f903181fad23be6853e2d209958e8c48e008be94a62c6206b34b4e994ca08b8f24a2df0e6394ea65b3b7aadb3bc43d04dc9d35a77e673c4476dedefd4568b4ade5d16f9d89486f3d5ed0566b1eb428cb0b688f10fe3901037744f278385754fca481f937cb630f60308\nA = 1cc0e3ed58090db55063c9ba11401636f89262d6ec096d361f448496e05181c5f7f2604333f26d511c13534618e90637adc807d622097f7eabfc03266135cb626e1bad20997e72da71bf2b3f65a4973dc27d2a594b1fd96b7bf7ec14b9e4b983\nB = -87871b2058d33cb67d83b6a56ab27839c6a6c771bd94e55f200a1257f2c737e39c4a0403fa410ea64e8f442d300df1c19c2f03d07fb74d94f86d26814fca23d4cd2cd3718252cf0cd8a0e36726f6e68827a1dab6bbb1d23b884381c702\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 35d7ac5cbc7e6c262ffa41be168b02a3bde9e112c512d1f68421d705ea34461ce3e0dafde67f44d44cf31d91b38d4d5f2fbf8c6c6a44ec3ed0298dd58f3d45c04346c11e57229dc3d2cdfea02c802732d9a811d7be5e81094d72172cd04caaa3c9d55a951c09f454f42add6e89e2d8a98e124aac86379df377606e7af9bc6baa\nA = -4ee01518f6581c560a186fa05c6f4bc26809c4822cc74a0bb74d5a6b0a368aa9bd0108f26113443422b8c589084ad49f919a9e7821d99127bb210670e732b7cdf610e464e300a39d3dfa7c82f90cf00ce329bc6763d7b1d4224a020095112fefa7\nB = 72dc8973f7af7122a05c90df190bbf1e39abca908c197590dc7ac41fd0712f48f838ca62a72a177a293ee6b2afa7a10c21e7993347c3df4f161a5641ff62ba123999bf1eabef29ec0d33ed0919818f4b7c35b5f41e654759fc9abdc0f80e7\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 5d83a9b34631dd6c63c05a0c012adf97b4d0f20f61907e1c2145330211e9a7e38128517b058e0a85e993c385068d1cec768deb814bea1323dbd333de091ad2cad72431f20c1e70ff7e1b119768ba44e14292c38b88dae7e55ac9e10ff98e9bcd5f0ac05af499196b4be0c6222d1a63227ee895fa6a8221a4a182a1323183cd7f\nA = -17b3e0c9288be15fda58c8fd228216bc466731d631218a7ddf1d2c9cc858c0219cb0757d3b680bca1b1964eb15031b5b9d761a8bcbd160db89be339067a2ea35e1ac3cfed701912a17ef9ea03999d92e3592e893183ddc05cbb98a656983b54590c72\nB = -269f96a4634eb37cf8a6608408128587ba45958405a29827d0d03d34816fcb1a2297f1319485439d3e8594532545086efbe4d21d31d30e2daf09b74fa8cb27df54e8f9f993630cd9a292c977eee70887158bd3fa3cfef321ef900a0598ac8cea\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 7fc1c65eade94d9de7440eb8dfaecf1004905135efd4f98257c3295b1e76ccf1e2ab6808d158d360b7419c6210c50efe960610973d9ae855c72ec0e81d423e5863c80b542ad455700d2d0dee5fc403dc01eab460c24687401cf6a3179642e59f2a30268df95fa80dcdac230702352bbf6b60acb9ff5d45c5b09a3403b954d173\nA = 7906bd8d3bebb1303c1df1fea0b2503b0abe9c69b4f4f5bd01eec9e314788cb7d44b93428adbcef570477e8ecac2a64822e481bdf520fc381e1bb0b2cdae2fe94e484cef5236dd524e4dc364b72f4c06d57f29dd3c5079e532b1ab1e71dd6a65b3362df\nB = 1479ef2807b9c23c094d0416f513894cc92e023b134f44a5333360dbbe98b8161ab899302f4fa11b470b97dca0c4e8ab7ae47e5fd0962834e6cc1763618193f4ee027f667368da580c623080de137b5869c3081128e6081b9d5e2dbafd791773242\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde", - "2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 730c04094b1ce944588e8291f7e6cf763c70b79cf362dc8a1bc63bb8790cd4cfe4eb51cf15a45a8464d69ddc3e1b9383cfbfd643f317108cd9ca6a6eaaea177c5c8b6747bbf40108cbc0437eb8f11bd2a0939da59b70c0c6129e2c249823897f2ee536b0427bc45035f121d2cbe7441c175899b97c490e6c3ca01539bcd05848\nA = 102cf23cc3b81785c73ac3613c816de47fd585c7d5f175185818dbb4bf0bd47d0dda9702bce97b29d66e48bfaae0fd07b47b40be2b48ed702ef21c54b10bb927f9d6b43604bec4f4b2796b44aa6b4e83f8bcd00f2fa3871dd901570e1a32888d8691454c40\nB = -cc5349a9c5280a933e87ca38ce458a711c71ffebb40bb1f7612b42b4684afc495e99c4a5f32eef1c9564c2b7612ea4cda7a0f5df6b3ec9026447dc565ca08563d46aec7ced9fc4cc5645960210d44cdc3944149051d569c9295dc50862f8f6d1f6cd1\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 1cfe1842a53d00e4619265e2fce7cb566ffbd912c9213925d01408a956af304eacb85e29fb6edb812a95e90769bf1c3d62b0cf6cd5bb8f8992391d2ad70f38a14fb9d1d1eb522aa7b7fd9f1b52790beebfc887193882377b7ce567d317d8432e1d9a908d6ccfe8d2de7de497d77b023b3959cc042ae30aefcc0229617fd2a146\nA = -5c3d24fdb193ed83f5f6a825c1716f98e3cde6b32e09659f253ca3fd2a39402b5bc3a6497ed7bc908838e93422559a13cf59156254bd3fe1e3b8600b2a777943cdb39b9d42c58043f1d587424425d3ef5f5538ea157112970ce3e09a87fbb5f7c96f1b5e65fa\nB = 675d9d2a05288b438ddcb330acbd59e4639375f3f14ac2d0e9e8b72de6ffc1d217ce62f997577f7eaddbe4603541b132cd41f2f2740363d9c331ef22df92029d143fc8495ed0152b918aed7ff22f564c7cd94fd3fe4178c90365ace43def8fe30ab05c0e\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 83ed1948276d689bb7fde814e67fcea72c4e3509c48873c3e7349a8fa1c08ae11ea4d814d8deb1021eb8b8ceec342cba5002a2ca45d5f340ae1aa500af4c7db120d0402c6cc8a840404be7221bbc46ffa10236043e5ce4415d3ef1355bde26d2d26eb7127326d4b8d671bb96a08e38a2c1dcc281830ac77202903a5e4777ff02\nA = -1be86e7c87827922d2e8a06e3cd6b64ac9a280c525749bcdbfac4856916321a964c9346d17465378251e6eada42dadf38bc9d7d87367bec94ebdc21af6b1302e520db08a64ba6b39920683725ef02b011a3e4ba46ef0eefadb98582cb911d0cbeae9c231b5e432c\nB = -352059faf97b433089a688c702b97adefd0c91d51a0395647f822c6762fee3287693e302fc5a5584a12c048dea1a320cb96fa70b5daff7c2ea21d249467d14c6bbee15a1e94c030e908342a939fbe8ae0de58cb6d6eae7758485e392ff6d5d64465b701692c\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 402525e19b6b68942253d1a51fd9b2ca36fc84cf938d80b3d52fd4302de142b9d93d1663e89340fff10c2b5efc8cd47fc3b5cc5ccd49a6ea3038ead6454bf190b7f88f52c56bcf00c6ad5b0f5dfb7615915ee8af137dd99cd3d21172ab772f36d291a6856a8e7912750139c09aa024b930a0a6b9eccc83c2c5c0ee2473ea32c\nA = 65e5db532ecae639bd56dd63045bca39b33b4d70b2db82ca3d0ee8ca436e671828cde80217b48eae7487fe110830589ab1be889f1e1463f3b0757d529b2f0cdd2ac92c35e8ec141885bbefb6040a3b5e00e64a541913a38fe05824a929f8c5a2c46568c61989c3ca7\nB = 1d9c73eef8373cbb1e8393feb26d55c33a245c33d7031c234abffb2f06a1601f7f3a79ef1e8664c51ce5dba5f5aaf3b9a9e42470d381219b4616ae93c7f6e64792d23bae523b6a224c1f714ebc82a11f9be42618922b8d2eb7b55e4d45572e68a19fb0ba72228b\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 7a9cdb5dcdfb6e04351057d731fddb9e85f41eb432f01c0d980673d294d05ba9b0180133a89930e74cfce78ed54991b494a19e7f80f310b85904784cebc5639bbc631e80751807868e7fe16719e8ffcd1f2cbd1b9f303c3ed488b647670be3080668b5fa0e53b6342c33c87f0ca1efe1ddb1c877bfe2556aeb61805b06f41343\nA = 1e412c3d66aea2c503f3aa5dbad368a61d969a2951c0094f9da32d2794e47f3bf4c481ae23636baabdebdcf0753d431426b1865e62de8eae7238a9245d62820ad7f17b5380d701f5db776cd4e1ddbdfd542901731ffcea5bcdc247fa9c83f7e08a9389e5a76d38be21bd\nB = -afd61df72361260484fade8b432713eb740df83a401d73492883a5139c918d5c911ff5dc00140637da1c6acfbab4b0bc8fc1f337243d90beeb1c2a083ad8069494c73a99372bd38712a5b5393c779ec1915e878600e0b48157bea44ca8e97c6099c4ab07fbda57d1\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 712580a1ffde78c8cf98ba71843c8130e835fee3afbb45e372d04c04cc388e403c9efac742611d7974bbae982c3aadfd1893f5da280afe0c1db1d81a9ed73b6ed9b7f05a20ce828316103259112d7754560d66733041e9470ae0d4dc95fd0484bfd56d66739f38ead7efa4051187ea41f7bea8fe5d958a29af41328246e2bc35\nA = -47c5755ca61ca8b7ea927f6fbe347f1362915548ab38c40f0418f4c9ba4ad520c3b2469d9ba3976669dec0b278461bae80eda53e9d11447512963e797f45460f74678acdd69fb9efe3897913b6568f8e03a6d90b4cb5bfb06af132bf118574b70e6bd2f6d6cb4d0089379d\nB = 5bda68c0a64218d3609d75eb4832d5468298f19498507d7d515f4c410f04dee535947571a5e75f1af7f94a5b3b05fb742fde23e7cf3f8b3dbee0a569e5a36d7a3d31a26c4a48a299044fd72339d2cee1a68966c851e76b93ae34130b75f4abe4f2260207d2254d23f56\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 4a1a514aa4d1ada84fa841d0b668930c904783fac521377a7d622201867d773ad23dbb667e0d4181616358f3cb088cd157c8e72bcd03db64647b37aa1813f870cbb0318ae0a3667f8e6c19f6e0706217646ce633f0cc8bf4e8f0f4d7329a8647252ca6d376416d545e73cb9a3cba40f8f9465d85d57c2481b84b6d95dd42d50a\nA = -1d68bddd8c3e6b78daa0acfc63a6f39e97f19527a43f6cdec47568d57b47f4e4b7ee88e4a28d683b569e406ecd2510351dba25f10b9f7c82d6da16d848bb970cedf7675e67937921bd334eec4bc8fde83d67aca57eec804ce22bb342167602fbff452d5f0f2a7f38b576e1e50\nB = -34d219765916a4c8ec843ebee9a7aa1162974d41cb4d6b60532513608452da9993749455d9701af6b7b6c7454d7f2fd5c344cc938baa5259301d4b56ae8d25b6f6510ae6bca114cae6791fa5a9551e8a405f5b1c0bbfc27138563b2d64f9a4d7a8f42a23bfacc3f1ec9393\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3fe24e66e381eca525b24cf767215837019f44ed4fac6ab118d02cdbd658066505ee5b0feb7af51859992ecb97d727121e38873f748a61d70201cc43228a7732156a80dbe399e05764be19e37dc1b93222bcdcbc45b1a4817460f7021dcf1d70e632bc6a306628790201222bb522f4cc80adcc907463a539b02f74004d42adff\nA = 773454a43f495959dd55b8a064d70b1b1ffe45c084f5f9553582e24fb402b564de68e5379a8d9d02af101594e717a6c6db2e7173e557a64d2f28fd45c4e06041deda040705d99acacf8086830af19c7ab5e27f91738ffbd937dc27e5b7869bb6caa12c2d7930366ff75eadc570a\nB = 13d884a2396268f1a8186748a15722156a172a56dd3d8c77b9cb7001b6ee06720653507eba9bb9918f2f699cb37f3b5ae514f5180108a704647f19b0fc075826153edda66dc1105c1008ea8ec6f8c10057f8e8e479e1a1274edfed9ef719b30827a30f26da78820c3696d01aa\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 715bab8708e53f76d2ef2afbb845bdaaf978b54ce25f84dbbf9074f16d30a18733a02a4ba5d7b092fa6c25d3b9b0d8243c743910f1b7b785d9cb02343fc6d59eb0817bcff05646030ce4fbb2b9ff76781cb1af66b46553d365d02c61e677ae97defe92d057d4378dadf8cba9824b0022c086e0d78b5442bf3d3263ba22c643f7\nA = 168186208c734383d472374fbedc2d5d430e85690a48", - "81b740008623120a4f7f83b2cdf85dc28bfaae5870abcd7ff1bc782ef11c78a75c99d41f8aacb52fceeb5f10266dc65eb00b0868937340146d8850887686d54218badb97647a6d82c0c6650ca1f9078d73fc6222aab95c2967\nB = -9711e5b3965654bd9427f79c89a0b3f3cdec1c857f4451eec236c1f221bb6773e5dcc30e7381a18a813ac2b03ff4a4ba679aad41e0e5d7181d4627f682ca2dc8af9a8b4f878771446fb225a979ef9c7e641cac819c307c8dc50d9c1ebadf912ec7c844e416f95b546cf09391f9f\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2714b99dcde70d6c3be8b671d78abc155793f13105fd4b7c5d760a4c68ae89987311dabf2a9238d18299f983b8aca69a9ce398fdf2c9775d90b11b3dba17bcd8edf661efb6e9c50b4e37553cbecb54eb214fed1d0847287732810e550a4c86b51d4e5da1cb7722ce4317e69644620ad806d6d1c94e1e3fb4d87de6178a997453\nA = -75231ed37f1dfa4487c9fc79a6f7b36929fdca086e42ed41f79430b2dff521919236fe415ccce590e1d3b986e16dda866f3f0d29ac1adcf55d87fa5cb67dbf4693293188516e360bac513303769c42181483fbef7abcbc4fea1310c916396d29f37d9058a62aead94511aded7c4b8de8\nB = 5aadfe65df0e5b877fe45d42d7ca02882cb6c686d486374da5ece6f87771675153c84d74b6f40df1db567b7e1e3c60c41d21816f958f5576fd2ce2f84a8c3be4749dfc7e5561266b7c9698c7581292d0d813cb77955458d63bf94ce87472924c4ca79504d1ae9d5f025c7a2504156f\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6613b1c8ccac0cb8fe2f59e76fef4dd05acf1f1b2bfc20aa3f193622ce3e9d4c7824ad544477553bc68f05f0b546e7c1ee87301e111af7929d1f40525291b88e211db7175f4e5c0953141914fcb4fb951dbf77442e7cb28fde495704f1b5141de1e50fbd0e359d0d86ad709c8f564c84dac81c7602717c269219ab1cf12e809c\nA = -1bc03897b02d1edb633e2c019e40c20c1d89a210b0733412aab675563fae8bd75dd7e65988cd8df4d9b343586e27f548becdde274f62dd421679554ed9eb127e527a69d69fa8b17aac0424dfa2a7692d1e63617ea45564b55f01a70325bca050862d583cdad96c4a2e123d0ed827348a745\nB = -3d5239dbe7bb3dcfd8027204eccf5e9444e68d322a0b0c535a203a1d0c054e7dc1e588bacb891388241462a5d2b43e6cce34ce46a23e6ef29670603d31001374dfa347dfcc794988e58945d0d2d17da6565cfea559203dec119fc357d396f65b296deb07686b0ad2d25a13fd4fad88d2c\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3a7fc5680aae875b9241200b9f4112a82cd624ffd9044138ae3cd65200631ee9d7b918fbffadcad7e598791a9f0bef3e23005d6bc0048ba92461283492df3bce74c66e417b082ee052fd8f808d71f3ab18f9ffc40f8fb51ebbb936d09c26a3514bf868141f7cf238c1abb3d88e5d50dfc188902254f07d63fb8cb611ef8e4149\nA = 4a30f32d467b29dc83b40bca2fc4ccee5f08a64069cb87f20e63387b2219b12aa312400c4ca59608f50a71d2535cde40a6d248290793fe01693ca40b93a5cded2dcfbc9aeb36e187c9d650782d12bea917daadbc6525f266e074037803e4b2f300778ca8dcb304658cdb502c93c94a16c6261\nB = 1ca5e5218dade077fecb81d579e1c9290431b34df5ec84aefaaf233d68f17dcf60ee010db26320685af13a821b6daa9d73d8f3a30826c3ae7b2bc5e219cadcff826283cd7dddd04cea7a5e0585d6e7c9f23b27f14ff815fe53bcd75fe700b1b91671bddaba737fb43bfecd2a77e5b752a206\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 768d312175ce7d2601f30bb38339f046e4c2ba5c19ae5f7ca5a562cc2462c579fce9985e9e8afe2578db542c8d9e7693e0c74ba161334b249ce720d568e9c18f09c87cd701e6f2080b752362f2fe6252a1d0caaaf1fa18199776e4c6078d89d520b9c63db159d5fba7e0838811e68794b1413c248f3f7173ef29eff28f15b656\nA = 149353e91bdb70cdca8f06648388508511a64d05221305cad7187ea40d9ccef91fe17ceb1e79667bf66e8e6b7a57faa90a83bad119c02984a8f860bc1f23ffd33d4ad84896610301cd2e8e80a5ca7e8d3ee63e7dfa459793c9dbaef3569eb4f8a021c6a3d032a9c94d3f6b8278274d0088a98228\nB = -a7cbbb6a434e4b022d312ecd4a45fc7fc4d3aaca038cca0fc56e529fe7119ccdddc8e76d51a2fb862ad3d27a16ec8a51e5f66b9c7fdfbddcd05a0ddea14172339cee340c8c651eb653c6aab6551c99ae94f26116e15dc62f2c2e63305bbf84590fba1327ee721150d46464d7e22d45d53ffd44\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 763912f4b16549e6ccd60eaf7a0a1f64d9c3bc83e4a9b87e209a3959ba3cf609cf47183bc543f08e346b6e12b8bdd5d1c07c603f74b286ad432d58d7001299ec7a4dcdb56ca875dfc7ee5c75bcfe2aaba14959bf3facaebf8df92bc12937cfd4a4865b3dd74b243ff62ba256d110b01b4089730cf48efdc66fe272f9241014e\nA = -4df3899b40d51c83dacb442fb143835bcdb550136921df78800f0515a6cee77fe3236dadd2a0800b79ebdaaf8cf4aba5ebb60cdff3e4b4531ecd0903c1674a4559339123e9f09158080fc53c4c6ae72c961c8da2f357b7c05368157b4956e592c41b25642457651abfecb4fed5d9fc1fc3825b772d\nB = 450eff382e73f2f38bc3a4abecd5f8de478f80a6b99fb6252173c90d7099629afe859442bb1f796855ee9a2940f21d1f9dc44f462edd74b479e1f2926ff6faefeb55adbc6152b5c97967b1dc8c44dfb85b5e02e870d2920b75422c8a427e99e35e2a4be92cb0ddc04cb7f4044f716be97b36f045a\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 56ef57d56c6d1b94cf0fcdedd3611a8ee444c2e25522b9ad175587619598da341916b183be03b1e73be300f9969120d8f3a23750cd8c4ffdb87124a2139e8ff2c15d8dc944bc3c3a066aa16dbe6dba4a74925e16acdb2b2e83cd7fd5cedade6a7f7409a509c00dadc182b2860609cc9a375cb8bbdcc350bcb2c0df9b3bff882e\nA = -143caf995b7783b1316b5551978727f06512fe114b419c735b3381ec351275fb7fbd6ca88b848c3e8c9faedebd6d084cb8a231636f68f6803d14bafd90534609d4a4ac0fb953417be7fee4e4cfefa452c5ee5d1e1b97ee75f83cca8691a0efeaa8bcc1f1e0f18c0c5d6c7684c9da6c9495d31a32f40a5\nB = -3025fa05c55826c40089b12741b7d406f748cabf692bb0227519a124653160142633700e3c0676000943556f97551171d231c1a35f7b7d8f96b0366eb74942466ceb4660f09aecb2fb2ac050ef699eb05bd8834a2ba959ac71550b5c026b9093c8cbbb7c5fb9390a7818db682b7c11e58996c9d0add5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 42f363c34c20c443c1ea7a1c54f98c6977b6671164a80308000533b2404a7f280adb1f3b98101cba25249131288f7ac68b0ae2572c7777e7381c1f4d05fd82188c4b1ed5636652e0bfca4d096bbf4189a9358b79f6b6333b99e5c4b7a940c2f7d1413bf9f47a2ef66b620b5e220b2c3dd7267452eb1b9d8d9cfb17bbfcdb6abb\nA = 499d05de867bda3118a8cb82b80ac91fc505e0fbc6c7dac5fb61713cb6e715f56a31ae8af4b400461d7ad1687a2631faecd90d7829f67d1b9e36ed7d55704b3f2aea65eac061172d698384daea710ed92cf1140cd4da427174bebd173c2ff1675b2407a84649b0a318602f33105006fe4d5ed8d0e015b99\nB = 17a426a12a0175bb46bf7a7e727eb5238af383cee6f4d5e2bd82b0d29b9fed35f3d8ec95cfdfcac49bee47b25d3b5f375a3340fa83f8dd9330a593a974d208debb7e567e59dbb7251b54e42dab2cd50fc63aab050a41bd88282373f8195c94c35f61bb48aa921f574cb4ff0984ccedc070efea8c46e5cf8\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2f03374e9596cb56cbbd89794090ca7a4b437f4c05fa38a09db60e5ca900b208fb85b52f71c29fd35e62c9f9529d7ffe46fcc54607ccb07f6f8e13fdd4ff1185033ba4fcefb1ed4bfc42c3ea9f05276767d8dc9b7b4aea4c8bc0ce84951d1f590cec0751f73667db19060e2bff64da30fc048a1f5700fe3f489920675cc3540a\nA = 1073531f678877ba854fd1e7f857659614c526847ffbe8ed131dc9f2ccf69e1f1e917bb44a7b905f7ff758f61c06dd59ee09567d9f0df2550fcb98b776ed1381ce052988aa08fc5153e31c621c6a51ca61b386e3a9163a5cd69608b3e200476a8ada35d906c41d044bafe71ef5c6f732935f15b53bf36f7ef8\nB = -d", - "e3563925474e5408e245184b57f328e265b6cb62eedcaba809d8f257eccc0a457eeb82c451f93af93ce9f36dd1aab386e7c02b356f31c2d170169dbe15e70cf5bb9073b35fe0e7c7fd7faa91c5b2b0740734f12eb741a9d9ac6dcf7cff59f6e16324ea39e1e07dc5b9daea27ac674dfe5d0a5790abaebde9\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 1aa22f9013bc1cdebbdfecedf710c1bcaa41c696a3d7dfc1c8c601fcfcc1c85c8cc24be7df2cf3c7311b3b17a4ef2dbce545dc467d2a92d371e02a196a9977cb9042b236acf99d8c0d34a1c4dd8792d3497cffbc87c397ccee5d01fc2c89ef051324a7061e423720d0a3821a36739797393bdf7a45b5fc600824a17043312bc\nA = -4fb2e3fde2a0c653104c077cc6459c9234f86cc2d7b317329b68289826d3e2b975f1a69bed1a53418a0dd86e1b2723f4c4c5a29d003161e667c2315ec24a36f8bb5f2eb0a94f261e791bb829db685cd0ec9e1e301dc140ea57cac1da228124ae029e2b8ab1fa3ab99c55a9ca94dc7b767162c0a24af851fbb984\nB = 63702537a07971e399aa9a1a0795db052d6c8185c79107216babe11d6d8d472b61e604cecf9eaa6d44a2fcdd1ef0b6b52226ea0c6902d929b09e16576e6d1a6921765b2134c5d23c69ed61f36ea9a5552e5819350366240693558fac7a9d09ecd3702076c8c758a4bf6843fa843dfd688bef3f73515db31bfc26\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6acb23ea695d4b60cce53079390da3cb3a4bc3a6486c238c421f3bf6c93c027a0475f656c3e5435f0211e90458ae81772aa956ef284093020f7b58ccd9373f3fdd39fdf4adb8dd64590f4a7fc05238ba20017bdad07f5f9a6f076b71554a7741bdd8c98ec68f8fee88396cb1f47c64d6da4c228caa3dfc7a9a1c032a9ba4fedc\nA = -1b2496ef929bc673042996ae80f27c6bbd33fa7c20580240ef8fba985d1a6117d6e746989924e34f281e7d2509175d0773dd999bde16662e88fcef52978d19cc45fbae3997fa580a66171d398f4f0e7605d9f4aa4f728902cb886e6b6dc9f0161e7cf1ebac05a09c5a1bd69a92273280758173fd2c14550ec221275\nB = -28399206ae2820d26a5aa0bddc4903776611d08fc4cb34a22a8bdc2a19e9f8cdab94217f346a8070a4145f989e1dfb49cfd100267635af0e062872cc879c534ff138fca603b5d45a6860ea85b6de37cfca000c81fcda3d14ffe81da919b2a25214209b085bab9cb511889665fc845acbcd038711533da171d8308aa\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = c012c4d17ea4c95a360218adfc3363f6d89f5aa524aec70049ef94c2c05e59a66ce01e25588e164bf2412f9517b7740de53d037e71ec3a1d426f05b18b128c41a878da75421e8c8ef3ebd5effd40735c00818eeb1ec63182b44e817403c9f1f6c1a0155334be63a3a15109be6d45ac0d1b1ef5cc99e9b284b00c487d91e5472\nA = 796fba6276fb7129eef2d1572b305f63d7b8c49371cfb3b2c67b141071e66ccdb5e321fa2c1bcf624c77317e2aa135e1137dfa46a34c3ffefa2fa3e316be81f45614d422bf86fe4518c2fdb7e416bec199de033cb5fef7f193a80c0f0e6ee924a12c8f705f5ed3793ab770914924b45cf2578bdd09c701169f0a881e6\nB = 12cf934763127284e642ddc232b1c889cd86617307b6ad72a9fe0d48befd7c5c5370a0062dfbde2add256dc0af850813b22320ceeaeed347eb9319bf22320b2fcadeb51c4bb26a160f7459fc172c27a91d367d5a232d00cf7bb778fba83afb744177bf1ddf45446baa035fcd0065f9b493d92eda37e9138f4fecf3ec55\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3de123bbd50c35805b943e76e97b7e664eb9feb99860750bf97e275029e836217375cc1910c13269ffbd0bd72bb82ca445ccc4b693742a96d19d3dc23f78e5ccbba46d9ff5975f239551c36403ad5fe86997536456c4a5ce54807c24e3b5317b1c7b2a1661aad85b63859d427f0703b460cf72b9acd3f87e2e69d7f8f15e972d\nA = 1d0433d84f1de082d2058475e0168ceb369013a67aa9417f066c29c28272a0b3f8be5ac7190ab78591ae72a1dc8ce628c683281a9ad563e134387b9258b9c96d2df288fc118a8cff068ee49d635343772c2fcc252facdfc93112358414e1734d6948b909b53e46263e9a0cbffa141ef77bc98e7fae8ae2bd85bd875aa7c1\nB = -a31a574d105305e47f4fc00ccea0cdf854556886b524901c22e6f3b59a42915932ab209a8d5da29ab70d1472dd5378d9c79a7447d17665f9d1f1edc1e545e417cb65415cb8a368075c16264f42555d26e83adc704b5c126c6129318a8f394af8bdbb32c8114470d11b2acfe806acdc7b96e1e348a32ff96a988de76d4623\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 770f0c3104c0f3395fabeb75ddfa2c21a111d23438463941239f7c63e4b6e6832b84508ebf3cde1d90cff0a2801beee05cd5118f9a726a987eb58def6780be899b473ea71c697557ff63a4c6db894e9438595acdd98abfb529d75bdf3c1d619d6165a9edb6aaab8ada50b61a3a84de654706a9aedb7321b0523558e8f18116fd\nA = -5fafbd498d610e9f29c38a5c6c262b71672fe9e9c84f0f071b549390353e4fd0101a059b7c547007e27df97761767302458f1936395142ce5776b0959fc5ea039429d64ac5d50c2ae0ee45d60c0c50b7ceb4ff9853d57c6e883f588017ffcaddf5a1aa3e23ab068877a114d9a2cf742f01f5f5d611424c8ec0d082f5c165b1\nB = 552155ef110c126afcb87dd20251220c7a43bd0215ecd22249a21c93583e120ba6f046c6fe03086ef3c97311c4d520110a450470a473d8633e3560d2cb44c25559af07516aff50d6d176e8782c06cd9aadd3354cc695c4ea8dbf85e01dad479c8e8438154351fd5fcc6fc7e9d2162ce2f0179247f756f0b9b34b54be74821c5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2e9ed66317734668c4c354d720a011fc65bb67439b2ac9203dca65a8f567682be40cbad4f55a83e836f1fc135596b624e4327acb085a61b6398237fef5a6e6560b488d4a673b5ae7d734b896d9647d71087621cc81e94d58e01fc2cc2dc775f9ab1b6031840a672fb715b77bd636e3d87b4949ec7bd60721bec8f9907b7c072f\nA = -1a6b046d691830d33eecf2c53953676ed3f6fdd20c2252f6e915052ec28ad1fbf7a5f264acf87ef8ecd515ed921ce6b85017f3d8a8f1d14f269f31e3307c6f935ad468cf012a912b0650a15106fb949cbae7b36c9cd496538bb0646a7a28989dfadc719424519bfa43cd8833d3a748c758f813881d83c98f7cb2a63c2a4d06b8e\nB = -34f87db0f839af6e4c4bf146789db36b3d0bcebb9bad81db690ccc3a35070d8830c9745b2fe730a1f3a252612e7026bf9889169b57b8984a5479cc4cdd6844ee3e150a2e7bf7680eebbef30e0591c895cc8b2ca488d489554f2339e2f55598717ddd8ce444a060cc95cad9eb478491ee8d3b8358c3762a970224abdc1068af0bde\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6455ff7c12bf3bc37120fe3f1302a9916a6ffdae6ee6a37fc23ca2f3a7ad910dc0e1027d4dc304a8eb4eccbcf3c87cf52a13dde472c07e2df2420c1d36bdd5e88c3d76e774ccd2ecaf6a0ef55b8c60231b1348a738f812a4fd9d0c158fd5a9fb19cc7cf9f000860d4cb6509271c8e43ae4193843324db02a029beb58ec2955ad\nA = 54ec203e2ababdb0348135c0679eca2a8e778ed46e53f195331a48d3828e5e40da804ecf95eed819ecefaeb9c5377cc1afb1fb220175990d347981353e7d90637adf8cbb16812af8a3783dd312d967a490f8efe3f23746929cf2a5a8df58e0b878367f6c5e4d3c086f947fc2bf70bfc3a0008a8bb1d7d83f002930640b6ed94c334\nB = 1311b88a05224e15f1465c8da26784dbaeae84f818e029301ea39a982f714c64312f9f02d094c401abb6a89e8537d64c178637364bd261f4a27beeaaa901cc7b3d4e36ebcd9453cda33d47a53c6dd1d121dfb83a222cfd16158eac23482c8abbfaca59e765f6c1fe871d884d281793eb19f6409dd6bbe4083bf762ef24c24f0127613\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 64104f6c06e563ec66de4442d35d88117f2535edf9e012897f44daab5a1b8a8696f84db7a68d64ae24a394debb993bf6734c9df542c7e473b2e497396ce39a064789d5d7b339b65766b002a18096e7fb9f312ea5997c2a85463fbd6fc18f25769ac2a2123ccb0e72f14b0608c4c22add72bda138b83f986e78d5c9da31b15b9d\nA = 145f580c2ebc6c0354ebdfdbb1d3d7fa17f0b55493b0b9a11b71001c840a967dc77f0206c3dde161b5a773a6b5fd9471fa08b205cb6f728e3afba44", - "0b55268d6a9542e234ec313d53583c580a391d8da5943f4a900b279ec9d8933f2cfbb260b74ab714a8b9a1af3190d914b6e42212df84f933a237728a5fd5473ce2e272eb82bc83e\nB = -c67f9b9295dd5844307b8fe3cb9c1875257258e4be6229ab097e148c0175ecd0de4d84fe03c8da6e27153c709c2526092b1abc73b5fb40f1d4da9e0f3d8d2fd5f8a4e6f3c30befd80e189b73fbd77e8547b34010d2aa57072db0f00537cf3ced95eb517b23e0c854b4becce128a575a31037c3a9e106a476d8b0277d26dcee435cebedc\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 11913c40d577f70a5346ff1cfdca492ff52b640eaf257510d311872c8df7ba9756973da5b9206c6e5254bcbbb4bcfdad5fc4594e41ee44e77f168e2d20a4b228480a9908b102dafddd039ba7f7619eed7057e8af3a72ee491a61dd049bd947e5b09a94ef94d5f336945f47104fddb8493ef22fb648ff5376b68e96c0555d74ca\nA = -5537630b7cfb8daf76d14e617f7b69f7b75b472801a9a818179d83ef2984d0abc8ea4214ed3d3d2bd785060e9c2819e861d0df760fc1daca8340e8a2c997c9ad201d6d2f12a82ae3883cf9f5c51ff1c25277c28175859a7b8e5b6cdec7cb3875071cbe415bb698b85cb19f617162587516f93c728ba8b2cfc19f238e2cfda115b8ec0431\nB = 597296cb27080f33a24241c1e98fdec32f7a4013a7340d367e4cf2a521cd462a2803109c27fcec353a30dd20053a1f744394fed75829e8396f8de434399bafd6cdb6e0ee81343f0cb99ef3087a7c69bd43bd722745a46cdff0c2c837fd87543c3c63df3896ac101a145b478dc224644996fc72460a89beb5741b91a42f2fbaf0d62c099b32\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 42f420adf5c6b32ce53fe23af4e392517e37013b8c3a7d035a93f6ff45142b0b0bd5525cde85f9b7bd9ce219bd3514617e89ef4d9279cb9a3e89e44f1994d72febd23ffbdb0a4f19cb76448199b31c5cc6d7ec1e46fdb67be1211c0ccd93c123d56ac0d9cd2ad11f0c58c713165003495b75b60665047ef80f6a393474cb727f\nA = -1c6ac9565d1950ae6c55025f76e0a040eed0462218e97aea87208ba879acedf413ffd5e63a92dd8658cf5f49d633ce7b126091a55701168ee4932db004dfe8c35c939887fae3a892b0b04d8eb74191bf8fdcf5566b4d3796a5d2596b1e750f64201057ae60aa705edd58aba4b48f6a2e511bf5007a6c44a27e3efd5bf2708f7046c1fff7864\nB = -244f2a90a57e5d066fe22f4d52f91b44882b8ef76d1dafc3387abcb224eda4a2100239e729bbc745237f8129d457e98eafb2ede2f3afb81e63520493da2a5730f1170b31fcac21259e90c894f8bc488c5e5dab2c2635bc7b1ff56c3685607f6fead73a09f83a7a168c4245729ce5b06e482d7d3d72eff33d14cfe2f32f72175484ffa292a9af6\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2239459025b257fd0b6659f54b8874f93f07f4d6240f8ad761c9da288cf1537d8bd001eced284bddf78edd611c7f28f1393c6fb879aab6e7df8eefd347d63628b1ae086148f488b01272f67ca19db71a2b284eb17e17aaf1e3e8f23ea253595de474d5cf47c16aecfae360eab7855868b8af361491f6ad96f893f9d3eb66d07d\nA = 558613de283911aea1ee21d6b926f531f778c5226e978ce329860682b5375fe5e5328ae27b00f504f2a2d24470d16c1edcb8e76b4d1a740e55538e79ac7da4b45c5299993513ec3bba7e7395dc829a00d4e228618dd348fbf838eaf0bd50f6c70253fb1c1c734a07d0813915be25d3163df13511f3675022cb85af7646c14ba5d13f615ded8e5\nB = 1f3c3c468146c29408d9207e15b25186d3b06b3fbf9556eff7ed7ef7788032d87ae1a4d2a0983902d4c70936c615d8c9ee26c89af8b58d60231ede54e859763237d5ac59af686300a3e92f456484ce77700557ddc0f93bb40e5d2e5117f2356ac7ffca26dcafb3ce7a5573e07ee97515b6b082fe75fcc9dccd76b4fd416e69a247fab2b30965d9be\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 7650985e7c6e5461268867dfa9782cd8154bd6a4bb5857d6555e9d9746ee79b37e44638940bf8d5e974911327f0e53bbcfda0739056bae2248015c35839f35e7e359e93d3a339e7af38c0cb43eac5b41e1406e34cdd4afd458a5d126f70b5d683415b490e0ad61269ffe7ea8972eda6addd447d97e60891e5099ee920e18f233\nA = 184845d3762ad1a9c925c51fabc7b9e15570a84a06ecef994910845d56869264273d75fbb84a31c97c27eb9779e8b39f6829638a78b266326b60546507f65128caaaf36d4e7f85939b75cfb3145e2b1bd8372531cda579f59efa0da9c95a8efc72faf326d35c660b4444627d328bedf50a919029dd164de051a4c0c924103e365cd640b9637d8244\nB = -977390f52af784b52c1d54e82131b072a1c308406e9b82587102e67c6f7145f0020952231a5f0ce9d130677bb5a7a37d5a06dc570a13a29673c8a9068f06242ac438806c37ec46136e7c1c1487ca2d330fc1f3c1f42ea51ba2805b74c44a61fb2fac109710dc3dae78a07057a753898d4e849b910f035bfd807178f0108812778345b256c7b59f8883\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 35d48c3e43070a10dac0e256afb83b219aacc0036f554bd998b9092ce3bf87bb5d3b00947f2c86fd4e7ab830502d15fb2d4e47ead087f5c779a9ba56e272ea86116e2c81345d379dda6b581e9c8f4df8ea56c78f04d4f7412d245e00ac645847af6ae97d5d2ab27e48cc878d8b510c2dc753f6ceb1b9e7bdd923e0e065a6c11e\nA = -76e575cc79d7f0c313a489b255e85d114f3933383cdfe75cfef649f639921eefb9b3b3184351fd0ad252c6e477e153ee586a0ff6da1e1b2bfd7e953e6dd778c849843fa5cc355b31f5529ca45aec81ba67a1e364d5a74a4656d266f7decdd47b2fc2d81d6c298afa2d1c39b5e8eed519a9997a14513537cdcddde0b5b41314476264d59b7d3f0e9a65\nB = 6b7faa437b4e8db8fba56c62eddb8a81e9090d1b6655a2185d656b2db0e85225992297381d653e707aa15f3017880b0f07abf3dc455cb09c4e551b3df3516c6db4ead79b88339fc33dda96bba76ff7c388363c36b67fd5dd0ee63f92f67549dd77e37e9902ae51cb58057579f03286fc48e3b7fba763fc5844c222e6a1eed9e1634d0bd034cff222bf147\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 445039f359b55eec647296fbff4f22beac09cad32cae79c13d591e314fafc2b77839816aa4f641250938865b0a2c30a10e23da71a6dff5985ebf3df4429fe64c327557b12d987ad9e9971f7c7b1e4ad01c94e1e5322dbcbc4707a959a401624619029558fd6f5b14564469b13146f9a2555916491e4d77caa70f51716b299135\nA = -18ddf976fec2090f7d1f4d41b8f875e56c813c04338f595d6e591b3eabf9e105be792f45354ee9beff997e6c0e8ec3fdc714c07b3466ad1a949b9d30da0115f5484c3b9e00c7cf0c117db57c3c6cd7434371c6d9ac7a5da1a0e2d705bacfc22f62785222d59bb5bcd3e3bf2df8e845953c6ddf1b546cb75b1698dc8e20bc611294ff288056723f1e46ec9\nB = -2cbaff39103570df7d85a5673b50fb8818434bbc19ab4e33bcc8289a4047d85de1b7029a5cda3976ab12e1d891b7efe3d5576bcb3713c597771f93532853290068761bea04200fcaf9b05d8553b960ef5e28064de89d9e5097d12b26af0b64beb40b33ff82a55af7c5838b44282917fd4342e2065942c724f3cca515d9142fb8e46652242e8f0ee5ae07b6cb\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6727c0d0ecb4a375d0fd1bc52146da1242099d445ed9e87b1fad4daf8369fbeeec49027d88bd98efb425c1e3f73e412fb327680068ae57d4a53992f3759af0ac1b96a92f56c2cf552e6682d1fa90c3910bbc5c0b1754862ee13c5ebd62d5b98bfe8dbbf9bf53bf9ed0b967f3c9da24d4334b9f3f75314b429b05b8e27142623c\nA = 5cb6c49efc6767cf956885690ef740337aa71b90c1d4b9b0a9e4734de0c0c50f2358fd45aeedaca6e1dd0fb510bf097bf46513ee09f3343bbd1c11f507eb61d51ada40c5d6b730561756480063f60caf05141bec9a769c241d367cb92fa8e229ba2e471fc73f48812a25bfc7553c395ca77b80443ccaa82fbb7198f8c35c3b5a2fff977d8b2a29cf9358ee1\nB = 16ff229a0e67a410555dbd4b687f1470ec854ef67db73a902f2d19953c55071c4a26dc320baa8571586f1fd54fa490b0d87dc83e5bf20b78956084275518b307ce69aa4ca1079e3aa753d97fa1cff62e0b5f3b99d96a24e411fc3a3e375ea21b7b35a578a72df68d28286fd9a324c06930905f696424780083715f77961532bad061f3901ed276a9eb6e81ad4b4\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323", - "cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6e9947beae4d934253e481d27e854a59c4047eeee4fdc7df7e174a8f045776109c148ba3721685195b8fb59263def88891c5953b5a0ae85fcdbf02abc76f4d3c0f5d9496327d063ce8b3ba875b4f119dcd8beefb3ac884c25955af61c35a69d0670c3c349564e5b84f7df4252d6d3b29d9a75f09e9ef79f0fa9f797bf75b8ccb\nA = 188785951a3befcab56128cb6fb9576bee2412e6cdd7dd1bf5643babae83c8011af99aada405e119c3be33653862440005be994bf37d3802cb6c73cc312824c56841004c8e871ffb560e93a1d222c93d63684e90a91394b9c8ba8cac27b414bf818ee0de7217bc2faf099783800485ce2e93612ce39fc7e2f1db708bf9bb032d92b66159073fecdb2e0257058f\nB = -8dddf094f30284c213577ceb7f1b2efb1e4213a548e6aa840f801cd6382fb6d4995908b7827078dc3f46fccdb9e071bb8531ea8971de0ddbb714d678bb71ba9d961e58cdd5f41b8472146ff9b814a5d1d6368bd94812f8d38f235f39aeb2421a57499fe7102c1ab167df7d33b32a6dc7c8eb8f4babdd6b6c929d1ebd9bf4774aa40cefbf136feda7b6e10ba4dbef1\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3f4a8d90017dbe8e77205e65fa7a0875a1ace6f3f215c2974e47dbac779804143da3dbce92db391c2614c078997c7d1a15439ffb51a5787f5bbaf98a4dcef576a6317b9b92dd8141a8fadc05d3be7c150630668e620a4e07b4b00519f34e422610a160de112f1ab8adf09a9169ba95b60242c89196ac6e155021dd84b3054511\nA = -65ff4322f8e46e03aa6c1fd10a207a5e51db6991bdca232c0dbc9d73ba77fc485d881868be7b14c25b05bb59b7f5bb6c4b2a7d53f35d2d7af282a0423285c5de656429ab7d3af7d92837e41ca701f527845e98c2bfcb51647512e6abc6675cec2a7d34ce55ea4dcfe9e7a8397d45a7a3e73bdff06e303a8f04ab6285eeb1bb78b1455931cae203078eaae826a6e5\nB = 4d936b603eba3aeec3d3f1f9acff02a0ecc28a8ec64b6bfd9b153b1bbacf4f1e186d3deda8c1c81e759237921cec53251250e3e838f5063c4a1eb6cc93637f35aca10b965533d18b713617a312e74c446d63eccee93cc97e3723ab27357ae9b3cbfcb3e2bfc589a1bd582480e776198df047c3ad85f611ca6fa480c70aeb98af02f57d56dc9659b2a6bee222dc3e0566\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8a7f3cde3230af1f1fc25e0c0e9ebeb69161d3864fa5a03e5d7f8c82d9940ded285df35c008f61cc151b4578e2677b2f2cff3236935de5bb1d113597eee448496fe29bb18343687f6e9f1c783863e949a0954de2993d47a03607423b458bfd18c844ab57e9e2a43930df159ce8564edb5a2a37a06425626502e3ff9363b73c79\nA = -100f2984dc1451fd7b71e5d290e4b7de2d26175a47b9bed524fae02bd5abf96faba06e955107329559bff3805689633a4a57275732bc42183acdc792cbf7b6b24dbdc8921b73c0308d0c0ce5d8aad75f7eb16352e67116e859b323deccfe5d9ffdd1f0265297bc9eede073146a06acc3c330458b07b8fd0bb652c7325cafdcfa165f69cd0de8b145d49ddd576fdde15\nB = -21ac4953e54347a56800d75f6feb6ad660b0442174cf3c5dcbcf6528e2b5da95a614d3a8399da14507df4b8eacaddcddd627b10ec2dc5fb8c43d96a38e6dff37189ba275afb9484df800587f4953e327af71dbd58780bd5885b4cdab15ea0f2864f961bbfa9bba6b2d9448443af87c0cf178990254c1ae6e19003b1621f3240a6e5d0a3be2deb5dd253f5e1f88dbb60b522\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 76f8b44df8d8547f8b3d8537393d2805c699eb37d19bd115bd5539adb6b6a00d004def3b7793d5c71e0ccd2b7e9fb87103c1a5f56a8f18ede1bfe1607a346297166596aa78dc584c7c32832e11b72fb4f2d40ae1591f341919bc0157080ee8febb7fee5461a918d2178fa407c37a8243e24206ce2c19c3addcc2b7c3c1912b6e\nA = 56f4d397530f5c90203df1ec799f82a0096888fd370d543e33b5a2c8042108bb75a86265204c40fa5a9a44965ad2fb41896b134ea56c79699a230f38c0e3fa4e5d346cda70e0253b9993c9da5642f4e645a0d96cb732f8f04c99a83d1f1360a385c6e1a972b89915489245ce58830788ce23b9e62d6b48a7ff9a486614d6979033f7914a0735d201c6f29e512374088db\nB = 10fe818f6af7a95cfefb0ea0726f9a3e0e7c30dc9785b1fdf6e2b810515448386c7efc656479794d389e109ef3efe37fa6124c5a7db3164268da0d98538606c57bd2f7df9482860e81f272a27c727d7d81a66fc1a9bc8c385cf02b7ca6bc7ec2d8d6ba1dc992caa216d02c9bf0fba8ee754af77567c6e275ac1b6b1b36b065760761300d156e40da8445712b8fb206c0df346a\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = f580f9d2438b22700c3ebb23d1dc296f3d33deae2d32dea51c7ed3a0ce7b06af11046bc1cc279bb744bc31e7f822c17ffcc5dcbbdabe213bf97bb85c7e19ee71a513bf59b25b3b5787e42e9f3ef6aa1acb8705d69924a107b4f88e0cf9276c2c7c47fa4bf56c4900b557aa5587418f0ddd899630ad3ff678b5b907c07247b2b\nA = 1017a4fdce8bf41ce804b7c9c836d85ff6ee899807e1736bf0357b015b701b9675297e5ebf588ac6c295feed3c6a367987e192be0d89523ac7d64b0b9576f311b5b2705c5398276a52f06085027480c2ca72884ad7be34967bcc6c8cb4ec4fb761e88c16866a2e284b40180eb14536810eeeb180ab701ec47ece62af65a0753f95ca657e7d04ebf3c3a7db02993da9089840\nB = -aeb03379fcd4e87cfd18957a72fce42e016951a72b673a9e81f666b3cb20d2bba81400ecc2b38601bc3270eac46a633a1a6b55c50f00e9d7fc8a20176b93e971cfaa4f41573b17b8ccc498f8a3230825afd0d7f102daee347a9d59cc0914ac8689c1d8b39ccef1f3def44054307a7cb7706535f0cf4007231ba21696424c3d5b42c8e85c278f7c2e8b7d1787effa601ad357eeff\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = be05efeee19cc91e30a9277a6551aaea63aa3861b63f6061efbb0b92296e09f4709529eb849d9f40406fc59c526a4697144cef9661b556040458940ffd6a87ed56cb073d2ee0e6d1f05936fddd1b9a8974a3088577847ddde6bbdfb3d69158d5b3899c13ec78fb5cb6aa7204efe308bbe0b52f18381fe838536707a8a27ba0d\nA = -669660e75eae9930dcbdb99c477c980869417ec9c0e8c4053f0bd8ae62d496daf7539f37af96fd1cfcf3149bc02b8182a46b413e3397b49d4b4d204491440eea65505cf5d33a8e797af08f3da41f5a0804214846bd95d730260c6545d51126278181719ddd396c55f119e84da71f0683eb6db8393b098b3a0c5999862644e073b4918b5c8aff17efe860744d85bc94b582d45c\nB = 6045f903a750b69b709cfd6a1c8ec9fc0d7da9c53a9d26fdb0ce9a17c6a0ed5ba633d6fc01f004f4a48cf247d61f7df609008ca5bdc8eafe06dcfa06bb67efa6a584b5a2f02768718a908978edd475a2d2926af2a6e523549a5cbecedc78323c5c295bc0b8d3e14053078492e82e339ea2c6301412a5dd7efc20da0aad0577a37d853eed820776e672bc6d23dc821b5855eabcceb18\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 705bf20b7d92e68a69019cfd721b27373c7ff22f911066907f556321371fba70dbcb9774d3a26ca43e44ab20c586a3c1546fc3152ce011be66e04a59c6631bc8bde18efb7bf1743b9ed75a7a6c5bf5a4117368b81b112a3cd4e1c44a621f534a11c426451ea5fde880939ee5bb28d9843730e284520a976cd9f60c94751050ec\nA = -17c1dbc1ad1d2d33dfe1af7b4cdc7b69fefec5a92656957e111aac292e44719c7c752ace33dc74a6568be38b576a5ba174bcba77a034af5fe101699c99ca39f8a3b0a20679e6d0180868a232fd8fc775089e185e5eb81585403f32619a2f4d857bb091a824a89de2e84529e5b0702b45771a5816c5a823d81ddc89f8a70cc3d3a0c6bd6d85e9d72b69d2713b61c46161f7f4700bf\nB = -2252b54c602456c5deb86a0f249f3982c3836b70a946f636b22fe00c6e3b91b94e19200a33087fe734ce9a3f92a6099ad03a95ca523b7edb9e1ed3464d38fb96c470464e1c54790cd48769677efc5e1d22f5be4c15288bc5ea1dc184a05fddd5e576b3b4962f37437b4f9709dcec374377db44c8ba1d8611c0c3ec35f9bba213eac59a047e78195ebbbeff941c7f862e8c80eafb72b1e8\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 7306e3172929c00c29ca1db360eb4ce82066f237e9cf6aae368d1f531620e9b61eb64f5b3e2b735a3b565587d7e955d052df94a20e4aaabe493dba2c18e85fcfb65df166cc48733632d165129b112598bf5e4c58dff662e558e5f71b25f36708d3ab6536b1cbdb5aa2ee56d9e019a9c3629185b188af909831629ffceab6", - "34fc\nA = 6b31ef80767a7693e7d0a9ecce54beaf5848120f036923d80b7a0245aa6a46135e32314f3b227268e0bfa1f45b4dce83bea890526c7ac3efdc8e485189ce2c51597c2864c2d3664584be23559c03670622a53edc2c17b3f1a92640078ec35189dd7953e55e4da0290ff1e2996d164d69f1bbe6f5285ae89209d611a7d760e413e23285066eab8e126c320bb6130a91d67ef26d4dabd\nB = 183f06828033287497322b05ac08f62dcc5fa67b7a10c6c5a319c9a1e642754230c6d9809dcfd2de4bb9e360d6e6e1180f6ec6e0d4c6185e34ed299b6171e653521d0f7b8975ed5e7d2c51d27f9784a4b6f9b5e97379fcdb42e4df981462cd5bb9d0501f93f217d954f6baf70343ec710065eacbd2b778430ddc36a7ef0515f29d5fe78d8708d8ffb6c3391c6f632cb1bacb4ec52972ce0a5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 361ce44d153f4d251952c0b90681a19b7d2d8df7a6c5d459691a80c06107b2e818f93f30f8dad352d2dd87b01530d51fd1c67cede9b1a6167697098e41bdc5dc5e7a3c310116aed0c7b5fd99dfcdb3517c13daaba6ad10879f600eab846cdc110d392d9bdc0e8ab34b317840a725a7a12ceb48c75e8dfeffe2947aa85b2a5158\nA = 1e1f2e44bc7c79a00afc3b2570d5cd27ad5ec9f45aa94f63f2ec3fa6b69077480212a1cbde25ded7ab1c6cb1ec26d5905948e5c1d6d109bd5047b1e038666054606b42e880b609f6f00a219dcfb504d481d6fe709f4362940f6c4b6f2e05d243722cb32bee5508ec94eeebb53b5befa551d3ab5dff9cba3daebdbc97179e56cb778aefdda6a0c24265728ff9e59ca3c2d615398d97e66d\nB = -e018708df037aa2918850fabcad82731487fb812213b1c067d0688462a4d518e5ec7c4c84f2cb2017aa6bc960e2faabbe361ad8f66355366cae869d366f06d7cc32ea08dc51631e7f36a4c775611095d8aed06a0086d0a471749246d7157947a1eb5d5503f207723a7062382b3e45bb84c6f555e48f6d63aaa1c04fe13c0108507c0ced669a5296bcc16debf18e03c32eefd177bbc1dd2f19cd\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3aeb3ff6e797d271fd2271499a740a91569f300d7392a7b5898084012a3c5ad379a57d5169e43089cd58fc7210314758d5368dabca2f0ec5cf6786801bc99b45cd60403c732d9f98936aed76da724bd3e7d4b622dc690778f11fb0310fd4cd980b220627f7a864e107f93a6259081c6581e5dddba4890508af8057c1af29a745\nA = -75e06b47f60edd23148c3736c9c125a617beea7c8fd47e662c9d9be883ae925b7801a0030df3f4bdd3c9fc386f18c4e002e5daf4a6f7fa27b2f71252c83d5f1695e50d62a10b99e1900987b342290decf681a064f789e11bc3fd75d64e2e78ace56e7491fbe0eddd6f9958a5f95775c920ad6c051ebe7750fa76891ab00f42c910550a42bbc1c1e5aea0ae13b7e6f916a5d228bd57e854f7\nB = 434c8e4767d0d7df2125def75a978bb1509a26bf8305cd03df748c6c12b6dc580a2c1ca9a4526eaf3936fbc4ec797d0733217a54ffc9e1d7c6ca04fb39679859d5bd3fa64cd0a09cf1a056094b9c20ddf1f00e134533ba9892c2ca7346ac8d0655250eb45df9f0b7983bbf71102c6f1a2d9497e7a45eea7b3095cac037b7aa755beeea8a6191da268780179a652d94a732a2a5c7b626c0de3145f4\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 734a429c91f5b0f06fd47725ded06222c0193dd407e9daf136696f203e153c9bf6df59016849284cef93fbd35edef2cd31c9b956fbe562d2a22100f177254144718ac7d22c99783fd523b642984794bd7beb0d0b363e28d3f3469ee332ee364faaafef25c1d4a11b5e517e44a412ba717a113ea9e1e8f2d6db8fad6f10d06950\nA = -18dcd213e9938fe4b6a64abee3b9867f65e47e5b0365d45a8dee14ddf787f34072ce32f38d4d48ccad236005a23c5fcdc02b72cf27001495663fc56f428072d3f1bf5e33ab2c5f9dd9facf122f7225ea03c2f67321530a642803f65a2e9428f32d0d974e68a25f705e4f8140568f7e4b132942b49f9ff53f04f241feaa29aa353925fcade33a0cc192fee2628c2111da1e652cace9d304d0f1d\nB = -2e5397658a5e6db9d30f09e93e67a30dc84b1e17c25786e041fca48ab710e1d0497ce615264f1abcb23d5aae8412b58430bd801775acdce06cd362438898697940712062b611c92ae6ad10da31784207c5e7b9362b20d7254da0df8caafe0736002dd466d76b1a03e91a8dbe8a71107abd5f07b00fcdca2017391c7c3263881a3d02a89b0e16a2a765a32d24ae6584cf44a88975c539402db9a301dca\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 427609751f28edb62c717bd98ddf999cfcf65128b652be1b5aac0dfe1bc0f7687c580ec70c8290455a9448c69dcb550c0cfdd109af561ece2ec8707c1d02e8097e780f32ddd932e706f81f68711acda0e7610f4dd0fd55f6ac7ca3a3184f655b0b29d2d62974739b43ded96b413b9e3f0033ca1edace24b6bb610bf06b5d940a\nA = 6576c31d48daaf7d6bc3658952c4ba18095f1a0d73726f6fe59381af45a2a6b592adc79fbc3b597e1eea711ab295cd991441fb5fc4ce5f047e571a7d949c709e0d31156184be4b8a6a49691ef93d7d3b120193f6ee82246aeb896b8b7b4c74c27c02cb39fe0335883a3f088a71ab42b947a0cd59dd2155c65a0274ec0836bb8c2fe394500724ef84d869bee40291363389e7012d672b1eab6696b\nB = 1ba2888f30be283b588cddf00eb3ae3c641e35fc0bb3a9fc85d7fac1e81052129f499afd3e8458d4cf893d51fe4a2bcddf70f28c8edef16c7bbfb791daedf1a8248faebe36953560498af652d1f1c7aa0e9a5a667d9c94f7d9525cbd5a82147d58b738dfbba5aa162858c2c66d0dd7d8db38d41a2261e6efc7d0c8b2dd2d6962be0fc796705cec8e87a13092e4a3febdda3d4dbed9d11a1d5f92d7dafcd6\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 533d6d8d7384e6e65569ba0daae0a8cffbec1d20e417a6edb42d401a59de0a91a7e6854db081ce33b76faa63f6d866993c245e69ddbe6c86d339f7107a4807856cbca23cee2bf5496388ae8fd8d7c78767d0775acd7bd6202dd75451b424034e2766185969b5663b638d539f718e50a9f752f406c224c000bf1ae1fdd60a2a82\nA = 111940235b144a42a13201a41a3f9e4ff02948f8e9127d9a3007906988a50b36d7622d1221155f2516812074a7888b1d8334a01c02ee33b3164d761d02b36729c299ce2455a462bf18471fca42e5b01615d53723c3fefa5aaf4a039a6caad35c348a0a4dd3f0204f084f35c0b93ab233c4066dc50c5fd3897a769a7c5bf309f7a9c30e905466c8394d509b79d62a69b58c73d8d3f1665ecd9a8a4dd5\nB = -e2633e43c38c0b4b8713c20bf4e2b8ccba680ecfc1139954fc42724277beadea438596942fea1094091671c2060dfccd0351b2fba8cbed35dc963cc18f8e8835052da884799d88ec1887712000a0726b17cbc4302421011d5be8d234440eecc363f09e2c04bc9cded3cbbac9a5bdf0b6d418822fdd90dead20e5bbbb3566ca94ab85f3a00d32842eee6521edd18b9aa6872340b2f47deb961f58bf231e01f9\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 33960d7ceac73f342d46275e04fed56563decf2fa4c0e9307c90288e911ac8782f8e1354fb051a9da8e2db83d7c710b5d2b611495e72ed42259ce783a7e7a8f601c07061ec749481d39a082f29dda1f9c7f444a33ae1c1055d37a677b848af371cd3bd41c851d31a07e144d7add66df39576b8200a8b918201630b3da8e664c3\nA = -402034484e499a8efd610200790d443c5d3be35d19d8808da85954d42dca3f24177de48f55fa2efd7e4f7f624d806a8d461c3bbe0b626fa1f3cad2145746464108b367b13f3537ff395262256bfccce5f0414e1f98b59ed29940171d46ebc4bfa1a27802cc30d9221cfbceeb92abdfa6e84ab4a54965568aa10ea631e82067ae358a1a93a3a3fe3a5ed5636a0c4cb373b4d49f46f8fbbaa665a19200b7\nB = 78ec7dbfa2b28e268619ba6db34a23adab25e7f8690aa9464a7d8fb7c6b87d5dd9d33d4c023bb665f2d96febf2638fc087ed30796fe7517fd58e4120c0d319688e67a32bbeaf62a987a9764be75384bd499b0e00a850f27e303f615031299c631844d10abc571f9f2a0f742cc0e8df2fe3c244bd825bf1d9134b2f1059e2a1b61985ae8daf9bfbd9eb24ba268ca58553891945ff1a314a78fdebb5444677ac081\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3a1ea3fccd6f336e6d444d68af1753b83145131954c20f1e3c433a89eeb7e267425a34d91f67fd65191dce85769ece2fc7ab12d032f3e30f8509095ecc05148e47a85391b21a18257c338a6a3ca9816987abc8143fe443342b34afd8a52fff00dda2e42b1b39322bd38c6a1f711051f791d6cad2a47ebd423a9b933485fd5861\nA = -1869c53f86755aa350115a9f49d6248cedd42a339506b8ff59cb878b7745956f142fc4387", - "322c41f369773ed375b72665026771d4ed1b9ece08f84e4782d4c3b0177853cf9ac3a55f7e52f39c1b82aa42b30628a4fa6a838754ec6ff9809308f675e455bca6f44e298394888d85fee29d8a0c8e9cdb9aa08d68cd70e13a243b5804a3ec199f52ccd462ba6594d856602cf1d5efa509047633923d31f78da3\nB = -2023c544b6cdd8d971bbb345300f7a101f6dd44dede6bfb5f4e6b4eafb7a40728a3063f6d4bdd0f606ddecf062828cf889b2f632d0c9254c28f36dd974aef116b73cabeb2bba98635841c2b4d2aea833e35eb1db9fa9a9d33bf7b51c49a14907dbc6036b027a039192b47406bcc56bccf375fbdf40b82ac4b3c660a43d5a6eb656868d383cebd099d2a73506f675cf29649617fe06097a46de93c13d1e590ef2cc71\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 4331f18a94c169cf0253136bc4eb7480c9fa4401c18db1194371dd53e5f7b75f07ec2e1e1c4116a5d2a8b2cded4b22925b67a88af9b8479c6e821d58cec7ed9f780a4c41e729982cb33f69b87d01c11cb9a8f7952db1920b6eb2124fd5d820555a99327117d7e8e26d18e748fea3ebc17e1d07161fda57a21a70c7f4e251612c\nA = 5e7d4ef7d6ace6cb106e38d96085d3f3505983fd952498af3c1d9b2af61e4ba10e14961b339c6e64e11ac758d5fa18c3222138290866970d67d0a4f4e19f453503eb8dfb85b44d1050c86943e7c5d6faf7851bedf7d0cb6b13d2acee25372243591d37dd230907457fb440f83b62395f80f59a2d02b87134887406a78efd77614f3193e517f234434ab3be084f1484d3f2c1f68c67c0d6e863585a8a5ddd0be\nB = 114b6e6726433ea88a2ba965f0881beb3ff4d377526e4e099741f069abfaf29e129a1f5fd243c6599f725a389728f755f9cad767ca1d6ae5c8b3a32102e47af211e86d67574bddfa42b2cb466d968f38b47333b1b55211fd9a315acd5ef62cfd3e83c13ee9d3fa20a06b2292177961dddc7dc39abad9ea31ead1fedd3d699f651b656edceebb0bace11bebd0cfa581dad577b8b42f0a844bcd8c8227880876dd7b0aad1\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2468cdb1a26eaee34db3d2724e37f023c8a1788526b3dca99321b574685cc8303c609c85401a58fe6da181daf4111fe8c6d4b7428b1cd301cdb9bf8cb6f33140756c8b490d3b2e538ff294fd6471c4d17b9d9e4adeae0df088cb9daee18e825a368be57af4a096056b9e76b94c8d3b911b6a074ed41082926773a585007752ce\nA = 1e6a59efe0b14fa017c32ffd0962700fa9752242b06ffd0b604b9bfd125114d4e0909534ede704cdf1c9e88a6567f4a2989df752510d087d7b7afb515ad594627ece54b8a8e539074386121c9a3e1c12eb2641ded8719e56d42ef50e2f3b5d7d59f8a6f897174cc00a7449d2b91f33e9df07902a95479731a44fc4ebe8048c449bd515ef6cffed70ae78c832cd43491203a247fcfe0a403862266777947fc2542a\nB = -8a9d3646831dcc852fecc8e2335549e8baa2e2d82fcb90846ee82bcc715c716d4a9f62be29d5e1531db73c2186a4d2f118266de33d966b78f989600d772ffc55b1364117d6750cef67f4bae851e7e3f8fbdae7b79de7eab54cc1fee56e25d0632b2929e352c882ce78fd64dd0a1473e80b6572f0d4eb67f6bd6e45c7617314219d6f7de5e505a9b395096cd36650d23e8d57d6abfa9faaf0ddbff90d32865bf5ddddcaf28\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2909d3aef7a21244efc9b5b16626e260907ac11f3d00647f2170ba37197e47b9767030195c2f6d5eda717a83a152141bffed2e26777417ecd8e27aed8666698c2e85a414dddd52b07b52b0da7e08b3217fa6a331f84820d21086a4424974e1e8cfed3501eb054242a9f8bf0803a94981b7b81776eca6d07cd50c050dddf81d68\nA = -73ecc8a6a1507fb5dad40677dc6ec75f0d130ea704d1e87b00d2bd56a6be21714bb30202739170b8dd3605f0553ff57439051efea2a97def70a6d2cc3fa2b9ec27a00c1338bbd588513f0f320272b8933fdf6635e585d1e79203efb5c95a454fcd7f33aa2aeac08902107e9bfb29587ce8610d50cdb7f2033c5b726742fa9f7f20b4780cf9244e6abf6b812171a64b870c3ca4c9e898d4c15e9f5b0194ae736c3783\nB = 4049ae926bb52e862606842bbcb4a5148bd1063b6a56f331cf10000c524b4aaa80b3bd914cd697ebc98d68bd3c2bd5c87fac4ec68606c264c56e25b19d118dc9f2eca19bebca07269714f2955e107b3fbf85530b1fe99c42d33031958280b8e8abea5a918a41cc7e6980149ad68fbf1c0041798d2046d7f88a395348b295858c61c2f33d8512b6fe75aa8fbad62e2f9b0b7876ef95af8a7b7338a2d6b25ec6355c276fc6ce23\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 22407e4fe280ff5a10eaf46d8e1f5a1e77a07410cba4106466d703b11764c60124fa355733b47327e952a12869476306926cabbd797fc80b4a6dedfbec0b7718ee754d447825cc405a98b85f1e09ebb9294c4a4636aebfc61af4545b921cbe759d3f389beece3f29c2c7c07691a4c46a1a72ce418a239fdec80df48732627866\nA = -1e165ca7e1eabd2ad1264d5ed9c3d2b687f2db5b507a0e4d21d9e042cd46e93c2444c6aea8491b5caba2d8146bac656b7754b7b1ae0f6216029c7167fd3b1c3ba2e20469d386d8566ebbc05cb51bf1f1eb2cad9dc4fa454b07cc1bcdb9b8f5a43e354c4e0f4e62d52798f667080a0e0a15414391269fe8c92f06da74f6209a3b215adafa1eb6866f8b3e419468e2e5b4db0d0ada80514249320cecf034477977bcceb91\nB = -3f314681eaa4cb41a3feae8467f7d76b8b05939731fdfc943235aa4d67bdca30e64de541d17a8971e829bc0159384643672bdffbc93b3eaded7844d824604f46aa58b1f1b9d788106aff53438954af015a0387268266a6ba262e2fe7a4c51b5af6ff7f918674b7407ce8282f66e84fd2582edd809b465e4401c67e5faaa9e5748c06e3bb8ddb23fa649ccaf9657dbf79b937eb8959aae8d5bd9513c1e601c0e536cf60c4fc3802d\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 385ba217033463cd9cb882fe30373c2d8e8475dee54aba1ca9713a709f40844905c2544ad792784cc8eafbb412dd68de6f98522dfca1c3de8e3bf4cbd09bee4656c4341153b17c98f9ac09411d16ec9880835cae772bdd8eee51eaba7c02ca6a1034c2c5d2d48e7ae3eb0e22f59bf69537ab6f1e49e58a71c64b8934113eb069\nA = 5137226623f4ce4dc9b80a783777ef4e53ad3c2ec648264db472c517a96383ba1173e52c2659a97ce36341a11e832f4ad293b89696f91a051c35bb1db6182260d4a276d1a9b4be848c206899f87a361d318d38b4073a7470c5743b816cbbc3bc1b20dfd7971b11ad4e20d947e352d42760104a5a3cc590b985ee3b5e98c779e38d2581413a2208d31873f9644ec979602671c9da72fa6f66c603c1bb6d8e690dba8bf4933\nB = 13b45d4105e3f5e8e0ba36c812faeafccea2f1a30e2ce8ffad57ffe0dadeae3a23e813758f270423ecda3da083b42432eead7f04842db8865f9f1e2226a3d298ec1895ae69adc55d1d338c3fb787f0676664564eefe46ca95206e81678cf1a2f173c52d809b1e06641a9b467f191ea09fcdc597271eb43da1a9a856784972ce0eeedd49ad363dee882438f09863ba5af063925871c525c6c0ffdca428054e039e149a424c6d1b5b2b4\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 7865f718cb30026837ca006f5cd997c5b917726ac6d9bd8c3fb9eabda0854d528d6cfc10e4cd3f93f6848582690c6a83955072daefc6959d33192fcf42a111650e50776ba9ae43d3d26e0ef2c6b60c3871aec33eda8c56353903e7ae96592fbf350b88d2f56e03f7f327022a2aa9b7c484a000135b85bbaba6f8836cbfc81901\nA = 16978c06a03276fa2e0bea45740a98d55fccc9d27321fd0a5b8522298a2a90d391c06c5c59e7eca85efeb9b4c91d4a1e9178adf816d597311f004ef98d209b59a2d4b901fa14c57b7297861ee58b89c9b2e931e4ce5818dd4006f3c40168bb4d3dbbd059c1f1cc24ecdc64d37df16b8e8d0529247c06f905ca88a5d283ca1b9e6856fbe8115a326061905b369791772a47900974339722d19b3aac16a0bedd93e1e4e4289bb8\nB = -de6dad276dcc0a9e271ad523620ec570fe6e3b350b934932ebbe36dd571edcde968b6590be14326e0f6394c0a2172052ff8dbc3ff15d94fb6e36a098286333768a84fd0404dfa354173d01f98484fb20897c439c48952b7f1791209fed94e9e72bfb3df5f368d420d587ae8bf036db6700f77b130459e9de2a541ed885c69c5641defa9436a4f7a69d2848d0e5d1074f77fa688b6dcc4d4c7de25a3b1b040546ef7f418112127cff173b\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2d3dfd14e7ec60f842d1db83e29a0f6b052990fe8900887dc44476ed3948870c57e72e91e1941c476baa6aa86f76dd8ab6e6ea41707242c46d39b54215bebdb1f28e59d719fde18bea9994610214ea6", - "8ad9f2da24e1ad8a06f8bc698f8e76379ff332a2745af472d52a4b8e57d60280e19f93d5be669e0832824321e9ad8e76b\nA = -5144d5ca834f7bbb35d3fb95818c1f89ebe08efdffd35993a7691c05aa1b67f6a28e219b27fdcb66e516097c9ef5f00e4257c561b1f94c52c577471cfcd7a55314d3b0fa308b59449a36adc884c48ef5f34753bea746bd6fab2f20b86814c9fe50e8abaab742916313a50e3c390c67fda8e3729ee3329dc5e4b7d3107083aa3a07daf7952ebbcfea15fae7338cd0b114e9ab2f81dc2e80f90abff7a7ac59e3aecf76fab87633ec\nB = 48b927a46dbc4e23d714b256084fdc7cb9d4c96a988a71c956e0bf98785ebc9bf22b9d5c6ba0c419e60afbef7b96cc0c4a13e397aa2d2dd7995875d2ccb127169423455d138131199a263151f28d232ff4ae24e316907ace1fedd02a02cb5ff9c831de33e6702010fee2232bbe3c1c193ce792eadcad0c81e7d7c17e49168377b68690bc61f22dfddb17d82a3b993804726037cfac8aabe8548befc52a3c6c6baaec89a392133cd9c45b1b5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3f66970f600a9d09d73fd1ff813e977f539d69fe1784b8a2f99506d868418e4b47338ee0cbceed555f88824f98ffed39befb69e8907a5822ef7cd2a9950a070aec8fe4db9d68e1c0620f9eab4ab529c7e69466e325fe1c6c011bf7ab62bfd1a136597d7d5c47e8eb161ea048477bedc88fa30e4f7ddab2cfeec3fd0bb3fb61a3\nA = -1343c391be3f2b72c4b79d8d6091389c9602e97774b18eabeaae81fc0539336cd8c899341cf75fa758421c7f32eba9df474c934642003408b32db66cfa92e6e414b42b1d49c7e655ffb4c80f5bbff8d2774ee4f7198839680175e1ffec0428939653c6697eb3681d0f92634cab1cabc63f423d5a71d65fc7150aaeea74f9e0153923a1c65dee4a165e6a01a88655fbecd2db7697f4d2b49fca2508e2b8f84129785d36d88bcf59f4e\nB = -225a0a4afdde6f6450f28736c3ef6e67d67ec6206a63b11763bc6e69b03f1494b275ac504868caa6d56d684a12dc1098ab0d030583e73a2f45a42b8607c0f19031b9c5f07fb71919868911806d210d43aaaced5894e844881e89bab85a203af9ec3adb105e50b4250343ca50c26df14c46d73a22c2e4804d26d44ff0bbcc13d0dc7e326c9e4eb441f493c9743ae0eea0de045e05d19ac32d2379196a165e63ba640ca42e4861caa24c29cbfabc\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 54e95e86e87bc220c8f53f8485402327885be34e34063a1b81e52a23fc3056758cea1c039ac4e513f70ed9d394f5806fb771dca8e342368184e674e6296b9a705c6380bdaf11550cffc73f9f55b9385c85fb648f105f11138a3e1f9dc0a39a0f9755f8328701484d45784e3e4b2ebddb32c9d9132867c6513201116428b791cf\nA = 5f1239e0b5dbfefaba906bfd9003336489ffdf634333cec2484c582dbc19b66782ba40942d047c3749597ec4d89ef61b7803d33a9842f0c903461be37c679ca213aea894d36c1e12bbcaa1c679599d2adda9bd23e712dd0d0bd3f91d146e7a04f3e7ddec8b0db7e12377ab32ba241ed1e01da070c1f3ec85efd8387a7b9421453969ecba8cbdeeeaae6ddb098084bcd250601af780960c32f0a1ad7d7e61fb19f40dff1060c5f332830\nB = 1113f145de014bb6dd6ca05de159b97e9736c45bd3bbd8477f739daf79615fe329ce948cab9787838d7daf797218af5ba7925685ea341b802690bc9588ba3e916145cd3ae9d0c4a149637b890cf50fdfa8f89a62e508eec68f9332787733aacdd57ec1f359ff7fde76138d5b33d32e64cf7d252f2bcff14be3adb1afd8da9dc930f5261e6d715ac75752b29f083bb1de7b0b89ddba633b8137f3fd299a7f77abf79781a10d897e7bf2c958a097227\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6e0160eaac8e1c31cd3cb6c5fb91ba086d033b4b69e41dfffce7569e61770f6629f23e12f0074c47c46653bbba94701ca798e1a242f7c4e25708d3acb5af6ea307b95cfa220f8879cb4cfff96b843d6eeed2b15c8f1bb21bb2b511cefbad0618d49d9ba33cade6da6ab3b846a6a24e35fb36d41201d3b85be831522b9bf509e0\nA = 14f4e24627c773527ed2243c0d1947395aba5c9cf95ae62a48827ffc1477614ad9c7aaea4b4fdd97e3272d3e220601565aebf87928c301656e9edb08d6e680de845615bb3a81c61ed043adb9d708ec1447f057087211673fa6ad8977166a2b4a8079a4f29d48e7fdd6875ccad05d2c219922b814589996cd9642ea2b798197407acd274da30d3ca008fefb40a25b38cb6042a581393283d6448cc69df9a5dc2b0777052566a8608a1010d7\nB = -b4188ebc5bf3ba31cf7c5e100e79806e92ff6f863c3d68a66aeb3ae8385f596dabe6f627f3812d0f2baea319d93ae00de41ab65e42eae7d396cc8fd0a2dfd35f303117fde4db5e8438df0c2b3b680dca538b42a7c844a9bf0d3697fc89ad0a73594627578dabdc214e0f4aa06b40987aed473e7f42d318bebf7392d9c898b4b8d73a94726aef65807b2ff746d4a9aa76303ed7b4fefbab34f5c87c2df82d20457f68289f7b96dbeab581294974e322c\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8dd91f390c1f85f153f332de17e5de82979755d835398cdf3dbda1ee73c68f8e7565a964ae33fd5b1f1060572bb3af67eec79c4c3e2eb4de118d471f74351b80a5dcafc682bc3cfde642e611ac1d5bc2c49b308c30985b1161c4d78cf7621b503e2dfaceed886befc004f3a729b4a9bcbb8f13791d973bf38fb8101d6b7a4d4d\nA = -70e99398673324ee83495aa0aadfffd7bb9c94ee5251fff365124fabc50175d794fa84509f034c2b86d83607789338b0eebdbbf709a129a0ed0afd21c130d94b279c56f1c7c1eacfc6cd13f724a9352b2b37412242a47b23ec61ef0040a8855371aaf238003c45ab9d18a66cc7dab9653b93c323815e5404762d3f964d4654a6995af507bb2db2149eea59acd72af4d034217eaec0be5ba1d23890081a6a234e125572e3bcf68a6ea52d9437\nB = 661d8832671a4974b493e5d71e547cd46b36730f4017e50c5d1a7520fbb75f0314cbc2ac948744dd494d566ba580a2108106b120a797cfeb1fbfdefdab6bd6b2e073f90c77e814cafd0b7f79afeecd59778b1dfee3446fb32139b2311011576674f96f151f896b477c631237995e11e61e715dd8dd38e802af93124c66eee735c472972000cb4788b26752a630ba63b45e8ebbd979f0a4da5b359abd2905f0b7f3a21b1d381cd02ac08e284218ce41c907\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2b591d2c57f6a5484b43cd7ca247c48a1b38319e843257331c8807d499c7763de4eefed529e70d4c144e5e843ac00ee8d106d0d82163cfb7afe528a7daad8e7ed105942d1128a67e38d59325cffc0c3dab9185247e0082e3ccca82a900d917c9bd0f892d4b518a752f8e9d38eab2acaf3b3b59f15b0fe4cb9a3dabe6e0191493\nA = -1896f67485a740720e23e1642ef02742ce5f10a92e51af19e112cc99c0fbddb60d7190086c942d293d076b474d056e74ec9f0c42055d745a57ba370c51ab2b761d889b766cec909811e2b2fd11d6916b753ae00622f038a4bc55b813a5d06e6ac136e81689407de721ee852cd21ea989ea7c8cbd00b64614caf0974a62097b2eb865f46fdb0c1a2e4f2d839066b797e51392e5ebd14dd92630c070acb546dc7438631fef01594878643a4cf77f6\nB = -3a8e2f3b8378a2605f5affa21c4fadcc655f2f8357a3427d2cec0118e55fc2bbc25931259e294d91bde8dcbacd39e6cbc125683da7d0dcbbc67d7c5866f08e7c4732cd4384d9366868370ea40a75beb23b81306303da4a3e26ad357c5c743d0a4ae775a472afddf8f21cb4a1a3350bb6aa71037607c334a0c79468668d3e727cf1d0610e49f27780901c68aecf1d145953e45f5b090855be714cb39aba2efb0f7db2786b331dd9bb8843de8c73c95ab13b6b1\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2f53bdd643b5b22445e2af3667a93de52f8bc7bc151e196c0ab0bf3b4e4dc0e5dae9e507508711a9e3de52e2aeece6aff7fc8a1db65588de3272839390a35a847e29204d3b9b70e10352c88a10c86cd33e067fb530d20a3a5ffe67938c5a7a9218f1164f36a73324adef64da64d5fa5540d29a76a87ce010fb7d73a59b109280\nA = 75e31ab221c08b3bd73bed03f878bf7742f9b36a89bbfa7e90f9b05ec11edeb0140dcff6e9ad1d62cd7af34bb4284b3a52bf1b48a40f744b561d9ece056a9405ab15f508700b14914e4f427ea1df3093497410a0108066e9b259c1a26ea72082b3cf0e3a99ad054804da7bfa0200d93d65354b75e605b47a4e1e17ef851a37c59a95e1b5172801e6ecabf70f1e6e382740998fcfd8a297aaaba7d04b668e3d6eed40358247767323a8393ec359628\nB = 107aca18938a9cb244ad646a37a212859b3dda7518a5827aa2146b47bfb3bd08d772eb7a866e1f674aab7a1c74cfdc2bc6e9ad1a365686213655b2c7b1977855bcd42ccecb804bc01d92bd7d2667069d853f18a0f0661f028955e39f71ee82b9ce6a81dfb2951b33b123e71264e819bba4d0a8c53a1d99964ad9ffb58b7cb5cfcd3e30b1baf5aa5b3cbd20a0df7ec37563e2b32b4cba91bbf3bb6fd1cbfb2fe0f84d720efdf36e9645c7e9ec70442ea5174528", - "bb\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 32d16f7ae2632b5cec2e90c34d191599acd9a1b5f97845595988c1d0d4ceb9acfafbc4aeee9924ce55e109ec88c57610fddc664316e0f9a5e3ed56ea447111c0383ecdf117ab42351b80e72720a4b1d98d4c73f5235507c5b4f7849d5e9b527d054858c0436ac3d2de2704c4bc25de4cc702f5880d5ae34094766938bee555c8\nA = 133a439cf006c753c132a8559ea13c64f598c5f8bd5043b89d04d7ecbf0ec58b225551c8df8dcb341198fb0b487774867e5b68f9058f58b3cc98168fbed0d0ffa86bf74b4fb0d4235976fa86d52b8dc7e82df176d70892954223cc484ae58b6a60459a9a0803ab856ff9699789172b163615e322e193bd758016f634c83cf50403e416ae241d9b1e44add17c2a663771ac88cf8b9dd94622d80d879ae41f0f4e7a1a32a1ab164f981900fc159aa85d82\nB = -fef33e21c07dc26a47d692c3094205bf4efae6af32f1c0f46ee579c1a22746a3663d66f2919f46f973fe558c61264157d531e66bb9ea10b4b49d9f6ad3ad8762a6ea8169a9cfe01d3dd65518c2e6e58e8c88d1b2f42d207399d7326752560cd45d0ff571309301683770793fe3765c1337d14021d39ea6980934c5fefadb93047ef07c807d0ea5625ae0cefd098988d6eb7af993c062ba313e23176e7abdebcc6e566304a5f9e03da05bc1cc58dfbbc898a67a5941\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 20877c7f53fca97f8e484ba31f23dcf51ac0f4fe4c5121eec576e043c6ec5492725f1b9f9ecfa64195f71909500a69fab2e591377cc2120bd5f60d3fb3812f9e80b2f6c787e0081c1439dbea76b819ab44bf6bffe87dffd771a870e4f5502609249c5260f91175fb217a9eece4166540be877d564049389306e0d6b313706297\nA = -534042b0811c9afca04d20d83898e7653f91a73de1e4b516f3228c6d6d9b963c7f8f4c36e05383da90f4edd072a7eda382c47b84b46b4dfa16f269c2d9ad0fc53ed2ce51cd31e4e32d0c1ee21604d3c7eed2deb35cf8df6fe1c0740a1515e4c702a2074ad6c0fcd403603b4a4e2195d19b265958ae854ccb0b41cf22480389a053f71544cf594f6833f3e4d91fd3d9091df0978d04d3922ed72a4fa3579c5fff50eee812dfb2a334148227a0f5739f8ac6\nB = 6935a3444434b0b03d27545721e253e4281884da027246e46ddefb01fa7cf7a9a030581dfe618431a68ef6d79b03b34f3ed598e7c8ac030e2b4cc887dd31664604fb8afe4e71fbc3135d6d3b4e596044d6b615de7184ebf8dae8fd58506286ae4d3b797aea911eb59ada39dac756d0e9eb6a6c767ab77b9348929a00f8e311f639d19ed88c86eb91f0d4cfddd34e98130eb520fcd2b77507c24b6804d3d65d1b21e6f6d55d1f6e92bba0544829687a096be79eaad7d88\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 24823628d4fe9540103ce5f611f8a6ccf18788120280179a40c2636f30a13e5076503e8a4b6b6ffca21da5b0f9f0d85feb2ce10b51292ed069f35289ebf5130972d720d20dfb8e6ee80c3ac598570d38e57ba33dbd75f1b03eab7847d865c3e8e471ccaf302461a6136dd13b8d31c9f163799a3c24c7284b8826608a9543816d\nA = -1d476cc98529efe5b926aba3160b261723b009e9b880bdea04e9b5b03f173040ffafd1627b38be8e00840e85d7acd3abbae2f7a60b305256b920c2b25a8a4373ebbf1a0c69f6e74792cb0d849872500519b6d1c190da30c572e26b44590b7ffdb464a900fc38db013feecf909b43bea549e05f1b7e70d6ad879c613293cf61f0cecdba1a6565eff1bfcdf740bf553ffd5bb7d74f7e9537897184c527b990dea20387bab0dec3e32727786bb14975b23ff09f8\nB = -2b6e12c87ad91a2fa878b9245875209cbfef400e637b557c868ccbd6e94dae65f1ef8caab61f292d739b139e384137a747210c09ee6f3b2ceb6dd212e14525852b8c54215191e116b7097f6729f6426a8bebdff86cdc16effa08d932ab512d7265cc0f57303aa5e6fd2afe0a45180557935c230558d02c3030b38ca88de5fc75c1240d25a22fe32c4e5096aad0078d50989812d7dd0cbb02c736fa563efd32d14109c44297cdb3d4fa3b93a2e15bbb6eb678e93e943979c2\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2c4bc23d0b4b1f79141be9149ee20cc9f1b58ee0a76d5f4205e0862492c18daa20171285d6ff0b600c358be487e78cb5450d151efcff8d53004eece94c5a37f49a15fb2b5f62a79568382cf0a4232407b139e1ec5a9595bee8435b4f138dd72fdc2946b03817e49864812b7b61f179bdd8389791178a95bb6311df0a5c60db2\nA = 5b0a181f07068af6e1e4b715d92c1b8391949a1e3cf0fe0aa49f3333c826f5582615d39ec28b1367804c1ef54f15fb83b3c578ef3ae957fc89ef22a343175df3ef2fd425f724ec1c3363aa000ef624d64c6d678a4cbd90b41cf7d69a7e03dd60c5d3470dbb75228b34d35469847772ff3d74b1a89a2c492c082d3ddb45ba4df6e3f228de6c64913b79679cbbbc36a2924e722c2c640d0c5a0e90ae86b5364dfbfae80df3d75823aa58ac6c1da78e988a11831bf\nB = 19567bbcf615b777b35fa7030db7da18126cd695ca7dda67f5146c97beeb20df24ba0fda4a4f03523a0d9b9f85d9acbdb5793ecf9c1f4ceac81299a1aa34417779175a4bddc0e95ac68309da51e4f115dad6fec33a75d0c5520692a38df64e8d684c9304f9e2e6ac6a66d2e16a03c19a30efcac712aed2b9ee774ea28af4f37c45609464289de3f9be379c733d711875216bc223f2f468a0c9b4a8277bfe49c590ebce2e027102537bddbf2856c3b6e9389c4d1f5390cb0f346\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 36e1e0b44e5afc35d1e19e88e75f030569eb99d326721ced9bd7416ea7367a98305354eeafd204f1f8a652a8442eb0823d2e6644e6320933ac481a3709777381dce8a7c165b23aebf31b2ea2745ce5b352acdf0707234c824da9e1af98bbedf80e940fba00c229539f310838bd625f1fc103f267265ac1243855622c5df72c17\nA = 1dba8bd9d1e6cdc117a5a01b5046353084946fdddf2696f831a942d9db4637a5ee76b84d4ba63156b8cbc72e40559a2fe9b8e2682d8ba1db0cea042bb86f8ed71f6609df52526c42e7494f6114bb62263d36784dd55d396018b8fa47fa49ca6e5c76ebb0b00e6c764e36cb3ec75e3af6a2c14dee01fab78070239638521743d04f184dae79d49a2bf209ddeb4cc72e0c94a93a47c107f5369070ad95ffce034c554fe2a8391e67f817c6cab5b88ae9748072da5c9c\nB = -849602ea3b79b33af2bd3ef9d1250c507d332e759d428902dbee054fdbcdcdc0a357a51d00aaafdacd696a15a64cbbdb7e1fdb347be5ddb1f609a4390a6f29f79ccdb51bd1f0547d0d9a2780517f8753a906428fd236f8ee1b433e57f2810d0ad51846304a5729f53a871d8b0e14355d24d3f092e50de4f044e2b8aa14cd8a51fbb2ff36b0b37defa7be768c56fbd4f5169d9d4698fb9072cbb0a037c219552728587d7c35f27456c02020f5f9374b6c53bcf8eeaa14be51899d3\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 77eb3cb5277ced02b72368e41f04a35796c2c6cc1273f109336fdfa745aba7c755b6ff3833e9b124d9c78584f6bfda1c94273522f020371107870c288592b7c23964320729d2308bac8813586e72078119852e1d7706d8e15c195486b8d94358736869b15d59c037ba4dc8032ceaa31eac3a9e3dc51ee17706a6956cff8537b8\nA = -6a0753edddef8b74f762bf802d7fe9b38638923ee2d81bfdda354d40df4422e6ac43724de1715c4088da2e68b63c10c90b236d7dcab39b9a0ecbce57628f4c2950c79cc88a89daa20d7a8679232c8ce5fa30525c56011570107697222e0eaee6871adced52ba01a3aea0ccc9901cb3a09eb4db2f93aba0083180bb41f3f9eaae00fb458381213dad01997e9b88f21b0a79ada1ec3837ac2b63611455fab6839363b796b105c3be6106ff284544bda2a32352bbce6ef8\nB = 542c5fde65111ec8a38d76d8c5735cee17329dc41cfd0f13bf47e6d0e0093a129f3449db380ee9a70ec1e44640839ff18b950c8fd89346cb4701ef753e6ef49dfd9bd27d9987e572bf8e68df399cf945813582fa1d33e07be938a7729efd9a5e7d730bf61c537770a0727f6bb9ea6add5aac9267bf910eac1b7d92ab4184734ef8b1d184c292b2b4295ec1bfd17b8a2a2e4d315a8b37b8ff9bf6a1e94a4772267195c5a7ea6f0a0c267337fb97a023f1b50ad697ea31451192cebcbb\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 660a1f378a23fc3b47f693a347d90640fef43add9729d74546933f4b78a26968cc9a70ad6fe8d85bf28164881bf7a99e8b96683c6f4fb54162c144f99a27e3feb736f0d382d7e5b934cfa835c723191e5692b7672cf6918c4a7a93b24af00b1beaf1b80320b14cf2d1539e3376779872542406a5df961f765e59f3480e1cd40b\nA = -1cd74c052e62ee8156ba5d97f28aada75211979b1c5925ed015ea75f693a", - "04c4dd0a705f6a723ae7b79958884c96fc07f81fca064ce2affc70768923bfbca6049952eea3ae048425b7c6ad1611ed4b8b77f7605629b9d198a77a27f25eff2f82867845cc868edee4ae31afc5d022b2ffbf43c14fa01bef8d7cd9d0e58362a0ff9abbf250e43ea5065512cd707791ea4868e95d8fd2357b3b3aec1a06888ae940751ceab01cf9e49015d42371fac30d48ef5853b6894ca83\nB = -2ac904d3632e25a4d536097d80a157791a6aca6eb10246ea21f4cae07aafe907c6e4c726694e14ce12e376c02d326f4bfc02ed539a5b4615a3cf5c838ffa52124f9b843598a3821cf9f1fe94e7206d6a525fad1ef77e7e77162e8c6d3d860d4f568e8f81153dc47f167860cd52c1ca59b15f1eaac6b9023c8b375bb63b6adf6972af8ca62b39f044378b11c4a969f3939d9fed5cbe18c06749956c7acbf963f640a1e1ceab73fc4c77463ee8d1575d018f49bf0f08161ce4f88aaab5a70\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = cbbeda9c467ca801ec66fce801c6765a20148787dc6becb199a15c58fae8d20c1d391a1d9d57e1c74bb412e1b8f271dc2cc53c3355c83f3e2f00f15eaf0df735160a48e2273fd1bd75533cf94c5175ce67e79fa6c1422996fae36ba288a658a7a5422a59d39dd81ddea50979e933efc02\nA = 7ea551efeccda23622a1a5029e5525f46d5ccb83c28ec9adb7a3e97c2b7d936238c483a4a9bc92fe0e21208d5703611e2795b91fd5019272d255eeb\nB = 19bd92c534f56dc4235dfb7efff6d941112d66acf81b079382c86fb10dc5473bb8adebfa53ea3fe6e4df8412e7807aed029694ca786\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = b18a9cd6a0a89578ea773fbfbf642e05935a995a38bbd54480ea3ecea1751370ef95ff5ad0e3203613f0ef6833237d549676a95b720848c5e9897cda82642a2f373951d5746b559bae2d98ac00fae26e5957c61ac1de95318b1b1aa6d5c64a6ceb6575f1b807060f9e2a241e378e6ebd72ade7d2df18d5353db7737caf52f888\nA = 13c68e450e9e091ae45863f6c1faed25906dcd90a43620b1a40e7a506e7a954256bab0225f3678e7ce6c4ba6e3a83c8f04a3491d9bf097adbd98fa6e78\nB = -ddef76382342178fa6636e62887fce6e19590065c766b047073329ea15fbba96f2cf088fa5a989f6ee3f6a513fbf66f621c6ea6ef2fe8\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = b18a9cd6a0a89578ea772021f58ce74cbdd8c44a09b3937b198adbd8e95e8e35541eca26438351bfdcd8600b4f9b71616e1f16cee707c712d40da9a440681f8c8647bc90ba4c68b08ce4cbca458bebd5110222f06b2ca980a2e9419e71064324e8c36289eff9c67f6d5d011e6db8538a54aeff8c20800b0949fa42c38fbabfa1\nA = -6d7e88715e9854b435876fc9bb2d25218a1451efb73ad9cc5f52b2bee929530e6618a858000b3f24fa5f47b5f461c84eca971e38cda6e1f475f6612ec32f\nB = 49eb76e4614ac7b0ed3f534811a4ea6da5ea24be925ffeaa38bb228fa117ed56ae976b590d6c9d9a7a8546d8a6ebe4bba771d6587ac44f09\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 44f8596fc06afdb72a6e4f876b70b8d5d734589f41089c510b0da60ade642fd79cf8e705f09910912624fa1f646da596c137f124ec1a327beccba62a44f228f3c0977fda2af631e249b2a4de17d170df07bd812c233a96d17e1e93910267682d24c5c485f99aeeddceb658a7db258a2fdf73eb0266d26b92e\nA = -122231b14c249820f0dae625342415f0c6e7f93787b4206b79e9ecaeb09623636730810c7936e17a1eece68edc7c97218efb17c069bc59bdb9681a79c910c4a\nB = -3cdaed858523fd55553ef85d018c1097d7b88f6c30060d1e77b84821ca20b5625723c7d4331ccad1a70371eacc7f7aa11220f83f1bf3595650b\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 6de7efcfbc1e8d2cb14cbe4465c4ef71f0d1d7e80a1d80d9ac2d0b161d45fc9d915c54e33131591e8daeaa11ce02404c9b8494added1bd83e344ad4de7c04f626315caa56fcc5ca2ddd4e1ff064a2957afeb5d280477bf1f1195c7294d89049024fe821dceb53c7d270a8b4653e2fc0a4d8a3863a854bc3794753a\nA = 47423c4fec1eb6779fd23e3d4070d0a7bf9a946f5610eb469876797a39c58577242daef8c34926f6974089fc595508d9c573d0a275cbeaf37172f10b8c849a493\nB = 18ad789cf09e9ea182eaf43b28b4f2540e533f0fccad325430b73101c00e440bb64b70ce0f2680184aa8caea2f6f6517e9b80285fea8b61887a41e\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = b18a906994d3247bf8a00f20e4b349a500159d086aa863772e71a68f91af9d19e4c021843f8bb6eeed1df708d55047dc8faf219e00d559517632dbd1cbf4bda61651b9644481d052903be1970f04bb4ee8faab9adbbf858324e6cf5aa9384ceba655a1a107210a9497552ba8a56d5e0e70b0c757baa71d1613683707357827f0\nA = 122773509ee608cd9ab3ff6763629a18eae41be64bcfb05122e0b3e112db48c64d2a5a515d96a042850c1c848ae5fd5f0ccc57b273d25bd8d68568cb00bb17b1589c\nB = -af398208c01ec9700e332f3e694894c7cc412a73bde8a79e08764ded92f0d58db8056883972c79a0c9e0ce810786cdaa3629baeb9e5c370a5a59d3ba\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 64ef5e7063a1d95226569a27218e35e93d870a19a43fba9889a2ca98ca5c573fa56ebd77f1403b3bcad17c1351803a809c245a97bbe32b45e21768f28c5b11ad542f5e687a17f7811df6c8735e1778e94d9313c19fa32a6703af7ccbd88b489c96632d10eebb580cde3b905f6345a2a2b86a871b4fab36fa4b0dab9a6c1c5096\nA = -7dbdc37a51b601417efdda2516aba15827a40ffc304c523a47c544d5c0bba6c1367a20d8a6268a5c3f723b1b68de57eceabbb00d44185ec4ba7ecdce5d80456f8cfe7e\nB = 641cf85fcb5fbacd6214be4b7b06fda1b80f4683c21c1d08311f6e23a15434b42d30a51912898a1c46b46c00aef7ab7663ecba683897825a4b07d2b7dd7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 370f20360ac844bf4275f78b7fe71ba5db6f0bbabfbac3384c04b256eddaf04725d2d57b31afa48f047aade156c34441b4a41c0b2146790a2e15d13b584021ad55965588c6e55ed3b5cf5c36b780a27c5dfb72678d57528ab17ca2ac696aed3d9abb0ca448d9d5789fe37e632fa9709f3bb924c4ce34244d239a940dcddd9c77\nA = -1a0cc5b07271098a23f01b3c0d47cab8b294794b74a8b162ff3b313fcf85ea81fc99433cdf4450970311e1d5ff81e9ba27eb867073ed250aaa7795e44ba8d4000e879bf31\nB = -308f93984acb78c5dac2426d9bccc2e3ac361143807c7d34c24ef8f8db5e68a904ac8bfed1edf3cc90d21c87ae4d224b8c46fa42eea77797f94aa848160fef\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4c8f466d1d9829aaca1a22fb6ca5bdba885606b9264933ac2b4c18e3afc0c406aa71ee7ff490fcaa804f457096e44576ff8096fb1d2b3c68450a8bc36d1a2797ab8b621ddc91d75e7d6ba01d86e959171fa428a5bb1f26766f94a553c94f6dcc2e0af90d7776ed3d9fb67e842e88f7d7342afd86e2f5d159db7304ae4d204a3f\nA = 57e894e37159cf3c161be9c97a946454e43bf09a7ae8e1437570a86c6b06f84005c1463d27d726afd2e25aebb1657eb78957a9a12c8749049d12007a81d766dbe008aad6d83\nB = 16dba5cf077403ff4af47438f5840f65fa4e058c5cab3cb730154ae0fcc982ea097c6d0e75bbd635e97314f33ec7e31f0e41cf285ecfafaf36382b33d5e83cd55\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 29d13ec304f26247a45ab6869720720fe019d6cf370b9e2df9a65828214aeb4f8b17969b8dd54339d08eb99bbc66720ed78ef79033fdce6da33501fa8588af86ec18be4c4ecfe01781f9d1379865100dbbc020b892e77027d1f04f8171ca51fb73129dd9a96568904eb4", - "4e19f56f842b223724a9ffe28826803185e4208f0ff0\nA = 135ebb133a0beb909101da896e3aad7e26ea72b23e60802e54cc6c58a07b1205e2ba1fef6eb86c420f011b70e3f725aaf9fd1873b6e1c1cc7005c7c09e55550414875cfe846357\nB = -e8cbf3feb7be7fd12b01d5bd024e47538f434b496613320ad71f48a8972f687992f97e4b69b5842d2d6a4176a5701327c40325e98b27e4c0f8fee5a457d92181e40\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4309b728306535bafa6787dd79e58324b3f86eb5409d772018cce2159f75832b87909a672b8b4b14342b352e76ec5a6dd66737cb0a20b81c5ce222133bfddfea878b132b6f9fd557133973a0b44aa41a01d54ab565d6b9c62da67378a4058255047a95923daf5f0f7adff2a3f06074ab1facd986d7d26cb475ee818199a390b6\nA = -7a63e108bc9790ab687e0fb8a1cbe1e9ff876e7b5eccfbc136ba05fed93412dbc2ffb1ec49518e9fb867429cea1d7f82e2b159b75bd40eb8370e8a54bf0e0ac0ff24aa3662774bae\nB = 51ee025b2ee8abf9dc5ebf1a4600131c00ae4b6bff966dae5c49ab5b9017e6b1abd6434736df6daabb2bde254022783764c94e66743dc752c9040563df7016a1581fe7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = b9ddcb9ab858d2229cbfab87d87236e8206cf5e1a042eb5ddde201d56e2695a3d0b2a42bda6a284fbd2a5b2c2b80446ce88c024137780c277ec80bfa6e9d15397cc5bac98e58c9130756ed0fde58d475a033fd94b1fe0ecc6fd91a8b42177abf3f77e87c0847a4244b9fd4980f3b42c7c955836bc994f2babfdf9c5b43315ca\nA = -1f971ee9a7c966d1e82166503681afc280fab255665b850645321f67da8934baba1226e9efb59e0ac4483c8724f63556a213f2224b993e4e082eefff0056f7aa8a3cf5b655e0f72ddd6\nB = -39309313b04bda1103ca6f56514026538b4a29ae258a2a66424abe2c652b959f5c1dc4755ea37ebbfe404839505c2807ebe069c9abb9150205fe35bc286ca12b64ac46133\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 47555924c31f040619681d4a12064790e981db2c7853efa17e4d20f741f33c56d80862caf86bfe0730870b6c0afa9caf66e15047e60256fec29469d1760d5e9b77d79a84fcf7a1dcd0168a59f870f1635eb033e0ae0ac17bdb73da803206d48cfc1da48507cb812bea540daa2393321ccb0d88b57abdbf3a3bb765692a2c2ebe\nA = 754d78d5608fe8c7ed8e26a174fa27833a24c48d23f0e702454b7eb578cb107da537dda11027dd6b41daad329e036794de562d7623bed8d9b0e909cb3fa38d4d21a95c5f4246e0b030a32\nB = 1839baa8b8fb6575832136f1d4632f72f36cdbbdcbd00f197fff3cdb88b851cbd74910ef6d43cfae9d3248e9c85662d7fb596ae45a460feaf308823f06345bc5fae8823230af\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 9b2f026b11d0674e9ec060fdb24b45fceade3070db4405b363d53df1219a02a664882819fe602f430636fc0bda935b14c55c8a0bbcc9b6683417e3ffe7f5d58fae229122ac6e42e76899254295dc5a08ed43c79120a5e5e4124b8fa6048ee90836bd2de51bbd2c6b9b53212e913cde871f11bf32f91b3a78575a006da36627f0\nA = 11402b3b1a45d67cde9730062e38aafe1d04fb1f8bb1975f25cd9098813efa2727cb229adf9490267bd437220d9ffa05bb993e45d2f889f140faed3ac3c7b53216455a830d6edceb02e8db92\nB = -d8e011f18bde068badedce8106f6602429fbcac4766334a0101b57fe94603203a4a8975fa499d8a68198aefd9e68f28e68914f920eea1083e37c67d59476bca9819a8bd628b89c\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 3a74066e7eebd9b63a1dd28548be60573c95f29816f3b3ceef68a5f6bb797d7eb0b0f4ee612dca794ff82f5d7461d995b9dcc09649e2587639ea017865328bb5deef17b5283691724e8aa331d75c635d5e19ebfd268fe5471714aaca8b48aeb846f241c1675e18d35f029b132f81128f19028b0a471b3f75a530321135e35fbc\nA = -6c5dca3fb7b85573d1c8899868940794e428171e207b5f9f89fce4b7159236c0755e2959d870754e902e9c40dc1fddeeff6364f898ec0dd669283e6d26a612d9af3c3ab04468707bb8a7827756\nB = 5446269bbeb613e69286f1012ff62ea767965533624542f3b5c866cfb569d6193aa603061701992cb4873ea8b766606da1b57d7b37cf52f52bf85b58309387200b0ed36164f30d52e\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 2a4e727ac67451ca9dcba648050a085196460e4aa4836c5652de863c3e2a76213e0f590de3aee8639304c54a9dcd5f7d5d3592f647e3d07d322708e1e26329f4a31d66c7f2e9d482f22cd9823074dd57d14040a4f00ac2af9677a2c98d58ee1e094b1a8c40092e77eae454638bc3655e77441d4f218c637f95c147776f5bdac1\nA = -19fa688008a12cae228c6ac4982ecbc88da248d7ec785bf2289dc9103bfa3a91eb1e5fd6afe9e0cc035d3312e9ba64028fa6a229db6d0eaf8af43d8c410be7c689c3e557137ebd60d3fa04edb60cf\nB = -3e8c87fba4a41c3a84874c987acee9f560b9f027338b584a775c1fcabb766700f758c4d451077a9427257334a569037b0bd006375f71223add62eca19b1e26b86dde0cc251e48d3b60ef\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 52e4a3f6892b425b935c6f9d1396d2034eb0331cbc5241e1d745a9619fa0cf0fc521585cb9d6b1034c5fbbbbecdc81c757f768c7a82f6ca291cf5afc98500c579f82ccf0be233066730f738c205c3c188f94b878c11268871ba42a5d950dc8a399887997cef2b6b68badec1ca641b88d1455e6d97a2841da49df7eeb766b7be6\nA = 67df01e34a26e8239c8edc7ddfccc3850f39864ed237d4dd67588efbeaaed1f884105508f69e20ff6a5cfae1516f6179ae6fb515a66ef0a7d633ba4218c30875287ecd0cfeb5bafafc492619942f97a\nB = 19f5076405b3c81519c0863d0c963d545b2834343e42bb3c779788cbb46d89be3f775b62f4114268a0ca0e6af6c0dd659607d40071dfe7f1ad0df9a5c53b741c04612158de396e9c96f7523\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8ac1d96abd2cbcaa8f7e3267b716f675aebd23694d24c112d202653979636d4d47e27cc36f850355cfc5ca16b78cd1848944f8759fbf6b03fbb7eb347536a9328a5cbb778a6bcd983081374a3f543b1380add14a9468358009ec2baa7ecdf13e7260968eea74083459406e8889936b2fb98c8b9a3597e5f9ca10b76e1dd0337f\nA = 1c9ab23ea37f324544280d176cc02762db7a39935f1ede9695b53a3ee2db49d0485c6a3742a3b5cfb51f3c21711bf89ed05afd0886bbf61cbd57b23439a8a165484ee8e4c0e1c0ca2b6478776aa2897d87\nB = -e30d28dd01655b7a419d939e3e7530258a667420fc759bad585802c63fe5efbb309cb502babdad0afb208aff5ce5830071c5a974604c69ee47f76fd87e2460a5b03a57ef0185881502625886f\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5df0700adbd880a5730d8c0637a362a9d42c64503c3b9784046b946c2459a619b5bf804a41c92ed6370bba730c7d39fb2e01558f7ec38511b0449d6e9db8df2cece4ed348782ff1582396ca8b3196474e7e5817f8c197c44d771923b6e286e41e7e23c33fcd8765e06793169999544a310f2e080ffe13640b85f21a18fa11928\nA = -5c01fc52e86f3a344180bac284d2376d1bd693f20a46479c77fa57077df62f83b1e81c94e577d1d6733d276f9cf70555b20e3afcb97534e4e0108a6cce87e9292d78b2d7367ff15fb33d2c3289d2a2913b58\nB = 6bbc39283be06382ea91ad6b1630b38f32385ec90019d2ded7ca6fdaa39defbe22585be0df9c0cf613f6f146c71f901adf525336f6573f7f43e661c44b7097f110d4551e8c75449da8fd39201ca0\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 2a01005f1f387c4d8d24a365708e2506b044f86dfc011262", - "d3577f7313a8f51ab943037361bed1858e021f8a46491a5c73284c666eb65cea1392a780219f13d7188721d7d4b975272293a5eef63480f30cc9618aa74bc51f4175246301a46fdbd34a6ec72d5974aa920be5f321a97b8f19c0ec56ba10eaf2e61f2b45f134b304\nA = -108bbd8824e8c16b81dfdd4dfee691e012e578cb9cc80cf050c0ec4cebf71a968732da36552979ffaccce6667e46c29144dab75132cb087681d5549dc5508f3719e129553fdc97f545d7ddb7d3a4fc575ea67c5\nB = -2ad4d4078c47a3c8f5f9b48e10d52d72349ecf0f54abc60bad63bbbf4d8efb185de90e5e1a686859e1c429e30977fca492aedbf084019e9ceb4490aa471776ed2e8a09151b37c5caed9ede66922b7ec\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a1b1b2d33cb610f1b398e03f274ef39a583d13af14b79e6766859b9ca748237b481a3cfd5d490a073e82e3c53d3ff5cb6219b2b2f71927f27ab6f567547a22dd35fb5919e1ed2b6dfae4d536d6d44fa6216d94d26b33f52db06c4ecb29702588b73ebce87569639f786df4fcf569bb07d5379bf8b83743327248c2d71b5dec6a\nA = 5bc53b3895cff2bf7bf10e24fbdc43d17d277a982d5d92f17b9b5a2b9ed8b6104229292ef3997591e2e6a116fca21ad5d061ce438f33b7f7110293770f8313077152c7546cd522ef4054147edbe1878072b1043e6\nB = 1599b541c9809779df3ef40971e7a83f21564bd5d6596d51a3d96defa4dff41e83ca6247969a3dd9a746ab72ce21137f2d7ea015ac6b2ffa8a32997e8b821064d35afde3435b23e47cccafa74d5192535b\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4fe8897417446c493725521c0ea5b2110f91a1b5ba236cbb6ff3f52b0036a49fc82274ca949ac2b592fa4bcc792114bf2f2a78a2cb44cb22c6fe7e4bee7981604de47f6da2ed1fc6a8eb32cd9b8aaca0f2feec76a2438126ae6f409645d897769a6d340308f82dbc6a98ac059fca6f903c5aecd668fa838b67300c654d4013e3\nA = 1717c6503d069103f10bb4b36427fbdd2371b30793e492e4161fe185b2e27469fef6a25566d6b46f6a7f97446315a22d1f1f662f912b17e71feb2c82411ed7eebb84d4f594deffee14934b75a845d83761f36141ecb7\nB = -8808f540521c20eefaa037fc5da782c891fdfc668b955eaa2e4edb592e027a964b4cfbc94c548d785d92992abe282d90dd137c4d76419926740ce138d567da7350d89f2e56772d8f5bcc9ca8d7076540fab3\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8b9311808bef497d8a5d14f7d851567a196a051610246964917a1f9d4f4449357d2411ba9fd93983f6edd76b8a8e1501146b08b6e1fcdd97b6a41cf637b6ff0cff7a2d6351aa1ded93f8fc1cedc81879eef751bebfbd1559d5d0320595c79e3eb1db0951d7c67c663bc57a672faed9e14c7da6be6b0c6bcab3d4d515e51a0b5d\nA = -511312fce1849c3d177d42088e55d534f9f7096282916e16b041f66ea90e2cccddab5cec0ba8ebf0b047ccce72da349f420cc28ab19bc156c1cccdcf5216f19ea922698127f090e97444751dd58fe7a2c90197a9ab3d35\nB = 6a5cab5e322d5f651f798aebf43a62af772fa2cc379905e72d253c49be8193a07ae6164f21cf08baff906ef800e361e1cdf1604f454483e10c8b2bfdcce77c12b0320dea63f9ac0afbb86115b656d0198aa883f\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 665e16ba6cba87c646637a233ae04805a302ef4a10d79c5b65b146cbab8c9ccd491faa32937d0ee955dff7dd0ea3f79fa43c133021c8680490b91d9c1d8a8102ab709ada7508bd59042940b2bd3a4f8c195f781313e45fa8d3abda1f8e13b35811b638b2ab101d1caaa92188d2b75b2b10d596ab159583135b0d4d15fcd3d882\nA = -1375af024e9974cf8170801f4a709b4e5862ab7d18464077727bfc2581e557cada991e9484a1acf80182458158c44871e67e783f7573f214ee4ea1f1821a65068f2bbbed7575f03a4bba36b0fa8cb6dc58c73b100a6c4a6ce\nB = -2d64b6bd987d496a3c121e89f4b0c88b6ebc6e30fa9d47981b52862551f3b7251a3fc376db0f2d6daab6e6fc5ea8fa10b040d0dce334ee91d8cfa6db9648df907b199bb11b2b5c41c67d72b760c404b0451f70fccf\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 49e9709810d9f3fef159e5cb45211453e7a94878dfdece19af839b89c0e43b226d7cfd46859963c7ccc753350e74c2501131474e3b8e0edcda18583b0392ee15f1dedcb7144000fc7fa7eabcbc83d12983d2ade477b4687d75b723c1a98a951d21b2e8ed95735aaec77e00de288d16422fd259c665a08a34331cb99299ac11e2\nA = 4e550ba2fc2a44452f068860ce2a59230738a7a15f5de0aeb4d15bda8c61ee3003568dc5971e48343d402112d7a86860a7f08f5cdc0de21fb1aa064ee5df26fa23839b5ff6adaf64a4a18c07efb3582c2fc9612d2208fe99f8a\nB = 16f31365545772f276d8ac952506bf4033a884edf1ce583a63d8d9f6809e29d9cce3b3d227f839e6c09b459951465ab4570d2d36127c0f677fc0a63975801896f2fd17887ca16ff7f265e2e7adab1516ce56ee1ee9de1\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 89ca20a3fa109a65b9449edcc729fe97ed45a9bd69eeb31d4a566ec1787b24cb7a2c25b3f89b36fef1cb3645b17c69ac8ae243cdba35e17f5738b35278478bcc391add0b5ec42db9ec1eeffa63a3ecd2ac0338db57cde9d2eb9ca4bb1df84f1a62245c4e585c4f20f26c98fa1957df34409a99a18bb442ac14f0bd309266a35a\nA = 1fd8a096be30e4435ce8cc604ded337a3d9d2fbc9666d1893c38546c4e155315b536d1bc323c1e7be162bb0fcd58440915b053ca0d0896e99265241f2afd46605a2a7486e1394a07b23f3382cd190e943e596c747b6529b04bdb13\nB = -a3960a51af5ecaaa70146ce55d639005e9b6b9b58592441d5876fa71470ade6d1e2cdde17bb80532551bee0dbbb71a0cb24dc8a129c1f6e28920055d87e9c66be27fc4b425737f36add7d72e39bc83aabee5534637e2e22\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 654d9c55d4a62976670a5ecac3a6165734a65f1edcc1ca81a8c444dbc98c3409ac8c4f6fbb92f122045fef8b7971a276c7dc4eaba21f7be7495394053d4f9bb14b63fc02c8a55ad8fa9bb9aa26aca5c47968ea1b7646ec606f53606d5529ded83639984683b8a020e8ded4b2d9f668ceadeaa8160245b36a819db14e58cf2bf1\nA = -67abdbc70db183b8c25b0664805ada269922556bf15aa80a47d31f215e216673b8d59edfa10a74f3f09d066055c3b9abd5434ce95eba91dd51576adcfbc7e2556df95fd6642a3b7e0486a635ed5699eb7fb285589c887c8659a2b7db\nB = 6ad3e854ea57aafb8980f1e99ab9cda24f183dbbc513e1fc92d4e239077816843f47927bac28e41d3f31c9ef134b72c09dcf14e2e9677a430d43002ae70c577d9958341243030fe58a800a068d6b01fd377e61844f0d434dfd\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 74bb23f7b0cde7924ee52e58bc0680f151e6898cc1bd4a2eaaa05faf218b419a19ebf85b0219f924a26002f9251b83506684af659e5b680e05138432ba227977f38a479ad9d1f3cf68a86ea214645fc4bd1a032f995307e9c9ee432e816fd852655ef20214e24522c17799ef41d1eebc6e097b9792757f7fc43124c609ef9696\nA = -19d3e6fd6de9092cbea55d65154208a0c93ae409c3ee35569cf774b8c8b7b1c9dfdd52e9f408e14ea3153073ed8d92746474e524a903a45a882fe46af92b033f2c41eacdd7e3c1ff661dcc5349ed6bd1aa845eb1762f27593708aa185c7\nB = -3d466d29e8c0008ee6f402551e3d62fe044787bc9f243db9252ea97da9bb75f5be416def97f13cbb008fee77f2eeda672bccce1f36fbcd26e1f1299619535da0a3fa3ffa0c6fee82a494efd7407cc770cf46ed1b8b143f42790a2\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 197eaeb8221b431d5fed3d701a175abc146a9fedf8060e8e611a54f8da2fb27d2fee4539ddce1f3481e6a64435f09a2d5012540d6069900a332461471b22192fb87b63221c7822d3f2fcc35cc38feb6b3e49b5b0fceb52b0ccbdb4e1fd7b0f3eef3d582a6ae194c249ebc52f215b568712b3e50bb8e01c64b114955ebac2da48\nA = 7bd216d", - "0acd4ee392258a7341cd56bfb0968492fe75da0c9d935713a6ac883525a4a520b5b7940b05e3f5e0c40372cb11b7ca193e93f0d3883fe5840e66346aff0f38829322bbc1f0a0e63ce5e528ba5b13596ad7ca19d20b2a7c9bea4214\nB = 1ed4805e53630b886cd733e5281f6d2699b3c79da615f4056120165cc63858ed2ddfcfd0af0c5fc54662aad90f26c55dcf70a30d04ce05bdf61028730b900587716e690dc0c6e02419622ab8c115078b92315e7c7a5ffe38c4a404a2\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 40f69f2d1660eeb6e1840164817621dc95eb930875333bc3f62a644ca5910c1080505de0d54fc9fb6404a61bb2c03b3981e558abf9e86f2047c3928599b529ef3d91c7ccd13c1d69431fb9ea3f02b001427cf519d9fd8182219ad904f47b3785fa05ed24cb0ceafd537311633a2e26c27e61be92eefb28a49d7f583cb6e072c2\nA = 155fb75044fc54a6ba6c46972e2f97531861b8d6afbc358db456bac33a44bb0545deea2fc83023c08b7be473eb68accf5b65b3c5d6af88bc6d8ce722c80d5d1527e475905226b01ab9d7b5a6557250cf8be935339db330df2dff92f2e88e80da\nB = -8c6016966a2cdea4b2d8625aa367e1d079638870f1b61e6b3c3a1e6281ece41018d2ce93684d1f0088d021107fb595390664c11435c6c0a7b93c2c6895217a89c469a37d3250dfa457b928ba6119b5c9ca5f2d47b36e60e4325bcb4383\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 9b9e6e1727326fea099eeb008a36539f3d47e3882b77d6089032b99c6cd36ad79fa75b7c19d1509b3ff022ef781b6a8c16fa6881f9ee2c4e00a4dbc93a49829622f4ce6ba9c55639656102d81167ab8a5e1fcf14d71caa60be732f1fbc71250256520c7c5a4579c3fdafc39356a2bbf2c7ecc526dacc0293c7578424c939ab6e\nA = -54cc11ea9806ef27911ba721f19e2ccb111045711d301863792f0cfac798758f0a29111e3a0f84d294a79721067f50858767abf507cc10ec9ea3eb27a91f06e7f6b7b4be7001b548cb7fb734166bad6739935081bdf6d35d58ef56180d377e5fda\nB = 7263e8b9a6f5387f44c55af64b64160efe97ec8a8159e723ca8977bc17c861e22041ea227c9c9bb467faaacfe352b03cc620eceecabb6db2db108b49c69752bd0cc61a5e998ac2f404ad052a51286ccbcfaa214ea8ec14cd9a2a6db56c3d9\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a18a7498ac9194f600cea3d66615595c27a3efa7ea196ba12a80b5f608f85fa72afc366d23f5ca98452dd190b8f86031a9dc097f94a217b29fa676a6042a3aed2355cc8e767d464a8adb888491c8cb82dbec8f117f57c4a07b41e7e6f6cbd7dc25418603b1d1d865dd2140a649c9d52019ef39dbb6809d1b28b3c1ae64fc6813\nA = -1b663403c73e4a9003467ed12766f16354f79073ce89b66066857d19f3b42791eb360004d23e02874254bc6db54662717739eced153944c4776f334576746c5c4145b21a23caa2b2a137498554c7b749efcaf3393c5457b2bb87ee2ca3bef5f191107\nB = -21d12aad97a5c6e639a2ea0a82b1292aebd418567718014465a22b9ac5c8c927963a2a4530c41d5a7a6c14805e56a7092c8716e4767b54a393d8552c5d3c366b39fb3b8667c60e6075e9293bc938e407c53afdd1174843b76aed187f56bb4be5\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 1983576ed73d4d87d8b94cd3f70c149c0273e966176b85fbbbb7b3202e2c843bf1f8f4546ad7a4916ea4c731a22bd337b6177fcd2da8bd301f3af9bdcad800449b57986e7cbcbc7eb313d6512b2894c0cbb6cd753a870860a49d6a682c20b5e883b8c4839b3321aede51bfc42bca163a924191feaf05e196d8dcb7fdd9941a60\nA = 576759af0f02406e8dafa330babe9473d9d970bf371ceab30d2f98f4470f669e042e1708e2677d52cb9f99deb9b53f30727d16c389bb63e71e923475314b615762c7612269b5ad7bcb5108068bb5159cb8dbb8d08de2bd4fa4d9db6cf6e3f5997b9b416\nB = 1a4e34794747cf4aa626e964b839ac497b1357090ff63088f9fd4399312df894e41b395d17b8ca1806baec6115b1476912ca9c4309f00a46d5f7a52c8f640075422af06d6d6d796359132f4955072ce90e61b40c992a155b2bc31c262e753aa7d00\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 3448648ff9f7425937b6faa54551ce14dd15566e5d41b2bdb1a8db62037459235a5b9546d289cc2295b0ed584fab2e1a798bc25a0c114238f61ad3381a5b441cb67f92cbf66007c980db3351adb9cfd2cfc769b5b9b0bd1701425ce1ee8d4b9f438ce1207fa850aaa1d3d1f970aef874c2b2499a150d29c2ceb7bac375009b77\nA = 1fb54cec882c274b98913e76342a9b8e631bf1d381fd8a4f7e0eaef475642ab3f5da70ca2e38741bd0182a959e5e985f1e0e7d737beb8c725c9b5ea22f7ec25b6e564809601e8405a5b1362e7792791f55ab64a57c03a99a8518d7f65feb0e21be619a6a95\nB = -8180d172d3afe00e0423245f47591d5f750f20d2cedd8ba6ab6f9aa24f74498a96c9001a0124c4f98dbd402b63e71eaa3a7af8b0d2fa417fb1d45f64e10030232b9155169153496aa202745a432e547002954eedda7cc9c1ca76811bd902b192f1a1d\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = ae0fd585408a99643271eef575285a6261a4c4a92c1956b1ab436d3cacc8d4cffc07044e57b357ffa43bfa9aaea57824319579c5c3e2fe4dd48bc818178beb5fc1ed60afa08828657d00bb88894c975378b1dfb452a5b88fc3c1d81099644a998a47a497c8a2b12c444fd2a088f47576b7f4fa40f34a208fbc3348ce33e59150\nA = -7dc7dfb753c0bc3ab4d07d5aa78664a7f57d64be4d4780ea81e3efc967fbf1bd1390248bbe259da32108ad96bd8b39f2c9f118bfdc96bd06147f812af831288bb687e4e1742dcd1dbf2b7adc41afa28d07dfb8df8bb2da5359e66330f5c65964096a96b31dd8\nB = 756f3e407a3ae698f103fa37759e90554f38378a9b8eb38581e0970ec8f9c00f8392612c61aca5fd37d1063b78c19e3109f35c0684ce523c634190b3164ef06959cc42e2b77e1bb2fd50eb59c3dccdb6090beb809ecb0ca30457a5c5948328eb218e219d\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a2aa4550e855623a8ed488bb63db8fa4ac374c1ae953781aac590f78a364fc33380ca2806445fca5bb9ca2fc7ec4db5819dcd5769e3b746286c49a7c80149e7fe276d095929e2cac6ae57e8102f7d4c96261ca44cb6f1601f429528495b6c3169e15f9babc5be696074d45559d5abdac42393094c450d6a4a45bbf60ed7847da\nA = -16d0aea9c752b2e6e4e13f7ab1f0a2c1776874967b0dfeeef7e00f8d9edd1e11d2aa702be45fffc284c47811c51dcee184a134b8f6d1874026eb51e2ec80c94837af4602cac3efde556ebfff578fcc56c00de99a43638ab68387ec087ee269ca64233eb5b1762ae\nB = -3c6b60b0ce4b13a5d6d9ccd67c76ec6b71b94ea7205e408eea099c7ced2f3a462954741d353d0af850b10ffede8ce0bf80b6893288413674504829793d7ae0cba53b163e3f26cd99beb0a9ad540f6d2cd5097beac604b1694a9a2f4c48b28338f9d6a63e75b\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8a1a8fcb68c53846b3edae33ec070ef5cdcc1346ab3a98a116344e6d2810e2e3f60f0fe435fe7ff257c7ef4c122b3c34c776f4912a9621b6949308e2cfe2e0827536c7464371ce804bd7cac1d76c5bf8b4a6fd4ed56b65434c3fcf0ac7be543fe2d09ac01c564d7b9b463740dcdfa9068d4d8e33f29297ab452e6ec55c263de\nA = 7c4878334ccd9e20cb11a643b206626ea5d0b20973f18535cd8f0fc2f0325a67d3558e4cc9cceed0d88c6d2215c220b8d0ce230fd701502b02081e3f6548e58e02bc2e79e4991f8ef188a84b0a367758b4e534b72cd87de7f82a26de14fafd162a50b359574812cda\nB = 117d8b1d2a3e2049e6edbb9494c68a97145ac3e658aeaa05e8ecec4b090d5f467cde34e05fa7f5fbfa32f1d9dad70955f22130c358468eb371555fdf57a40e1df398c166a22a9df2e1f4e18590b00856b4f880f6629f1a4296056dc66a29b6f0f25490c6a8209b\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 2cd3de06953acb87b773b8bb28172b24adb283d6adada676f5f4548990827635c5", - "1506c85670767828dc5b4b91b45a7ab89a700d70bdba4e0355da32b52c173305767721d18dd2cb6c55f890611e7abc854277a453c7500efc4cd4fb8e6c9bb7a73fe5c77045e715fd35d415b3496f7463ec902cbdc18f9f6f67c33fd78c3210\nA = 1a20ad042f46330df937b879c72ef00dcf39fb85b59186b8e7a9d40723288677ff6ab2b9bce95f34f2de37887c8a9cdcaf231254bd00c7e25b6042695d7dfc05a11765120d1dbce29dc74f35aa1492ba0c5ee65114d9a246b57dcc2eb2ea4a310be98383fb934121db20\nB = -f8ec67323cff9d53499ceb3afd44b28f0538c39dae8c965ea27d645b430c2f8a4965eadc8ed864f2549eb636ec558419be71f986f4c5783d0dd5253738b876d9034735bd13b18fc670438387f84848308d9357ec2aa4f6a453bdd36ff08d54a6800bb41df416b17d\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 1aebe2bc35eb2e449bda63513b1bfb55988cc8e6ec8b3c8fed5ce4dcf53b95f1b438c41e3b2348412b35e1f734edba30273935b03d16efaede429960442a01849c352349e23b4af88de4d01e9ddb53ae900418d49a84b7fadd2669261a574557c4fbd782f8e8f400895f6a6c9679b72983ce01bcfdb641f5067c94694e9eb80\nA = -5f97994c39265b5389526e3847876a10aa3699e3c3762a127d1a9f892180cce68ca6139a6f71b235da26c287bd3e1aaa1436746d983c23c3105c33ed2e06baa1e880f1744d81a80b98ee1f16220940d721a92118a9b949d4da7d1477db8f5b357b3ceb7df34eb5f62078cf\nB = 4bb4f8f4f4c8e63238e8774ed61a7eeafb3fe9a6e19cffa648defe82f4846e3378c892d223957564fcce79596151658a726031a6921cdca0adf0f5325d858c048a6b94312ebfd19b803eefcb93bbfaaddef120ec3b8c366b6d978524d5c74218da77e4c3b5ebbc66cf8\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5d64678a32c163874d1c81824d628a1051bce3b55c37055acc47a8630d3fee648df5d319e50b4c56f465bbf696433409b89c07e442425d3018a059ec757d77b3a40d516ca3148010036b003721ec9c999665915a3c442d95ec3c01c232feb201be08c88fa3c6b0769e3da30f1d73b66f98e31f4306bf4e23de78e74743b224ab\nA = -178d81e419f0473c426e24428caf25d61b648bbf963f7fb753ae15e5ea3706b53b00bfc8fe917ac9fd6c7096518584566ff71e6d35197f9aa25107a235678cf9ff8ae1501c1d5a15d2a27d39d066e169745e1e8c808209bcede0d732423d0c9cfbea322ba3201ebefc5315c0d\nB = -27ed464895b65d9518923fde5caaac0c72aad0d1b38fcb7827d6ad4e0c8dc09e119b8b98183f0ef8d5d1133f3f108e951caee035bed0d48bbeee6d1ddbff5864bc192b84eb8a500cefd223972ed51c7f720d1736646825f95f2f10ce6ad47a267bdd8c80f65d644df158d7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 52dfb6bcbbc5cff46942d76ba45301cbff76e9b894703a6a7fd1af29d615336372d147c3932589affe5c6533f28d3e6a57ce2d3cd7448bbd81e09a13266ea31630cf044f654b87ec3fa3294eb65873964110fd42d86e78d128bead5f117cac98145051552cc3a86c193d738b973f866d068a8994a49df3fc7c7314fbd9805e80\nA = 797c67ebdc083f3c8b3ddf9847b7f3c2a39e35ce2119f746ec87fd5d86671d8fcf2b4f6d440c43e93f45019032e629879799eb58adea729d43d2e40ede6485143bd35979609a12faae7e4393879c40c0511c886c66a24454e4f9912bea944eaa417c9942f09ddfb227feb14e4b4\nB = 1a599d1cd0ab3614f50b71b93c999942bd3d4cbfe7900122d5083151c71d9e0c299bd927095c5c3291418424a7c12947389bd4e0a3c2fdf67b3f512094ec0ce5b52695e527de2b3804dca2edaeb1ea4b487911053272ea926cf2fb3386dc4b1dc268b808bbcf4eaedd21168ca\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 99bb9082e4537426c61f3b813f8c97675c44ba9ca418960ca6e2464cf61ad4eabb01ba00798463567ed3d829d3f14201c740f19fca623b1e9b57b534a65df0f070a2130489afae89b91003cee432fab11426c4d13b7721e6f9db1bbaf0adc0064b33e4b9f4b795511a0744b52f93e3db7bc9c0a991e4e122c463ff344fe14cba\nA = 187a8144a0045a92dcad94f0bae7285309ec8fac7dc864b08914e5a4dc3b1a6bb9212161a18c22682ace16a4bf3c03dbaef088b09844902a3255fd6adc0b7c6397dda86d6ab67204d8061c36ca20fd4bb348202037b249f6c110c31580148db46dc5b1bfffa38a683a27054c35326b\nB = -e93ff16817b725016279a32dac247961ae9bb00af890fb49c4fd8cf5e815cf98b58cfa1e3735095e6034c9a2f2b5d8030ab30e2271abb45b347d755cd9ab5ab5ce37950380cb306bbec42b6b8056793a0955bcaeb23e2d6a9548684030566eca2d34c458f224c8e337cb8e3c252\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 631f53d02c031f592b3dfaeed106160488c08e0672083ff195b22a2c0b006f11165a245acad6f35dfb15a871a9a2b45c544111f71f86c920b42fdb6551e56c55199e6173c00e27c9f47256349a80236bcfd3acd1730f823031ff9ef594725cb9429ea183a7fb2e03124ebdd98d435313e43819d995c4fe81fdd4ba718aeade94\nA = -72e20f1aa2b5f2c4218fb9e11ced3f45a218f4c83a2017d97d0cfbbf227c9082cd43f939c8909e52c8795cfaa75d80392d3649dd85ddc35bf1cc54ba389bed9e9dcf867da1c05eda080274beb6b868b54fc85e12ae127dcbfffeb043f9d59333d0ab3374c24971e1bc7269450b418c8b\nB = 61cb021a3a957703d14061c21d3b0fc19598e19a17df9d6f2418c76d4d37b3f62bd4037aeeb1eda37f83df44c440f5e49924cc72ec5b153856c6b621350ec89d98859d9d1ec7ac4f0c418c6599674322e7d618c5ca588d5a873d5af356d4771c6cd375f5dbbbc69f50b982b8c4d1ec\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4654a62d9491f28599a976288cd2068d8e3228da12f645413a92f482efc66d1737495cd4a4c733f147eb5414a2ef6266a116ce264491a3463c9df1b030d83b315f76f3bef8cbccb5c538478a65092547b91e991e6be91ce4549c3a6e34aa7b466e63eb3b88054f6714083695c616a078ed54e1ae46e00f3593af845fcd0ff51a\nA = -1a342c154aad619e567fd32e7053aef8d98335a4fa0e35bf06acd7998c43d821de1076dc1fb67dfa1156d7ff30203ec736384a9aa7f5f08cfb302eb3a2a7179b2664094c2cc0df73fa05bf2af24a62b8e394fc76014dd83b434df26f8a67a624884a0b9b4f08f33e9828ae64f5d0c8cdc2b\nB = -2c57e15889c3dc9c94361c17585d506933a72fa954ce44dda9f5e33408552ebf49cae87bd0be35197f887fc6c7deca1452a4345eb67d19bd2e7d3dcf651667a8900388e4d5ec71e9433e3b01d2b3d91bb94d0fc3c51c70793f978e4b5ef93a9c6356c0b2f7accb9e4eb457a2174b50dc6\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 6124d9ce4de2880ae3811836235d6d89a1a4b710f1d5a517153ed7729dfb5b56b0ac10a4bbc811db9b26465f03cda355701f9f28c5257fe288743cc0789cc54a8661f46e36eec357580b00a84f1d4c8e3d689bbc18242f1cac30a87cb7a47ea06f80d7c5633cde4c8cd8a1a7e27acdc3a2aacd608cce9e2efe7864d41a56ceb8\nA = 7b48a9663d914e0225d7275e965d866ee6649d7267474d5336d28d54027ffe8572f4aa26230dc7abe9957d211e6c2c8f3185cae962b878cfdfaaf6cfe32058c299247f372ae170a1f7cf71380787f6e90995da9ca5a4be8ab1ddfa8e6e5dc65b6f168b9b8e29e0257e0eec853a6e1911b1afa\nB = 1fc4dc77f4a18d4406a4ba536e500aff68d133c6e7725717ae6537b527c6f40f93202a2292522fe7d04e0ef804d1a7013b04cd3d88462fba31534770b56d2e5672e8a6ec7a723186024c40b4717defd1433b9967bd692ef81d5d4e39ba10a3223d250ab6e71d5d253dd0a732ed386ad57e54\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 6443de73e1c826c90aa36fd7ec5d0c3324c42058b1c35d3adeda1685470d363732d23cceb08c3f973034c24fe65506bd33dc45d7d617a53048dcc103d3d1b4fd0534586c2fb7489ff5ffb98303bb068fc14b1bb6bb43f763dca2c891095e613bb7b6920163aa6cbce8cd93d9d39f4512b6e0b28d361ae11cf76037eab4cbc819\nA = 13f739846ed2c3aa0a1923168cbb46f4f0a2f3942ba57bfa5c426cb4d4b3d80d9530405a31bda329a1814c560d54defa3e03fc4f808606a598607783d539dbb1338d5bc0c2e272a7ff6ee6f93e1665d6f5a0ade30308fa047d", - "b086646c763106cb875e014e2c18ff8837e4d4d86861b85a5b7197\nB = -ba019333046f76325fa9f258006a7c10d27e89f6d482b95c79296c07a65b8e3bff4a9c9fa7e5d0038da129390ac851f8c0651dcf655a3d4164a731cd20a701895c12a906c732906038a8e459aaeb293fda21346964a6d53fa3e370ebf43c7ec8f66229405095c6a509d0fa15dcf45de8d0e901\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = d3a6fdf4a26993edd175de9a0f012e1eb15a5a1c4dd2741dfc6d0f9177cd5645508b8ab09c7fb34066ba893c38144c7f2ecadfc2b0d15728b407e5db4fcbbaf1871580426400433f14dceac43d28f03376e791b7ad01a112981f29ff4b66102305f0ecc4fd134c2cdc79a5e9d9f085bfcb7e6c187980e68b6c7639c12e8d200\nA = -464cb16fdd395e32fdc613c63ab4768f8cf72a5b74a0a5b0cc581ee4aad1972cd97db7966d3124e30c9a1c80d85c46da2d36eecd7c3bba5866f9eab4d0fa55b2d440a311654466432c681372a80a7896c9163c12314ac51f652aad68fd9012dc63fae6c7673c5da8faafcfa1b4ed5550f2baede5cc\nB = 40389ba4d2f5fc152308c9e8a8c36258c770fb2d03e6189b96c4f8dee97ccbe426cc14595c8482e9e22486b61fc570f0e7aeddad2f4e3a480d4b75d14294a3b912928da5692043bd98ab88ece87a9bbd973ec82f990c0ae6091245318c2810187d69c38fa80e835300ed06c0723fe475f3fb22de6\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8a0f9eff3a210912828fd7b5f2d72479cc9ccdcfd3e8d21739e301de02dd5c257c7ce4bee2def06c9d0c90d5a86bc45fa9f31e456d353775916b3d5684759e4500f99ca1f91f6767a5e2f4b735ae4b756d56c358a06447fa2c2ccf0ce667be4ed143e9e1dc627a561d92ae53a62477270a7944482cbf671138bd2a85fce92b08\nA = -1da555639228fc6ead68049d836d60a4927ee77472fa0ffd3c787d55b6067012560f5b1c2ef8bbf6119345dc6419444c675c1c9cd50602a93ba3718a5b3e1a30bc108d796998b24474cdad19bc2960b295fee97e03f2ca7589a3daf35bd28eb37a67b5d2cb35a30998d5f8622bd7e6b7d3fddd1ae9670\nB = -291fea1ae6dd1c66c62ae3a3d22904f4b4adb2a48cb795d50074095345d661a033f67b20c5d7231236dab871892deaa9458c235c342bc81457cca3f014a75f5124ff4da005dcc1108e75527528e5cc9c051a97fc6cd202bb9166f9e72e366bdd77c965a70592e5684fcaaf2e03421a2025ca190fe158\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 50f4d25875150bab63e4162265a632109d6b4743f9d6b55306858034732a4895ffb3720286acceff287c38320ee9945dcd0a1bbe5ae1456b7f36337cb7d22b679a6821a450765471257d52b6ab7d59a763e75e9e64581a93aa54761f6a760866d6baf186cdf4ad2b1a6af26a3e76cdc261d1f07b0a7122c8ffdef595812e7208\nA = 78a1609a7f08c93c9bf9090ca7c93459aef815719b5dde5f217567a9f68ceca05594f6ab17a4666ce1c0c4434e0f4f38ca1f33e501d6958a10da47211cc011da219d4373d2bec4b7c6477b1ab3b00b6c45279212db39bcc11d1e7ba49916c4271adca7eea531adad509ae119348f374ef1203c5af8bc019\nB = 152b46095d3f8db5e6e1a9e3f35c085da00e52764b261c3aa775ecfcd38572d2e86bab2f4bf29c2de4fd2fb6f35f66e8685714634e1be980773526bdbf9c43b1335c5d59f4dffe1a1fe2495ff9b7a3fae3e53e7c3208968e1ad1dd1dc8cf2e2415cc76dfe5df9e2e1eb63f7c7687d539706502d56247728\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5a3ad8d6f1b0763b77f5d40169ff0013de638b459e401f50f4cfb505565c8a4465e28ca1bf988071701dbf52ac456e01e170788ebd2b7cccb50dbfe1a65a89a8aee18b3c11986c9d6e6571f964f376f322e10a1ddd9310bbb40f14b0680385c40975aba43153970237c535c6b0e2cbf6bec918a8fa26cb2f69e98d77215c23a6\nA = 1d5c14b0b51cf31e9d97b7c49cd26097d40454978663f8a74095fcbf9c63e533708befb1a467f94cf599a41220ce13493a273fc30c49275412c5205db712d5e1832b39e65c150c3a4b251e2aab853e4ecb4f00ee5ce6982ef9215775a33565bde3ddbd932665aae506941d3ee31b3f9e4ffc0651f1fb4a5c6d\nB = -93cae5dd84584a2a3d88028d6d4cec4146cc5e350b4d92c52ba2393ab69fc1dba96e244f98e2f93f31230904169641aff30dfbdd3dc5fb1f3489d63aae1efd29335345a79ded546e42f2ee4a70ed932699fad17a771ba65fe6e689664bdd1135219aaa905c962d39531eba3e82c3425c24041e17858cbbcf2\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 61211c706730a1b98c628b3c8cb070a42e2ccf9fc6302bb1c2960fb165087f210e9d93416ad9fa21634a05dd0723cc23b8d2a846ab7c3bc402999138433725e737102094db5792249b4b5b1514a416b80c804ecfb04653c5ab18b0a34d8777f6c2955ac66fef62c9ec2819f0e3c075920f951f86b32e02bc43239d9218580067\nA = -46c8c68f492d8f7ac7834f89bc76098146432c59b3301d4eb70d9861a6e24c7c9073f910108c7b35538a79de10640291b54e5755359baf47482b97af56475211573576e9412ee017dcf961a090a6ffb5cd995992ab68e3fe60b6186f7595bd9b8acf8695c4f7359cb2ac709f032fb993d16a74822b4935536453\nB = 46953f424d988fd20700ea08880e7e09ac22d60cfc294bd4aefe637408a3cacfcd0ea6822a679b68b665d6bebed3506d25edc83cc7154b83e22953f9d91157cebd219cd5177fede28c63a15710d0f92bd9e542a7586855bbe57a94c520408fc920b3f8d65b194af2b2a580c90db1cdb27ec26ba929de4573c6eb\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 50a063fff02f2cdc68edccc23976f4b3db99641073c85709626292b9475b9a988fb8509a6223f0a517dbae0cf7cd39dcf1e8ae75196d9f5008c661d8b5153cbdb9520c71068e4719820bffda4c393032edabacf99339e0cbafddb6042ef887b8c498e87e16b62417934015172e63e7457242b864a47aa10e203f47320f03c0e5\nA = -1740e8be7b4775725516d37ba643fc64203f3a61e6b0164d112af56666ad97afb0059c2c4981fa81d72264f8669db4e50e11865907655b1f669c88f5935cacf1b12c1db63cc84507af12cf0210f990994055d04d93f148f213e3d4fdcfe9dc42117c059897697914e3e3fa8fdbf0eebbbb9c3b9fdaa7efa0c9d5c93\nB = -226308f8fbb35b5f9d129c0f6a2bd3e5c272a408bf32020905acc6d02d7e506191e76a3a2ac47cf7a63e6306b256f489ca5cdf76c7c3eede175ee4a7acedf922955e92599647b69d463cc14f2b178b88cd471b8a1c1512caa66b6d5fd8840b98b8d070e6593136e98cce9643e006b714388768920a79944be36624f\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 747cba0d1cde75dfcc0b2af9072c5027986b3e3917845870c73c452858ba21d6d1615eb71ae1b5a03ca44e22845d5432b368541b52a4bb02498668e8b99dfa2eb90ec1948d90564e6ebc388ee9816e329e1d8da0d3e2b12d901d47e22e8a1fabc37408be0f89e7a4ab0f30a03f7e2ed817006809e69c21104d0efe548165f64c\nA = 5fa76e37aaf0eb3d34d4f4c590e02b6c63fc62b1d4c9e172cb0dd82409df87ecb43a1680a2764f62d13a5e919db2db08feaf98d5cb92a859dd42bca1047ff57b8fe5974fb3ac11ba2c0d8e2203750f30650db4b2cbd31d07fe18c4df84a0dfdb30f9e528932c097e89d8f8be6ff029dd970a7d2c2551529455b9131e7\nB = 111199f91b3749f8cecfe90e9b9b6951472cb701beb39d63068c064cbb2a1e1d30736026f781836a52ad0d828be6c20303c6c0bd03ad664dbf6044a5bfb67fc20a049fd37c62ab0795d836487b883768ef7c8f427eb98e5ab6621fece77b4955822f8efd190c417ced398c221215b50e9532a869eceeb605fa1c936554\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 646cdb3ed472a7b4599f02329054846a8da173000eee7533240ade4dba82ee3d7a6a92baa3783c19dbd3f76fce6b5bdd83f1f229b1c71a6faa18602e368f1b0b9f8c62bd8c854844af85c2081924c9a153e27853b2a48147950fb614028e090e2198e613631c95e565c2b9b64a43237fd4052089f9d1dd2c00525dd35fa946ca\nA = 1c8438247c0ca376f508ccef7933724df512f9e0877596f7f4ea73dcd824809bbc472749833b537eec01ab23656e9758da22ab8a4aaca1aab3fe8d2cffa6672ca0c44ac029c2ca6c3e71780c28c31b5f154c8dee782f6ba009a69d83b1a3a03a2d6275bb8bc3932a1170470", - "fb7e405ae081f4770b535edf49f73a12ba589\nB = -e365c8edbca8dcc4cc11986a5a901e4ed0adbe89b0ab70a53aaf5821862432a1320cf1850b515177b630e12692cb025e3aa43e9acee0d8ad5e48bb15e9a3f34cbfd39d285127b52dde58751f572ae68ad98692899ab12d35e33652c4426ec60c5029e51f7e32ec3d2031032aa7b6b2b63f84fb0023c81d031773f3652cd6\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 7a3e22f4a3f7ae7512ed73a07abb5ce291bc90bad507a5ccc0c17185804b9d231b0ae2e72bf270dbd60170f34b240f716529a449abea0b3d98ea2890a4ce3d9e2214819aefd070e00201e9f271de925c4ba59651e55174c97a13a30197e46997c6c2b152548111aa98df120a617c54b71f8eb8b0c8b4dbd5251f5509fdb8a1a8\nA = -78a99d206b4f095847e9a21de273aa6c47034c9afd4c081a8e93c2d75f4ae5b090921ff5108c863785c413e2f7b4a361506fb66b7561b8b1c5cd537e90274bddaa4e91ce74ad81c6dfbfe1a34a631dbe455d74ed9d041a9183da3bc469bdb214d2ffe893f89c3ae30f8ab99c3aac4d2fe864b891fbf4f537745fddcc60504e\nB = 5c41274e9590c1ea44c113ce505931758f2cef80ba3b10440941ec9aa2ac984b29868bece2922eaa225555dde84a8334f1caede99091165151a39538e5b7390e81df757f521236314239c213e9b874e396a022f04629c09bfaf929a0e9fe0b0c7386b0541446f6a2570491067f64e662d8611c4fd6d1c78a9f3ae69f34d14fc\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 7fd27b6549494c9bc860146a3e8ceee785ca03faa94b0ce0a964844e7871e813414cf3f111da49fed1ede5e71e5539f34173d41f9a17ed129016bb9b04c86487f5def9fe350fd4dffc67b6e181e3cb26378ea15ff9b9ebdf1fc86c072c82ecd8bcdc241301daf1b774af5f90f37e45e6126c5da7dd3753a1e5b366038af6ae31\nA = -1930548d105661dc25a5ee303b61b559c4bc1f2e28b2c40cf3e25f98dfe01a7dcca0f3dead6463b55a5b2e0440a651cc9e08e125535e081c742bb3b2f8955ae897909cfca683a4822896d8a4a7073c29a80571445c6a0d53d2efe4a30a79d2fb5d08c0f95b735a1cab17ba40d71b054c9270ba6bc870e58591fb1bf9dc9b7ee8f\nB = -3e2a4c1509494f94406e3843c9446edaf0a6060144637234c6d9ce84d70fac54ed163d77d210bf557bbea0404922c8aebec67a0475a3c7b74bfa2f226403ce987c705c712bb8eb0934c2b390a173c3836378fe71a6939e48d187b27cc7236ac115309fbeabd9ffd0396fb7fcd6d46a1dc683606c757ddc3212f5d2ff3f2e450fc7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 2078bb5c82a394c30a287aedcfdc5271eb3246be05954181ae4f86ad2880ce674640ecd55c2ee3f4e89e2762139586516a28558481303e3071cc9ccb9a538f887553bf5726f3849fc41ab027fb1c680ce7dee3982587ec71b3760e5da6956d6894ad8c4526d8de953c0e681ecd44883a21f0abef1544fe601743efd3e5eadb8e\nA = 40b4ba1e977825b7accb941fe0c0a49936a8a47429dfff53502fc0680d705b9fa0efe003eea3ff0b649998fdbae8d0831bea7f34159aa4c7add6bc7cd56fea97d25fb9a6a10f4572c26d792b76c18ada19b0ba06b6142c420dbb40d66be669b7c51d8cd2a5022fe1a8aef7b60965c0176eee69c32ca5023782c5410adc1b15dbdc7\nB = 1bb2f18d7c8d306bf80ae1901115c8dc3d286baf537b812ce06d6872b61e5bd44f3c53d7f31ca8461b3628b255f85338cc325856fda5a6248b7c476532c1bcdf9713dff9932a50e52a9441aff96092d3fb0fd76046a8d88288d0cd55741083a1bdb20fc6e9c20e82490273354bd826bfe001322dde9a15763f2c0e6ffd2cf60019aea\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = ef21dcee9eadceaeab13287d6e3c9741811f6ea9d5bd111799ae05260b1de2ffbc192818fa45dd7befc3baf6840e3b9d24cecbcb2cb1c3d653c4aec6531b941d926fb6692f548cf81526acd0b6b0289d70dd11ba50ca8de6e174f502eddf47e57440142c7f74f594a9abcb48ce1873df057b132ccce8b364de3edf411089d28\nA = 19d0109e0c47ad45f57b8bb8519265a4390534d2ea07f969d84ad33556518b6234d40d1631be3c3cce6d59b7be14750aed114008458f50a6a84ff75b4ee7e4b826ddcb2d2293842ed29e4e484260a92199c5c66367c402bdff0f1a8057127c6ffe452498bb352802e0005e6cb084663bcfa82783a3d72f3a2a341b8075983892e86756\nB = -81fce71491eda139ed996f6a289dde8635a3a257ad6756e844c768e66746011fd797658184fb44b0e3f3c5600c56238ac7687b5be42529d5c9b97c3ce10f3219e1e451bb2dfbbb44cae0828ef894eff3b52b8dba4c115c3b471984441045f2c2db426cf5f86949d5bb7662cd40bb3b3172a19ca3fb6858315d688f13c17550e700cd5dc\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8a5f90344071790373044193cc4fd92116248aacf05ce639b6aac4461ec3ccb0805ff9876ef44fa71088c295db14fc820f7ae2c0aeeffca055f8f7238c6c90db706d02f2cc43b4960abe3ca4b6dec8bba55327b958e75c60c5d1f43fcf9136f12481c267481a725eecc403a16aa6221346df680560ff316a63ec8b51dc37aad6\nA = -7a54e7ca04b9a22e2b986e72e634317ffa20f6f4ee90353d559db3f3c1bc6b3b92ac6b364f6c5929090373962b49b59cb5d87554387761164982955470cb45dd00c4a8982dbaae3a1ffe700e8903a4a8e4a21eff9d00fa496d475e0e1a205be267499dacecd31551f8a9d437f37dacfdf5a2754f0876a3e02509b78674e7ea2169c43f29\nB = 652001f073d63ddd526abc957bbb48ca74154c8f9698b988178b3313dcde9acbb19ea11a935184fcbcc31e0117d8d2ec695ac56b5a71614a12cf90f21c8882187428755b6a5f11c314ac8b952ced0f65db0987f0f87e20b82a811599f4160e65c7418af7f33604e7b8952b70581e3e02dafa025cecda970d04383ee552abc620dfb9c5df9a\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 67f903e0e5623258826b681506f3e94cc0b086e262bafaa1395294aefc9f6b6323410a44427010d5e8d8288993973ad9939199b85cf02ae0a09dfb69801536a3fa6af5ac373add7efd25ba5fee6d8f040e97056f9f6fbb45795c0bac94c51ffeaf496710b00bc9ddd8e445261d976168771060c9bd9d83838a84ee9428f59d6f\nA = -19c695ee3a4ada840a7e3626e61047c5081867b15843ee9a6506ce45540d23ad25ff23b72f988bf26ab8b98363d9a2997773604f43fa732f59a4b16ddf3a45acdbc7976a1fce01b3dd55559c20acfbb7501730f794bc45fc09b1f035d60413bbcf32a83fd3c41599049a674f165ac5283c42aef213d777ae47eea960f7727f5758146efe5bf\nB = -210697d47beb73f45207340a183a729a1e78d84bdde1c7d8f80bc84559c4aa4572ab0e6927ea175acc7a268d05616201cb235e610d1012500c8ba9351a37bd68b4ec42227bea55cef5ba7d12ffb180873ab9d33d09e6e969df99fca728dc12dda6903169acbad38388fa9b001edb09056a2ee2aecfab0468822bca14a4bcdd3a4122290ec5ce1\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5fbaff0ffcfb2330283fe59611ef51cf045bc2690e31f2ad3265046fedaa990b5d5060b3c38f17bbe8b2696e527fd77ead8650d329c2e0c1f3b2f5bec4dd85641022f3e0ae6f66ce98cde1a785bb52eca796ae45c33142e8264621ab447cafe988de926544e1a7036710128c42fe8b574f7ad69d830894237d95a55d1bc7f5ec\nA = 482db04e35f9fc1d87b42bc5efe25a049ed924f816e1b0f9c8ebe34bc771e67e26d6057563fd5d5320681e1207c0b0f4b7df547cd6d5be6a2e0f2bfb088f990b0303d0ef263cf45681e0e9a1147c29f2ca5251faa633ca53f6e0b109ba69bbe20c58a76a22789243d1acf128dcc936602e832a20a2bfbfedf963bc1027650f483814d7f5e6905\nB = 105aaf563d4c1d436c6a4552770a527776f40bbb844b7701313c5ada95180160e7cd4b7175ddb943e5a22c910585dfc184b52935f06b12c84b6431395f28af2eb9ccfa66b2ee8f40fd44d753c6a83d67a6f3fe3658fecc7fb2f4a8f357c5d244422e48a33d0e2971059695a59d0d39b235d5194e919facbae7623ffc92d771532b6b0cf771912c24\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a9d204c1a497f350fa1300cbaf682c947eaeba8b3aa0450c1db9120852a2edd2a0249dedef3b3746298ee42834d869e9f765ce987a2aa4712a1f35ed10d0f7ba9cdef938b073c3a526e5bf45f3510c94ff1fb84bc77b08e2a", - "a50f5cc75e2f4da37a8a711f8aed5e92f7e486877229cb4ff2a4d0755029972323c0b51a14fd1e5\nA = 13fd3d7cc9d6d6821d2f2b1c40c8e070bfa85b994ee8f3e0baab544dc71328a1a57b7ee57392ab6d24bd85f9ea0f2a312148fc4f4b22c589e9a265d97e73c7a5b420bee180409ec179c438a67abf37eba61ac76197f3c9ea5edf2d4b8aab91e9bb1a432ef1f214c043664a51ceed1f2854880dd458ca253f09d6f6acafafec310774a672d07147b1\nB = -8c90ecd56d6c7cb129d1c9c26e94cf919c5747450542cab52281d11d8fbfcf9ea797b29588340d146cc40e77dce007b68c0c24356d4b75513b75eccbef6e22a5b88417cb6c516578d17d871e7d0957c09795f9a0f19b811db75d61c27e1827fa2773846857fec020f98444e307d3e52af501114b962ea705cb0cdf815109054abd00810dcc270d7bd3\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 57aef35a3f5388c810f576dbc30d4e4e5a39248b319b7766311157179d8bc1d7ef019cdd8c2c0175a8424abe7b33565afc0128724fa38f0900140b6f96bda2e78d7c803124cec8c2f2d6649afde4030c76cd33394fb386342d1ce97a4ecd180872134fd4e22667a687915bb4fda21f7e0bc9100ed8cd3a6668ed3a235d7b15a8\nA = -673bb11795d9d20a1e4ce8ae71d041705990463964505befce5949f895fa31c92d53f91fbc110df4e789b3f3f01f184c55df92927b8b680cc92864466ce5590ed2e98901cfb78b32ea79bf68b57a14cddb53209e08a7f430fee23f4a1475fd2640a515f8b609e98c760b4301747ecb61f1e6209b07455f1c8a7bb4e20c269e17937f39c6a2fb7b2990\nB = 46beea6005cf96a2acb16f37e357bc8975f4dad502fc3aefb4666344dde456c0ee7ea43ec493b6aecbc7aecc7d4cd107aa09e874ff564f5d59d7e12047b048c1da1faea36a7e2d02d0567bc4db41b54a75110626d13597db698fffd577a5810286ea8bf50625296ee8070419345fa269a354ca2eb47fa3108387f6a4b2c0ea3e779908a14469106eefc14\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5cdb7c451b2950c9d87638857407276959142958b06241b2010a9f93625f9106f065798f79ce5c534b9e5a31fbcbfc63cd200fc1cf10217096aa0194acb9043ccf7ced30d9f0bf66e0dfe27ee2ecc40bcd8de66fe2ed6f8cb0d874ff7b5fe71951412731fe4e19c34bee64c9312577b9e7b2ac08ed15aea753a6cd3e286192ec\nA = -1eee9d5d3854db52f9b43698e05d6a0f1d1f8df5f32884a775b25110309c46ec5c7e112eb64b2d7f948868bb9670068779b0a78bfc7e17860ee02692ec6790222b4384b9bd7db5abf29c46261c10d95f503b821a4694c45553e0dbaaa977892b916cb8990ac9ec29ab5c3d63ed77138fa1e95f395b3b233d039ab5daecb0296203166e9386d1071c61cb1\nB = -34587c2bf3473a2c5d7f3399d5ba2bb09be8105a0b9f3d8737d67b03d8b91b1c869f4e223d6246abd36d99d84052ae5894e58288a614a0da8d69f1aa57428632c2b059ba99315ea2f68ee210e65a741e94125ee4a723a7828bcc410aa2dae06ea8ed6cd23f66ccca7e85d2e071055787f230ee405e50d1519377cfe0cab4e5f97b6cb893b01134813a7c2c6c\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 95d0b209654de56bd7d6f74afaabed2cbb3247f449d80511d2d3c689f84c9b79587d78abdf0eb37f1b89f1f8dc8a83f7f9fac2c8cda1fd3fd64e16f5597b7f0a1df6da6db9e828ce7be0e876012bd52f5a74ca73ff8ca4611dd9f342bf77b485305ac28a1f8ac7538169f2bf3e4ff4dc5fdb9dedb97fa743fd8ac8791b8e288a\nA = 7821d4b65d529c30b8747e184e450cefb11b5ac5dc77905e6fcd3df64336661c82ea68d588ba616d23df485ff0658fb3376d5276027a40b392f47219edc5ecbf510cf0c5b431b02c65e5f432092f941d32ac5f71ce3496e403c7637f63a23b91e3326d01d2d32e99e0ab265108dc5e7919d3983839b3c7541848dbcd420a594e850e587f1846951852ed76d\nB = 1adf5c428f2a95c27a943637758d5dcd7ca36592fcb9d52ac0b7d27adddad5804e3edef257aa51c716801ad0c731e13c5dd000f11b5ff1b69c198f236695c1b2f99c0afffb5d084f80fdc534de3b0df4597404b50c7e784c3c55dfc9753c414d145eb0ca4d07e2f65b63f3eef8d391250a5500ef64d9bf963d7250d6906694e7670f92e3d5a7930f0f85964a21a\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 46914b197b84fa99addeaf55dd803182083a7ae34d6d4d3a55d6272af40a600563cc8d9f6b48110d0521b8b99751235bd5a340b1743497ef1cc459dccf5d6da970c4c3103c978ad2d513298f1fb3e68b24a9c7b0795f47d8f7f6ca9caaab9a9d80f15982599d764f8738217f9158517806fded5f3552fef8b7dcd2e725ee04d5\nA = 1c9f5f2a0d72806dcca92dac1450a50cba05b5dd571c2b3b988d33528d90ecc83444e3ea8df80802c30fbd5a6ec2ad9969be73aba6dd27e0dd2c842b95371d7547768916c0cb036964d041284cd323c8073095b2a8cb8797add5cd80f03595de9d18af8df7dee0d250ea7048faa47ae0131ba3f350d82864dc95e5829b88eeaf2681433dd4d58b2c6f70426af3\nB = -aa1e1b3cfd5ca0facc75e46d872584d55144620f849ab05931210b4e1526f12679bbd9cf00efdbd8863970e2abe8fc9fa7bbd21afa9e364e3c9e32f51fe66844fea4bab7f3b1bd278fd803f6bdbd0d296321e67751a0b894da338ab431871adf1514269ba05e0cea5558cd5691920fbc18237914f3dbe4b253f774e5dc1dc57023c080a3b90a004b809d237658ca1\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = ada55d93c533716ebd8c16e23603071950aa714deb942ebbf77206753d2676a7aaf61673c03a4db69d67faf6273828594d85e3c8cbf38460fa2af603fe9c1b6ce104854e7281757b26589f079da80685aec153fc5fd1a223004cdf30247f8398b8e92899857dd199d5d5c32412bedbf9d55f20e52895fc1dbd04c84cabfe1264\nA = -7d22392a8da1966e6cc5ef50d7409c614f8c8f8e5791778f68a00b4a056d0002707933043d05e48347bbd4d0dc1b6ca32a1aa4bab9992e7e620263283eb68d97af13b90a29c1b7dce39ec0b8a63878e8d65aebfb3bff4e67129e3b3725f999f1ec9ae92007911f2cdf738499661c5b6c9bf27712d0f29e871b17318e95c3d14b2e472cf9e466bea91fb71a493b2d\nB = 40279eefe59f954aa8c51c9c214fa07707b1d095f697ca40edb820401a45c472d1d7bb413eeddb64c14ce6144b4863fe9337ae4ae8698db92facacd6a56f3b33129c5b608eafa29e9d92dea620113051b926b80b75f320d7ca3d2ab597168c68774e68c47670458f5ef2ffd4604f20bffcc7817eb09c9057fd9989a6786a7e067ebe6724a89e7d1580f94ee4ed502cd4\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4dcae9def5467526b0ff071003e56f5537852cc0bde9d86eaed2c15e36e6429c68c061e12d321bad12e29626b5013c28f118ee59624ae2f35d2c53bfd89e6afdb6db79f0321ad5c55cab03e6a1a97ff7bd58c760d0e9fd7507de987ed2f94f9c79569fe7f03652cd53c67ebc6bd3c9e6c5672891a9d2ee11b300ed3b19753c0f\nA = -127f5ca6924851faa2340c4c8f425b1dcf41b313c5c2910e5eff8ef2faaeaa43305de2b3a65a75fe54c00fb30c0ce3e8007db1ea222521190ff1de6d0cf2e777ed61ce8211dc167bf115a77890d0bd1ca786e967a04f077c89939ce484bbb1c560f669aacf7756a4338d97cbd7f09a376d2dfd4d632bb451f52c03c05762f050ebbf112f8dc5acdd9b631292fd7073b\nB = -3bc5e9c352c46449a9155b7ce5478c771293599cd2dda58a962010f1f21d094aa6bee03f9311545e8dc6213f6aa73c08b55bcdf4d1d84fecb9eda35c83eae5fedee75b2d15a003f8a82b2b788ea19f7460fdd8f447d973c950b3b250a3022c19ff312ccdc86b6ab50c4ba627b15968c8a66d306bbdae8e88fe28c1853fdfb3fde92353f46b5bc448ae42306a4c91202f03d\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 62a812e35f46e04b3afa7d26c8fd4eb168b6b64cdc839ebd0a46bf2a3a712af8e97380cdf0bfa8a274f7b73e887bb4cc73c6104a176d425aaf5352f14ee51ba549a6926bd8d059b8e3826b174385d4635b0c36df75a4e7da44c34e51eb82322b34ae00e8c712eb75b3882822bce5a2f2f5fd74355319ebe1973284c690bed2af\nA = 71c57b08127a956f0c17fd3c639bd1923ba19bfdb83c0cb9dd78e62b8fe4b7e0019cd0a6b73a334c622118f96fd6d91c1e06d4dcef8a3d0d6bf8f5beb6389226c50d14d3947ce9f24f7e0e6a7befad2e4e92dc9ed8fbb9811d908c03ac074b2a5c67b67831a350c4d548ac70810bb5617d261a045e53cdc48117b9fe86d35950d0a181b73c8cfd35edd31af031178523b\nB = 1cda2a51a707f8c4d2cbff6337c3f63519705614c26a489b545b1faf366b705af1d953701b568a684856fd3186c035f878788f7e5db", - "ea16b5e7b6e767cf611452a4272abf2a9c5e72b7251a1ebea5098c60cc5bf649cb70980b97d48580967ffe2913309b6b78cc12d91025ae403928851902dcdaaa60f5b323a1302a5ce114cbe174e3eb3c2fb5eafc44076396c23d53b028d\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a9213cd809d41b6bbfc2123bb84860788ce22d5b91f8e24fb616efc286a218ae9652b42912a58bf8ce596a1b48e4c72f27e52c36be1940f7d2138eb895ee36bbb917a59f73e0b6c3266bf4759ffe2ffaee3f6179492658e0778bb43c4df4bfa1a46300c9da496033142ae2c1e33333fd7e82c5a14686b255e224c51aecc2a590\nA = 1cf4e2d5924510a5fd06ff4eeb94a740e430613277149993004b8de1a2b96ada54b05365f305e896df5fdffd3d7bcb54f9a9dba9689e5ad498012f7a684d083c31d7017aaaee720bbd42382e526a35d2add21d9369f7faa41dbcfe3dae426948a402635771a977e19d5c353ec7c1abd279975f2effc0b7bc19990154b723f2f8c29e606581ab9d3966702f68d8bb8065e9d8\nB = -cdab60f9b8e1add4c54427b638ec5f76b30654d3649b500f833b2943bf6cd5d8647549657a8ff999eaffe413ed87e06267b97bfc1b77637b57f29039235548a7569fe6d4bb16ae9c6cfd38c0b8c73aa60797d0d69b03d5a98314f7f7ee25df8b896ecdfc782cf8057f038b6c3e79c99df52f839fd4eff302ddd1256e51eb31cee24585782a0439da3db2eee79a58f889d8847fe2\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4dde3d63aeeee47441a7e733bcccbd4f2e495ca3c746468e9855177f7672d5d82e51da8e268ac24e8971d802e25d842a16a6b8d76b8e46a7724108c02d38a4830453408ca5ced7093676a1db4bf4c94b9b7a9531ab7c26f8de520bafe4431a55a5f5d8c7576427a0f5bf2081b998b82da2e8e959f2ec4d5141b55e40bf6ddeef\nA = -5770ea0a75ff451fc2c86d428f2569884b2c88cb6d9d407cc22b191849d389f57a5765b83adcea21c350b37bc6d750d4859f547da22ea8a3698a5cb6154b946331ae2ca18e7eaace951dcd49405bf8d8a716f7762eb242b8bf5e4c53a662c906c3be89e53ddf7a706ee2406c7d0ac17b54ff259c1bd5a092325938832763ac4caf0232e80a016cd1994441808d8db7e546de3f\nB = 7e4246ad4af268695a51912053ab6628969af4fcaf7f1e97dd977984a1604e8c9fe6b920f39a764c27d89f75986a4bbc122f92ccd1860f24677cf346474fd9441f572f769daf834e6a00cbc027e15d6aa7ec2030becad41e1068740cde82abed768de7e2cfd325848f6063e2186faa76982b9ca73ef22434a28bd2e3a5ac477af50f258140bff938d3fa02fb904a8ee0ef3c1f6fed7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 3d8bde8d0625fc46dec46fc657c49c8ab12a988cec4ec1c24e6f4d8ff94514c8d8fee4a08399c6bd23fb6464a38bb5f249591456c283325e343cc289c85df0ff2c1707a6e407ff7a24383b66ab603b75e2dc3835ffe9274eafea148f20764b8ca30cbe483c1cefd51f82dfb93d7793b3ec19a57f2ba03d884f345bcc3188fe28\nA = -1680dd51d8be6069c86ae157922d55df3b58ee6f53738677bcf7332d6e7ef304ecc7ff7c5a5e1f525459d77202f3e815c68f17f9a6bf358654a92f9f9acb252ed8e9e6a849da7491f26d0e33900541ab67ce966d042607258b4382b8108729a703b429babc34496528f198a7e0f814db80fad4900fbccdfb64908febf5e09805d3a3049c0f164f0bcdaaa9bbb06df8f05309be83c\nB = -2c6c6b3c89f6e1d1cdd9abd1a9706e4f642a25738aebbc97cbd60e1f4ad79b419dd54bd14f2bd147b1d8e9bfcf92faccee61a43dbd1a2c084bf06a2ca476b3d169fa2c99794fc827b7f4dd010c0534e7cdd03d00456033ae0203b78a7ed229afcec2d1cb96892eb18898bf53584dde56b4316b3bc5186d97e3a9edcd059d7fe14561eefe4881beb8519c1cb7c3ba22cd2e13d874aab77e\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5b4fbf0445807c8feec7efa3c2bf8dd86b1070638f3c87f1e173ee980412a28847b263a266506e70381aae919ae05d306d3a67a6c1e72c8ccf1c27d6296526e87f0f436c98fd1391f83440b58fadd4fb1905a484bfe8f516661e7176a268660387fe6a7266ef02e5fad91ffa69247bb11cfc1b5c3a88c76b7923a26f8a31ece4\nA = 65fe4d55bfcbba2bbfbdae831aef3dc8c8746e1d04cea174c1d336974d81d026f562225b4a297b1c3b044ccc5dc9c830a805a399bf26c0369b52ab0dd2c0ad19e723fcf9f5de2990ebe5a1266653195a2aefd9a392fd3da8c22c523a362f195babbbf5329018e3b454221b3e77cd0dee79f612f86332b1d104aeae7d8d84ad06b107715bb76bce20220d1340ecfc666b2bfce812814\nB = 12f775dbabf1c112523feab443f6e95d773e8220d66fd87bb7fc702588136a048e17ab6845a9c784dca275cfa445d007e8d8383740b156df7048650f89c5ef1a84148488fc405898f9e326cb8052f626c8881abeb70f3a0f52dd83e3ae0cb82d178cbfe8c393449caa2a87e7c8e2901a87e276b49b6d012f3cbb65641add3694fed3e3177777e78fe375f3a3b378091bb8d2998286562faef\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4f0af7cb0c4e82d0e6589b24b55528818bf2164d41f58505a2b302a8f677df146f8077945dad3790c323e19b37e3379eb95de8abdadfbe4417f8bf8da643768a622ad4898513fdbc72d3b1d2791ec9ff40634678faf0e17d6e0851f08c39405907db85b74937ac403a9a3a1004013c7bd95a585728010689fcaf63b2031bc8c0\nA = 156dcadeca94985ea8bc0d1378daf1e85ecc4c7f8b6d6c7a5cb9f9ac368a97c07e381004023bc575691c082b5e9e13a02fe813a55e76196e4ad4b0f9b1e089bb71a0d5c94254b66e3e645fea25d69bbc5af266e730482a60105306d664f0ddecbd76d54e7235979aa2d806b809b3468078b5d90aa22cbd2c441198d4a52f6259972cf3d02003dc39dafdf3581638e56d08c5181d36e9e4\nB = -9a54586072d093939ad86df11fcd3337ad7e9e478dcbefb2b89d7555883fe8565abcd5b0a9c88ab135ce5327b2a326db645bc7c0e3ce24f902544675ff9d946abf30302f123aeed0f4e28edc72758ffa760277caaf4817a3ae8615784c81896d2404e2cf47c06b09085cd0ad1ec46cfc1f04d0272eac29e774b30f19939d08c036b185983c93ba15d1d27aebe4a357b9f6a298acca3940d2730\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 7c3ac09486a6fb518b98a9bc8a8b382bf2293e2c1154470ff7961212430fe2dd28697e49256b1ad8add082ee27b6ecc016b120e971665be801b720069d30c0a8c6ea4795613017e8883e5c0d0e68f982c328379d7a0afb7825c553e087b33e9d78f90e0b95a6597076b8ec2c1d375e2143bb778c318ca0680a64072cf9a4fc08\nA = -71d8e7ef13d63b4f417c01ec1241020a8ff4c9b2db531500984fd3e45d22b2bd581894c8a248ed7cc345e70a5698407df8f0e4ac71ed2c0d42122a4f92279346f463aed899253206786928a0eb7c37f2e51e1cde7f97cf9288d85c3ed7f49e62af0bf9abf062d2c6544d83b9d3438b3881e0d07b1fa0f2a4446fd43ab3b4f81fa2cdaff199c87965e298943c68cc15f2f3f3225efad68b73\nB = 64d52de221f102af62ab1e9526935b005c81658f8fefa019bc58e641023fa785798ed0dff8f7f999dbcc2ecfa47d5314ac6676c82170d6f2b18122c17c1e1ec1b9b54e333a184a46ad35b2150c8165f0de19a24b98327715e5a641c1b6d3ff9d247c89c8749e775e6fcf5f967c6eb5e73523d4f1ec12db7321b14398f26201a364e1371f0ac922781ee252c6d2b3c657ef259ab73cb7992a370598\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = cd08b388ffd41d0aa29a3dbde74106c57b18d325be8f446a2d9ae95fa4144037dbd41eccd50fa34096984cb11bce555c117c5568d76a8f79d308ce11043fe2413d37d6aa60c366af6c1da93d525e4b2d79fc82c0a53ed62fbf72c919db8a3ae11f5ff8057d7501f5f6dfc9ae461c308d21919d0de9e31b759d1d8e3526fee58\nA = -12e58708c30c93383cfe6e99ee3c5caf1900a7e610605706e77d8f428fd59db2884f5021d7a382cb18b75ed22528961cf43be1c700c581ceac3877e83eabd860583e6e94f3f2989c179ee5047c82b53d37054c9cb7ae08be60a91b10d49510e9f0b90ddf89f93790c3e18cccad5a9d223c605a6c567550e2b4950e184fd97dd68bf30681d3f9c585365de2cadf36a43f5a5305dae555396dd50\nB = -26ea5079ba7ed137a14d00d413d6f818e911cc183c88764de4d91d7a9b4cc7af3fad703142dc7905992eb8bf489f6d8231bdb25603ddf3c31fda8bd9bc4d78835f9ddc1e6445037f05125cb1ccd92eea2e927297e5eb915d5d965a25e5d58feb8d79a890e6036c80ee91e7469d9eb672d7a8db68905d06f5981fc40bf486575a067d35cf14ceee3ccb79b72871bf8f52b92e4910ab17e5e59ab3ae6f9\nM = ", - "b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 34714506322dccb91308c403c267f1ec75f80faf3cc4272dff4a84c13eb1e6133af6681387006c61e7e087046b64e7ae74eea8a3c0564a7c1f381e1c940d92b2c766fffdaa7318d07dbeb877943a73b50517b49e5117778b8a60212284fb92f29a9f5304f8f537e88acf8afaf01fdf64773f988cfa9551d6884baa70587ab76a\nA = 638b7c549ed14256956bad532945ef9e11a50313172965386635a2fc7db79deb0cb5c157e9854117c17f1509d505d01a0e138d2e510dfcca45b4f7ec968b5214a6699b61b8ac68adf64d5394f50d577a154c013612090e2045462160d1f552592197d7da78e03491ae284dc9faf643805f2674af8652bae93ff230fc3eaa833dc62781e5f74d0f0b90290d51d481b0a94ae6e972197c6e84ad7ae\nB = 141f62297ee88ad527fd1e0e09d9ab5dd80e17b32f34a674a27b00d719839701664ccca1b00da2613396cf633b0bdc4482ad3a0c3e209eaea7c22f33706ae44155f527c9ca4e341e651760d1c39f65d5e99e649d013730d2502b6b65adb8a73e6bc734b7d879b430798dcd53fa6c0badd57896cb566d9f1e0a7b3a9161e9808e762ca819330ce9319dbe7f49bd663a9f57ac53d65c6851dc7bc4ee66e08f\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 7adf54c77eaea2a1743bc5011ace45b7651846e77f90402297f117d8b1c0377f93f49e92a2457f3d3debec3022a96c74c166d01b2279553ef518ec0e612bd7b382529184640c55b89255b2679da9cf370913351592de39f804f1724de36db90c045fa644e8ff20627f67d6afd4546f00d7af093f668629f9a06c07fab5654ac8\nA = 19c491d5b55aa25f2e18cfb7fda18ed4b020e3f63244eb9f6c4dfa86eb8a70875cc898e305a7acdd3eee081300edb3e4c837940bbc1927f5ed9f651e46581639e133515457464e9c451390828e5e7e00a688daaea74620363706cb69e02717489ba9ad05774c424c18e295278caf4df4ced80b4cbd20cd631df43f2e16ec0334564d9dc03dfbc7111e4252504fb449d5a25cb13630b7c0c565a82ea9\nB = -c3f765349639beb80f888d9c8b7b335ab46b55064ce2a88180c80ad280c6b7314df52b7e73095dfd82896e24604854a48121353aa1de663eff07882771803010005905896357cd5a56a59f0db0045f1aa2c0b5626e132c169abc64b9893f95932f54c1d8cc25f215a9ef6e4cfdd6dba85f6faefeca81793b2258ae1d1427e81e458482aab87f6563abf435be69a05b195d1eda90146a8cc92748ca6f798b10\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 32ba5fc81a7747c3d812cf036bc0edc49f08824d53b91a65a6d41edfb1651d99c11ccb4c074d7f04e652276ae3fdc8d6eedb72c6e46cbb1f7f4070dc9d179ce3e21a3826f7dd2c27943a8d26b192d7f5c4aee9ba0647e406133e3e89c262d37cf468aa3ab8c5dd1b8900dd06cd600abc6d372d9408497d9e20c86a9a6a4ad9d1\nA = -73958019a5a52357b9c1d954c9b14f51ddaced32a4d7b7c95730697cf90029564118ea168d23a54381f7bbd6718a6b662e4c87410e48ac53b7767148582b0bd6a3d35f488e7fcf2b128e0a58b5d468dedabde4d624f4a82e808dd7b175af0d3658c6df1ac0da6495bc9a8dc012f8de55c2003da9b2d478e1a089fab776d99026684026968fc309dae46a6ef2412039a8207c3084f96b4e38e4fa01d131\nB = 4330fdf00bc6d13ffc267073b68aea7419ebef257d63f8f244accb9ee46edd04fe5481292de69d377ba6b6304804ba7ec0a063b42339e6e37867261b9945ec705d3a0029c6f499420e02a773476546993b3c5e1efc2417f51afcec7145a9c2625496865c11636e285d4c8b053ffe66887333c51a712fe9c8ea57606103fd689dc88f1fe37dbc33ae4e92067c5bf51b53e2f8205164c800e5abd677c73949b00ef\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 69b850a99b471003a56931f7856da357a2254ac50ed81dfae019c9b722b95af16047a0d5422cf7ab66ccd898e85caf0e03e74cc8a5a413661e5da483b3f0363e63a7031bb30626c8f73d6e99e290071094b7fe5bbaf4d303192e59acb5e53fc7cdee78576b51595d9f7a25ccf3c7f8889de68b9deec167778ca27ac9d4c71c3e\nA = -1976b3bbbf92acbfddbc05b5d9e7b62a7666b239c1e6270db7ec6dc2929bad1024e745b897840853d14cd815aabb01aed580e1cc66ce37f9d1cc4c9bef8ddd35d28285faa29f2003d2a4623ead7d73302ea9f380f16b3fc06b7c2b8bb4ce4c8b03bfb6056a61c620e4decc6048cdda5e2d3ed8a13b779b8829e2bbab91e9f6b0304b1c08bf8fd85e0f3cd7ee72255e5342e077ababdbb545d7f809bdf8145\nB = -2cab554f7a5d21c499a1025f61e6c81ab0fc68a874bf60470cfac57425a451365be62c380ddd31f6e202f29769e2b6106868da7c81522e03fa6f0704522a5f8bfadbd007bac65595e149f6c585d7fc022db016bab32819049e7547bf85d4232a7fe19084907c528e7eb0434f2e5a375ad9b7d463821bef2f6a721a635252576c176ba42519bfa5d97d0e47facb4426aea0d755507dac81ccf1537b1003ddbb0727f6\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 2ce33adf34f2249f8a2d2e073976cb4c78b71414e027657fcefd56fceb022a06c1969dfafd519eb9e2542662c7647102f5c528734dd005fca666be57b46234123bc3db286cfce07bcbb399eb6764daf2b9aafbc2898a5ff43ddfae849c7549289640edc4ab7c4b9fcf5e159623e5497f509ad6f0270a41fd864c9437302ce380\nA = 509f5d5b160e923b4fdd72f4d522a713d780daa4bfd10ddbd62b26497a2e7925c495afc2abf0ecfcb7980e588f96c4078bde51c7b2c19d86d15bbdad5de72fec2e0a284dd693ce0902b40e54af87ac5a5df38ae6d1d882ea6299fbe6910121ebfebd06b454ec5f855bf3e7cd544a4b0d9a764428662e824e2a6185723534f5e6ad829734347d240c48c2c0f8bd6be6ae8a495a9e383fbc7402a4096b8c2c214\nB = 1a3b7f55307031609afc974857a6cc75821e73a1a9535bd6b8e141437c3fd4a6871c904e22c5d9289df7525ac69a0341d3620bcfc5f04b38ae540e26beadbce0002a8a8bfd0f6a270007e4c52aec2fab11fb2a831b9886997256e4b7e7ad3b0ec64c0f31fb0d637869143712291f5073a5756466d7c82c31e08e09683478229bccdedc2cabb7e426af9025185d8dd5124e08afa4e981236180e0a390004adb7918de6ba\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a81fcf9a18ce476a839c896cc5d9b639fb1d74610e2f618c25310147b57cd77806c2aab90be7be4ed10f0122baf9b862b141ee8e4be5e0c23ea776267f14c31e50b119bdd33f2b41f6a4c43d35bf6f095864593e0d8c0f1fd4656d8371af844d197308bbff14e5a28b7181eb6e6a2b31ead7361e287f3b4550ab0484bf7baaac\nA = 19f1ce60ca50bfdf8e02313f1c9a45496720a2ce467f1e8bdedbb32525d762878b61476989c7f6ae8dd29c983ea596e521bd4cbf74dba4d505dd9ea5df423474fa9725d5b65f1575d26ead95725e2a59a6c8a5397ebd6b54123e42bca44781b84c014b8e5d2c1a86cf34d764b242baaad5be285cec72ba8ace808058a0226c04f95eb2b53a828d0ac41e6b40e5a4c4092788d9f7e988752f175f075d545f421205\nB = -b115a1101d97664759538d22154de4b000c008e551e2ab10ad05f12274b10a4cbfee762d232df5188fa1161f37ba61d146e8b95fa715d98e016da8beb0600de65216cecf8b8816f6e7e73e2a2bfa7d0bac74b517b906bbc43357fca69de9cb5507bd95205515b97b3a4d6842f3d7b09606cce1c7436c462f49dd05e915d04ab6fe2748ccaf025bd5d19749cc468d228ba43452ccc479c146ac6d781717bb9966bf3835dec\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 1473f092540ae30de595666beb33e430cbec42d7a28d4f7982e62f58025cdb617cfc33f1e5ab93d2ebefd7345561b81271bdc50bfbb0db6381dc0ea023ff7c72605da26dc7da2b5664d2ad7967426ca97b3745f82528964bb68e70087e14dcf2d71d30fa0d1f7b3f10b19b357e7053fdf22bccc5188c6919eff1e5c402b750a4\nA = -68f280cecc512d51ae534f30aa198cf7b170c346c1159fa9cf158d0127d43e50a8d4704ec54b8b4295dd7f51c6771cb5767fe0c975414cbe6d2bb58ae66a095e8832d5f443498b1ade1f5bf249da58595ebd878677b34e3b4c99ba6124e2b71d86a8d99727a16746469de51b0a61d9d981459a6cebe206cd36a09f00ffce7f532e2c31999847ba000b9e01a4b84f454544b6362a5c093b9abe9d583716f4534f2de4\nB = 5b79684387f18d7de6eec3a63d737490dc2a46c0616ec16388dca2be60adcda11ae13063ede3fec177171a51dbef430f8c4b3f6d297b9d6c020fc44e3ffab891d0d751d033fda813861bc067c181118dc613335ce89c5960f952e5fd28bc72c41b7b6e374ec29b837f1e00271cab646c794579d315260921dbc3b984b86d98b8f8816aca4f16de506", - "57e4102f34d9e29ec3a03e0da06e70f69952339bf2ec4a7e74daca82239\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5e4b3f4aea7115d592bde9bf7c6594fee77372ffb19f7745b4de878a4024f81e8290c77d2915424df20004a7abb64c214104a3123e7c8f230c159ccb99bd937521b433dcfb065b186a685fc40f9166bad9380a02e297ffd6a307ce8d2c8f2f1330447a9c06c327b74f3cfc2e98f3351a8b385bae855941228969d1c29e9da3e4\nA = -11c1d396693139df5bd91825c119d1241c3f57b7ce95b46472dd82081738cdeb0868d18eb7c8ee7808016b3311f982adebd5a2e5f4e201ec4a34f3037d260fe580e771222de5a1a67947a4552cc03c5c59f9e60e25063a702ad3c3aa43f061a22567f938a91f1dd697c3e3978fa11ab1d65030bf327f8049bda745658bdd4ba8f3e34b060c6a2c6c5a8be54c7cb5f6b106f54a37d2be9f674f7747744d4350b3acdf373\nB = -25a65b6acda692ba3330d70dbc3ea4dfe208c0df358c50b7872245a909c5ac19ec568b1a1340e1a094f5b8e7d1e3b7e04bb4df002558aefd4540135d62d75bd5ce959128c1300b9d98429d7369610866d98b22c345e531f2beb80b042b6ad48da077043401a82e223e9e529e7407bfa466dd2680973006d047d837c26a60cabc36a7ef538f603ba19f8e923f168ebfc3834df8f77a559c9e0342e33df245f551bb242e5a66e5904\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 47872b544fa0425981ae17bb450ea346135e6ed7a9de0572ae14a6e85e8319f27cfab778cdd8cb5f93b417d9c66ae0fb7bcc6652620f7f3f74acc2bc9f2c090129fa8315aeec9ca7adc5356484474ee803883ba4695d7bc47c87eec508d16a15150cf3f757c4713de71366e958d6af045b2d282b6ce96976692c80b1e0b6f846\nA = 7e8f55c040862f12d8cc6e506608eeca65ce38e9e8ab18ef7007e3cf0f1c9a0696795bd10f8e1e1f55bb4f4f3a35c2e0ad18289e250571ccc26a961f730346efb1e29fb143ed97cf72deaab19834fa2e98e9c12ae4cd23b9c5ecef4a04c439f7d42e110b30caedc4334372ca24cfe4171ef1430528f7b57bbc823fd606fbd30915c5817e6c57c967c4c404a0847b1455da17effeebbec3f9357358e00001239aae209228f\nB = 1cc00b95f6bd3abfa697400c98110725a7e109aa9b8cbbe9ae16327c4fc8e5bc93afc7a94da32e98e85e4fd5eb545192c73007d97a4e84ba64fe187ef61d17f0941e165c9fe64c7b8054e24dad30f92b50d1f526b4bb031e6b1b9058be24884b170a145212273c51692b71bc57ee53176d8702b975bb6ba96284b462da2ce38e12d86b342c7f4d3cd489fbce88a309c7df1121d7bbbaab6814cd1e54953e5cc46813ead98f02360372\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5d193b085e57c3f1e825cf3b36c8bdc936c603136bb782a244b04a79fa713dc7b08436b85ca3b483d2e100a012d6430679b30c8e4101c8f08ca0f9010dc0f27fb37be842054dfdd99362e03a7f55ae58db7b47f694bd35d91a58975ae1f255c41617e773f91c2640f768bc702a213f073682dc761e056b34c57edd85585fe04\nA = 1bb1c759ea94b61a1721ef5680f42af30fa31444b27591a03b7c9bf5b90845ab965339f463a78bddedcd62fa21197c32d6850c61bae195f86e1c7a23e7a20dc618c59ce3a1c6ea6306c0b01b11a36d0fadf8214c36a133d689438021ce7c78b20c85256ec607360cce14f139513d9f3ea6eab067b1ffd0935d7c43419b93ecfadf2c5a902b7c39a69bdc023173bdad574adc77706c1a666d66f69578a5bffdc7cd6eee28ad8a\nB = -e8072c49cea603d48f20276df188fd2fb28f8721d578220cef7db1e56379c04a6b372e56a047cbe59ea84ad026adc5d0aa930011db63bf4959f15781e060e0240dfac0e2a2c26be12a21e5650d12140bb49a2a8e0f6a86e4b1eb79d9b8aab3202bfd339096529170cfe3e0c18263128686bd9305e92a3c43e1523f97d8a6a2707773e3d441da162a79089c9ea1e094cd5a23474121188013c8c287965a5e77599f6a7d64174b06cc165e\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = aa79c899c2b9518857c9e4f96523a44607c3f6a97d1f40d6474ec79deb2feadd955fe92d789df4d362c828084559fab56b5e33a971abc5449208d31671c7e220c5945886e33ed1d804c059a8e439a92524a785076f9730732bc5a152aeffb5b9ecf3a7e4b55983016355c4c29827496fd4d7e6532c270cb9ef263573e4c63074\nA = -41b326c2b86e7ac14a2050bff67bb5bf9697f02594789c4a2b3e8455df4522546278d0620f28a680f6a88ab545de5829305485422f4e70a5ebf0ad15508dfe3f16ac556436d8fe8a8cde83ead549d88e0bb24dee52ebbb49159ae71589d918d3fac8011cfc3afad613ea09173856b7b79b55a2e43e0f7cd21eb9122d5f6a1fc5408414f5aafcff863b870c67b740256d317a0c58af9a81d8025a086a1f3d79f7408d4bfa06b9dc\nB = 4730f03c389f9bdd92fd864177e06140c9dcc02d01fe7d37b51d44de140696f116d11bb67adf7db797edeb7c304386a7f5e37bfac46a5462a6d4c49b1bc034c2e0dfa56f14bbd2a4bfaf86bbad4f6d0dfa13c782fe680847d4b43373d7137f5c2ebe4ad58c695a7d4c407bfd888ce04abaaec60a3fd33db10eaba6b6acf0e16cb61d1beb9212c2b07921bfb5595ef1eb389200b356eafe8b5288d8f0e2cf252b38301de65190d56bfadf57f\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 23f9850dccd2af799f18268c3a2918a69019513c55268faf2477c50677fce277d8ce58a0cc06dfe389170faf5f0ae13ffc4954c746eebae66efc14eaef2c2ac9001f3c7ef7e32fdc31dd725b6a8093e33daa6d19808908e0c2d3e7c1c58e0fe9ed92f4d7cf3cc222393ca4f95feab5d34fe29116410a1882dff7cd92acb87590\nA = -10a75953e5fb9903411869a2949f8f04144d6e2d61f95704ff55a02f40c4f283add405353a68bf7d6acc1b8cce738f0c6f9271a538b4c688dbeface58eef0a0a1d491a9e66958750db97bd01466edfd245cef03bb6a3acb81acc63c38538e7f15deefd15afc422a8641c357c31a069258dc0ebb63f06094ed8fe7d4d420246b40302361967c81f0a9ca542fd1de01967514ff2565de7ae3b4a200d63feaa22fb99a251cad66624df4\nB = -351242b6e6d0122f7120deb8357c3bcf25d221a15f83579883bfb4dc2e6099e6b7b95fd08f6e573d93354b0676f7bc9fad563d6eb0f3567ef43efe3d874b9c7733e4fe1ef491043e1f80aab6094cc9b9c236570972233ea74e8779a6eecda23a65d08d878850cab6005159265893dc0f66920a12c26dfb421ec326a1ac09e9ab8085825c31aba488af02cd51f96b205c50e692dbf2d844ff0a989c3ba9f1c2bc7f2e7dd9458a72d310eb28d490\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 69c7fa326630d7de69249807cd8bc55c9315acac26fed3caa3c8a9c6b51ee96a7dd0b3bacd5cc13c15f199e268c5eb91d1ec36c085f83b437b9906caa6e39ed7bf09778610b621426cc8d36d96f541d0bfcc7693525d33e0c2ecd77ccfe80289a11155b37c7ea7791b5c2be3f9b954e230c19d746575afe9a1a3a9677d23c5bb\nA = 7cb78ca8e5d903096630744c85975719c16333e2e44931956d8c45b001d35ed4e184dec88c9e2167d2f338fe6f25540a144cc419590a4ac7caedea3bbbc565365d3357baa62fdccef2c5ea616614e0bff60e81916eb4abde0c9725b1bf6869e8b1e11f6d0d08fd712bc68003e55ed462ad4946f7f982e663f65d45c07c659d9620d5139d2b3332a68d33aec36e21716a3b75f44272a19f860e6ab3864f06def9a5ddeed340ac0733353\nB = 16d5b074e008fdd30e73ea95cb5fb87de806319388b3a44f33c94d38be0e6f1a92103dbdfb3d23b6e1d19bdb29ac14833003e9482cb7524d0d7b4c377f4911e3372f2cea6f84c938d84e3994e80f0d68e7e385ca29e02f70294c921dce7cd3829c5854ce51d1f4fcf7dba910b51b48a3f53cb1f187182435f21f6981cf8440f9c8287a9749c92c0304cc2bc91eef32d8e6526be802de8aa16684e8854cb0b67d9f7ea00f6f0145d14e3c251f70881\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 72192604b2f3f68b9ed3e261120ea52b06a05869f6abd21828ce8abadb3a71c360a14947bc738e5d1d530b9636d796f785bb44508477eefa80c4b77d4e8e35463e15ea2a48c682d3288c5abeb66181e4bed7d5b4e0db20fdf5ed68513aa5ae7e0978ec1c4646368f206636ec90e808817bd1d03acf9adb9ba57dc153873fec11\nA = 1112d291463b28ef45e879412e6607a3e20d50dba5044e71883bb3cdfe9bc694a577fd7d896dfb836a171f3a4d8fd025d3a979b43e41baafaf7b535d9050e47f4880828640e952435648960bbb74a3c25dd90bccb3fedd254dfc0f031d0e8a468e93bb69f771ed35f1653cffea1a763491fdf6efa21aefc287cb611f5ea0085f64cc3705c784f87ce00846901833d01a3c45ce047d822ba390b538f0a24720", - "155409f60ca0d90e13991aa1\nB = -d553fa2dff0265cd9d083ad097af87a99af3d8d93a9f4c07440a28a427082004ae5c81d22bda1dd2429f540de8df175c1b4d0d50f0227489ba570b28baa35055df951d05b584ae6b051a135d7eb2a501b2441f82c135a8ec0eb81d379b96ef8f2fd526ee62293bcb934c76ef8083727a4b28bbfc9f515ebcc2bb7ed9594a106e137ce94e9105b2e2f4776aa9c6abdf426a181181fece3251c3ef4f8eecb634e6bd47c5878663fd51c74a66b92713fb7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 459e19faf105ab17ff794927aff86196b3cc3461e69cada53ab8c8c81e2b1820408421ea1af6ae10257e8cd9dc16386906410761fed62cf9ddcf0da2a92800d99563fbb9cb1ab0ba46a17cb9dee3f2b68992c2b832a5932e4533fbd5c4487d870f3fb5d7a1c358f4aef02993360915a9e9cfde234df5f51c761d84568400b618\nA = -7a964c62e38e4124cd2bad727138dd12a086a2bf01c095b078ce2f81288d3c8435ccce0c8e00229184091130989434bcd107a3a0787a2f5f4b0e8c23b1cee9a8f39ea279fb6081efb6c3df1704fae9e87d63ac6eac4c6687b3551ab7ddac5ca0541e12047d04c2fc760fda0916cd2b585a90d25880fcc1bde8f0a1a413969938d42e8b3b5f73118798e85b901c2e15860e29e2ee8b1c95336b97dc10a21f5300e0352adb60b40a8a99333380\nB = 743ff4d91ea3e0f9c4f72e5daecb4fb00b15b86e30bacebbe4384324523d14e22abe29b00573733f594d652a88d98c987f8db08b27b4dc68577784fde02dd410ebdbfaad9e9afc6a22a8cbb13a780222bd212fc61e38faf409e940fba35ed909e6938e83b0fdf5b5e3ce138604823e788efc3aa0df924554fb70fd2faf8249e17a827c5d85942005b328bed97e5ea1f1810219d77f2fe121ce66518e37c84d64aebda3c397684212384deebd520a776b95\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 183950095d9424b0ed09985aafbbd2e5d64bf541a56b68b42ea8cf9b2c051615ee7bb6c0687ca6fb0036888fbc927cb7aeb303750871442ff2c0087a95f4efad568f48b03bd2b9a9ac26af8c259a3fa97cd2af7e3d8f36148c26785489cda6c00a21e7eca219d1f41b2e82ba8e2c1cd752eb08a2fd50c6f9077f3096e2eba05e\nA = -1d2fc778cf44c6992d1f3a056860eeb12f969358cadb087dcaebf5f96bec42bc0aa98672260adf1732da057e9e0d22081e33f5fa71f248cf89dd361036ad58692637cdfff584a191279f178242ec0ad397efc52e99462f496caa0f3133c4238aaa877fa7094662f080eb284c4cbeb992a368c2d157ac5c8c9160c167716406190fa39ce0abcdac52c8020969b87a4f84bc09a51f7b2ca288c93b1aac64e19623a7d9e69976a31074f637e4c82aa\nB = -2f188f1245b75cd21d052ec76edeb5881944a143fee31c67370fab0420a748f3f1957bb8332ffefdeabd0ca806169629f130c86c99bab490a9668fd8200f4a9b1704c589e75b5c8c855f133d50b2ce06191875e2872b36c78438d6032d53004c047f49e4cb81e19fa84da16d053e6cbc7c8eec0b9129a8831eba690e0542ca3fefd204258624e92844c8b7bcdccab986475a47c8b22e89079ea6580ef8f496099cc24dc2911dcb1921d1451e2163b55bbb7db\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a02c38d5df9ff7055ff84122342ccdf6ed7f7d54fe8227af091371f5ae62844645586adaae99c11f4ccd828103a81471bac72dc20625962e41d603e760591bb3569a21f45bf062b86b5fd1c617a4769a4d767a0ee14d104084c12ae875316a8f2be7adec0104381dc02c20b5851efdf7d4bef0d68076975e0ada3e58e101e8b4\nA = 5daf37d616da184acb278a75fda4e4fa49e544eadcf373c054b203a309ba198233f2285a1b55dc92e05d0213b26c82e261d8383a845813077b2e1b5f4553400f09410987c8dd21d4383e0f05747d0482d1a89f160a5220b22c78393873564fc5b1e4d5627ef3d4a05612709f301381df35606e99560fba07a917d7ea7413110fb5a8290e114d5200cfecb00b6c53b2ee29911bcb2fb2930eadba0ab9dfaf46443370307d9c3b61a329f0b8b8cbe7d\nB = 1d9539fdb1afabeb9be6e774dc7c7cc4bb4fd63af7abb557a5fc80a3fd23a4600de3c7fae89b91f3d441b61d3e24b2fd3d7803cd71620e7313917b4afb89ef5171a3d8a68c3c74aa3dfc8058d555eac429dfb6db40a9e0c25aacd2050418d6f32bf21cbb76981269dcd5883178d4b69a931a0338b93022a2ed0f78f3d8877989cc406f19d6d082ea344309318c56be7946412ea0867c78418ec32b9fa3a61017c10939c9345021133116933a3d1eb86a3ef16424\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5fca287abf1f487e0ec18c230860eed4a2e550228b1500b1e33bcd6675646b5afe505b55073129f22352dc2b113c584ea1b98808214b6916933e90e036b129b61657cdea9026e1fa087ee300e055ae8f94ffca933a2d70453ed220468a5a3cf1a65d81eca11cf570d7d038722397f487af60531f24a5f069671354882c8bd2c1\nA = 1d9fe15171dce97475f4ad329fc8fb5469fb2b8086e4b01eddb6ceffe5324cfbd28d791705848569739b6758ca7e7d7d49adf0c11d891b0a5879ca870d1ca5ff475513322ff218cd26024f97623bb8a53084594e1fd64154e1db702522883fcf4c0d677a7fe90096fc76dc3800816996308d8f0be2dbf3b879f8a000c0ac534511437e2ce2d7ebcf42fd1698a829eb846b3afa581c24d5bf97abc6e247f110f4e872a2474e3acca6c8c0d518104c3375\nB = -dc0da8f7adb8e9f7b0e3f293cf623528dc8e9668317910417e52301c50c62e7d30e77ec7e38d6817d1f5a93e851f8560f642f23a0b9f836812d27b1b41c0867088a3108332b8711047560052ea30c8840f03a25c65b227a175d8f340095823788adb5bdf2b7ebb801e20f6b6435e154f78d17b8fc4373aecee56ec7b8f5686a7d22c8571797fde85cec884d45ddc4b1f2cc47ebf56a879bf286f349a0edfb531168b733d43de3b86b49eacb10b06a432c96c63440b\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 6222c1a14c6390d73944cead58eae5e7a6c19d19e4563c36cf624f5b61d99991bed7dbf6a0723abc56469eedfb1f7982987c2c7af6191178cf0933ed5f191b8117c9d726cdfa8b82a2fb25ca5436023f5860aff5fd482c611f134569ae87395dd99e5e9d400b5ab1e3064210ded096411654518110ea45899f4be2516e35a229\nA = -7f6766be6c6ca9bd1fd7ea1f80bfe68693f7ee4b5ba2946846839060d6028eabbb9079a165c1a07eb6a01239f3f14095225b8617753a1cc3d9c1e69b516d8705cfda396f4f0d05b0944a0f08b478d261e968c06918914ba87c8e7b7adef5cc2a875917d00585571542af219bd726e502b7f3f0bdf0cb1dfc6796be2e22e8ffb5b8bfac7e15e991022974e75d3a5eba214ab8a1aab2fcfcdbc6ded2abf834d1899d2e3ff94bad9c696aece045212531773f\nB = 49c6f869745983cae44d33cb7ba141234905441ca53172abd1a2dd8bfeeac4b236605cd2dc5b04ff9aa13de84872145b935b85479136065d2d57fd15fbd97480c25c6354636c17ffbca33c9319d65e82523e39fab49321380a130fc160857a451a69b1d0509d5718a9cff8b49c2d677c1f66bf77333d2511f58d3eb2fb47b3c162cc9be8b012d8df70278f0e21123a69724a1f126369a236d54da026ebe222c513f24b577707b5ab4b90ab0e22b4e38ceb4181d4ca101\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 9e9cc8c5342dc6d6daf55fc9aa9f79ec18592e8b9724a66881c379245c91f06a7df50a6ba0964603a6dac97e77a55d06efff17c93d5faf107fe65788d0f56483915f6ea0f1ccbda7656eb58fc032b5771600beafdc12c2076110a9b9670bd0754ff6a72c5d6e1a9e4e42c688e1cc96d7aecd815bdf5dcb16fcd1be1275ce7282\nA = -11635fe16dafce21efb1c599305e9a16eb5651187cbf054cd9d911c13e8eafbb738013e212f9c2b3662ea15ac9bd82b5751d43a38e4475d2310945a812262309094ae9cf59e0e9f3d02c92d8ab01f5733a20f051054a240bcbe3a7b6bb3f7c434229f631c4af239d33bd3ce30a372a480fdb49b2716091d26071aef372b8bd8ee8eb7f2965a372a836000b3737d2a833a39230e721e4844e16031ad69cd45ced60a64510c1248fd776611934d8d2a913d965e\nB = -3bb2cde9d3fda96fd7e6b24645f8e00b43affb223f2b5c3f4b7cfee905ddd6703a9d6c01f1f099ad1174da215a645ca4707d8156e762e2a253d7cfddd05ca19823ada9d33924013f677cfe4d86bde025391e0aaf91c6b776a9cf8a09dcad7cea59ee7aea1cf5f5bfe67c9d4456332d1f98e5310db9a0230381e1867a8f75b8757283f911f1a5e0d4afe5d544afa8d86637f9c9d87428fdcf8b4eb8f477e617960948253b24565b2f23081c47e211cd3c788a92732a49077f\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 30dc89bad4b449d1df9ea9b8f9d40b323c7", - "1d7e1133bc44d33bdb87c38cddedf83bb849e83436e4c92a06546fcf3e24ce6cc89d2e97a48aff2c7e3703da1b167a112f662a89742355e11e131e41052f1b379753cfa32cb0efa3a07465a258c585cd68c86bc9a473f5262c86c50992aeccbb9725b69ea8b3a7ebd2b6a24db52dc\nA = 60463fae1e9354559160d55a453c12d75775a53d1606d1fd16bef7e4ad1c78f9568954112f9280c46781180951534c5372dd5aaff3f33ac9c2e0ce4934d7009aad2ab5d6a5e5a141a36846e8925c7a28d116c68fb78aa9a687ec9bef173c1b69e0d7261f96eacacf237e1fe5874e5d553985b0fe7692ce8f2a5feab9ad9a2ad9c4bbf050b73b8030ebc36b94af8c6ecb67f8c94607d80cf600efd4ce4aa006f9b1832da8a1fdf8a564be0b4369149e8639e1714\nB = 15bfc50290b771ad147695a4c6701c47f2e8aec0657a4ef999eb45685200981b0ab5f8abc143d64878b85e9548651a1afd0913e3b14d11d3a26ab9793596801662a67b0062fdc8888feb029266f71d170518b6a4a040f59996bd4f257f221e830d0faaa9688aaa6afbc1f9b40d25097eab9d71d80aabc085f3a07e48bcfb37119aa00de60be55fd07d5b1281adf7b98bb589cdf2026252edf2f075ee176e23afa6b1f924c9fcf3c34c76752e833278a2e6b62017b88b77eece5\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8b506c9bfb75ab7ab420ae6c9b371ef035fab512188d9df76f0b31831573b44cb08266186a04d20cc761d61b6df3e33ecb86c269205c2c79ae6aa4d3ebacac8ec71d9bce1d7ab146530b131c9038041c6ce8152a6f1c09b9bec8eea4462dda0f08d75edf296eacbcefd62a0c197ed30f799343268bf6edfee4995958db7e0420\nA = 11c16713fbf8bc9696782cb5a88174cddbe68a04e8fe93dd074aab33dcd85f92baa178b2f3b8817be0cecb802cfd3ebb06734c9d399a1f090e3a8a2110aebbba0e920427bcda74bf11700b945985bd532286d44a1a615cf7c501412e454edd647f8371cb8149474557a0d47cbb782f460de7a3cc28991491ea0fc510286711b882987b09341c079565414f2c930e7c3c3a3e3e0f1d786260a7f45c70e0fa20dfc63849906af61707cfdf5a9b7a4291a1c1586d16b8\nB = -cf5638af39c6da3757a09a92e0bd54f852742682dc91c71dcdc6e72f7825a0979a1ead2e158479ce5565d22472dc3853e6bf7ba43296a5e0e0a355f0703cecc02ec79da83e3e9de10a6eccb858dedf7d4c400c27486a5b8cb34d787cde6a5fd271e83a6cf66057838fe30db1f30663cdfc22ef5d002b0b5a05831228ea200f95382a58d0d8aba36523d9b5cb7506f193131916f3ab66ac9552c26cd0c2ab1c449eaeb8fde752f4f3c3f9b060cc1f8a1e37c4fe5ec306674b66158\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 347706abeb168205cef9b0b8c6b9d6449ac501af7dfbdfbd41a20a6a47872cbd7d4cd32f7b0805ecf1573d534418b7cce98181e079d5061b02639fdf0161cea5314dbbb2ef39ec841f695281f3c7de45f33664e0dd1658f645adc1dd225f781a3fb1634517c556403587b2aecd56dceca9ec19b930cead2b1d303aa056d28bc7\nA = -5e1c869e5dbcc684c245d5c69093bfeaadf388cbf928d33a8ae2148a2b5145937e4f654c5f6a36de1124bad1de8bcc9067fe1f9a44fc6ffe55ce7ed5cd0dbb6337b0e1e96bac1eb2a3606dd97b0bdb975ea59448be50191cc7ea36481ca9fc85c1c3e1c97378dbcd6b355622046888df2ab3d18d805f4d31d464f62a8e630e955beeeb5e00c70242b8f8df708705abbeb95dea3561756298b5f3f7fe16e965294eeeea4546f5e8bacf9d6b4f2136d2e206a87dad1f47\nB = 70225f0cadd328be36ece2172c836405db3fe80ef99ec74fca25406b73a537adf5073f2b550abfc4c0fcc2c2850dace0da9a266768cb4d5ff7fc6c1c248ad74f47592101b61ef96c1302924381abbd96cf49f50c44bf7e0551721a8ae85abdf9925548d13b8c5d1a27be8a40d0f43eec3136bc3035057b75aea779b4262cc66e6bc68da93c218f1920979291105d4b02117d66deb92c3e511aa588b27130202acc9f69521957f79c7e731bbd5461552b9b6b24240dd71ac449be9777\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a2cb238f326d47f95869e2dcb295eba819a443dcc7c2785461389b58327742702f4c86e47af129f1fd4611cda93631f9333c358a29121d58286333083d13e66f30a9533b77ba3e26089e7eff7baf19bef8054af4e24735525908864ea9c4756b42a69c897003cab7b63cfd9a5927ed562e29845308eb2a55e7f8f03c87a5b7ce\nA = -1aa7ae6f56c38b654b281525b9da953ef366c2b9cffd3042105ed428dc7e5f2f2d53ef90b468bb471753606cc7a3775d86bcd2f4d5119cdde3c487cd39bf31752c5ba297e529c1b8121487e0e1de702156d0166ccaf51888a24fe7b48624eefaec855e2200929c21858676ec9bf4ceed0a832b69efd5065af544e49a3d209b85a77b0953652cbf0aa897527c52c9a98de9ae4c827f762e251478c88d410123625ea52b3478b52f6b9987d42009ae427763357ab53195772\nB = -226630b6fcdb5e274a25066ae2ca2c803549dbb935a97c0d7f6ab2c971d74cf6acd265c9d6815a6b2dd23dcb3c23b390fe8b1bed92b8c64c76c0ce62d5e7ddd7ce445bab0ca905dcfd0f128e5f4ffe966f3903d7ff1c61fe174e373cfe35a6d83249ec40b4a354d46fa1c90682efe468e895ea3da710838c262e8a47752dc6e7a79fe20051f51180173b58e0aa37b22eb8efee5b6dc264459ce4d135f430cb15afbf8c53f0de894bd2aca1f7ea32b4209a22a075f7b3b18e86f778a9e47\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 9ea62ef634\nA = 55cc58c9d8\nB = 6b49179821\nM = f753311ac9\n\nModMul = e9ab3a2aa60edd30108\nA = 5134a36c2bad180dd5bf\nB = 2ba6485656d041690666\nM = 9b9cc4409e86c8b0fbbf\n\nModMul = 621f9b797e866028b7bd1ff828bf29\nA = a202338dffe171c99434d84f3\nB = fb71eee7045b3e3ab5dd809dd\nM = b3e6e8d53b7249df670e3c59c55d33\n\nModMul = 808d463d06b7b7f98e3cb2783e2196c349d62672\nA = c669426a92d3cb5b316e2b5b9\nB = ccaea3874008dcc92450d8b2f\nM = b04dd2bb325baed1940cd000e8cb2d786009ccd5\n\nModMul = 872164b92b9426b237858c4cdafe1694f96b0e0e4c19e894a0\nA = c3255cb24a813e27c3dc410f0\nB = b144f39e7c2d33605ba7bee16\nM = f3639f4dfb782f3107eb402fabb5fc878903acb5e02e129077\n\nModMul = 6124d7d171\nA = 235b938139\nB = 3a56a22a28\nM = 83eb4af4e5\n\nModMul = 9c006f56095d442ba98c\nA = 207e14237c42e3764e5e\nB = 8a495a26872432fa8e33\nM = d0cf2b8ae5c67d6736b9\n\nModMul = 97387cfaef652932a230c82de59cac\nA = 82ae0fc5e943af5bb8c4adebb\nB = db1279be12d59ba3a9c036a61\nM = aa36dc1d13390169cd54d711eb511b\n\nModMul = 32ee73c98da657464c6fed4274df20b099689e00\nA = 9baf08248ee24bcb17714e420\nB = a7f0428147bfe098666180749\nM = ce0bc198331c9ed1d21f0d498326e8185d3d602d\n\nModMul = a8b3fc0b53df3b92753edecd6fbcc5f4840dad3a44da704e34\nA = b36249e259b303e453757721c\nB = f0c1db50670d92abd93bdc84b\nM = b05cf978bf2dc7e093d7d164e46d547219c480382df32b33d9\n\nModMul = 2663b741ff\nA = 58c8e7f7f6\nB = c84681fc87\nM = e0a50dcb45\n\nModMul = 21af3c0b42328f41b81e\nA = 1f79f5b5bf78c9700d\nB = 5bd1734ba0f0e59c2a25\nM = 9ff3fdfb5c089244f327\n\nModMul = cbc280b5106c2c36cb31ad7e7c986c\nA = cadf6482b769e83ce7f7277dd\nB = f9862a06da1a9c89547b76c61\nM = cc36144c88139ce921d2fd1740bc4b\n\nModMul = 3813f2fabe016e19fd8e70687ff473651a5fbb4b\nA = 9c51a5bacb5d9f055a9ac2962\nB = bfed5625b21b4e82d1f105a0b\nM = a47977acad7c5deeb683ccd265cb30cb193f22a9\n\nModMul = 76ff291a02715fc87ebfb3e99153c04e53358dbd7beae43478\nA = 997c4a7b537d9500d73a205a4\nB = c679ce666af284a459ae5a26e\nM = d0d0fd4922953941acad8beb65c00603b19eb44fb8ca51e3c9\n\nModMul = 1a90c92fdb\nA = 94fa7bb475\nB = 564b0a3339\nM = a1501bdc75\n\nModMul = 5e7ae5470686bad7996a\nA = c725797912c6c5f30d94\nB = 3a7f4c99ee3f5fa9582c\nM = cc50c8b7408f09a74973\n\nModMul = 72a15b13bcd1b63747342a6be8f0f2\nA = c33357af48a2df569e3c11ce6\nB = a4b4c5c14d7796adab54b6cae\nM = e22a0fdca62a37f4c8a61c96a429b9\n\nModMul = 31e179bfbf65b0695dde36a4fb72d131830dcdd6\nA = ce8d3adab8cbf15c332c0b289\nB = 9333f94eeb7d7a86b82becc51\nM = a532a76bd5cff409b580d54d12ef75ad8179b381\n\nModMul = 8f4b8a585415adff3a7bc35fa88891ba31e4a82672c664fb14\nA = 9a2b56a54bd0727ab4be57ff2\nB = edf1781b4296567990773005a\nM = c5a7c3b97ba00d6f174a019c6d37eda52036c528f351bef0f1\n\nModMul = 917bcdb402\nA = 55c7dbd314\nB = 997b29ef79\nM = af5b4cbd0f\n\nModMul = 660c4bb2b771f523a4fd\nA = 43fe52461d5139620a11\nB = 1f8ec4b67de1db54ddda\nM = d0458e215b7e6903d96f\n\nModMul = 7aeff02c143e4426fcbcf32bd1277b\nA = a2671586369a990dde7829f36\nB = c7ff67937c900daccc0ab1d8c\nM = 8ad9c1d4d3cce681d1ae27c27982df\n\nModMul = 4b153d57433f0f7276674d3484e9bd0d25227d07\nA = aea36cf51dd2ce06c66b7a407\nB = 80c9fe5bb0afd2bf8b3644f96\nM = 8cc22a67ed7e5a7a2322aaa09ec2be94998494f9\n\nModMul = 7f8447dd983b113f04c6288f9539e53a2e9cddbca8b2fefcc0\nA = f67636b03821c8f13f21217a5\nB = 8473a29f4ae33f", - "36a0d2c6dc0\nM = b829af37b557c3ddbb5257c8b19144b90708a45a274d6655f5\n\nModMul = 17fe4644a2\nA = 912611576f\nB = 7a10d36b80\nM = c5fa605133\n\nModMul = 8159b23d4fd697b4fd35\nA = be2d646e76494439e60\nB = 60fa770d05ebc69772b2\nM = a6e7c940cd749925a85b\n\nModMul = 7c412dad5c9fff91357bf181caf2bf\nA = 80f476ed5acae75b34ed54c52\nB = fb818e2bdab3b5f4bd84db3d0\nM = d0339f7ee41337d8462d1a9c207d1d\n\nModMul = 70432c749da4ade2c38237545ebfe6c4c6a92f6b\nA = ee9c92de52210e61adaa6eb4a\nB = 8ab55a85b1abab62d33e75fe3\nM = cd3faa6de4cb62fece4c3f94492d457834a6a041\n\nModMul = 9fef1c18778a8691c5e71c0b5208e82778e9bfb632da0b7e28\nA = bd162c90bed25e84dd5b6b77c\nB = d887ee03020c5df356f091db6\nM = a2c2d45fe9decd93a0ca3edab8fee46d27ba23fad9b5294d5f\n\nModMul = 958951bd0f\nA = 12bd0d3375\nB = 668bb65b4e\nM = 9c617dfaad\n\nModMul = 8a109ebc9cbf86613e43\nA = a3e7019f1bbc35689a77\nB = 3189ecd3fd4ffd0229ef\nM = ddadc50600dff2abc1af\n\nModMul = 2b4d9f85a398c852b3a0cc82524619\nA = c244fd157267f707319ba6c6d\nB = 8a07018a748992429bbdbf326\nM = bf3813fb54f749ea5627f59ce30e07\n\nModMul = 28cab7d574e6dc56a6a622f8a7523cbb8dcc5e0f\nA = c9909dcfd3a59a3cfa538b267\nB = 8bbf89cd5a4e24adc2d8c646b\nM = c8f02682b9d480ea98faaca53b747ced33ed0419\n\nModMul = 69b2dfb3f1d8dbb13e9e479f38edcc427d5968acb7751a226a\nA = 8019266c548982a520ab48eff\nB = d33c3e3b13576dcdb3ffaa796\nM = e6255103732475604df7c6f7ef7e6b49a8ef9e2b0c717925a1\n\nModMul = 3eaa4c99fd\nA = 6fc42faa85\nB = dd0b4e318e\nM = fd7f22301b\n\nModMul = 56b6b811ced3433755cb\nA = 145573d17cb0c996c69\nB = 9d3297d5ccc184896822\nM = dcfb3b383506239e83e1\n\nModMul = 34315b6bc6d3690c28060485ae331f\nA = b963a26973894cfb42fcb2d22\nB = e8523304bbcdff1a0ed4141bb\nM = d7a379aeac7d8cf94f19e7924d35d1\n\nModMul = 2ec9466e8b3357496f07e37ba24d36a237883846\nA = a75f3904e564997695b6707eb\nB = f9f47bd779834dc1f5fba0654\nM = b3ae5abed45d09c4dc5abcadc3ac9abebe1949ed\n\nModMul = 88b4d86b2c1e1bd780e8d2499c2221e05fab4f9b7047c2a044\nA = a38eceb9c551f0e69a544072c\nB = d5f8e7c2d534b2b8985bfd213\nM = ff81809b84fb8eed3508ad891d3d8208249d8a902a12d6acf7\n\nModMul = 172f2e2e22\nA = 1584ff1055\nB = 2e0aee014d\nM = b904cb0bc9\n\nModMul = 122c10d3200270b9eaa1\nA = 86fd189e62a6dc1e4ba0\nB = 5235635f7b0336f5f235\nM = c93da97d0e95fb63dc4d\n\nModMul = 3e461e10ac4eb749512097fbf76616\nA = cf4ce10cbca07164f3812f89c\nB = b7e4639c233fbb0f923fb5104\nM = 949647857e1406871593fad5c30101\n\nModMul = 88117b59d9fed79dd6aaf083ee938215a995a221\nA = 94c888795567d434123d441a7\nB = c60ca79e61a352e34e0f78bee\nM = d2553a7c5dccd639a3927697a2e1af03845f2f25\n\nModMul = bc5f0076a8c2f6cc8f4e61540d2d6f6d6b13b775b363dcd71c\nA = c170eaddca5295d6ec6272dc2\nB = f94a5685ced7661df2efbd34e\nM = fa6bc46aa05033af72aa42793e9174af2e3ba38992f33572fd\n\nModMul = 1110cdbe5b\nA = 5db02b38f3\nB = 3369537903\nM = a8863f7979\n\nModMul = 90fcc5f3a346d3d4ea4c\nA = b93373680ea0feeb31d8\nB = 37f9dfaf0e180be64bd5\nM = d595cc29237d1c19e2db\n\nModMul = 8623a9997e514cf3c1d06c33c14053\nA = b396f5ede6212f1fdfc7e7b77\nB = 81a1ddc18306f2d2e84030148\nM = a6be32a91b34857842255ef8b1aafd\n\nModMul = 63f8f0254df06356f5cab8941b77619ad58025ed\nA = 806b2627b08d987438f920bae\nB = 83297039f4aa8efc1a185fea3\nM = bb8a7e7c19be02c25cf5682a0eee655fcd5b69a5\n\nModMul = 697238dbe3d395e81f20c9fcc8db30c234a1f75f3b2bc27438\nA = 930b04224bc097ac1d8bae8be\nB = b79496a80e45212c4663e5b64\nM = 8ff7e19d967d317c255380411898d73e3786269f09079f19f1\n\nModMul = cd93b5b8b1\nA = 47a51b2d5a\nB = 86d6ba5155\nM = efb0ad3643\n\nModMul = 2037821ea789118bde0a\nA = a92215dcae19be637ff\nB = 93b9a3664a406737958f\nM = 9df360b69ed26f610253\n\nModMul = 3bf11785d28ceb668dc55b870faf7b\nA = bc8758854dc48e057cb6210de\nB = f03ca689620a77ecd8a6f0de3\nM = f3ff0747d6e5f34a0ba4200f579259\n\nModMul = 7b30b44f75ed12f54136858ce4fe77d00e0952cf\nA = 993cd09f3e46423a8ba2053df\nB = feabee384158032dd013dc08d\nM = cd0b21388cb2033b1e792ec4078334df70b6c8f9\n\nModMul = 8ce1e17972f1a9d2e9437d0c5219354728a5f31337808d7650\nA = 90e5d18b017118177ffb080da\nB = f8e7e09032574f6c66e623ec8\nM = da795e6ef63ff7dc4baef5c327022ccf65d44e3c4e24823f11\n\nModMul = 8fcd412054\nA = 2e7f9b1a\nB = 6283de2c9a\nM = 9bff560ae7\n\nModMul = 57d0d3b79f1e2f3632fc\nA = 2f8cc403de5af54cfa39\nB = 3b798c3ead52878dfb2f\nM = 805e6cbde400d4b4bc9b\n\nModMul = 23331614e88633af879201f568c359\nA = f21f19da4b20980979a645dac\nB = ea752050b79883dcd69222536\nM = aed3faf4c88f7c4afe257c5ed90599\n\nModMul = 56dcf9ae1c787e773774df3c8762babb4675a212\nA = 9accf901fa599da05fa6ab5ff\nB = f7f6b9b1d7bae06237532e39f\nM = b5bcd776bb2eb0805ade3c8b47e883962d3cbdf5\n\nModMul = 61d0ee0786963906a028a1df01f836841ab6d39d88ca2717c0\nA = 8e57680f213d088ff1a1e7db3\nB = afebecc9943b0093f87022940\nM = b6201f68a45265d7e9183c3255feb4c110c05dadbcb13881bb\n\nModMul = 143ae78a29\nA = 334abb952a\nB = 74203e7a50\nM = c9535a9505\n\nModMul = 897a2b57e69f5a1469ea\nA = 1ec8ca0ea4fed52bdbbf\nB = 3a6273cab05e478a57b8\nM = dcb33163a8ea42c1ae6d\n\nModMul = 4a2c10e90e2d37111db79a44d3e31b\nA = a90e7bbd63fc4af6de83029ee\nB = cf09c3dd50b41afc7045e057b\nM = 8ab85d47e4270116a64f97dc4f0f15\n\nModMul = 70f94276c9d85fd3f71edfaad6051456f754da85\nA = fa3e9ff6e1aa1fb78e51711cb\nB = b115ed197c50b7ec4040ca255\nM = ad63f69ef1346e7549ba71c13b24b279f53bc9bd\n\nModMul = 861e7ef401866f815b983ba18a612913ecc20a67016d79cfac\nA = fc41a9ce06e882942f751be7a\nB = 881c05a51d1ba8134d126a48e\nM = b12200b39526c33b70e8aa23ebc400dea0d4d8fe42be103d5f\n\nModMul = 4e0051898a\nA = 2a06523f70\nB = 651b5044f0\nM = 9da4eb09b5\n\nModMul = cc8274c88d6affc3742f\nA = 9ccf0133f9628532f4f6\nB = c1d80907057be7a67b01\nM = d6e76e362da831f32685\n\nModMul = 568f15bed5c4405be9dd04673a9c46\nA = dd6029c3196feb6da7f0f4a48\nB = a5f6745f2cb64913d1d3236d8\nM = f62f02c9b9ca8993e3be9a02b444bf\n\nModMul = a629452d5ed19df040eca26eaca37d82c0fb1d8f\nA = 963c51a9415b03e85ccb09f25\nB = b1cffe333afe44311cb968ffe\nM = ab2128698d498e8d75455033cfbbf4487535773f\n\nModMul = 814030123025d287aaa8b826792999d72f2d589e0c7f7f3dbf\nA = c3b33f391e78bee97ceddf313\nB = a9136f3af450fdeb245eff425\nM = b6aa9c517eaecb70781e597b907583bbb569e970d229235a35\n\nModMul = 8735bd486d\nA = 563e15c52a\nB = 31293264e1\nM = 92f4b193df\n\nModMul = a541f69ca163b288dd0e\nA = a608b48c1dcaa18424b2\nB = 891b0b296e911068b00c\nM = d4140921f4b2c84f1eb1\n\nModMul = adc1b7cf65967b013d046866b4ed9d\nA = e97941448f65060cf63ecd486\nB = ca68936f76cb87a8fbdd37311\nM = ebbca2482fb82eeca2866057cf1179\n\nModMul = 44aa9f0dd58d4510a7364e130698b34eda23a632\nA = c11f83f01bb964ffac93a2e30\nB = e05ee40eea39f4538d735193d\nM = b5e8b511738979dc740a6a1f7291cf4561787be7\n\nModMul = 8b16b82f064f471983c7154abc9f9ba355111bacb90400372a\nA = acff8da571e1c96810bf95707\nB = cdd23e5504cc26d0c34a62b06\nM = f38902a99190ae0b5ef26849a6e943d651925666fea271fee7\n\nModMul = 193f453197\nA = 8cb3078675\nB = a8fb003a87\nM = b60ff22f4b\n\nModMul = 849c26c8cf5cae426a80\nA = 5d1e3d2b4d038a0a34be\nB = 34f70325565bf0523314\nM = cbc189f9a732cad8f425\n\nModMul = 9a4e64ff530c53a4c6c5b6b5021920\nA = f53b81723cf74f520a61e614e\nB = 9d8ac2e6b839143fdd079a2ff\nM = a115375435151798f3644bede9d863\n\nModMul = aac303a4623e80158af1cb3331965cc8e3184edd\nA = cce0a88606ff962fdc37e72c9\nB = 9840a500a2051625c517104db\nM = b99dafdbd91ec3c05791031df5e193c03d6a441d\n\nModMul = a31401dfa761bbe82b66b5f094151865b18a4ba75bb9b3dedf\nA = e6f48c027284856aaf3b96425\nB = b4c326f72a6a22fd4b93ba5b3\nM = e57d9608ac6e5b129b2c014958bfc59137f63838b1ba88a4ab\n\nModMul = 8b0929adbf\nA = 61fdf77ac0\nB = 8892f05400\nM = f12b3766eb\n\nModMul = 91b57f353307b173679d\nA = 33f8e73752072b4b5cfa\nB = b4c730f79f4f2c07945d\nM = d41be1d8d2e5753e3ae9\n\nModMul = af04c564adfeb120bc4770bc8c650c\nA = af151333b3d4cd1d29fd801db\nB = 9ccaac44ff91be11b30bdcdd0\nM = e0bd6e70d5f5ce08fbbfd48d43101f\n\nModMul = 1b8d623796a5065d9e993a53a9587a0fdbea1bbd\nA = a2fd08df2d4eab0cd6d29e213\nB = 92c9d26ae7c215b52199ee28b\nM = cd529f4cfa46f3bd3e7fadf167fdc02f6f881da3\n\nModMul = 4a8573dd8dc50a4fa39f3579d3869745eb8c1153ca508deefd\nA = 855f941d085305725da617f5d\nB = 8f09b7d2c36e0340523da5421\nM = fd8caa05edeaa81beefa01957eed97a981ab34bdeb6d8c704b\n\nModMul = 2d278e089\nA = 59d20a1716\nB = 8e2a58bc75\nM = b3d61ef699\n\nModMul = 2f937ce359d0f6cedd1\nA = 1019d11d26040ffd5b1d\nB = 7cdb6252087423d43e08\nM = e8f537323004447e669f\n\nModMul = 6567332e25af83089f7458786ab0ca\nA = bf9565e9f8a098894447b58fb\nB = fc867626f268c24cc0ab7bf8b\nM = 930f39183353363dcd822933a438ef\n\nModMul = 3692e73ad1d91ddc19cad3808eba2c5fc88e2bf9\nA = d0a42ce512629f0ffd233a9aa\nB = 97f6d3c4c655c7353a62d6ac4\nM = eac2ea84851f880214b8f40f881a2", - "e56a6ba6f2d\n\nModMul = 81df390c9e51b30bd639db15adb464c7cb1d011cb5e260be58\nA = c237eb242c40960861c938c08\nB = ab2f481f0d768eebd90d2574b\nM = 8697d7a28a5f42c9a7b31949b8b568f861142f44fe66c6cd3f\n\nModMul = c952f9aef\nA = 81973bbcb3\nB = 28ddee3bf7\nM = c4a40993c9\n\nModMul = 241dd53d93f7bdbbb2ee\nA = 2136eda4495c45c9f96c\nB = e74c4baa8ca3f6b7cd5b\nM = fff4594e7a5f0a1d3e15\n\nModMul = 5f861ed8b0aa835761613e6c869cfd\nA = bfc5c1572086079f5f5d18d1b\nB = 95902e14923c8010b7e905178\nM = a819c6c109d623f9b845aa23712c9b\n\nModMul = 5b8ab089c4e4c6804e48a2bc1d218718b3a32598\nA = fbe65d3852224a812c432672a\nB = d57a3f38da966d2471d70a048\nM = b9e6a626d3ad026d14248fc90c882bedd64a1f13\n\nModMul = 761438baf5b02dc095b7040e082da7b167c2b9ace956284ed\nA = fd91701ed2151f8e994bf4ee1\nB = 88b66e735b76972bccd9db182\nM = 8008b2d1274456aa68dc627b1ec3e1762c6ed2d660c64a1a55\n\nModMul = cb743c97a1\nA = 9c69ca9b60\nB = 7488f48f5\nM = d67040ed0d\n\nModMul = 931b2bee1bc30725a31\nA = 650f567b544ce02303d4\nB = 5858da30dd1fae88a675\nM = 91ce30234bb29fb9e833\n\nModMul = 5b4f262cec958a20390b5e568ccdaf\nA = f7e240e8a077e8e87506db2f1\nB = f8653fe64e3bd414782f51634\nM = fdb8225eefc1620648737d31dfe1f7\n\nModMul = 4c011d1ddfa30c901793cc6ce74db47584cebbd1\nA = eda8e9a9ea3cdae17bd50b1b4\nB = 992e8ef4a45593e4ceff67876\nM = 95e2f120cfcefbada1058af6c8853cbebedd5763\n\nModMul = 6e99aa5b8107399848cf24fbd88ed6350efb68d737e505b466\nA = ca6c51ba2f410d09bf71d60fe\nB = 8bdfa8fe5ef3b2ad02bc63c4d\nM = 84daecf412b8c50ad6dfdb546c3eb783dcc6f32003eda914bb\n\nModMul = 536175913582e73c1002083cb0cfce5471d4193a5b717881e60abfe927c829d\nA = 9b474b6f7d7f11dfbeb7a0724694f2daf9ccbaf2ec13269b5ae3329e8df95f7833baa68324509dcddfb5afa1d14f2dafc55e2c225475f16fb396beecc7a66dee\nB = d74a5081f00af2361c3537642c06cd47aae7e366741c9b4785e185af8b328acf3e2ed71e3b9a4b6fd49d956eef76740b3c6ec5850a90e7e444dfeaa7214c5eca\nM = 5efaeebe212752b28b5441a5d0b2600190504467c6359e9ab26320ee72cffcb\n\nModMul = 6161cceee2b74e7965a926fdf5344ddf8cc41994d72154a8b6014c18cf71634\nA = e7d6b74a1af0834aaf93e09a6488340b661449ba2bbc73d775e7d828163813ddbcd82719351879a6d67ab6b518011e1db43a3d620d1f24403917691d15ed6f90\nB = 3ecc8fd3103fe52a7e73ec4be4e60b69584bd886a030f017b482bde9d4b0b964ba8471cb32b3e9bd49864d9028a22d6b6b46be0451bb4222c3987b74a509f8fc\nM = 7c3e3b8b1a6110da82674aaf88c288cef4cfddf22e7c9b75640fd67fa5fad59\n\nModMul = 2acd55bdcccd55882eff0bb262bb62f78bff8e932aefc9d32f54d5d4e9b8bd76\nA = c221d1f0d1b7efe7e078dd01bed773f8876fa324b3fe91985d47d343e7f3878b457dae2f9ae68971245278a1d23cb541c56b94dd9ac43a9fbe28a46efc627651\nB = 49f94c19ff7ce990637c3d2019ed66f7e6dbb1442b04a4593cc480521b991cb1b878f8c31903240f89e34336d9e6785433617e729b71adcbef622a683357e035\nM = 43760c71742e9cf22cae6fc262c008b7f1b97a78c8063957b74aa4cd370c1eeb\n\nModMul = 504c11e38284a30e3647c1ddfaed94503d833bcecdff05e749422ad1d9442540\nA = 3fbabe2d65f443e7db0a6f332330ecc4d1d40e14fcb510499552020405cafcf10a50a5ee47cf60fd8c22a22b3f753b4167c213851f32109babe4b5c298d6c4cf\nB = 62e5b0f887dcb1f1794bae7dad46a066f810cf5f82a1eea99207b5f0fb0ae9084c5e62cc97b2672b1cf4cc1400a19bdcb093c97404876b584a6482931e7ba9b7\nM = d79fab3eb31189268b2a0689cafdaa0826f07d432591e8aa8bd3c7cdce1470a7\n\nModMul = 13a6431c57ddf0ed3979412ba8454a0dd9a2694a0dd76453aae63366c46e41db\nA = 7e1fd0bd9ab0aa75b264475604aea09f24239f94847ce2549d43b71890c0549938d167adebc7890d3c492b5874da7bf18d895ccaf1803b9776820598928b407c\nB = 5e54e5185bc86f16177f1354a57d36ac2980def141b389e4bfda134fae7c158009ccc61ef66281905128b6297f876662104ead2315024f129c56eaa387f80b4d\nM = 182572149b860615dd853f37f7d51a35e85f5e4a4249a60fde58dc68e0dd7401\n\nModMul = 145a44566bd75103083b7556a822ea6008ed3a6a1bf135b68fcf87a294c09b4\nA = a195e4315caa8cc0707063c7359c28139d4dfffb57eb726156336e13227ad9766ea1fc99152893ebb194fecfc153d47cb927a633217328f05e4d8782aeb89d04\nB = a97ae97dc7e9a224cab94ecedc08d0cbf7a012dc5209b1e1e8b5b843fcf61e65db3457d6085545a633be47b742e8237cc716357ff5bce9b00e23671ec1d049a8\nM = 29b060ee2aef7e43e02163d279ce49259127198adf462d13aa195c7dccf573a1\n\nModMul = b00740cef7791692d45f5a7110f3eeb260638f19f87c9245436fc0422de90658\nA = e6b97c11ad44fd451d168d65d1691d2220db8c3b6c8436d59f4c1366aac52558d0d6b61f5d6966460a4a31085fac711e5a09af5563d938963555d4730982eb0\nB = 6805eab5a4da534f07def6d2c320a6cbdfe4831fc2163dfcef740607b3181d8647bfae8f8c16237c1c1c5d14b9e3417132f81b3a7db4b7fc11927aab30dca590\nM = f975a94fa62b4c0e68df5c3ac5917d18927c0a6d9cf39c26f6ed97a81cedf227\n\nModMul = dc04b6ba2eb1e34ea8942a50d1d0c5479dd22109895796ffdc9cd32b53d4764\nA = 7fd3310af09a67e0684dcd8e3b4b651c7c13c2f6a0a47b59a7f5cd8bd80854d1d4fe02eaa61843d6bb2b87f99d8ec4842864681eaf056538ffff610c231e1d\nB = 15f1661c59ee9f93400073e18a91503a93d47537d2da5cf5e4bc69ccc87b07bed171a95f1c5eaa9c7d7ab207ab3f1f7634c5d16e706969e869364207f61d84bf\nM = 22e2856f4c2b6c01448d4aef74aaaee3a14e9660b5b277200f2e67464ecadfab\n\nModMul = 19299c9e960ce15087e9fbd66f95cafe82546431b92d70db1de87c3425c1bef2\nA = 8e3abb1f24e1f91496db99be9409f57f67cfb6e0e33d603a2a31e1309f1d0bbdc413c3e4fbb5e3d923f683afa9942b9b9fad6a6e558b2297889fff47ccef7d23\nB = dbdf5940dcd68127d476badbd5a2f3018aa4d8db79f81337ddfcb108637110b934e946d3284ec09d5255605ad72424f1894238ee4f7964dffc27fad838532321\nM = ab6b4e3d3909512f5d1d62a30c1ab8dd5e584cadbce9dffd12fe203f8936ee93\n\nModMul = 4f88ad4e30e6e8e38cba0452d98d4a3547c680f16308692e33e5577772658764\nA = 5137697bf48982edd869e4a42f3cb858bf65ad5b25d1c0e8b75d054460d0944ecb5a6924721c5728964d84231c7ae808f556837aefb23fe3ad36aec9f5f60f20\nB = c79554304620f8116b9a8bb56f6a23620e9fd504f7163f732e1e6367d25c6ff98cb01d16faf3e018dec6a067d1204a6aa95470598ce757bcfbc3ab4f5d8ec88\nM = 9ba20dd78923d8ef82897ac46a509cf22c9b7986a4facf42e5416bfe3576a735\n\nModMul = 985a4d2a7431e09fcad03e6a3f926582dbc0aedc588f17aa5db40c2d3566233\nA = 908bff40440aaeee6c90b6312dc017c3bdae884a9074e02b26f01be1f018390e01f0d111f99a06c16e20538df8000d4066cd4bb3628da88a3a5cc240cfac719f\nB = 6ebfe9fe53909876784f9d6e5dcca4cfa9463fbd8426c5bb8890ae84c2fad119615fe1e1f2ee5fa544a5ac713ed1da8c1e04f282f1f1b9fba4b4c4bd9db20538\nM = c66842e0a11ed6ad1e8f192ea97f5f244536cfc5234c7fdae1ff905123c72793\n\nModMul = 133d7b31537b627da2c042217cd28625437c28c3e06258427d9a4384046a1f4\nA = afb695e3e40347f60a500e01fba4df1c1f2fd4ed79e3f65913d82369f79d80db6b3978e6351c70c148f572b9c0c2b1efeefa605251b3156d9b66d240467e550f\nB = 8855046dcf50f80f278227d5260b9be53ca2e4a1cfe1afce4d35b11d0fa17a36a8bee8126e13bbb318d476becad5a935e9d160fa481e1437b292bdc169dc7d45\nM = 3eae4f0d6c7e1fb9de1a4c160404a8767783c7f839fe27a543f5c389c679d47\n\nModMul = 7f4576a315bad5c7fbb1616e8b26c5b34ca6f701b9b1adf0485fec181c41dee9\nA = bc2baf0153a4598f6b5f488c43b2546cadfaca2c1931b919f98ba71835a8fe78886da1fea25b194e60ed6f9e0ad23c988b64af9278155c1722dcf4983a1566c2\nB = d8374d91fd3c523ecdd6bdd265c9a8958dd222f9f0e25454fd683bd86d7900a273b56f1f47e033c46527e32c721094ce6bc927d25fac05d7fa6db4d7a6773c94\nM = 9975d8e7f2a4d9d1ff8d442b93ff269a83fee43a18bbfa8c2ccd7ca5fac3a8d3\n\nModMul = 57ebfb39605d4fa6ef5fd03bd8e4fd685664297c29b7ad75a40b133e15fc5ae9\nA = efed8e442154b1eb6c75775cc23e01fa65c9c361e222da123d07daad3039f305e7102edff23b65c333f0caae4f7929857c3169f4ae47c9f0fd920c38eb42bf2f\nB = db05415ea90269a74b0919ff772c148c0eeb2ff9dea76a6e73e82eb86bc76fb42308b55ef83a769a91d23b7840d5d2f5129f15279dfab7cd8d63778acf202f26\nM = 7704390c4b1da86d51ff817003e5451d601a5352296e339e5da219ec5a330479\n\nModMul = 40b6b0d44cf8a5ca7f4fd03dd6e1e2a11f74f3911dcd8727e57db8d65cd490d\nA = 6500f3cf686eec4e1f243616ac0ea8e8d11ddbade490b86baf231e7b2fd55968ee14b6bb7badf8c898874099831976af46bcbfbfaea10d49aa803c6e51238e2\nB = 1fac744fa1e26e789639e049679d0e2eb57336279f09555e10210e7143199a3df5fbf5294edc386ac762fa3a3b0b4bc28945adf21a8af747a29018bf76d3710a\nM = 5c0781a87b84ecb4362b09c623d511de53c085671dd4f08e9a551685b55ddfd1\n\nModMul = 6b778ae9822221e6a8376379e0032d7edb14d7b5e32a7310897b54d1d5626113\nA = c4a5737a9496129a136753f8c2e52bbd2660f2d3fafe4ed702900b01c14e506d13e3bbeab19b357e5ba9fce8a4fc3dcc469406a16248d6fb53862781fd9d55e4\nB = 444e5a673eeb37fd3b4f6b6f5133b0f46c2ea532e1953da4a0e144407a8e2534c5ff40cc9af7756e5aff9df57d938fcedaffb868dcf4e458b36f506ed7fe0ce5\nM = 7f5978c0c066132a9bdcb00727bb802b72777b9e8e4265f76b80cfdc3a788817\n\nModMul = 5c717e5dd25abe60f761d6f9326ed056416add4c1384682d87b7ff12e112f855\nA = 4351965a421c75c5b4c251861e53316a300ed7983e27e17f9308420f0d2cb11e9c476294fcd9042a525bc1a044bb442d1d9f853c", - "9e07245170e0e2711010cd1c\nB = 4e1046647c362c8f9c414be54075b4e9d151c6fa0c3da40d90e6042625947ca2c9f20cfbcfdab8666dac5a15f6cda9d47b09f654131fc5addc07e382c9639323\nM = a6c789884c66c7f028099e0367b3ed86871277bf070c541ee12fc02fcb6181d7\n\nModMul = 4452688244f542125168853f1d444f96ab0f82903bb12a97e59f0db633edfd6\nA = 9fd1cc81981bff977244c044146918057ad06d3cc26edfb8fb4118ee02b959d45555f9507ffeb23c3688e29ccdfe5f583fa3761f6727573542bee8ab5f5b600d\nB = 856e6a03b5c93fc19deea51b3bfe42c810c5bcf9ffbd08e2625eb209baf6a4e24943a3c090d89c1f70aea9f0128e511fe92e03715d917168c1e1ca77a3a8731f\nM = 2c245d407a78903ef2b279ddbe32106e6333b6f44cabf87b8641b047c79ea06b\n\nModMul = 375f8474ee47df6b9a038512002e56cddd374d69c69719d8d369232c64a839e2\nA = add40f1dd6d4a2414b17f0c628eed9a8f082f3ad1f34ec41935fa86b34d4505b22ea80c062386a9ed63f95c67e55c686f837bddf8f4da791f98b08c02f32d4b2\nB = dab1caaa11d5a208b7a6b7a1d6482a4859daaba5e3a77b1b1020e8ae62a664953dfddd0b47d40526e7a3c6a5363c6d41dd9f529fd8b58d5d31bb67e745cb71b3\nM = 4f506313a4f49873a405f2e5a6e9cfae9cd5e9f67b5ef900153366570e28a955\n\nModMul = 36fb0733a26902f0f8f11625305a3c94fcdfffe294eb6ccba110aa628a314df\nA = 52ee1498bd6a1677db801ae2eab4951345a1fcf8fe7d38e3f28dbc27fae508d87c9958e02a375ff4891b88ee916b96331e7cc082615faa028f6d541b5ce37876\nB = 9343cfa074f50c20e8472f8f7c4a7d330aa30ee417ed8027a4c956e84cc5cb31d5411c14796d9325fceef79a51b5d8a4c89182ca273ab633e6a7b22a27352300\nM = 9d7c334aa33634f9f313b71b42476a3b627a6c5bb8ac1d07a8d732d5c087bd9\n\nModMul = 4a377267508eb045e00cea66a417112dac07545304bbeac6315625275b7cbfad\nA = 19616a82b75b08499d4b1f869df2db8f71398672f3f97ffc6177a4a5aa913605ce8a6ab5f778cac508f0b3f2aa680b01ccdc57c0fdd6cd678a2ff2dcd7f01f3c\nB = a5643a9a9fe3be4134082daae4ee7dfd85d9452beee856fd939d3be9788b6bebcf3571c67ec481ff9b20f70d23e82e2171b1d0ddf0a9435b40115d32aedb6811\nM = ea0477e7f1a02cb6c21171066f3dab69d4e24429043b0f049de660fc80e51937\n\nModMul = 7952dfdb91252658430e365adeefd9093740de92cfc9dd3d92294f2dab6ca0b6\nA = 8e6cd7639b7c134b53e6ae6ac5f51268da83ed09e8e96d65e4bb130dcdbbab9e48226ddba6efe93faa510bde8ee92f2a641774c4272b5a2f88024b77a2cfa110\nB = fe4e8109a49b16b96871e384564cc096277dad4e1bbca8e5feb33f140a4fb800c8f3096b1bc7042bccf249aede88e6055c0db609f94e214b1251eda494be724b\nM = aa46853682af960824140c35d145a6dcff6283b2c59994b30ecf9b8def41a025\n\nModMul = 1aacec7f7e66b0cf4eb2dfda9d8d3fbf4eb8e928cbbc967d13e3e38612f0346d\nA = b0fd7a936b0908ba6fa797e4b855d673ff85d665ef3a345e560e2c0049becf5c25b6c0068dd617ab47a8fd151939ea0631f86806ddd40e557933c0e880fcdd0b\nB = 105c87fe2b1bf0be5405ca0d530beda1780f0045e892d7810f8a8abbe890f0a19de66497cba55bf38e190c52992467c22a320c38a4bd167f774ed812f1271d5a\nM = ac4f0a2b22df691331ded955a5d0e7d1910d7920a59d4a87636b2635397b7335\n\nModMul = 2c25d180156fa7d2fc20c9bd6d9ff0b111c9ad76ada0784e2f8fa0bd06413f66\nA = 2aa4a0a73df11f4e60956619d0b35eaef45730d619f9b920298e6d369b9861f6411de28a34af038f288d7a3d6a35b10c8082b8ad0fb275a8f67c6832ac46ba9\nB = fae1d50b72feb25da2581829409391bf289cd9f730c99d265b5b2d63889381cde4adbf85c3998c2478f2866526b8f64605d75765edd09b78ea45337207d173\nM = 65c9d79a09a820adbc9beb152bef387c1439147ed50cef872d36a69f1c7d5fe1\n\nModMul = 56ec8624fc199e7b4e68358f88f1a99f1d4d02577b8c6f7e28e4ccfdd981f995\nA = b0a0f9d05d144d2ef257c1e63a7127a3b8e0d8b64ff8f6447618560593574b5c5da6258b274efc28da0defd988bef1efca0f481f809665a78954b36741d668bd\nB = 10901b9dbf0016cbcc671da75a75b7a6ec6a66dd17b53a97344864b08f037098537380bfb0137b6becfc36a75206686d16bc4eb8fd54299494374e3f383d9b10\nM = 73882376ca850c125ce9f20c291e550ee48f0eb0d571109ab08c22d6719496e9\n\nModMul = acceebe131aa34ff21b3235f045bccc8a8f762dca20c1dd1ef6eb461ea971c6c\nA = a7714b249eb0f0cbe3e6fa0b04e895fcf14c404876197defafc6b57026ae7e5e993fc47c1819581adc03860ce07f2b7877a3f6d0912c0cbc659f5f6170a1cb2b\nB = b7278ecd154ef5243ad973ead291ea186acb63e09977e644a6a9fde195d1a33993fc47c1819581adc03860ce07f2b7877a3f6d0912c0cbc659f5f6170a1cb2b\nM = c52ae49e1a4b21ec392b76844ad559653b7b9f67a58b3bba6c2ce250017eab09\n\nModMul = 62b5b04dc84bb4ee04934c03ef361bc6e59b42144dc117b9f7771525c67c3688\nA = 2b65f491caf0b5cd9c66c859fbcadaec7213e6b848884638791b1620d6e4bc9dde087af0e7329d3b15a45df2d43ebde61b053ad7f63917aa922d58b4f3222620\nB = c1bfcdb34b0766be980540dc3256b9ee4158310fad2c43cf24bfafca08ee185647043f5842a9d9eda224449259341b7c50998086434528d47661bf5762a7ab5f\nM = f73398c32191b436d14a0b76c6069b1d61395568753c832dd0c707780a232dc9\n\nModMul = 5613c8fb0721bd3f605089def48fb2c38a4862bb387886c1edc1bc37d10f0e15\nA = a3d8b12a2c8f4021ca045a4e4903687dea63ee7e88893b1911aea77efbff00f8f5c7884cbafc71f59fa2636195c2ebee61edbf642923f34d87ba5eb49b06a7ee\nB = 3231829c81b26dcac432b502ce22e126ab564922b1e9818cd3da46edc5ce7df026d0e515809c97bcfdb9666581efbfd364437ba9959dfad099f90472f97c69ec\nM = df8344fa848d1066afe4f8d985cff65441751677dcf3a4e99b40365fc3c978e9\n\nModMul = 30325f7ccbc2c69e11d739ad7132a947c53377aa902ec70b152f3a75e050c244\nA = e4ba620125f58a63fe12fbd3eccdea477d56b120c76d5d1421bebd74e8686b4093f8169070453ccc04b63b173568385313a1d9c841a4aa82a61cb84d4286a941\nB = e87aaa990307855f8e5f2e5509d2ce31dd4b13bb7199cf5fa0593e350326e222efc33a26c69245565d6ebb5a484cfef7d2558f22dea8054d07831d536803d0dd\nM = 43d57108eb0ab9bebaa8ce137628ea825951c6accb9acb7f1e991c93b8563897\n\nModMul = 1975db7b72434ad32c9aee412645f6670b7f4af1f8a424a5031c559d3e18dce6\nA = bd64b1db27fa7da4c92a4ee092f58a2a53ed0f12d009fe13b36d5fd585defe778fafea4a60e8fe567d03e9ba3b72b189e22504ae8ca6aad7c2ac0f44abca2f6\nB = b487d8116198560d6c5b08c7ce63b0acc0c98e6f2a8d709cf4e3a409edd55f64d72fc27a70dc341e280ff5a1b09fe131773d466cb31991d2db23a2a86d225c80\nM = 39d57af763eabe569dac1a103e169e6e3b4375168e41e5c3b961b6e743915923\n\nModMul = 3bbb5bde9e3e240694326571360090e1fc0a4ea7b2311c1e0bd3961f6c159385\nA = 4181ee3bf9a98bcd49eaea243a179cddbf160981efc720685c7be1dfeb5aa552685a2cd46f340e1e1da893b3b460692fa2eaf6c100f24a14f239e45123242d53\nB = 77cd04d86dd5da322af78be54246dd6b7af490d903db1db03cbccde535570b81c6053a84110c07f097540ffe7510320024b7bafb77e9e239761def76092e1d59\nM = f3b9833a303eb540cf8b6cbc3cf16394b1634ef517be57684e42d364d8bec3e5\n\nModMul = 2d8174211f0367233b3a8df7c5bf0066d6aa792be7cdc5e850a477454d5c829f\nA = 1c08cec52d96136fbd9078b7b8db36ab63b86e19dd3dba7b2e3190ff566180e89dfee9423fa4e99be2187eda6aedfa86b9a45eb1e4655257315ae6a280f0a6ee\nB = a8b4bc9647d8df9b7c76cc6d0f2248cdbc41f5da9c061f9864aa8415c9557582cada456cf23cc32d47d1fc1caf19d36b398019aac4734e10f55ce3cad419e5e7\nM = 7eacffe21f88413af94155a2a8e37f70a431a59653738afda04a1bec72d0d9ed\n\n# Regression tests for CVE-2016-7055.\n\nModMul = ccd6f75b5f24b7c5ce2ce755fa89c2450c6a7d96ce8c8791e659eab84577a7695e3b2caa7c980fb23f60634233e9798499c28b0338c1f1a326d0ca89fd41f2fd88b759f317889832966b551a950043ec7a4b6152d3e2cbfb40e88458e70ab783b96f12d271f828d5b39e198ccaf8665411d85026282dbead5d24cd01b6c8a8e9\nA = 7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878\nB = 095d72c08c097ba488c5e439c655a192eafb6380073d8c2664668eddb4060744e16e57fb4edb9ae10a0cefcdc28a894f689a128379db279d48a2e20849d685939b7803bcf46cebf5c533fb0dd35b080593de5472e3fe5db951b8bff9b4cb8f039cc638a5ee8cdd703719f8000e6a9f63beed5f2fcd52ff293ea05a251bb4ab81\nM = d78af684e71db0c39cff4e64fb9db567132cb9c50cc98009feb820b26f2ded9b91b9b5e2b83ae0ae4eb4e0523ca726bfbe969b89fd754f674ce99118c3f2d1c5d81fdc7c54e02b60262b241d53c040e99e45826eca37a804668e690e1afc1ca42c9a15d84d4954425f0b7642fc0bd9d7b24e2618d2dcc9b729d944badacfddaf\n\nModMul = ccd6f75b5f24b7c5ce2ce755fa89c2450c6a7d96ce8c8791e659eab84577a7695e3b2caa7c980fb23f60634233e9798499c28b0338c1f1a326d0ca89fd41f2fd88b759f317889832966b551a950043ec7a4b6152d3e2cbfb40e88458e70ab783b96f12d271f828d5b39e198ccaf8665411d85026282dbead5d24cd01b6c8a8e9\nA = 095d72c08c097ba488c5e439c655a192eafb6380073d8c2664668eddb4060744e16e57fb4edb9ae10a0cefcdc28a894f689a128379db279d48a2e20849d685939b7803bcf46cebf5c533fb0dd35b080593de5472e3fe5db951b8bff9b4cb8f039cc638a5ee8cdd703719f8000e6a9f63beed5f2fcd52ff293ea05a251bb4ab81\nB = 7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878", - "787878787878787878787878787878787878787878787878787878\nM = d78af684e71db0c39cff4e64fb9db567132cb9c50cc98009feb820b26f2ded9b91b9b5e2b83ae0ae4eb4e0523ca726bfbe969b89fd754f674ce99118c3f2d1c5d81fdc7c54e02b60262b241d53c040e99e45826eca37a804668e690e1afc1ca42c9a15d84d4954425f0b7642fc0bd9d7b24e2618d2dcc9b729d944badacfddaf\n\n\n# ModSquare tests.\n#\n# These test vectors satisfy A * A = ModSquare (mod M) and 0 <= ModSquare < M.\n\n# Regression test for CVE-2017-3732.\nModSquare = fffffffdfffffd01000009000002f6fffdf403000312000402f3fff5f602fe080a0005fdfafffa00010001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000002000002fefffff7fffffd07000109fdfffef3fffdfd06000405ff00fdfbfffe00010001\nA = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff00000000\nM = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff\n\n# Regression test for CVE-2017-3736.\nModSquare = fe06fe0b06160c09\nA = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f8f800000000000010000000006c000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffff8f8f8f800000000000010000000006c000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff00fcfdfc\n# A in Montgomery form is fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8ffeadbcfc4dae7fff908e92820306b9544d954000000006c000000000000000000000000000000000000000000000000000000000000000000ff030202fffff8ffebdbcfc4dae7fff908e92820306b9544d954000000006c000000ff0302030000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01fc00ff02ffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00fcfdfcffffffffff000000000000000000ff0302030000000000ffffffffffffffffff00fcfdfdff030202ff00000000ffffffffffffffffff00fcfdfcffffffffff\nM = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f8f800000000000010000000006c000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffff8f8f8f800000000000010000000006c000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffff\n\n\n# ModExp tests.\n#\n# These test vectors satisfy A ^ E = ModExp (mod M) and 0 <= ModExp < M.\n\nModExp = 00\nA = -01\nE = 01\nM = 01\n\nModExp = 01\nA = -02\nE = 01\nM = 03\n\nModExp = 01\nA = -01\nE = 02\nM = 03\n\nModExp = 01\nA = -02\nE = 02\nM = 03\n\nModExp = 00\nA = -03\nE = 02\nM = 03\n\nModExp = 02\nA = -04\nE = 01\nM = 03\n\nModExp = 01\nA = -04\nE = 02\nM = 03\n\n# Regression test for carry propagation bug in sqr8x_reduction.\nModExp = 19324b647d967d644b3219\nA = 050505050505\nE = 02\nM = 414141414141414141414127414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\n\nModExp = 208f8aa0\nA = 86b49\nE = 2\nM = 30d26ecb\n\nModExp = 27308229\nA = 17591bb\nE = 6\nM = 30d26ecb\n\nModExp = 2bdf498f\nA = 21292626\nE = d\nM = 30d26ecb\n\nModExp = 11317167\nA = 4a655df24\nE = 10\nM = 30d26ecb\n\nModExp = 2e1b88e\nA = da6b761a86\nE = 35\nM = 30d26ecb\n\nModExp = 20a12ec3\nA = ea811\nE = 2\nM = 23bc042f\n\nModExp = c42ced\nA = 1011a6a\nE = 4\nM = 23bc042f\n\nModExp = 4637d79\nA = 28d9a601\nE = 8\nM = 23bc042f\n\nModExp = 20e5669b\nA = 72fe6bc20\nE = 11\nM = 23bc042f\n\nModExp = 142ab9e3\nA = 9a07b9363c\nE = 29\nM = 23bc042f\n\nModExp = 14c64646\nA = 822df\nE = 3\nM = 30915765\n\nModExp = 160e35a2\nA = 15ea542\nE = 5\nM = 30915765\n\nModExp = 2f23a488\nA = 34d2e02e\nE = e\nM = 30915765\n\nModExp = 28e67f93\nA = 636a32703\nE = 14\nM = 30915765\n\nModExp = 29bfeaa5\nA = c8646998e6\nE = 2c\nM = 30915765\n\nModExp = 30959e22\nA = 81dad\nE = 3\nM = 326dd68d\n\nModExp = 1a1da4fa\nA = 116adb9\nE = 5\nM = 326dd68d\n\nModExp = 272bf0d8\nA = 2d21ef08\nE = 8\nM = 326dd68d\n\nModExp = 29f5054b\nA = 76989850a\nE = 16\nM = 326dd68d\n\nModExp = e6c7b77\nA = b88ee70d2a\nE = 3e\nM = 326dd68d\n\nModExp = 369605e1\nA = cf26f\nE = 2\nM = 3ce082eb\n\nModExp = 168a3c5d\nA = 1f82caf\nE = 5\nM = 3ce082eb\n\nModExp = 125c4bb8\nA = 2e9c4c07\nE = 9\nM = 3ce082eb\n\nModExp = 1c5fe761\nA = 523ab37f1\nE = 14\nM = 3ce082eb\n\nModExp = 21703009\nA = dc832165e8\nE = 20\nM = 3ce082eb\n\nModExp = 1228d1e\nA = a5555\nE = 3\nM = 24665b27\n\nModExp = 5226af4\nA = 1077bd6\nE = 4\nM = 24665b27\n\nModExp = 1b14eac1\nA = 2db3a834\nE = f\nM = 24665b27\n\nModExp = 161727bc\nA = 6bd962cb6\nE = 19\nM = 24665b27\n\nModExp = 10d61d0d\nA = c10caed407\nE = 28\nM = 24665b27\n\nModExp = 233da406\nA = b125f\nE = 3\nM = 33509981\n\nModExp = 24032799\nA = 1656b7c\nE = 6\nM = 33509981\n\nModExp = 129ecebe\nA = 2e671504\nE = a\nM = 33509981\n\nModExp = 20c20bac\nA = 4d7a2de44\nE = 1f\nM = 33509981\n\nModExp = 2e3ce9d3\nA = c53b3def4d\nE = 31\nM = 33509981\n\nModExp = 12fadfd6\nA = b4cf8\nE = 2\nM = 36e9d4ae\n\nModExp = 45", - "7ac85\nA = 1b1c7e9\nE = 7\nM = 36e9d4ae\n\nModExp = 31debef4\nA = 3a973028\nE = d\nM = 36e9d4ae\n\nModExp = 2333ad93\nA = 552b97c45\nE = 11\nM = 36e9d4ae\n\nModExp = 99ba1fb\nA = 8bfb949cbb\nE = 28\nM = 36e9d4ae\n\nModExp = 27b691de\nA = 93492\nE = 3\nM = 298fdb16\n\nModExp = 3c2b70f\nA = 14e7b0d\nE = 4\nM = 298fdb16\n\nModExp = 1486cda7\nA = 29acff81\nE = c\nM = 298fdb16\n\nModExp = 11725275\nA = 507489205\nE = 13\nM = 298fdb16\n\nModExp = 24d14627\nA = e71c55606d\nE = 35\nM = 298fdb16\n\nModExp = 222b8d14\nA = 9b1a0\nE = 3\nM = 3db59d12\n\nModExp = 3b8bd47d\nA = 13f4e8d\nE = 7\nM = 3db59d12\n\nModExp = 17e72356\nA = 334774ce\nE = a\nM = 3db59d12\n\nModExp = 306447ca\nA = 47079ddd2\nE = 12\nM = 3db59d12\n\nModExp = 90bef3b\nA = a75d62616d\nE = 37\nM = 3db59d12\n\nModExp = 1\nA = cddd44f47e84b3276cc36a5c0d742cc703e61c4756168601fbb1b6eb598c161019562344dd56ab6f603d920a12c360b285e6496a3605a2f8d691c3598233ee9366b5f2692554893bdeb67b7bdaf35ab7273ac593145e26bed82c70ba5793bf4bc5cac4c80b01785d1496beede493806e4f4aa89fd8d41de80dd6d0a3e2742678\nE = 0\nM = c95943186c7567fe8cd1bb4f07e7c659475fd9f38217571af20dfe7e4666d86286bc5b2bb013197f9b1c452c69a95bb7e450cf6e45d46e452282d5d2826978e06c52c7ca204869e8d1b1fac4911e3aef92c7b2d7551ebd8c6fe0365fad49e275cc2949a124385cadc4ace24671c4fe86a849de07c6fafacb312f55e9f3c79dcb\n\nModExp = 0\nA = 0\nE = 8de689aef79eba6b20d7debb8d146541348df2f259dff6c3bfabf5517c8caf0473866a03ddbd03fc354bb00beda35e67f342d684896bf8dbb79238a6929692b1a87f58a2dcba596fe1a0514e3019baffe1b580fc810bd9774c00ab0f37af78619b30f273e3bfb95daac34e74566f84bb8809be7650dec75a20be61b4f904ed4e\nM = c95943186c7567fe8cd1bb4f07e7c659475fd9f38217571af20dfe7e4666d86286bc5b2bb013197f9b1c452c69a95bb7e450cf6e45d46e452282d5d2826978e06c52c7ca204869e8d1b1fac4911e3aef92c7b2d7551ebd8c6fe0365fad49e275cc2949a124385cadc4ace24671c4fe86a849de07c6fafacb312f55e9f3c79dcb\n\nModExp = 5150fb769d5c5d341aaf56639a7bcc77c415fe46439938a2190283409692f29cd080bfe3433005d98d24718a03a3553c8560c5e9c8ed0f53b8945eb18290e1c1a83d919302510f66dd89b58acc2de79ad54b8a30d3e1019d4d222556beefca0821b094ecf104b5e4cfce69d2d520d2abf54f3e393d25ed3d27e8c2e3ca2e5ff9\nA = ead8c5a451541c50cab74de530c89376d9a55c723e0cac3c84b25f0093c08a2961e49ab48966361c42c9f99111587252d98395b76788400d75c66ef208ea2767a28d6f8dc3a859f39c95765d57f139e7fc14f47c908c62df051e7216d379f52028843b4d82ef49133cce8fe671ae179423ac8da5be43b01caaf425cd969300cd\nE = 8de689aef79eba6b20d7debb8d146541348df2f259dff6c3bfabf5517c8caf0473866a03ddbd03fc354bb00beda35e67f342d684896bf8dbb79238a6929692b1a87f58a2dcba596fe1a0514e3019baffe1b580fc810bd9774c00ab0f37af78619b30f273e3bfb95daac34e74566f84bb8809be7650dec75a20be61b4f904ed4e\nM = c95943186c7567fe8cd1bb4f07e7c659475fd9f38217571af20dfe7e4666d86286bc5b2bb013197f9b1c452c69a95bb7e450cf6e45d46e452282d5d2826978e06c52c7ca204869e8d1b1fac4911e3aef92c7b2d7551ebd8c6fe0365fad49e275cc2949a124385cadc4ace24671c4fe86a849de07c6fafacb312f55e9f3c79dcb\n\nModExp = 1\nA = 935561297d1d90255aef891e2e30aa09935409de3d4a5abc340ac9a9b7dce33e9f5ce407f3a67ec30e0dc30481070823f8542463e46828d9cafb672a506d6753688cbad3d2761079f770c726c0b957071a30876c4d448e884b647833befbcd6b582787bf769d63cf55e68c7b869a0b86374f8920516cf5d528f348b6057450a1\nE = 0\nM = dcc24236a1bb94c71d9ec162a6aa4697b932717e82b667cad08b6bd1bbcbddf7cd167b7458de2b0b780486b39574e749d6405f9ede774a021d6b547271523e9e84a6fdd3a98315607ccf93356f54daa9c75e1e311e1672d0dc163be13f9ed6762f7dd301f5b0a1bb2398b608f40ac357ae34fc8a87d4fef3b961cbdb806d9061\n\nModExp = 0\nA = 0\nE = bb552be12c02ae8b9e90c8beb5689ffefe3378d2c30f12a6d14496250ecce30317c642857535a741642c3df689a8d71a276d247ed482b07b50135357da6143ac2f5c74f6c739c5ff6ada21e1ab35439f6445a1019d6b607950bffb0357c6009a2bfc88cd7f4f883dc591d4eb45b1d787e85aba5c10ee4fe05ea47bf556aec94d\nM = dcc24236a1bb94c71d9ec162a6aa4697b932717e82b667cad08b6bd1bbcbddf7cd167b7458de2b0b780486b39574e749d6405f9ede774a021d6b547271523e9e84a6fdd3a98315607ccf93356f54daa9c75e1e311e1672d0dc163be13f9ed6762f7dd301f5b0a1bb2398b608f40ac357ae34fc8a87d4fef3b961cbdb806d9061\n\nModExp = bbad67352704a6321809f742826bf3d1c31c0ad057bf81432abeb30dc9913c896c03e69eb1cde6b78ffcb320c4625bd38ef23a08d6c64dc86aec951b72d74b097e209ce63092959894614e3865a6153ec0ff6fda639e44071a33763f6b18edc1c22094c3f844f04a86d414c4cb618e9812991c61289360c7ba60f190f75038d0\nA = 855144760f2be2f2038d8ff628f03a902ae2e07736f2695ec980f84a1781665ab65e2b4e53d31856f431a32fd58d8a7727acee54cc54a62161b035c0293714ca294e2161ea4a48660bf084b885f504ad23ea338030460310bd19186be9030ab5136f09fe6a9223962bce385aaaf9c39fe6ed6d005fa96163fe15cdfa08fc914d\nE = bb552be12c02ae8b9e90c8beb5689ffefe3378d2c30f12a6d14496250ecce30317c642857535a741642c3df689a8d71a276d247ed482b07b50135357da6143ac2f5c74f6c739c5ff6ada21e1ab35439f6445a1019d6b607950bffb0357c6009a2bfc88cd7f4f883dc591d4eb45b1d787e85aba5c10ee4fe05ea47bf556aec94d\nM = dcc24236a1bb94c71d9ec162a6aa4697b932717e82b667cad08b6bd1bbcbddf7cd167b7458de2b0b780486b39574e749d6405f9ede774a021d6b547271523e9e84a6fdd3a98315607ccf93356f54daa9c75e1e311e1672d0dc163be13f9ed6762f7dd301f5b0a1bb2398b608f40ac357ae34fc8a87d4fef3b961cbdb806d9061\n\nModExp = 1\nA = 9d92629c1ab181c50c31619e8acd0d235a1f5fc7a0bef4d4fd54b4f1968d45921f8522efe88e69c6c14c576c564592b9feb00d1554b88b038934eaf4a8ce81a2582732387490181ef158360c8b2d9ccb326ffe043f776a50cb8202837f08ca743b562eefa007150ab7012c341b16248478d4775c02ad71ea13d5e82b71e2d600\nE = 0\nM = cd607549668469b792f495c141e500871880b0611c8004293a561ec7f9ab6561f8a9b90872742386adafb5cd1890e8204ae12aec529cca0a9e382c96439137f09de9973b12c8492c62847e107deabb7dd946ffbb9d0ac73b462c481092bd65326a17f21d8d6527c47a5dba50aaa20c7048b8788a49eb3ea5f29bd5cfce24eb3b\n\nModExp = 0\nA = 0\nE = 9f43dcb641f3ecf4dbc97450f2bdf3b7ec6a2f3e8e96bb1df2bf34b8d2d78e1a9018d04d960ffd0e932cfc60d3b9b923e3f9f29b3f3d61cae3a9f7245078143475c7fcb896ff200f7d94c4f2708bb42750e37c185a31c876814e4f06a00771707654e1da2fb69c16b6500b16385e3b933e2276ad3569977473f699b1c7926c3b\nM = cd607549668469b792f495c141e500871880b0611c8004293a561ec7f9ab6561f8a9b90872742386adafb5cd1890e8204ae12aec529cca0a9e382c96439137f09de9973b12c8492c62847e107deabb7dd946ffbb9d0ac73b462c481092bd65326a17f21d8d6527c47a5dba50aaa20c7048b8788a49eb3ea5f29bd5cfce24eb3b\n\nModExp = 24eaead5b57883c2f454928f8edd470a344bfe07a953194f7d635d705ef13ddfc64140c8ad6f363d4c828e7c7891a6b6d4df37335de4552c319dafd1c06d1f743240082a3535df4da1475d3eea3fead20e40815fd5a0876c881c162ab65a1eda494280c258901ca953d1d039a998bf0e9aa09273bbef4865f3054663b72d75ff\nA = a31618b4532f53729ba22efb2221432fab1dbb70853d6a1159b42fd19fc949965c709b209de106a652aa422d88922ce51dae47f7f6deaf0055202e13db79ee84fc3d3c6f4c003ef96597c49d6895fa53c22ac9e4819f7048146b5272f6279424fdb389819a0b251c823c76f4bebf4f1246de455aafe82a0d34454f5039e90839\nE = 9f43dcb641f3ecf4dbc97450f2bdf3b7ec6a2f3e8e96bb1df2bf34b8d2d78e1a9018d04d960ffd0e932cfc60d3b9b923e3f9f29b3f3d61cae3a9f7245078143475c7fcb896ff200f7d94c4f2708bb42750e37c185a31c876814e4f06a00771707654e1da2fb69c16b6500b16385e3b933e2276ad3569977473f699b1c7926c3b\nM = cd607549668469b792f495c141e500871880b0611c8004293a561ec7f9ab6561f8a9b90872742386adafb5cd1890e8204ae12aec529cca0a9e382c96439137f09de9973b12c8492c62847e107deabb7dd946ffbb9d0ac73b462c481092bd65326a17f21d8d6527c47a5dba50aaa20c7048b8788a49eb3ea5f29bd5cfce24eb3b\n\nModExp = 1\nA = a8558e7f455b27c0c46d7d0862eb409cdefbeca945e0284b5bf425b7ac0f3d316bc365594cc1639decffc621214d61479bc75135120d4ac09ea8b742ad7ec1822091b62b1c6f564fe5e2f4f5b7def92cbaaa9a898549207ab01b91c2324fbd306a87f7d6379b6fb6493c5fca76729767f136120da9c90bdc7d364f7d242d5acc\nE = 0\nM = 88f3c87ac5e3272a21b8a858da640d6939fb8113a95412c38663a0f352686d69a5d7927e60b484b9fcb8ef12978fe25ff2ebc9b61c5450e04222ef20ba3cbbdc5ec45581ce0f58e10be7bb9de7fa08752303a7a1db23b2ac9c6692ec63bf09ecd6639e06c5491ba568ea886620d71da32d329615f0e1443a75d09ae35b8a2d7f\n\nModExp = 0\nA = 0\nE = a5524b41dfc6b570df1d8f6633ac7777c1131abe3a99c6166b0d29d3b8883c41b00a0c53cdd6f42820bf05c810b6ec53e77a8c1b9344ea0c91d4f410a2f204c369f3db33bf8c88217fc2cf802a9d9bce8119242d8e781875b85431be170076498c0963574ee423551aec9557e2fc672ab1ab5d0cbb1c400535df9481e7934d8f\nM = 88f3c87ac5e3272a21b8a858da640d6939fb8113a95412c38663a0f352686d69a5d7927e60b484b9fcb8ef12978fe25ff2ebc9b61c5450e04222ef20ba3cbbdc5ec45581ce0f58e10be7bb9de7fa08752303a7a1db23b2ac9c6692ec63bf09ecd6639e06c5491ba568ea886620d71da32d329615f0e1443a75d09ae35b8a2d7f\n\nModExp = 292f0b39", - "ca0f1c850b1a00cffd2d54924fcd5fc7e7504c9d593e6c0ff74760b1f4bdd81679fe06c50248336f3108c593fa111072ee87d0fcc89a63243a1dc89044503663eee9bc18f51c3e0193d9108303e12ac90ff78f6ec752a4386af09c42db524a7cbe9a3d4fcccd56c34d283bcc9debc17158b5fe8df0c1888a9841bf8f\nA = b4fde2908745ff92cc5826a27dcfdda09e8fffee681844fa4c7f1354d946d5d84e0e0c7a4a4cb20943d9c73dd707ca47d796945d6f6b55933b615e2c522f5dfc33e0652917b4809bab86f4fa56b32b746c177764895492d0a6a699812b2827fe701d40ef7effd78ea8efe1cac15ff74a295a09614bf04cae1a5017872ba22efe\nE = a5524b41dfc6b570df1d8f6633ac7777c1131abe3a99c6166b0d29d3b8883c41b00a0c53cdd6f42820bf05c810b6ec53e77a8c1b9344ea0c91d4f410a2f204c369f3db33bf8c88217fc2cf802a9d9bce8119242d8e781875b85431be170076498c0963574ee423551aec9557e2fc672ab1ab5d0cbb1c400535df9481e7934d8f\nM = 88f3c87ac5e3272a21b8a858da640d6939fb8113a95412c38663a0f352686d69a5d7927e60b484b9fcb8ef12978fe25ff2ebc9b61c5450e04222ef20ba3cbbdc5ec45581ce0f58e10be7bb9de7fa08752303a7a1db23b2ac9c6692ec63bf09ecd6639e06c5491ba568ea886620d71da32d329615f0e1443a75d09ae35b8a2d7f\n\nModExp = 1\nA = e2845c572b46496ac158a731f612fd40ef626fa7134755c25b1b7614f4d7b29164e6142ddb7985e4c7ebc575855ff901e95927fe98a5aea2ad3a4720c75782323bea1518b2c57790f44efd9411be4e95b3896bad1e73c59658290b309e5a7eb5ef8be08125063e57336b80f17eacee88966d12bbaaa15a25929c82e027cf696f\nE = 0\nM = cf0dee80177869a532f0c6c3a0bda3aad79bdb6b70b6c227b32d75c26e394a90c1f2a6c2bb841ba9f6556b15654a79d8b1dd0c90709a093497bf40be0807cdbb378a74de5893c25067224d3ea8d37387ed6c4a981138853cb89caa9ce6cd0f6a1e95de24d558e90960f93844db4d01e372650350d45a9d34a36042b4d4b9e78d\n\nModExp = 0\nA = 0\nE = a55703a72ca3f6074b939ed3d748196a684a3c8e411c2b39a9beb98993b6eb7ea3fa16f41bc5b5c3710b91c0fc74a8072793052f872f61695db3a2df872eaa427a110f1a8d568c85d58bd350d0df8eced7a10be80f7567360c1a8047b9c44aa2967cd0d9dd2caea2c1492358c2db4f0214da343fdf2e34272865dc5c63be2ae4\nM = cf0dee80177869a532f0c6c3a0bda3aad79bdb6b70b6c227b32d75c26e394a90c1f2a6c2bb841ba9f6556b15654a79d8b1dd0c90709a093497bf40be0807cdbb378a74de5893c25067224d3ea8d37387ed6c4a981138853cb89caa9ce6cd0f6a1e95de24d558e90960f93844db4d01e372650350d45a9d34a36042b4d4b9e78d\n\nModExp = c90e4c69df92e26549b016950b59080947f5403430698e128477782480dd70be96bed2b9042dd8c708eb432e02710555b97af11ce6fa9b53395022851c32d1f53f04237fb0763563b440ca6e81a50d909d907d9c26b7d3c420dbf88f7dadd488666848135f8cdc608dcfb0691989289fb54379c2e84c262f9765f68c012ca1b9\nA = 882ea1b9b6c79a3b1bdfd284658cb6227ad825e0178cab713c7413c2ec34f03cfaec470c4f5c521f5e9899a2123878ff0f5b36a4196c08ad1b04d03746c4bfb5d126f5eefbfe172627d6732710a8ac8890cedbd4fdef69a19f2b3253a5aa0e5dd5484f72d59b17bdd1dad3db209a3ab839368ed3975069685911d7b35e41a9e6\nE = a55703a72ca3f6074b939ed3d748196a684a3c8e411c2b39a9beb98993b6eb7ea3fa16f41bc5b5c3710b91c0fc74a8072793052f872f61695db3a2df872eaa427a110f1a8d568c85d58bd350d0df8eced7a10be80f7567360c1a8047b9c44aa2967cd0d9dd2caea2c1492358c2db4f0214da343fdf2e34272865dc5c63be2ae4\nM = cf0dee80177869a532f0c6c3a0bda3aad79bdb6b70b6c227b32d75c26e394a90c1f2a6c2bb841ba9f6556b15654a79d8b1dd0c90709a093497bf40be0807cdbb378a74de5893c25067224d3ea8d37387ed6c4a981138853cb89caa9ce6cd0f6a1e95de24d558e90960f93844db4d01e372650350d45a9d34a36042b4d4b9e78d\n\nModExp = 1\nA = d7a99e65b8af86b1c51d851f0447e43cd4f343cb0ada7236283e69aa7ebd383826acc9809e5dbc4002d0f2430022cb026458189db3805ce2de1142a31ba71a6c064ab51f0059eb4b931b8bcbaef023c38d57aa5f3e14f5df77e547fc028702071b58bd57338be1e1e4f98d3553484e4de359cefa29c5f58d3fa5d823f389dbef\nE = 0\nM = 8315dacf124bd473c578946347e83d1b20c750a7d9533d6215591be40bc78bcca77821f8c8f95375bbd6372515ada63d22bed2fa49bd6fabb0040c538d08db25b09d2fda02a93ab086cd1c27df93c37ee9c6a0527d089179b8f92b5dc3acf5ef1c75906fb80b03f5c2442a7a4088640f66376575ecfa4c697c1a571397ee5a0d\n\nModExp = 0\nA = 0\nE = 95793fe33696f53e37498b2b65aaf27079e27acf1da97dda2c3e0803e8a02139f574e04ee03f7d1ddd029f528e3f3644515ad6f10f0beac2767f23d9cd8a8b9b6c6e376e36b64a0ae2711d7d31a5a75011641935b503110edbefe9f0ff2da27b5c5f6bb8cc151fdc86f67191bb99160c6cacc86ca368d5bdfafd3f3ff5161b1e\nM = 8315dacf124bd473c578946347e83d1b20c750a7d9533d6215591be40bc78bcca77821f8c8f95375bbd6372515ada63d22bed2fa49bd6fabb0040c538d08db25b09d2fda02a93ab086cd1c27df93c37ee9c6a0527d089179b8f92b5dc3acf5ef1c75906fb80b03f5c2442a7a4088640f66376575ecfa4c697c1a571397ee5a0d\n\nModExp = 186c50ae259aa0fd31859cbcfea534e626a254de33956d5d719334bb32e7cf37cf199a21f079a5b90497228994d05efe19ccd8c769cd81f896286e8ae557cacd1630a928c629ecdfece29ab3697794aa707734e007318fa7029b050bb09ebbe6986187c6ca843f55266d275620b3f0fec0ad5f847ce8b314d929d128b33a249e\nA = 9d5e345793faddca9867f23eeddf6816c1e837f7a2cf96fa077212514acb6be87ac01a237d8f2f1d07d27a8ddd1b0ae0d97e1bda4f205a89435017284cdedea3e407b1b940d6f52112b6359b3e86e4c83074b17c210ae2c8856b42b169b4a7a6dfa65b368a7959496cf9bb1ee93d019dbd79101830e3f5ed08604ab90890b914\nE = 95793fe33696f53e37498b2b65aaf27079e27acf1da97dda2c3e0803e8a02139f574e04ee03f7d1ddd029f528e3f3644515ad6f10f0beac2767f23d9cd8a8b9b6c6e376e36b64a0ae2711d7d31a5a75011641935b503110edbefe9f0ff2da27b5c5f6bb8cc151fdc86f67191bb99160c6cacc86ca368d5bdfafd3f3ff5161b1e\nM = 8315dacf124bd473c578946347e83d1b20c750a7d9533d6215591be40bc78bcca77821f8c8f95375bbd6372515ada63d22bed2fa49bd6fabb0040c538d08db25b09d2fda02a93ab086cd1c27df93c37ee9c6a0527d089179b8f92b5dc3acf5ef1c75906fb80b03f5c2442a7a4088640f66376575ecfa4c697c1a571397ee5a0d\n\nModExp = 1\nA = e6a079bdf7b0638d50b183475e9ddfd5cbdebfb29f5fae8e9be402a0bd36085737b556492ea7fb4b1000ae9ce59db66098129b757cfb29224275fdaa46b8b7eb18a93ca7d3e446dc38c734b683d7ba7927b008d993aab01f44239d3c76be76d1503908e9b5e73b36c43ae0771368b01f39c042693bd92c4fc50810f059e1b332\nE = 0\nM = 81dd561d5d5327fc5ed7c9236b5fb21ef713c6d5e36264ba65ccc801b8eb107b714aad65bb503bb1f4721c0a6f97e5ab89300f049f42a4616ae43d29c089c286687484d18629c1be1b5befbdd0b3cfc86b1d28add89df4cc5e68dac3f56f2490a9068ca9c634ec258c030ec5023baa9133fd2af32fd1112895f9da549d410247\n\nModExp = 0\nA = 0\nE = f0460c5ca9b3a5c2d1b93c201d020dc43e1c81d1daba432e2cd310902da23eb81a5172b0b357484eb8fa2c04c270893b8198c8ad35453405dadaf05195b3aeb5ec0ccacecb4b6227ca43b27b97e240a4148a472670ed60f304302f757495fd4a91af0fe09800db0c3043a6ae213bee6703ad80523ca433d99ca0eab1e0b7c929\nM = 81dd561d5d5327fc5ed7c9236b5fb21ef713c6d5e36264ba65ccc801b8eb107b714aad65bb503bb1f4721c0a6f97e5ab89300f049f42a4616ae43d29c089c286687484d18629c1be1b5befbdd0b3cfc86b1d28add89df4cc5e68dac3f56f2490a9068ca9c634ec258c030ec5023baa9133fd2af32fd1112895f9da549d410247\n\nModExp = 60719701a2dc0bcde281a93ce0b8421d1a718adee43c1b5d9fe9e697a48ab3db4f9f33c73cff305ab6b6c300c149b05c6b289dce4580860dc56bc59de81ac074ecebdc65aa3ca040b44e5b3c80ddba1658d78b9abbc4c77e5f171f5582e70ab4438a8e1e2f062d618c4ad09c70c73b5b5fbc9f8f0bbdf1d530a933b705f85af8\nA = e1b400cd3b1f2f1c6b437adfdb970d2c8108f1b39bdbb13582179552011c6c97cba6bff2c463212b7f62776aa3e3aff9f175990e79395e819c144350b0a23d61638d500ecc97726b098e1af334aece23a851c718612442c04eb7b3805a24cc8f5b90042145eb5e5d6a408092832b6bbeb8a621419a9282fb5c075f41c7f1fdc1\nE = f0460c5ca9b3a5c2d1b93c201d020dc43e1c81d1daba432e2cd310902da23eb81a5172b0b357484eb8fa2c04c270893b8198c8ad35453405dadaf05195b3aeb5ec0ccacecb4b6227ca43b27b97e240a4148a472670ed60f304302f757495fd4a91af0fe09800db0c3043a6ae213bee6703ad80523ca433d99ca0eab1e0b7c929\nM = 81dd561d5d5327fc5ed7c9236b5fb21ef713c6d5e36264ba65ccc801b8eb107b714aad65bb503bb1f4721c0a6f97e5ab89300f049f42a4616ae43d29c089c286687484d18629c1be1b5befbdd0b3cfc86b1d28add89df4cc5e68dac3f56f2490a9068ca9c634ec258c030ec5023baa9133fd2af32fd1112895f9da549d410247\n\nModExp = 1\nA = 9dd1e6f2d3ff24096b54e0ebf0f10e283e484a1cbafc0431adda1296ed97692f3ba99440fd4f67c96dd8bab850e1123361c99362df9ea205ff8e90d1b329459f54730992d5a360e46fcc5f5a909e691abb9a06613d6991bd7c2aa609f0d7b441d7ded0c07b8c394327672d38a905efb2d76aa3be5bb14d0c002aa37e287aee79\nE = 0\nM = fda6f9d8588e3614f5a68ce867a5619f6ddbb8d64450ff402e1c4f1a08b518f79dca21e5983c207c5b7324c16895a1e9f1282fc6cf60b0645f6b02b652ed5b129e67c939e854ab492dec30ea878c3edde10a4b7d1d14c57100c6cbcc5fc085a0d7308715ed132fb917251919c727487fedb66500d5610b0014a43419acfbb92f\n\nModExp = 0\nA = 0\nE = 8622c37631e428402343dccf8ed09d47b3f4201e95058910289a62707c3ce0b7113c390056cc4796cc9893e471b12cb3f63f900f3356ffd25c8b2fed6f6a7fba2c684eb241ca706c76cecbf72473d8a58c02338e40714b5610465cc319f0a529a7aa3898d9e638b2", - "47abd1380c6e8f7fa210c9f1a1a2164db6db83a6bba79436\nM = fda6f9d8588e3614f5a68ce867a5619f6ddbb8d64450ff402e1c4f1a08b518f79dca21e5983c207c5b7324c16895a1e9f1282fc6cf60b0645f6b02b652ed5b129e67c939e854ab492dec30ea878c3edde10a4b7d1d14c57100c6cbcc5fc085a0d7308715ed132fb917251919c727487fedb66500d5610b0014a43419acfbb92f\n\nModExp = 86fb0b8dc161c41de2adb0f3ddcc8ad49c1efd729a52793a3ac987d4011c9c1dadb18657dca718df75c8ddcc49d60f152c46ab85ae9076ee7bfd405679a7da3a5195a1bbfd7d2b998c7b135ea91f8c445cbafe1276fa502c2a85477716829a2e0d24ba02623405a3654bed8f355bc7ccdb67c3f9a01e249e358b60d7699498a9\nA = 816610e6018ca47074d55750dd16a281019dbf95dc752605794cbb8ea8d75775317ce685737859728320b529fb3b4414b40bf3a93d08d8994a21ae54682cc1c357eb529837a7b0129a0843eebd9341c9bee3a8ae30475bdbff517e885a0c9f2b6a680643bd981efb53bf9dd49f3dc3cb757e117895fb34b1b4336d9bf8384558\nE = 8622c37631e428402343dccf8ed09d47b3f4201e95058910289a62707c3ce0b7113c390056cc4796cc9893e471b12cb3f63f900f3356ffd25c8b2fed6f6a7fba2c684eb241ca706c76cecbf72473d8a58c02338e40714b5610465cc319f0a529a7aa3898d9e638b247abd1380c6e8f7fa210c9f1a1a2164db6db83a6bba79436\nM = fda6f9d8588e3614f5a68ce867a5619f6ddbb8d64450ff402e1c4f1a08b518f79dca21e5983c207c5b7324c16895a1e9f1282fc6cf60b0645f6b02b652ed5b129e67c939e854ab492dec30ea878c3edde10a4b7d1d14c57100c6cbcc5fc085a0d7308715ed132fb917251919c727487fedb66500d5610b0014a43419acfbb92f\n\nModExp = 1\nA = 9edfce4691f46eadaa2043c7b1092b831ed50f3429f0bca02f985c0b77c686d951be84d772ae4b55f08935bed6e3206c8441574f215736b5c1c1b7595b3b789b55cf56db83741b10144d6767ba2b97b23a5e83504c60e06ab22834b0145655aa0463108317a379cbfc8a93de8a66925a999b8b02bf88dd85fb9898cefe9c95c8\nE = 0\nM = dcb68f6aa530ae9b31d078e2e82670adcc98228e7cf1aa59f81e66426ef14b1591b833d889463564c75b5fd5551ea295a0da581dd80f62c7008ff0f26a1c9f4f756431d48198af157149be8698336b306b0a8b8635d3fc2c4c2194ecc4d2af31ca1892917cc2e621d702eaaeed0d9a0c3dca575451eb8bc5487e313988cae745\n\nModExp = 0\nA = 0\nE = a3be10ef04535fca6784e5dbf3733d677dedd50fabbc3a860496628950b4747a328c2ce0d903cbe1e700f0af30f59fb917202257815097a2b516df5d0a82642faeffdfc3b7883766c78fc4be5901ebef891a9ca27f3bcf00960729e659bb3fddd54a19ce628e95ab86e4c7a168588bc9f67b05dd21a583acd8dc36e615945648\nM = dcb68f6aa530ae9b31d078e2e82670adcc98228e7cf1aa59f81e66426ef14b1591b833d889463564c75b5fd5551ea295a0da581dd80f62c7008ff0f26a1c9f4f756431d48198af157149be8698336b306b0a8b8635d3fc2c4c2194ecc4d2af31ca1892917cc2e621d702eaaeed0d9a0c3dca575451eb8bc5487e313988cae745\n\nModExp = 442866609915aa6f1bae9dfb59e721e1b63f42c0f75fbf0a88344120fbbd7aacf15208fb7c9d8bb8477d553cbd826d7e685ad764a8423e81c2131c040ee83a03cab8d5ce50866a941b48c78e9f1330794d908562d4141cfbf26e8c80c69551339eec41e37e2b37b54330f7bd75748f8d26d56ab9eb3b0c127540484c6445a7fa\nA = 8ff65e2cbcbcd8697cc3ce9a26855d6422ac7eb4e66500648c08be697e005cc3c854a54cfab91d43489cd60be8b516a9b3c9688e5e009a1689c6b164a133859a5464ef422c86344fef42cc477c9df27768377c126a066d1b62f593b7f6d6e906feaee16addb7cfbfc043d741b7dc81a87c17f167b7b8ef1b1fb3dfd1eb14102d\nE = a3be10ef04535fca6784e5dbf3733d677dedd50fabbc3a860496628950b4747a328c2ce0d903cbe1e700f0af30f59fb917202257815097a2b516df5d0a82642faeffdfc3b7883766c78fc4be5901ebef891a9ca27f3bcf00960729e659bb3fddd54a19ce628e95ab86e4c7a168588bc9f67b05dd21a583acd8dc36e615945648\nM = dcb68f6aa530ae9b31d078e2e82670adcc98228e7cf1aa59f81e66426ef14b1591b833d889463564c75b5fd5551ea295a0da581dd80f62c7008ff0f26a1c9f4f756431d48198af157149be8698336b306b0a8b8635d3fc2c4c2194ecc4d2af31ca1892917cc2e621d702eaaeed0d9a0c3dca575451eb8bc5487e313988cae745\n\nModExp = 1\nA = fe9f77f7d0475e00ec964c0effb9b8e079c32e376ce77a9c40ce4018c3df44a77b4f294d9565502b2b79accb30cb58dda6d15e1543b6d4a53296543ed11c7f51baab60283ef03fae37dfeacb431392487ec2839551a933895c4dbf18844f7b375d3e6f558d3c39993cea1bbf7fb743a6a07bd3753c03eb7298811476d7f3ff1d\nE = 0\nM = e7a96cf6fa930f73c8bdc2726bbba246001a9d27f39cc2b978c99dc6f15af0e8aaf26b565302f1112e607e2df4066948baba931b89cd9bbdea2072e05b9a4968fdf282c43d997987c3a3a0434e925a679ac81f316b7a7b724b79be3d6888b66f4512759bf66cfaaa88b9513dd27a44aaea75437268a014c4eb50ba2e50093511\n\nModExp = 0\nA = 0\nE = a0bc148ed50a9b54036bb8fa1f214979052ebd47db8b347af3bb03b806bb457b468ba34781f8a25f289a7a90af4903dc14809a166df2f4c3527de2ea6911cb1afb9071a4afbb522a7d50634d66fd584c73f32d05217dc9f7f16394c68a692a953492ca85f89cc11da95fd8cac6231647923ced48a1b3b0ee68c010286d452836\nM = e7a96cf6fa930f73c8bdc2726bbba246001a9d27f39cc2b978c99dc6f15af0e8aaf26b565302f1112e607e2df4066948baba931b89cd9bbdea2072e05b9a4968fdf282c43d997987c3a3a0434e925a679ac81f316b7a7b724b79be3d6888b66f4512759bf66cfaaa88b9513dd27a44aaea75437268a014c4eb50ba2e50093511\n\nModExp = 91fd879d02f95a9f40fcd1037726f73892caf84e9b43b4aa4126d9062a0d22c464e7af2fbd91aa849612d99d9519b724a7fb1cb018fffdcff321d883ab2519953c9f174f09dd8f13ac87339887385966eb4a94842276637b2c36c0a5036b1d3bbea438bc6efd4b4851c7ec06879d60694df894717569bcd31c4b13d80df6cbca\nA = cdec5edc1cb3ea974342b85aabc0f9385cf877ca328747d40dd4d297623ad69ab6582653faeed5aef225208305135cfbee32e066cb43e18afacea3a32acc8aabbc49617ac33e741651924ae56dd6aa044a12a1ea50fef573b5befb2f4b21b9cf83ab2aaa6fd153580a0761666ade8fb94f202a3c3dc4f33297eabb4564374168\nE = a0bc148ed50a9b54036bb8fa1f214979052ebd47db8b347af3bb03b806bb457b468ba34781f8a25f289a7a90af4903dc14809a166df2f4c3527de2ea6911cb1afb9071a4afbb522a7d50634d66fd584c73f32d05217dc9f7f16394c68a692a953492ca85f89cc11da95fd8cac6231647923ced48a1b3b0ee68c010286d452836\nM = e7a96cf6fa930f73c8bdc2726bbba246001a9d27f39cc2b978c99dc6f15af0e8aaf26b565302f1112e607e2df4066948baba931b89cd9bbdea2072e05b9a4968fdf282c43d997987c3a3a0434e925a679ac81f316b7a7b724b79be3d6888b66f4512759bf66cfaaa88b9513dd27a44aaea75437268a014c4eb50ba2e50093511\n\n# Craft inputs whose Montgomery representation is 1, i.e., shorter than M, in\n# order to test the const time precomputation scattering/gathering.\n\nModExp = 9442d2eca2905ad796383947b14ddfcc341f5be8fec079135c36f6f0d9b8b2212f43e08bf29c46167ff0fe16b247cd365df4417d96cc31c94db1cf44b73b0ee3ebcc4920d9b0d003b68e49c1df91e61bc7758a8a1d2d6192ff4e1590b1a792f8be3a1b83db3ad9667d14398d873faf5d885ec3a2bef955026fae6dbf64daea2b\nA = 3a4b4c57e62c5e9d1a9065191f8268fed9d5f6f424d071acef66f0662b8210f4c029ed991512e40c9c912043c816d2c4c5b53fa0e5c253e16808aad4225130dafbbb89fd4f30cdfc1c2f2179b636a7ddc4be579795820b4b9377637bd8a21a0ef5a90d0e0f865321eee23d9be2a3b7320b4012d02941b892df2c40bdc85c1898\nE = a2c56ea1362511cac0301918e15a9afe7d37edd438a5c3538d258ea01f0a6df758de07111e868b3ad8fc89b629b4955d78a1b3af902be1806410ddde25ccc6a196ba5949395c1ad5d8725b18815dc1cd5ac1c7dd17773f571e3f2e628255af14476e0494be23a4a4dfd18e23142f33d7a59c236fec61660e360d9676a747c69f\nM = ede35a3a7afac817d413373a2032abbc067b1493f709ae6e1282ee5469743391d891b904938857168802b7872d3cd7ac18ab249a9e540a86f970b1d0f310a4cc29df1cc9d4063d98c554f1a32f4ca5eba3523cdfb142e0fc609907c7a92bb0187009d97ec471db3545f42dd5fd29c07b7816085d09477ba31fcf90084660116d\n\nModExp = a7f5844fa9e7202d4b70ee252c9846e63d3d091b0387768ded872cec53458e19df0d9b4960226e269b8ca5dd4c4eda423a67b6dbb48235c08c12c6c7c78db47287756d3ed9cecb9232f7d18d5d80b9676cb68ba4a290c97e220beb1a069976b5e6022a4c1e5ddbeec86b62dda24ffea1deda37695c9f61a8817218e6370c0679\nA = 7d6d0cc947ceb949cdc4e9e1044f5deca5bb05a491041e0d85bc4b92a0944a57c72845fad91e59010c61ad1712bd2f612d53a846a044632262a9f2e3373b062fde2484e0c165ff947f2469f743ab6e2e5e13c640fc4029b1c9213eb8473c674e7f9e95a4a5c5636d4656c1e696962340d77b322daba47d6fc894f2a2cd9e0afc\nE = b78012afe806e2344d004c739c97324256850980ac97d88c4ed9a838517639ca112e235978d21a176c33f5a68703aba0f2a05501bbe3fc8d49a000fbf530cdb431581dfaf8683cb15a2aee5e239cbc542827100da3b47babf4a16ca7c588aff9912e674abb449e0b767a15e415f4e7f2bbd6380d7131da3df8d49b13bfd35ce3\nM = b72d5c55bd2998472f1965e75a51be6155c1ba04656da8f66bcb34db36a7b1db66a89d1d05b1bde10206acf85be7b474ab689220faf1bb52ab39d8dc00512dd4e26df1179c11b973e1274db85a88c7cc2a17113abdffe58cb930ddc5f3ccc4d68b4e65c913730509f7ce5656e8bbaba9b1be177ab9f766678f018fea05da9cdf\n\nModExp = 465ff295786a88496828fdc763e9292d557957544e9322b7996807b87fdbfa7a11614bffeec557ca831c4824c8e4ca3b1a1c7f3f4f95ec3fd6a86b73bb13d78b73af2b3c7e76954d0cc03bcb0cd606867ebb3765a8b3d0108cbe4f343a14016be9c33f6d200f0dc547e7d6b02bfab1e79dcdf9c9835a814cc6c855a12ebeb66d\nA = 89ad02bea3e9ab839a6e23f20122409daba52c68e1e893034b30d3", - "21c0305434a6af940015e3fa5ca9c35230da34beeb1ed4fbce6c1da3a8bfe3f3ae172276c1d1723b47ee61e6f8fcfdafad102d6f7ee2a79f510c7edb93096205a40a6c9e665b88b18f39a979e2e61286d939952a6f02fe8148b7515bb25f4252337cb6e60d\nE = cbd6ac628cc7afa3c61bee9c22a06a395087ec1811fe9681b55216700c435996c815e7cec8aaa90016dd2382d0306a5414630124e14f3d396a4ba02ee17851bf720f1607ff813e4bbddf01338983db12f59bd6371a738eee3eeb716f21051d6174d2d6c77602942b9edaac18d4b3a723096c0d00dd23a8a605c585022f311560\nM = fa7a3e40364c8a8d0f14f0213a3f3e035222ca0ea19d46d10ba41580e5dd2805c8a133f3856d7d5d97f922ea540e5eb0d10ad04dfdbb74f518f58da0099a6fc2b3f3def92985176e07fc78aff2faebccca10a429794e5f15ff92f75fe90f527c60ddea8093a9078c703c372ca09f7aeb27ade02f3595308c61dd9c44e62fd101\n\nModExp = cf08bf00261402102e9fe03f3074471dcf0e9b3c96d4d1503f099f24ec85e1901b023e9e048c1ad042244f5f70b38b25a99f4c0a7b57d5844bb0d0137367f45f4ce2cc7746105b77414768cb97648dc5721149aed2d4c682408cc0d50d26dd0bd77e848911f8625c727cac5f32e63bcb548f41a57d718d772f23983a42f603bd\nA = a419646a6631c2c69b18f7aa65011825eb31692eecaee9d74f92d92203811b68e9764bda31a1585bdf69b6273fc6f9f508c395ac081336506525dad88473512f08a205621ac8b16e9864c7a7c5a4f17435de00d0b32badec6ce4897e3e1076c562b6d9523f63d0b2079eaa416cb090471657763f24931d955d1fa2720c80a9c9\nE = d5a6f4a1842aaee39805356dc8d0d678ee03b2c81277345beccb2742f899132feb43271f95968a01ae68aa8277201851992dc0aa7a71c90aae71b124d873ee264ea400fb131be0fc6c4ce8c04c45f6bdaca89ac743635caf6158983d257e21cef6800d7f990e912ba21bbfb8fb779afa4abd19e07e7e07eee9908493d1ca502c\nM = e739689b6cc6def1d45fb1a2ab551643beeb303f4aaa4da47ee5e4948510f8445b4c40e99ae8354dede60b2ba6694e93bc4d573b7e8adf871b7a9a9636eb7d70f2e49328e2d7978143b177cee8374ef01bd1ee2d95862765883f5e7971668b53ef0ff41b6539faf63c397522b0bdce916388e72e26c8d3d2e58dadeb9eb5d479\n\nModExp = 827e6312ec3b14600203bb83f5b277ded197b2967363630ef673240df05edd3ba8ab2b11c86251a612206569c6c33952b31e264f129909bfe723bd0ee1624b36cfcfaa893a6ec8b5a1f7de79f83e79b459a3350f89f412ad1cfd6bc4c2a7a29272c783d6ecceeb1398fa17041835643f4debef9b5e87b098d104bb8912dddf7c\nA = b8e49c637829021d32db3a39a0c1e58cdd4c6e4eda7e8e9293be379e9c2e2d184f929d278598a81ae231cfedcf69cce4a6e31cda3c8ac14d753a7311f2436e29795f0dfb60259a0f61a997918ff984aa2284b43a9d64c974059e9682adfffd018305835f74eda8c75fe4877d811c1620f654ec9f7f32d1af5ce59115e2f41785\nE = 80e0febf369d234bf1aaad4f82df2e2ff02882c3184781f6ccdf4f7cd93b6887af86830077c84dfb02109ada05b40970b1c65228b0c19030bd6361c3537fee22a8155c03b4e7007ca006c6daa3659518d05bb81ea0079456d0ef6116df248dffdb0c935f321f5a1034deefd5a9414a0652aa6548de33325b474b9e5a8507a082\nM = d5eb1d14af842a9973274f7463d90cf0ccff19c47d710edbae184478d4f29b02693ed7958bd487054327b9e6d8879e24c9af7730b92f323eeac05558da6c1b952e5dbf13de236050a77628bb5325fe0d14cc5773bf73338759d5ab43c212b414581280f1cee250007e53791b800b61c90de0328acd7bc43fbdda48158939392d\n\nModExp = 4a1efd29c7e78549f5cd4deed1454b37462c7810ee6a8a2493b764dfa479be13b314cf9ff98259517d61865567ef499a511630c0038c97914625df181c6fe07892f329f98b344a78d751e9471483eebaa7977371bf97bb25187ae7e93a9227d6c124ccb4644423c961a11ae59c4354f89d5a95164c23d9aa256e289e9cc0858e\nA = bd86c9211fa6a47a06e5016c46cb8a99e34a043a29e22f8c3196fa7197c26b38927b8d9bc0ddc11a5fa4bcc44deb69dbf37cbe7ebc9a2fad6c74e09ab5a9dd929fa04ab4319b6caad1035739be78ba631fb0748d9e53944836d37ccda6e6a62823c696d8f31139ccd7f2f86b22fa026ecf433cfb1271a3539ac4f1c83aaac059\nE = c40b9972006d28a84c2769a86e526a2b274f73afc7c5c6a2742166757f61b5f5fdbb228afa157af62af989ffe966f232bba9e6beef5403d1690ade31a6410f7f349a35bc4267a129afd647993df7d45cc0e1a1ba4678d7f1b6e8a344d8ff7037679e1f4db25a454e4246f6b55c416567fcfa188e8a3865115851d9edf0aa8902\nM = cf424d7af75ce7eef90cad75ae55ca8810cc7b4703fdb5bce701e7bac07e0c371cae06df2aa8facb55a0faa6793e4d2bd9d7969703743b9be170be82792aeea55e2bc0f7ab7617b276486bf474dee2f4556aab595ff3ef115139cfe5e21ccd4ee05c0e1cf901bd85df86cc17195a783b0be836d00bee82ce064077f9191188f9\n\nModExp = 3137a3049fd4ad2e26d870f5c998cf11bfe82101884a82e85e43facd0928cd7434a2e346ca124619769fa141bbe92ad6f36b99231032ddaec3b349a410f82b5ca36f45e56e5fb85dc63d32053dc90805d3f1854ab385281a71a57726bf97158494e7476057214ca7379ab8b70f5bdc15f70bdad3adf33c3a1f9cd1b6bbbad556\nA = 39a1dc6a4c3f14d9c350ee968d5ce139ef725952c967a2d1bedf48ace22091283525be03807e2e263d2640be77f0525247bcd07149bba50568cec5a082c87d72962cf9e43bcb5cdb1e7e9a650fb53e0ec2fad37f09a9f036c0d7dfa528fef846769f80a9a60854910ca1b4ee05dba82ed2ee018348d6b3e52a764b8ffae61e0\nE = deaee3a3f80c9f684ed7110c0653847ccc7be5ff6d982fd4b49f59b5dd35f7210b1077babbcedbc127df35cd469dc6e569a0f84e58149b5605c94b09fd7f0b098d02b4a04631328b3fae39e6c2fce25334225cab71829abdb9507cb903701559660f2c08c3b743336119d1260a0db27054cad3f28bc1b04b2289baa58fb33965\nM = 938388927d06ed3bb1286c0f06d3054cb0ee16dc7a0bbbf13a45293c09a5f40f1d611b2e1a1b0ec2ef109b508e27af4274954905cae52034f8740a744153b4d22059f0dd262ea51785522098ecacced6da07709ee6b5acc8c4e99331379a7c3de7f4e2d1431e43b19570140955b7bcba118dfbaa552cbfa2be531e8f781166ed\n\nModExp = c15ae334455d9f4d1030cd33e734726a27c63624c2afc576238cce5e0498298a4a0c93090a0d19568b41290303c4b558f3d9dd74f9cde8798710f68569ea0d6fd971ce67ec5b54495031de3d8842b8b49288725bee5c9f72b99054d64986ccd4e18d70d5f33943f08cd694eff538f84438ea993ebaba0910c95b3a694f213510\nA = def633b955a917569df3ba8517455eef0655e7a35985edda27097a063e0d82c7c3a76dc36c5d8a71ba9d540790ddd0ea514aaed98925f9a1808eb288d387aaf9605a9ef8a333ebee7ad7057bca012efd619d5867f02266f65976ef4b16da17468426ac4f99b3e8921707e01b4de20f6f9a068e6a19d872079a27f3a44449db83\nE = a465c47b0d15d48e01bb8b1d8e3b3253e11515f6874dbed6c25818adf1a8fd927124d5593beb367f685c11e46f18415be73ccdf16fa2e93a600b728163d21d232849e5278c3749d903edad3f1c4535a2f55a2ab65e7ebc64888bd2a0527e876ecf38cec3ab1980d08138709fad8eb88ae65d960adc3f0f8e92f784fe96fcb693\nM = e43cb9ac1446154356cdc31ec771c79b0e461e22d95185bbe1a279c0945e3af07903a0cb54d553380716fcdcafb4b7cf5dc6da481dc74a8c583d75ff6c1f8e429182d200246ebc473bb56e173787987c1b7fb2dd23f5b2e438a97bc4a1df628bc044fdd1e80c0cf37030adb7b04784dab827d0dcd64f0dbf37c980612570ce11\n\nModExp = 75c3f79ab7c991b98e65505342a8a563cfb08b5d3ccf8664c7db1de50256b1d17ebf7096dc98c7bb5d7f027a894ae5cbb14dee04d5d445e775ad7e239acc82673b0ac2d819a69c83864f34e73d9a636f05de8279619a067b4c90ad038db5910447e03841d2034635018f08cbcd21efa00994247763a249082594128112f95232\nA = 34def7d76f6f158a359fd12759fb889cdf6af0a24830dc3e84283a1ab4e9b2647a6a36b86482f829b2cdf3e3d6028f9a884b1f64f7262315446bea8b0231828e2f3d990fb103c17f820b39e4b8427c85643ceeca8f5dc8f191d1255768300e859bd7d88c770319ef38269660d221cb3bc061389b6fc0783485ef042b1c7d6fef\nE = c6c46453dd5aac6b37277a446b1d0c69cbe476eeff55b3ac35edb89ba97116b0e7783660f2c7b31b2a2d6c4709d0ab45d01a838100694b0777c9c9c14c959b07c437c73a5eabb7402f1001e802d797a2e7707285834fb6440a1c2f727f7bb84ddb2a49312d32fa0ce620c43872655cb5c394749c9e75d7fa25be00efe50d47d6\nM = fbbab6698a9142095c46b38a732592e4366c1838b84bf40f8c8fc7b630f73380a0d09765562365798f8c8030ed1b6728329d8bb06e882c35a1d59bfe84146a9db2afe42a414014e247390281c782fce806d62adb54778d2bcb49555459429d6ed446af5359657667f6aa19e8e3e0e24ab2bc312b2d90b5cb1ce6f2f15af15d9d\n\nModExp = ba16d7f3f6e162ce248490d164a13c00e7720d8a667e2d3ebeb13f1663e15ef5408d5b56cbc7bc793a8ca787cc50f8e15e0e9d4ee764531d04a9114eea556bb3e206ed7d85267151a056b6e68fbf35e03f2cf829708ffe1de13e95ecfe365aff1eea36340ffcd3892dee659fb1ecbe50f5080e54737c10f9c1ba638b14ef537e\nA = 9025e6183706105e948b1b0edf922f9011b9e11887d70adb00b26f272b9e76a38f3099084d9cccf12d04b1a99c0f654f8b9ed90c6dff9478c60bf05d58d734ab60eaefa14a22230ec60c90dc1f0704b61eef0bef345785ae0e6a9af7db069cf6bd2b4e0fe58a0ade83c7e46a04b9fe1d24cb9b65c6f80de713e61d70eae5b286\nE = d7e6df5d755284929b986cd9b61c9c2c8843f24c711fbdbae1a468edcae159400943725570726cdc92b3ea94f9f206729516fdda83e31d815b0c7720e7598a91d992273e3bd8ac413b441d8f1dfe5aa7c3bf3ef573adc38292676217467731e6cf440a59611b8110af88d3e62f60209b513b01fbb69a097458ad02096b5e38f0\nM = e4e784aa1fa88625a43ba0185a153a929663920be7fe674a4d33c943d3b898cff051482e7050a070cede53be5e89f31515772c7aea637576f99f82708f89d9e244f6ad3a24a02cbe5c0ff7bcf2dad5491f53db7c3f2698a7c41b44f086652f17bb05fe4c5c0a92433c34086b49d7e1825b28bab6c5a9bd0bc95b53d659afa0d7\n\n\n# RSAZ 512-bit.\n#\n# These are regression tests for code which historically reached the RSAZ-512\n# code. That has sin", - "ce been removed, but the test vectors remain. Note that the\n# lengths of the inputs, especially the *bit* length of |M|, matter a lot.\n\n# Control: No relationship between A and M except that A < M and they're the same number of limbs.\nModExp = 7f34c1cd63377bc3abf2bb5b2d1bf5f06454e1e8040fe19a72245ce9731cbee1bf9e84532300776c8021ed4f3a8de508d85b4cf320bd82065a013754857b50c4\nA = 8e4e67da6ff890643d0599387955996ef6f0c2045eb9944576ddb965ca64cdb6247727ce128ef178d4a84e5a56d2e67eb0fe389ecbf691f9244ae80f4c11b364\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n# Same as above except A is negative.\nModExp = 71fa6a4c8ae75368eda8cc6282c26afa69e2af12a97fb9444f16b7dd6c99e0a5d6034cab4248cae4357346b211039f4a2bc4c5a20a297372094162417af703cd\nA = -8e4e67da6ff890643d0599387955996ef6f0c2045eb9944576ddb965ca64cdb6247727ce128ef178d4a84e5a56d2e67eb0fe389ecbf691f9244ae80f4c11b364\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n# A == M - 1 == -1 (mod M) and the exponent is odd so A ^ E (mod M) == A.\nModExp = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490\nA = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n# Same inputs as above except A is negative. Note that A mod M with a \"correct top\" isn't the right length for RSAZ.\nModExp = 1\nA = -f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n# A == M, so A == 0 (mod M) so A ^ E (mod M) == 0. Note that A mod M with a \"correct top\" isn't the right length for RSAZ.\nModExp = 0\nA = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n# A is negative, and A (mod M) is the right length for RSAZ.\nModExp = 8d76eb0f8c7bc3160cc8bb0e0c3590fbed26c5932f5f525b48045c0bd46dda287ba5483f97c851fb7c12c2e858ee7a4a4d1af745cbfb3eb311fa54bea12cde25\nA = -80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n\n# RSAZ 1024-bit.\n# Note that the lengths of the inputs, especially the *bit* length of |M|, matter a lot.\n\n# Control: No relationship between A and M except that A < M and they're the same number of limbs.\nModExp = 8984f8c16044f9c0ad7bd72347af90f58e6e003acda92b76e3c7c4a56ea8e918409d8e9b34884d4c89d0b17cb40fe898f2627c084a0f1698e46beccbf6f48eecc281e11ea9e5135adba460ddae157f2c655b5f589ce29b254d43a960a71cede8a08dbb86be4dac22458da232fb1ec2470856827302ed772c9ddafa408c931aa7\nA = 21158da5fe20356825e72b3f5384ec57720d22f727b27ce2f945c8ee311db781add73bf8fae96b775c909bd22fca75c44c2b0584284a5bb1c07f8eefcd6b0a44047a02b185df34f897f11d4fb9a86c9eb841b4cb8d0383441fdc5af3ef385b5e8380f605d73ed41bb42eb2c2a5704d6034b3ad058dafffce83dbbfb6295daaf8\nE = ecdebd112b3b5788669449dcddbd479a203ee9ab72a9bb9c406b97623513bf0ab9a22f1f23634d269e16bfd6d3b64202b71fc355057411967b6ac70f8d9cef0a4e06819a9a18cc06bbe438243fa9759303d98be8a65dc1cb13595ee9b99f138554425d50f6fbc025d8ffa3eaea828d6f3b82a3584146bafde34da257995f0575\nM = ff3a3e023db3bba929ca4ededbace13d0d1264387b5ef62734e177eaf47a78af56b58aacc8ac5d46f5b066bafb95d93d4442bb948653613eec76837b4ffb7991cb080b6c8b403fb09bc817d026e283ee47ab2fc9af274b12f626eda2fe02004a8e27b9ed7d3b614e8955c7e7c2c0700edd079455237c4475fbd41857e206e4b7\n\n# Same as above except A is negative.\nModExp = 75b54540dd6ec1e87c4e77bb93fd50477ea463fdadb5cab05119b34585d18f971617fc1194240ffa6bdfb53e4785f0a451e03f8c3c444aa6080a96af5906eaa508862a4de15b2c55c023b6f278cd04c1e24fd0711244afeda8e3444256e51261ed99fe66beedb52c43c825b4c7a1adc7d4b111e2208ecd495df91e175573ca10\nA = -21158da5fe20356825e72b3f5384ec57720d22f727b27ce2f945c8ee311db781add73bf8fae96b775c909bd22fca75c44c2b0584284a5bb1c07f8eefcd6b0a44047a02b185df34f897f11d4fb9a86c9eb841b4cb8d0383441fdc5af3ef385b5e8380f605d73ed41bb42eb2c2a5704d6034b3ad058dafffce83dbbfb6295daaf8\nE = ecdebd112b3b5788669449dcddbd479a203ee9ab72a9bb9c406b97623513bf0ab9a22f1f23634d269e16bfd6d3b64202b71fc355057411967b6ac70f8d9cef0a4e06819a9a18cc06bbe438243fa9759303d98be8a65dc1cb13595ee9b99f138554425d50f6fbc025d8ffa3eaea828d6f3b82a3584146bafde34da257995f0575\nM = ff3a3e023db3bba929ca4ededbace13d0d1264387b5ef62734e177eaf47a78af56b58aacc8ac5d46f5b066bafb95d93d4442bb948653613eec76837b4ffb7991cb080b6c8b403fb09bc817d026e283ee47ab2fc9af274b12f626eda2fe02004a8e27b9ed7d3b614e8955c7e7c2c0700edd079455237c4475fbd41857e206e4b7\n\n# A == M - 1 == -1 (mod M) and the exponent is odd so A ^ E (mod M) == A.\nModExp = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964\nA = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964\nE = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103\nM = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965\n\n# Same inputs as above except A is negative. Note that A mod M with a \"correct top\" isn't the right length for RSAZ.\nModExp = 1\nA = -b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964\nE = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103\nM = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965\n\n# A == M, so A == 0 (mod M) so A ^ E (mod M) == 0. Note that A mod M with a \"correct top\" isn't the right length for RSAZ.\nModExp = 0\nA = b5d257b2c50b050d42f0852eff5cfa25711", - "57c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965\nE = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103\nM = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965\n\n# A is negative, and A (mod M) is the right length for RSAZ.\nModExp = 9cf810b9e89d5cbc4b79ae64e123ea06d92965e2bab077df97a1b906dc2e1ddcf96a9c4ed14e2cd96309b829ea9cc2a74a7d4b43c5f34d792a7c583201427754b8f78b783608070a84b61f18913e3ced7f7f530972de7764667c54e29d756eea38a93cd1703c676a4587231b0ebfeadddf908e2877a7a84b5bfc370ecf0d158d\nA = -8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\nE = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103\nM = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965\n\n\n# Exp tests.\n#\n# These test vectors satisfy A ^ E = Exp.\n\nExp = aa6d7ac431\nA = d0e07\nE = 2\n\nExp = 12d416b110dbb4e467ff0c89a22122f4da8240\nA = 1a18cf6\nE = 6\n\nExp = 49a3b33e23d84f1ce0d5d83f5dcb651d50cf3920f0143da2310d0512a90a06cd8f38977df8a756c30883de38df092000\nA = 2a3acbd2\nE = d\n\nExp = 5b4a0d5a956f885f275712b194459980f24708bfb6393d71bd37dce852ce455724f5ee5030775fb86b4295edc98afaafc097e4d82a97c0078ec0eac763db16549c5145c4cf2d3124f88cf9a5c71da0625afb99b26801786fe49a778415dc025954021753d08691947a208b613f0be5c1\nA = 54b3ae461\nE = 1a\n\nExp = a0ea5f6a4de49beb8fb7f0dab280d6a32c5a3814c9a5153a7944cec0a9028497846a8a89044348721a0bb5f0c3ded3e980574ea321b0cdb0ead4f4e93841ea7478a7f15d9729b646a8165813a0750e8124f5465dda9b105e1bbeff18fd09c09a2e26610d9176d253b877c3a8908a6be521cbe1e472a7a1b7820e4e890f8f28aacd34609c686e76e15b01bd9324a71290812724ea564d11c874a6765b262c3e57d479da0287a76026a1e8fe53da0b02405da1d379eaa30fc65f\nA = fccec0f6df\nE = 25\n\n\n# ModSqrt tests.\n#\n# These test vectors satisfy ModSqrt * ModSqrt = A (mod P) with P a prime.\n# ModSqrt is in [0, (P-1)/2].\n\nModSqrt = 1\nA = 1\nP = 2\n\nModSqrt = 1\nA = 1\nP = 2\n\nModSqrt = 1\nA = 1\nP = 2\n\nModSqrt = 1\nA = -1\nP = 2\n\nModSqrt = 1\nA = -1\nP = 2\n\nModSqrt = 0\nA = 0\nP = 3\n\nModSqrt = 0\nA = -3\nP = 3\n\nModSqrt = 0\nA = -3\nP = 3\n\nModSqrt = 0\nA = 0\nP = 3\n\nModSqrt = 0\nA = 0\nP = 3\n\nModSqrt = 0\nA = 0\nP = 5\n\nModSqrt = 1\nA = -4\nP = 5\n\nModSqrt = 0\nA = -5\nP = 5\n\nModSqrt = 2\nA = 4\nP = 5\n\nModSqrt = 0\nA = -5\nP = 5\n\nModSqrt = 3\nA = -5\nP = 7\n\nModSqrt = 0\nA = 0\nP = 7\n\nModSqrt = 0\nA = 0\nP = 7\n\nModSqrt = 2\nA = 4\nP = 7\n\nModSqrt = 3\nA = -5\nP = 7\n\nModSqrt = 4\nA = 10\nP = b\n\nModSqrt = 0\nA = 0\nP = b\n\nModSqrt = 3\nA = -2\nP = b\n\nModSqrt = 3\nA = -2\nP = b\n\nModSqrt = 2\nA = 4\nP = b\n\nModSqrt = 2\nA = 1e\nP = d\n\nModSqrt = 2\nA = 1e\nP = d\n\nModSqrt = 0\nA = -d\nP = d\n\nModSqrt = 0\nA = -d\nP = d\n\nModSqrt = 3\nA = 9\nP = d\n\nModSqrt = 8\nA = d\nP = 11\n\nModSqrt = 6\nA = df\nP = 11\n\nModSqrt = 4\nA = 10\nP = 11\n\nModSqrt = 5\nA = 90\nP = 11\n\nModSqrt = 3\nA = 80\nP = 11\n\nModSqrt = 9\nA = -e\nP = 13\n\nModSqrt = 7\nA = 7d\nP = 13\n\nModSqrt = 6\nA = 37\nP = 13\n\nModSqrt = 1\nA = 1\nP = 13\n\nModSqrt = 8\nA = 1a\nP = 13\n\nModSqrt = 54d4cf0fafe265056a29016778cea6b712bc66a132fb5e6b6865e9b49e4c97ec\nA = 599c10484b22d0b5a115268c7538ca99b3253a311a4ab1ca11c3665b0bec393a1167d1ad94fb84cb2c7ad7e2c933e8f613bdd08fe1f1aa4a9b0b9de0c8a7c9d4\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 38a7365a15365e911286c1be2a7afe76ef390234d76269e04dee17313f6ea54d\nA = 1c4aabb4d8369710131c664ecf2849e963c1bc31d66e0b939bacf99a870c71f24ed71bdddcf566f3908271fee43fc1ebb51eac7e3153efae641b49d2e796a12a\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 35ab18a560dece04725667f640ca61d1d59f14d191f94c79f58531acd097d444\nA = 685168ae855d60eba220d803f5296459b30a289580668db9ed51bca51cc2d453a937e13819ae34f7a9a143ac96d17420c53919167e46279b562b550be1cd9abc\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 288370029e87024175e5bec0eab0929179f42e16995e7f6194eefc61061e54f4\nA = 2a14ab77c045bdc48220ba9c463e1a4b4049cb01edb53be0937767eb2ec19b7d719855052281250a36a0b76d9a5d967d0756e1ded7a052f7056191ad66bcfc9\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 32255cf01dc943577ec2bcb221b98491d7a1130d046d6c68e95fedff643ce3a4\nA = e26f6dd46a513a1dd3fb14b71be1d4c9e9d79eda1cde10ea4d1eb8abfd4d5857572205e247184dd0cbefa37b5c0bf680ba2bd28c5741f725cfe2aae37419baf\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 5172345e801ada63fbc4782e32583cc3b4fea88b9e6dfd542f3542f8538ade66\nA = 40dafa8342b302bb04b1f3ddb3b9015a8fc1b597857c115b40631c7be9e22de89358fca23b331596ee5ff304dad7811e6d8e8822f7aa533c9e7c882634ea550\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 4dcf63c423bf0e39aca2293d57f6792d023db649d6719fe936446904b9f7e60d\nA = 5bcdb514bbe84261e169203e8017909b60c9bb330400c766ee01b0189378e70e61867a164a12643ddc9e94b61e09e5b158cbe85be228a3cc48f95a552958b8f2\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = cf77c5c2d12a500b75cbfb1f3e66ee75d886b9365cf4f8b4d1bd18a6be0f387\nA = 4652ddc2ea7b460d8ec3c9059b8f9b5dae6cac55b51f2ad86fcb336b25235737965cc515e2ff0b54835015b7ebeeda6fadd986471d8cb424d309fc353d1e269\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 1e0549e4c5a26023e9d24fd8c67419960746f82b1ecd113bdac66f570a475d87\nA = 5f4a6d450ab1390d96ab1deaa0ba18f897cb63daf0c9e1ef6c08e804c26b5e842f6c08f13db5d4a6e88f07af2a3cb04fa06fc3e59c410b9356f025ed81acc74\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 144481a781d831c1ca046ca9e322d79ad4d2c6dd9f780bea9d1ced9cd20b7b23\nA = 4c254fabca441017132b9eacd4ca40a336db3e5c09715773fa07af095989a91cc968ff07a9ff56ed06b0ce0c5269f7b2ab68564ecab9f4467a7e96b6cc6b21b7\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 216fecc7667f488a3d2d102a38b46b4860ab858300b8638af4f34e1103fd73ba\nA = 17878f8048227573a9d70f53c0e76ff13fe9f56e9c984c92514d3d13dec23c816661f0618d21371b80dfd885cb59551bdf80046f65f22ea9b89c78645a6e455a\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 458e5e789ccd2417174f7e30bb31914b9656bd8cf2b9f5a9752a8737a67707bc\nA = 5c7d39a4bb04e69201aa519f80ee7e62ea14ca55e13656d1da3f45367e2fb2d061aa2940708d02ac67d35cd2ccf54a1bf95bcbc759779e692cfdcbb3aa1a05b\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 543125a16c2bb8b8f8a2c39c497e5224ec77533602d7dbe24002e32dcbd2ef1a\nA = 3413afae333b2ad9ff45c7f3c7e5934b3127e8b1a55225958ee6ccf42423e81559bf070ad3f3353b78c0ffd41475af49f59d268ef78bdae879f5155e8d1cc07\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 10e16859c67bdb2eaab52a7c847dbf37162eda258a9f6262ebacfe4cbbbc1080\nA = 21ce7905894faf220bdf4a82a2d855994ca2dc9feaecaa53c7f146e1f49934215695e9bb46ba370b7005a90c399674caa8969eb442e7914d90f749774d7fd194\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 32a00586adc6f6cc2b1a04e1be0ab569fde235e1436c38b6af92bc5ebd60bc1c\nA = 350da4fd8cf03c12f7dd6ac6d3ab801a3413964083e374662aaf878d6838b97d4feb9e52cd307a25b113e101661a865463ee2480c626aa4e2ec437d72e7bae4c\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 971f75bc7afa8b4b50f1d4b05e52deac7d4836a08d30546f29649bf1ca6a247\nA =", - " 655ed4c5d8d0afb4f9360372ee1ef1303898d2423e585108a3303faedb55064d2ef25666ed4c4d71fe6063fea1f3142b435714b0e30b339dd791d347c884654\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 48fa882b7cb6a29de9e3769f72eb67f1efd4d2af56f0c7e410c610efcbce2065\nA = 14f3503f33b243800eac1defaab33e04c01e80163fb3efd03860970cc016832431ca4fc6d1b760f4f40166b0b8b3c40dbebc81460cc10890172243770338f090\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 236fd7e397ea7f8bc2a288eb7236ca41936fa702b7dccca56c8852e147511f7d\nA = 1bbd0980feac854782813bcde4da85e8a054549a1b515e065da4236528035e756882e29e762cf60453e375cca9dc6ff637f9558bf86646e3b928f68f82af7efe\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 693f0cbe8c81b0afde0cd2f83e53795dcae6b0cc4ba930ab5c752400d787f14\nA = 7b20f9664b23907e152ab8c9a907f72e8670c1c38ab4cd1411ea7c2159c09aa131afe068929b8e6ad1409b74c04975180d1cd0a9fa74e923c3fd451e8da2c34\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 4a086c50b0bad576501ddb6280743b2c9d247841eb7f14d90561432ff7dca6f0\nA = 4367431ec0cd0d7626538b93a090c30fe0c97c18ca03b97ddae304b619112b5b4d02bf0f041fa3fd673f9ef2ceb07eb2079d11c56dd903b1a87e8252a97b8079\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 18f8433fa468d8065157708f1f1e53b8e31d39c6011fbc2bad93de1b5548e19c\nA = 739c032bb4139c199c40f548d37234298772e4ccb9d3ba28412b60ad23b4c465b0787e2382f1c5a4a87af2d20eb978b7dcbe73f2112249477d15c8a85e54a79\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 49e3c8eef5e067cabd51a7c01384ce05ab8f4342f655559d8a689eb7b20e0106\nA = 18400c2cc3e06b99b4e39c77b9af5ff0e9c683f1708321afa4cd5b6988d13b36b1d9eb4379b7902d9ceb40c03f814b2b6a01b90509bbb4532f13ab1571c4d04a\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 35548c530745f440329325cc8a5fbd90c16a7f0788879a4869bc4d4f73acda0e\nA = 181a3c5ab02566e7166c4d6d2f2bd4a8ecc25991a98d270bde80cf4332766a7068b14240bf5f5dcd45e90ef252596da3eb05b11d68b2063f7b3a825742593ca9\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 1ab7046e6af061ade5f9719008fa4d989007e2a579a134a5b9f19ec410984096\nA = 1008a03e211fab0d45856377079bc96b0776c2d4c0175661f3493246cea2ab0a02a706c85314fb707ad9906bedb2cfd577d62092ae08ff21d7b949373ea954c7\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 2be9e3e7515960d90f115b89f60dedc173a73ce163b4036e85b7b6a76fd90852\nA = 392053a9f0100540a8e1a0c353e922068a84dad3a4a8e8962fbc0bee2b6a06e20d08ade16eb1409a16acfcac3db5c43c421505e07035ca308b15c4a6db0864c0\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 5b301bb93bdcf050183107e36258b53b4805918114ea1c2227b0911d5b4dc077\nA = 55e55e5f94dc3d7aabc921f6469d85fa2e1e92a87347c57afad5872306ae69f9fb99297d1e3e793dd9e8632244208154de5da7114fd876383bf1422f7ece024\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = 2df9609e2f5a5156c3260461b2ee52eacdef00bd8b091479813143a6c5283f71\nA = 2099325b7f12fe77353ddf3f2b2c5ef77b49671b150af954cf84e9675e3ecde3e057084641a633d19533b4712ab49924c8b5c31d591abcc88291f51253fa2a7\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = dfab751710e9008e25e422d1199d6fbec4dc7fba35b4da9d225a746eb4126a0\nA = c006af53d4737fb293584df6ffe2e4cb3fd8dc77fb7c1f13b97bb9c249e3ee5fb9feff7488265b3093906c08a4946f142ac7b491937d24bfba6413366ce371d\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = 26bc030008d6c60a09fb0e16093a649fcb40c6c21a8e2da2353ba4b07c4f85d5\nA = 1eaabcfad2ed349ac9356e6f4da0b301266ddde811cb0f817aba8f5c10fb8b8ba9d0ef2dd386b668f16eac296118fdb8cb7afe1b865648c81c2fa3cf21f2711b\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = 35051b1482ec2578f3dc0000a422cb5111e43c37f1ac20b1844d3de2128c4556\nA = 315ff9de178681116f2a5fa78eebf4818e1d680435eacdfaf9d0e5c4fc01fc034b352c82fd52c81ca30d68864952dacc99d08269c9dd7ca99ccf22da98c3840\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = a5474252885cacf004c460a7793ff0b0a2187bb1a9ed700ae3470199faef71f\nA = 19856fc1351c4b02abf573bb2fc6ff92355fa369d62bb8f2260fa772fb1693f509a56cad661930abcac049dd70f4b16bed4a4c172e73e772504c9990ce7f92f\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 12daf4722387ecf47de1b0b6b110a062dc5ea2685bc9dbde66b8d15622985029\nA = fb8479787069116abc42abfd7dc0c24d2ad04fe0c04b42a6dff714af715d17e0fd77855f950f264542b06d48e8818de813ddb7975798b7debefcdaa5ff86beb\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 397996ed5c0ac6ad32e43c337e9de421b87774cc162bf7ac7bbedf4a9029255e\nA = 5aa04353321bd2de92481be740357f979da464b53aa39111fdbb734cf7af6b3857d1baa08d3a126a3dd34a2fbae2bf2b84e900686c1d31505b390185acef5fe5\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 2cf4b844a54ba359dc592ef1b49f43fcfeae84d1087edfefdd0b9174b43c0a3c\nA = 365a8650510bcfd8fa87432f167cf487234c215857403b9270b5eebeafa48cd6da47fd60dc311b94d1d72baad0447c31f0b212d755f46c256e16e5e015e6546e\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 9277c73043ff767c3fa606f0cd66b9d854a600c8c18287f191ce277758c3f31\nA = 62cec3901626d03e8df66299a87c54b1f7a55cafc99f0b6bba1b5d51a3d2b7d2171c9135a9d8a5346d436e0136b12e515e703e3cd84ecfe154eb94c6772a6d72\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 4189e5a90c1b1abdc1c7c05b3587e6f362e06f927b6cf5f0d271aab3d6f90765\nA = 336b8d0f9dac842c696bc020f49c6aa023842c16f2052eb02f17959006554ca0012042c80c72590f21c6bf5a3714c9cb552aa69730e33db93a56a909b273f39\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = 36ccd38cb5a6bd8a73bca55936a2227c503664422c2296faf7e2b1c6a375a43a\nA = fecfd60a376befbe48d2c4f6d070d716d2f403cd5daefbce62b720df44deb605162c8f20f49fd7ec30d4f8e70d803d45b3a44b5d912baa3410d991165d7c507\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = 198fc8569be172dc9b71023ed3d42d2ba94bae4099643f6517ab03f540527fdb\nA = 65bebdb00a96fc814ec44b81f98b59fba3c30203928fa5214c51e0a97091645280c947b005847f239758482b9bfc45b066fde340d1fe32fc9c1bf02e1b2d0ec\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = 21b7f74c30ded681d6138cf8e6fd798f32a049e94138e982f1845df3dc9e686f\nA = 9a30b791c1ba4f394b4e3dcd5837e474237f4fe8987b255c098a47b2c14c598ec69d2beae444dd4fe9c4ede8173d2b187677cc706a3c28f3b81627d8a5fb6fd\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = a1d52989f12f204d3d2167d9b1e6c8a6174c0c786a979a5952383b7b8bd186\nA = 2eee37cf06228a387788188e650bc6d8a2ff402931443f69156a29155eca07dcb45f3aac238d92943c0c25c896098716baa433f25bd696a142f5a69d5d937e81\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\n\n# NotModSquare tests.\n#\n# These test vectors are such that NotModSquare is not a square modulo P.\n\nNotModSquare = 03\nP = 07\n\nNotModSquare = 05\nP = 07\n\nNotModSquare = 06\nP = 07\n\nNotModSquare = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951e\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\n\n# ModInv tests.\n#\n# These test vectors satisfy ModInv * A = 1 (mod M) and 0 <= ModInv < M.\n\nModInv = 00\nA = 00\nM = 01\n\nModInv = 00\nA = 01\nM = 01\n\nModInv = 00\nA = 02\nM = 01\n\nModInv = 00\nA = 03\nM = 01\n", + "def8105ac28f2ecc8598ec0c4bfc9c1c80222fffc776722eb0621cdd8a0d55f08767fc2922282a76e529d81e4d6e21a2542b8c9a403709ed1132e3b52786b81e684591438fdddb5df2f0b72e6b39cd2db6c0cc55c759c2dc1b6ccc20a5cfd10c6fd345fc766035c7478570d4ac534db3fdb718e2bdad3d096b137bfc09a562043800957e2afe4fdcfe292881f6189edfce52370c0438c2822ce3b14d73b3eff32f7e5ca97e989326b4e3a8fa35544193f8590bbb0ddb1f914894ab87998090771a0be1fd23917cd792be86ea0b98e6eb24\nA = -ec953f1b7ba7d561edaaa23076987daf86f50e9a66c36f0993290549a9006dd9d424885c0fa77295cfe34fc81c5edce9e2371b3039ea18d8f998d1956196284e6d81eb1c62ecaa8cf3fcaca28ca7e64342803c8dc3c139080bdd4a1ff30d7288b085a579d9e90903bd363b48f2072bb6fbfbd9ba2cab30a8a63784d246\n\nSquare = b33f4f3ae453058f4e865ec78f0844bab7af66a97dc2f265ca73ae2232777474bfdda39e10652d7386c16f145272192af728893c3d8a8e92c60d77722b924c30269ff5a399a2449ce15e50320c528c22655ad06227ac4efe5a993179ec61c2fc9115f89d75b53961fd16f7797657f6fbf55662b019608a1d30f64a2c0838e0018b7526921fdd34fd462bfcb2462b7065e2bc7abd57d71371e45dfd8fcfcc00a71f7e45430820747c9a060b72e4f6d2919cbffd00beb0c31a2bdc32afe2cc540b38dd04a2b73ae5ba481a6e535f37a757bbd6aaa972986213afadfa47cb7a15a6f1d443f93cb0ed824a10b4b7d82cae524a096b65ccb39be3c37c07f59\nA = 358da59ef65f62f633675764e292e5a68879df24a4727eca1fc4d232b3a6d936976c92eeb11456b5e8c11319838c145c6529d2f3acc828e55b8274bfe9afb5db241b102715f8e8164e454ef39f13ff1b37cf367a5a66c4f743c750896b7c3c29026e448bb36c6c06b0d9a3d048086ef0c3cd922a02e794223f388b5d646db\n\nSquare = cd4246489f6f221f920acbd8bdcdd17f47d2b77268f72254de4190685c123e8c5eab8517fded1852e8316c9e549d3fa355142d91b2921a3c94aafd8862cd2235429340da38a2af131b8d002f17662354f5805f6a7af7afb6dbd2f641036600614cea42bd8b24d86a5109eed29c0865a5f30c5291b1d1ef3223f9b9826dee773d98ce972da92daa19e843f84ca5f1cd77925a3c1117242ab0fb509b94a83f8de4fc8d21f856f37a4d025b3024bd0dbb6d8acfda4ab2993fd6eb7a7448d4f66ec725d37f0eb14eb242c0ff3f0c4572ba6b98a4ce905fe1b7ca3daca56c225171428c56af938fb66b37e99e54139157bbf41f536989ef813af738837afcd62290\nA = -e53ad05c88568f09f616797f0b7f2756fb543d691ec2a5b645c1e5892a247302826419a35b1348cfd2c1c569c23c31b4c46d6c57d4a488c29ab5beb77904d4adfcd0a01ea0a26bb0cc8790441cc2c8c900f030d7315b4319f1a3cf5685a140e03abe6b94730ad79e8de1f4a0cded86a3d6cfe2db267fa7dc9b2bb32872a90cc\n\nSquare = eea8028b26e0df090504d54da714a6f5f2695202e53cff479c78aedd47a8dc676243ec586740fde53b3eca9ca02b91031ce766242184109503fbe25b1b6d318e3cd5970fabd16dfa22984dd2e9f1e0f14c189170fc69c031d66663703e6235a942d51a4545bd7b0769d01d302ce2b00b83f01568a1e378f61fd0ca6201b0490330580cd9de85719e174a71915d7efbf65cd73d8f4e66f27e0dd3144d58ec09ed0f7ed7d1238ee596922807100fb7a11127944ddcdec6a9ca3bbf6df7301e354f3f049bfb7c275b43c3d8cda5907a932fba507c9145ea3166081c1b48fcc710ee32cd931f936c796b14f8a78a592e67753a7c9e428a01719c8ba82652f3a89fae110\nA = -3dcb44be1e54c5a5d7db48055ca9afa1ebe2ae648aa6e16ac497502a7deee09ffa124720fad0ab163ce8b3ea6a90f110ea52b67dbc424d0cf1e8c9726dfd9e45bebcefaa5cd5706edeed27896525f31c6bbea3d67ee97badefabf3e2532470b66e3ae3100f66ddf50cf02fc3a8e3f44c304251d3b6a7ca3a6e4bd5d16a41bd97a4\n\nSquare = 0\nA = 0\n\nSquare = 1\nA = 1\n\n\n# Product tests.\n#\n# These test vectors satisfy A * B = Product.\n\nProduct = 5befab3320f8f90542f3120235abd926aac3805a19e343f690\nA = b057af553afb120db6b7764f8\nB = 857734c4c27a1d17f7cf59dee\n\nProduct = -ab1ce167f4b2945c55ae3f87df50ad07d4be87cf9f8aa07b0c\nA = ae7a6a87ea8981a567d0b3ecc\nB = -fb0fed5f8c737bcacef4d6cb1\n\nProduct = -c2606cd48e6b075c8da79eb4668e7157f1f175c2860fd4c475\nA = -c28dc31984d4583e9d45424c3\nB = ffc4581a5c3f885cf42767e67\n\nProduct = aa6805b5408aff7f914472756da07830dcad902834dbdd6944\nA = -ffa07ff9f503511954e5dd3f9\nB = -aaa7af472ad8957763f5a7c64\n\nProduct = 58ca2569173389df29b5ce4b784086055dee821a7243db7210\nA = af417d936f4690008811a1ae8\nB = 81b26b80b43aa65aa55ded52a\n\nProduct = -a043d31dfce8bd01724d31c863d0a64f1bf013509d77737c42\nA = fb5fae5edefb6997d44a1ecd6\nB = -a336e50c6f7845a1686cc88a3\n\nProduct = -b5d6a45ffce851b201239d938ba551bab7dcb59fc11fc35fce\nA = -f918faa58bb57a2ffb8b01f05\nB = bae08c3006fade695029a1df6\n\nProduct = 6f2fde7d1a18625d727c6345ed85e597d546d9228bf7f0564a\nA = -8d108d7a16f0696d4ceb24445\nB = -c9c764cae465207097ef8d2c2\n\nProduct = 93808b1140841dc9735cd61c6f855ddbbb83066689b0d7e1a0\nA = b386d08daf3fa2154e9c768d6\nB = d2557dceb2d02d04d9c578670\n\nProduct = -ad04212ca8cadb1f7861c5130ba3a747046a2a7e4a0c72b69a\nA = e4e5f7d1311e0c5f2e404d55b\nB = -c18057a328d8c7375afdfd4ee\n\nProduct = -685e75c232f2b4a0e455fe5ee8aea52f292ad8b8178320e692\nA = -a683312f132b2320632e74ef6\nB = a0758f12791453b4af354730b\n\nProduct = 6f588c53185c503dc5b0dc3002d3817ca2e7eb2370b3e9a647\nA = -d70c9b93170261091f0c53f27\nB = -848c86c51a186ac4c9080d3e1\n\nProduct = 5e3bc5a04e054a9a244bf7c86cae215072fdb70e9199989427\nA = 898b64ef09d7cf63966e1a3b5\nB = af638b12f26aa5d12e97439eb\n\nProduct = -8d8372b235b16108285203c03a8aef6fdd3c0e1a9fd31d4f68\nA = f6003dc83818c14fbe36c9998\nB = -9343f6cbcc81fa4c9399dce5f\n\nProduct = -5ee6509abeeb7af7fc5caef40d1822ad3150c8d74f522dc7c8\nA = -875ff6f56ca72cbdf614bb9ca\nB = b375a68a21dfb1f159c22fa14\n\nProduct = ada25be404a17385af5a330da799e5909da81bfa0715baa6f4\nA = -c9b8df392e76abc3eb7d5ce04\nB = -dc5ab818c70594dd917b4243d\n\nProduct = bb24422ee4656ddfcd50ec38201b15baf679d3b75e5cb878ca\nA = f8e12cf4defe388b78510f687\nB = c07ee817b4ae95c2915b88966\n\nProduct = -93da296ba164c7220a17330647aef0980c94eddd2cfa2a3b2d\nA = bc5dc74ddf7a1363d1c2b1f25\nB = -c8f069bad7f93cbfe6df51169\n\nProduct = -6b2e1d132c4e0b0dc9b7e7de7d424fda5180480cb5ff47c755\nA = -a8048acb66a8bb88df39266e7\nB = a34e0b265d71435ae8c92a463\n\nProduct = 6ccb2cd93783576a8602ae43f41c786008b6623a4cca0a010a\nA = -b071f1f54790c951c1dd2a1cf\nB = -9dd89bb4d9b546207e282e2d6\n\nProduct = 5c742ba47d0d64bd97509927ce957deedb855766cc24c60016\nA = b44f3f252c368096fa62747f2\nB = 83439b97dbac579fa4f7b7d23\n\nProduct = -7347ba65691c913286c2fb55e45b177f031c1d86ae0e9f654f\nA = 937cf0643ffa53cdea24d642f\nB = -c81881f78243dd5737a7d28e1\n\nProduct = -9bc0649a703674e59f83ff9b8a560e5cbf51f65ca310f80f95\nA = -b536f8d9769be6f62da941ae5\nB = dc0746fb101881ae0cacde6f1\n\nProduct = bf4992fc3a124de350f9fb90ea825cf663b1fa051282ef22e2\nA = -ff7eacc7de1bb01d668c693aa\nB = -bfaa6627f9fc7ba68ae41bb2d\n\nProduct = 7c8992d34cc0b63f1c953f68d4e12a99d3f3a34d16bd76caa9\nA = 9e0d5a850d078890a983c0ec9\nB = c9b72c118b3e1f1023a696ce1\n\nProduct = -a75840c95082b9a0ae0d6e0a4eb5e09288e4e2a66e9697d9cd\nA = b2b042a21045a74ef1a5091d9\nB = -efbf8b120b384e869692a1b15\n\nProduct = -a510b333bdb4ed7479c142e8fbe2b12f7671a42acbe16c0998\nA = -e7fd5e0bb5496b9d876c27f65\nB = b6262653b2be44501af1d85b8\n\nProduct = a1c1e90afc4684754155526e307fc6ed798746f347bae2c880\nA = -b84674832b26ded0a690a8ff0\nB = -e0b7bdf2fd05a038ed3640b78\n\nProduct = 5588e0c33bffbefcc5695ca0615abd383343f21a8a0d22b222\nA = 80cad81ad9a66ab6a1c2e5669\nB = aa0453a77c8af1584f54750d2\n\nProduct = -6460c2fcd6cf3304ab163ea883ac48e2031cd10f2e9014c0ab\nA = c49ad3d7c8848d4fbf913b10b\nB = -82b3dedbe3cc7cd532ad632e1\n\nProduct = -a18717330b711669e85abde8c4dce426529aa621ba3da2a477\nA = -cab4a9c0a331a5a5e826dda1f\nB = cbfee5041c13075dfe3399aa9\n\nProduct = 8ab6282ee892b53c083d319a9dcab48af97a1ac8493c0bfcad\nA = -f7d13e47f9aaac8c25f9bf75b\nB = -8f4aa95231c1e2336aa092297\n\nProduct = 8f2d1c23c78777ed371f13155445ca3c88cbc0a9b299bdf9d3\nA = 9d8248d00defce1ad081337c3\nB = e8b479295ecd9cef7301f24b1\n\nProduct = -86d5e0c5b581fe59819730b4b71e33d1f85f9ab504c7dbe2d6\nA = b21b45e88acff48562a19729a\nB = -c1cdfebccc763beeac394b997\n\nProduct = -484ca05aefa113bdfcb1bc623f730c9f9555b462a8ab4c9606\nA = -8c12b406c02c4417163c0956b\nB = 8422b15c80c1c087b17eedd92\n\nProduct = 614c3c91f60050c785fd229a3ad74674577a90cacb654e0a5c\nA = -93d45bce155a23a397506d96a\nB = -a87e339c3fd5aebede5fb1b36\n\nProduct = 9683285f194a7e4feeab196a36bdfc4f828035fd184b9cc692\nA = f196d8fe760fdcae7eb60e2f7\nB = 9f7d88a2163ad818bf3a6377e\n\nProduct = -988a64599c19cc64f3cadc1a83fea6550185f6cc3ab82af822\nA = d0584b2a306671e4d2c9d0c7b\nB = -bb6e7559df199c68d6df3a3c6\n\nProduct = -68456814cb0edd951196d04c853172afdd5787a5bd69a57876\nA = -cefce1b0a1fb22862418bb597\nB = 80f614139947aea5e76cd55fa\n\nProduct = b4b1cbf5d6566e7a57aee0cc5c9c8ec4ad885e8766aa7662a4\nA = -d68ed1bea046c6cad057e21db\nB = -d7988b9be54f6e332d019032c\n\nProduct = 6b09212675ff5257a1384371e17b37dcc268bbb141577902e4\nA = a8208053adc20a609d5d01404\nB = a2fa927c5458c4fe662d7a3b9\n\nProdu", + "ct = -8361bc26f9bcf55f677e047d822d3004027da0d0455b244d10\nA = e82b6410b29020c2d6810a977\nB = -90ddfe0e7f0d6b9cdc0815f70\n\nProduct = -f1b6da00923fd513a83e32040a515649fbd362f69ebc016d9f\nA = -f9b697d9ec774a8d1ee5ea905\nB = f7ccb46a8869cb028492bed53\n\nProduct = d06206963f2e150bacdb32c823c3a47f013d5a267c3c0d0c88\nA = -ea8e63afa99c719897ad7f2ab\nB = -e36f11f55b6148d1b4f46e598\n\nProduct = af774a5eae6084df5ca499ef005642730adabf6a4f9533e2fd\nA = e4c7af7eea3ec9cc2443b7319\nB = c457bc264c8461789931baf85\n\nProduct = -76350f428bfbb95e6c253ec0f457aa84cebe8c7cb1af2a2120\nA = 8fd1ff97465775d44dee58ae0\nB = -d268a7d328f44baf80e35119f\n\nProduct = -787ae3f114f9a8dd4d249d5d3f3b0897b02564b9469416cefe\nA = -bc0b398bd0ec045b0cf147b7e\nB = a4050955c234e473257d0c641\n\nProduct = 9d6320b3d4aabac097a079b9bd2aca7f1898bcab0f23409fd0\nA = -9d7a4ebac630cc0662b816fb5\nB = -ffda517d3eb3214986b04e290\n\nProduct = 80bab8bd800ac8c9dc3bb57dca306f10af6fd88c5d8314833c\nA = 834bc50140d6c6ab938dc58b6\nB = fafee47793cbc533b3c66af3a\n\nProduct = -b08920f5922226b1dec87151ae087d8a7e5c1aea8c9be148b6\nA = bfd5b1ad323c79428cb2db36a\nB = -eb956a10edebdd658e6810fcf\n\nProduct = -6d428e08e8350bb4b0fae3b662c82df2aef7beadaa17430dbb\nA = -a57da276998c548101f514e9f\nB = a9040c1909712e1149d295765\n\nProduct = a57da276998c548101f514e9f\nA = -a57da276998c548101f514e9f\nB = -1\n\nProduct = 14afb44ed3318a90203ea29d3e\nA = a57da276998c548101f514e9f\nB = 2\n\nProduct = -295f689da6631520407d453a7c\nA = a57da276998c548101f514e9f\nB = -4\n\nProduct = -867614005cc204a8d19720fe13\nA = -a57da276998c548101f514e9f\nB = d\n\nProduct = 12bf3b676f64e5929d38c35e803\nA = -a57da276998c548101f514e9f\nB = -1d\n\nProduct = 24d8f92c68303ed0b96f91a8167\nA = a57da276998c548101f514e9f\nB = 39\n\nProduct = -49b1f258d0607da172df23502ce\nA = a57da276998c548101f514e9f\nB = -72\n\nProduct = -6fd5e6ca25c3d51b2e529f22173\nA = -a57da276998c548101f514e9f\nB = ad\n\nProduct = 1276d4705b81b82da4c7e82559d7\nA = -a57da276998c548101f514e9f\nB = -1c9\n\nProduct = 1ddb9abfc5d4017f068a67b5f4fd\nA = a57da276998c548101f514e9f\nB = 2e3\n\nProduct = -3a8b41c914b1b4a4e341433601f7\nA = a57da276998c548101f514e9f\nB = -5a9\n\nProduct = -97c0f4ba414d6e7d4c8b7ced84d4\nA = -a57da276998c548101f514e9f\nB = eac\n\nProduct = 1198739e0c23639c176d46d13f7c8\nA = -a57da276998c548101f514e9f\nB = -1b38\n\nProduct = 159150954ee0dedf541e4dbac0ec3\nA = a57da276998c548101f514e9f\nB = 215d\n\nProduct = -441d4bc44c86f02ff12c3d91a1562\nA = a57da276998c548101f514e9f\nB = -695e\n\nProduct = -64726b76005ebee27592237ba5dde\nA = -a57da276998c548101f514e9f\nB = 9b62\n\nProduct = bbe4ec7cf7c5bbd198e0ea86bb658\nA = -a57da276998c548101f514e9f\nB = -122a8\n\nProduct = 21f717d05681fd2eb1796776a69ef7\nA = a57da276998c548101f514e9f\nB = 348a9\n\nProduct = -396ac788a1748bc6955f99be4d2c64\nA = a57da276998c548101f514e9f\nB = -58d1c\n\nProduct = -54a213eb083aed1a04f3d1b2da62e7\nA = -a57da276998c548101f514e9f\nB = 82eb9\n\nProduct = 1366fb9c20fb14b8b9a9be4b3e3dde1\nA = -a57da276998c548101f514e9f\nB = -1e037f\n\nProduct = 238d65fd26da4733e5d93ab2485d40b\nA = a57da276998c548101f514e9f\nB = 36ff15\n\nProduct = -38272a99be154d531e922be405aee9a\nA = a57da276998c548101f514e9f\nB = -56dd26\n\nProduct = -64651b62b6a454c08951632c7f2c398\nA = -a57da276998c548101f514e9f\nB = 9b4d68\n\nProduct = fb272e3597b816144f8b945ae6130e0\nA = -a57da276998c548101f514e9f\nB = -1848320\n\nProduct = 280d9f5ed7243712ecb9a7c6358bcb8b\nA = a57da276998c548101f514e9f\nB = 3df5795\n\nProduct = -2fbb6bb8e1ba78cefc47fbbc20e188ee\nA = a57da276998c548101f514e9f\nB = -49d6652\n\nProduct = -57f29c13691ffa1642d2860dab9d288e\nA = -a57da276998c548101f514e9f\nB = 880c2b2\n\nProduct = 139c19d7668e6aabf2d7206cb0723ed34\nA = -a57da276998c548101f514e9f\nB = -1e55aa4c\n\nProduct = 2950ce04bf0cf836d4fe94b88fb757d0a\nA = a57da276998c548101f514e9f\nB = 3fe968b6\n\nProduct = -5175239488dad05a58414251496d2a06c\nA = a57da276998c548101f514e9f\nB = -7e020414\n\nProduct = -945ff0ed38bc6020cf679cbd3e0758c6d\nA = -a57da276998c548101f514e9f\nB = e585e573\n\nProduct = 11c69ae98f6b27e95477986f796bc67c8c\nA = -a57da276998c548101f514e9f\nB = -1b7f653f4\n\nProduct = 209afe75e8fb5ac76d13c06b545f5d4d73\nA = a57da276998c548101f514e9f\nB = 3270154ad\n\nProduct = -386d64b215e41506514f4988ed237e4da2\nA = a57da276998c548101f514e9f\nB = -5749c891e\n\nProduct = -6c13cccdb1d140d0babd52707ea72fa278\nA = -a57da276998c548101f514e9f\nB = a72fb6288\n\nProduct = 136228a8a45540372b9b3cd7f82021f6546\nA = -a57da276998c548101f514e9f\nB = -1dfc08a2fa\n\nProduct = 1f0ad3babf9d132eaa08cf5cdb8f19dbf01\nA = a57da276998c548101f514e9f\nB = 30050f2e5f\n\nProduct = -50d615ce183258e95af77319b766fac81e2\nA = a57da276998c548101f514e9f\nB = -7d0bf92cde\n\nProduct = -817d358293b86a56a4e881e50257c549471\nA = -a57da276998c548101f514e9f\nB = c84efb12ef\n\nProduct = f09b9e80be251de474d726b16e25a6865fc\nA = -a57da276998c548101f514e9f\nB = -1743322a484\n\nProduct = 22996cb0f9c60e35dce49f3825f8a479db26\nA = a57da276998c548101f514e9f\nB = 3585acec11a\n\nProduct = -2b307a37c91791a61c0691858f5f783e4678\nA = a57da276998c548101f514e9f\nB = -42cf6be3e88\n\nProduct = -8826698fcba6c30d755fc523de1cc25301ae\nA = -a57da276998c548101f514e9f\nB = d29cc8af592\n\nProduct = ae37fc99fd419809310782714530d7428d77\nA = -a57da276998c548101f514e9f\nB = -10d8059d4a29\n\nProduct = 1d544a20f9bc7d95ab67d1f65743979f23bba\nA = a57da276998c548101f514e9f\nB = 2d5eadef1c06\n\nProduct = -367897184e9929a0294d320f10278889fbeb7\nA = a57da276998c548101f514e9f\nB = -54431582d0e9\n\nProduct = -943a509076a00060a2e7fa1cddb7468d734a1\nA = -a57da276998c548101f514e9f\nB = e54bb102f4bf\n\nProduct = fcce6e42879af5ad13545c0bcaab85b690cea\nA = -a57da276998c548101f514e9f\nB = -18711db522cd6\n\nProduct = 258c49f86d0cbb14ae9edbd3456be8cede2022\nA = a57da276998c548101f514e9f\nB = 3a1562c7c269e\n\nProduct = -4a8bbce59ad7daa51136d557f7fa16e9a2faad\nA = a57da276998c548101f514e9f\nB = -7350e780b0f33\n\nProduct = -82f53ec9333275d5cc271876a7db936db49280\nA = -a57da276998c548101f514e9f\nB = ca94ad312dd80\n\nProduct = 11daee4fcc713db5b2806e47fa5dff3b5b770eb\nA = -a57da276998c548101f514e9f\nB = -1b9ed6758f9635\n\nProduct = 17038cac4f0c94dc24985ea108ae6682e175752\nA = a57da276998c548101f514e9f\nB = 2399b8a9b1116e\n\nProduct = -37e5f14394bf347a3ed061769fe8e6424af4348\nA = a57da276998c548101f514e9f\nB = -567840a7569fb8\n\nProduct = -9253d4a32a88d8f725984514d969012ead7cc9a\nA = -a57da276998c548101f514e9f\nB = e25b246f733f26\n\nProduct = ace3648371c16a931d29004e79f5b9678391da5\nA = -a57da276998c548101f514e9f\nB = -10b717b27b6a13b\n\nProduct = 1faa5b45d04c143c339b09d3aad94d39b94ef960\nA = a57da276998c548101f514e9f\nB = 30fbd672e106aa0\n\nProduct = -3fdfe246d27aae0d08d63b2bc501461d2bff3b8d\nA = a57da276998c548101f514e9f\nB = -62cef5f078a8253\n\nProduct = -5b792bfaeff04ee3d948cb343a249d49eb344f57\nA = -a57da276998c548101f514e9f\nB = 8d805ac65649c49\n\nProduct = c5f824406161eec321da5a58e3e00d393b55abe9\nA = -a57da276998c548101f514e9f\nB = -1323dd41d2e1e077\n\nProduct = 2226dec8a57be8e84e42559007e2d101ccbe67f8d\nA = a57da276998c548101f514e9f\nB = 34d47842b5d0be53\n\nProduct = -340f50f812c7420b502000940788a700f6769788a\nA = a57da276998c548101f514e9f\nB = -508836d8e1193d36\n\nProduct = -a00f1d96e19c590479625c5329a87774b5964cc78\nA = -a57da276998c548101f514e9f\nB = f798fc858657f888\n\nProduct = cb94f830cba8997331912a6a31c34f1bef826d121\nA = -a57da276998c548101f514e9f\nB = -13aec7a5c52a0883f\n\nProduct = 16b45140b048d6dc0b9fc811df7ce7dd88357fff04\nA = a57da276998c548101f514e9f\nB = 231f27f3e347bd67c\n\nProduct = -2aa94179351b4e87de5849ab619d94f47450640199\nA = a57da276998c548101f514e9f\nB = -41fe3ec2189599cc7\n\nProduct = -5489401d3da93158d4284e557d74016c0a7cfd935a\nA = -a57da276998c548101f514e9f\nB = 82c5281df41bfc066\n\nProduct = ae04d5b212ecfc9a6d7df07794d565df52991fb70e\nA = -a57da276998c548101f514e9f\nB = -10d3139229f5d02432\n\nProduct = 27821bc811f45d63089790b41d307be978d4b19564c\nA = a57da276998c548101f514e9f\nB = 3d1da85cc012b3e234\n\nProduct = -3de3c9e9d7fa3020a578706339314890dccf63096c2\nA = a57da276998c548101f514e9f\nB = -5fbcfb28bfc9044bfe\n\nProduct = -627dcb299a6720044abcf11469bdfd3f951edbb5bf7\nA = -a57da276998c548101f514e9f\nB = 985b930517b78e6ba9\n\nProduct = cc0622441497a37fddf1856d5e2c99df52b99ea4573\nA = -a57da276998c548101f514e9f\nB = -13b9b88948fb7e95cad\n\nProduct = 1a5168e1a492210591ad1ed660adde9110390e4caf32\nA = a57da276998c548101f514e9f\nB = 28b631c6e04b6ab0d8e\n\nProduct = -4d8ec27b7460ce616421b9f5cae708c2ac241daa59b4\nA = a57da276998c548101f514e9f\nB = ", + "-77f99bdf1eb09da6dcc\n\nProduct = -55afd796db7bce822a00073fc8926d3bd0c79772f036\nA = -a57da276998c548101f514e9f\nB = 848cdd6212b9bb3620a\n\nProduct = dc494b0d73e8ec07cd2bb6dd8191d2b4d48e7700cc34\nA = -a57da276998c548101f514e9f\nB = -154c39567bd8be5f6b4c\n\nProduct = 240e9301b4345b914ecd91a49a0e651524dcecb6fdc6c\nA = a57da276998c548101f514e9f\nB = 37c6e7ee89cf87674814\n\nProduct = -39002ecfd6d96661b336157ccef6536756ad2e9219be3\nA = a57da276998c548101f514e9f\nB = -582cdab09915a652203d\n\nProduct = -695f49fc891d53f396f0593efae3973082b76d4f9e944\nA = -a57da276998c548101f514e9f\nB = a30074dbce2246af043c\n\nProduct = bba2b7b45b97cb0d7fb30fed95089870742ad69e7aed7\nA = -a57da276998c548101f514e9f\nB = -1224195afc7b394ae8cc9\n\nProduct = 1910edc278515ab7d4cc09b496dc3c06c32c75bc7368af\nA = a57da276998c548101f514e9f\nB = 26c6701c39334169e7bf1\n\nProduct = -3670b7f9b661aba35ce50984d83173c84c8fa60e04d100\nA = a57da276998c548101f514e9f\nB = -5436e84b4a29858a68f00\n\nProduct = -7fa0d3e0082b37475342b7e22e5dbad7b8d4cb5d64f871\nA = -a57da276998c548101f514e9f\nB = c56e0f44fc63bca242eef\n\nProduct = da7fe3367ce640fa5941c033ac1874312f10ba5950da75\nA = -a57da276998c548101f514e9f\nB = -15200043166ff309f0426b\n\nProduct = 1871d72481f66b1d413100edd6b339cbbaa67b3b2b3cd57\nA = a57da276998c548101f514e9f\nB = 25d057879db26fa29a5e49\n\nProduct = -3cf1dd1e2df3456757d72f35353c3c7a659b2ef844ad857\nA = a57da276998c548101f514e9f\nB = -5e46be70de21949df67349\n\nProduct = -5e861cbe47aefab2a7ea59292aab1258932b9a322f66e63\nA = -a57da276998c548101f514e9f\nB = 9238670897685a6c9cbdbd\n\nProduct = f623344788efb857db55c924e95a437effa4dc8bb2bcd24\nA = -a57da276998c548101f514e9f\nB = -17cc0ec84c228225a7cf45c\n\nProduct = 15514c916b0ae7cde6add16c629d3e19ba52a101d75dff72\nA = a57da276998c548101f514e9f\nB = 20f9f925b3ed307edbb154e\n\nProduct = -460cf5b14f9d0b547c3084bf44207bf881745c409b08d07f\nA = a57da276998c548101f514e9f\nB = -6c5cbfd29f3dae1dce99221\n\nProduct = -5ddf7fb91d765af97dfda5333d8779e80837c2b51cfb4f43\nA = -a57da276998c548101f514e9f\nB = 9136aa79080defd1bcf90dd\n\nProduct = 12c1a0edfb6ab6a0caae2553fb3743827e1470a8954e0a3fd\nA = -a57da276998c548101f514e9f\nB = -1d03b512470dc3052779f3e3\n\nProduct = 28388a244214abf046488a8d95308d95f021eae4b994a5a52\nA = a57da276998c548101f514e9f\nB = 3e37dce784274962ff862e6e\n\nProduct = -4da476e76119deef291c0f56934a912a0877278a19a561ee0\nA = a57da276998c548101f514e9f\nB = -781b2f2dc40094a7f8fed520\n\nProduct = -5792496d33dd45e225f9dfca17419a04e075ffc0c90b37b82\nA = -a57da276998c548101f514e9f\nB = 87772a4fb582acafd3e4ef3e\n\nProduct = dd3a3506a7d748de16fb43d666928a87de0354d8e8a1bcaaa\nA = -a57da276998c548101f514e9f\nB = -1563841bf7851ff158a395716\n\nProduct = 24e8fb09a9ab0808ff643122479dea5ed41060c6c5b74e8752\nA = a57da276998c548101f514e9f\nB = 3918c30b5568318a58e9be16e\n\nProduct = -366c125f96b38b58d01c939c27c4100af3377eabb792b5491a\nA = a57da276998c548101f514e9f\nB = -542fb814f45924aa09a16f2a6\n\nProduct = 0\nA = 0\nB = 542fb814f45924aa09a16f2a6\n\nProduct = 0\nA = 542fb814f45924aa09a16f2a6\nB = 0\n\nProduct = 542fb814f45924aa09a16f2a6\nA = 1\nB = 542fb814f45924aa09a16f2a6\n\nProduct = 542fb814f45924aa09a16f2a6\nA = 542fb814f45924aa09a16f2a6\nB = 1\n\n\n# Quotient tests.\n#\n# These test vectors satisfy Quotient = A / B, rounded towards zero, and\n# Remainder = A - B * Quotient.\n\nQuotient = 1\nRemainder = 0\nA = 8cdaaa7c422f3c2bb0ace2da7d7ff151e5bdefb23e6426cf3e6b21491e6e80e977bfa6c65931a8dee31fc7992c0c801d5d7c\nB = 8cdaaa7c422f3c2bb0ace2da7d7ff151e5bdefb23e6426cf3e6b21491e6e80e977bfa6c65931a8dee31fc7992c0c801d5d7c\n\nQuotient = -2\nRemainder = 1\nA = 107f0e6cebfe22ac11294a06fed2b994d01c9b3610d50bdd254adafd08c93be8ebdd1e85e1286fe9c9e682a90cbbd6351681b\nB = -83f873675ff11560894a5037f695cca680e4d9b086a85ee92a56d7e84649df475ee8f42f09437f4e4f34154865deb1a8b40d\n\nQuotient = -4\nRemainder = -2\nA = -3d8746ae2123c2d3f1d35910b42af1f86f5e81f8e98986cea20b2a1bdb8af6cf111f1258f112c837accdf4868463fe9eba536\nB = f61d1ab8848f0b4fc74d6442d0abc7e1bd7a07e3a6261b3a882ca86f6e2bdb3c447c4963c44b20deb337d21a118ffa7ae94d\n\nQuotient = 8\nRemainder = -3\nA = -5645d65662eaac73050de06f8f982a9b2ae680467712284be3e2b0e58ef4bf4d72b5be5e12ee1fd803b47f161759662ff5c4b\nB = -ac8bacacc5d558e60a1bc0df1f30553655cd008cee245097c7c561cb1de97e9ae56b7cbc25dc3fb00768fe2c2eb2cc5feb89\n\nQuotient = 10\nRemainder = 4\nA = 813bc46ee19ffeab364073a89f96913f340d43ee72129ea9edac1beb4ebe1336450d2eabc7b26e51c400cec60d6ee459033b4\nB = 813bc46ee19ffeab364073a89f96913f340d43ee72129ea9edac1beb4ebe1336450d2eabc7b26e51c400cec60d6ee459033b\n\nQuotient = -20\nRemainder = 5\nA = 12805392c55ffa0e27e85e15f2b339872793664e9ed3074cd2600aa52459a57197130d1ea46775ef43115c9413248cc7b34805\nB = -94029c962affd0713f42f0af9599cc393c9b3274f6983a669300552922cd2b8cb89868f5233baf7a188ae4a09924663d9a40\n\nQuotient = -40\nRemainder = -6\nA = -3579fc4d6083394c691b060cf9e20318fe17da0487337f76710bd11512578830ba94ac7b587a2d5ab7cb4afe611e349cdcfb86\nB = d5e7f135820ce531a46c1833e7880c63f85f68121ccdfdd9c42f4454495e20c2ea52b1ed61e8b56adf2d2bf98478d27373ee\n\nQuotient = 80\nRemainder = -7\nA = -74ebad4b39ebaaff82cd91082408c979527907c363d8f0f75db410523f8477c074c45ff85851b6275b1ebc5279029818e78d87\nB = -e9d75a9673d755ff059b2210481192f2a4f20f86c7b1e1eebb6820a47f08ef80e988bff0b0a36c4eb63d78a4f2053031cf1b\n\nQuotient = 100\nRemainder = 8\nA = d2d8a4419fb3b1c22bfca04ca08c2ee066ccbc9fce2f41861b5eef91efd3c13eeb7eae5abea0ef1849662cfdfef7bbff892c08\nB = d2d8a4419fb3b1c22bfca04ca08c2ee066ccbc9fce2f41861b5eef91efd3c13eeb7eae5abea0ef1849662cfdfef7bbff892c\n\nQuotient = -200\nRemainder = 9\nA = 1bf534da2f4365c96fc5dd4928e73ac24b157b5136ead90cf6596033ec387a2c14bca828000ae1725f3a5ace8ad67a8c07a0a09\nB = -dfa9a6d17a1b2e4b7e2eea494739d61258abda89b756c867b2cb019f61c3d160a5e5414000570b92f9d2d67456b3d4603d05\n\nQuotient = -400\nRemainder = -a\nA = -3a172cc9483774544311a1366659d9e61cc9fac7dc11c68e36aa991ef4d5e96becf5bac3e0967c904d926617ea11bb9551b980a\nB = e85cb32520ddd1510c4684d9996767987327eb1f70471a38daaa647bd357a5afb3d6eb0f8259f2413649985fa846ee5546e6\n\nQuotient = 800\nRemainder = -b\nA = -5ecff3a3e47fa615b6e3ce2dedfdeefbfe1d437c394631820968a9650b59dc3a2dd1c9a0b06537e4e5c408a59e580921503580b\nB = -bd9fe747c8ff4c2b6dc79c5bdbfbddf7fc3a86f8728c630412d152ca16b3b8745ba3934160ca6fc9cb88114b3cb01242a06b\n\nQuotient = 1000\nRemainder = c\nA = d3ef80fca0ab3ac3432b22e2b485131d816810c39d02a9c82dcc05ec5e6406bc216026de3abe53ab103ea3b2ddbc2ea377ae00c\nB = d3ef80fca0ab3ac3432b22e2b485131d816810c39d02a9c82dcc05ec5e6406bc216026de3abe53ab103ea3b2ddbc2ea377ae\n\nQuotient = -2000\nRemainder = d\nA = 163956bc32325f28f48d41d32bb08d2a9c4ccbb0d818368fb13941e82b27da21d04094f7e897ce79c2d0ff8470505f1ef63fc00d\nB = -b1cab5e19192f947a46a0e995d846954e2665d86c0c1b47d89ca0f41593ed10e8204a7bf44be73ce1687fc238282f8f7b1fe\n\nQuotient = -4000\nRemainder = -e\nA = -3763f8e43bd05e6ffeec6d509bbe6ff9a9022ced8cb191c9abaf5fd0e0b75a53e2ad581455e3af09e702a77b164ed3fb54ae000e\nB = dd8fe390ef4179bffbb1b5426ef9bfe6a408b3b632c64726aebd7f4382dd694f8ab56051578ebc279c0a9dec593b4fed52b8\n\nQuotient = 8000\nRemainder = -f\nA = -531dd44dfa9e79a5aec8fa7c84bd3b753c146770d22d2c14a6d2125f7ab95e9b320e84c31cf3e0d883e1295a220f2a546550800f\nB = -a63ba89bf53cf34b5d91f4f9097a76ea7828cee1a45a58294da424bef572bd36641d098639e7c1b107c252b4441e54a8caa1\n\nQuotient = 10000\nRemainder = 10\nA = 900996b61f58713f0755e68bbdfa4e0bb47f034bb0304f77829847923d14715def1771f43b526c41b9667438b434d2b966c20010\nB = 900996b61f58713f0755e68bbdfa4e0bb47f034bb0304f77829847923d14715def1771f43b526c41b9667438b434d2b966c2\n\nQuotient = -20000\nRemainder = 11\nA = 179d7ede3db0c105525286551331d5b9e1f97a7883f0c13cf250afe9765bb5aaa527af7945c19cdd4596565cbc8532a3cfa5c0011\nB = -bcebf6f1ed86082a929432a8998eadcf0fcbd3c41f8609e792857f4bb2ddad55293d7bca2e0ce6ea2cb2b2e5e429951e7d2e\n\nQuotient = -40000\nRemainder = -12\nA = -293dc443c294c6a6c53dd49e84f58305d59a432afb6c7ea2039cd02a513231239571ae07f29b5427e869b9faa485511ca45980012\nB = a4f7110f0a531a9b14f7527a13d60c1756690cabedb1fa880e7340a944c8c48e55c6b81fca6d509fa1a6e7ea921544729166\n\nQuotient = 80000\nRemainder = -13\nA = -5b637eb8aa51ef15a18d9b144031c9756527fc0fb96c84b6df03700e5079ae1b3e96940a2c1e07f3b47ad8a9b2b8ca99171a00013\nB = -b6c6fd7154a3de2b431b3628806392eaca4ff81f72d9096dbe06e01ca0f35c367d2d2814583c0fe768f5b153657195322e34\n\nQuotient = 100000\nRemainder = 14\nA = 87c846f5469d4c5819aed0c7e77797209b2c", + "1b83a7a0e2be70280b9f30946b5db9bd0f25a06cf4bdba1c7183a1b9eb75c19400014\nB = 87c846f5469d4c5819aed0c7e77797209b2c1b83a7a0e2be70280b9f30946b5db9bd0f25a06cf4bdba1c7183a1b9eb75c194\n\nQuotient = -200000\nRemainder = 15\nA = 11c2a4509f419aa977c3d37fa446fcf21b4b3b9f983fbaddeba4f51c285ac4032200711a54cc6edf24297b1f3d46ad020131a00015\nB = -8e152284fa0cd54bbe1e9bfd2237e790da59dcfcc1fdd6ef5d27a8e142d62019100388d2a66376f9214bd8f9ea356810098d\n\nQuotient = -400000\nRemainder = -16\nA = -39e37ae0edd92b957e84682358039f5e432c42492a44f3de01cdf74d643760260f2837946608663e12291e9b0695449c1153800016\nB = e78deb83b764ae55fa11a08d600e7d790cb10924a913cf780737dd3590dd80983ca0de51982198f848a47a6c1a551270454e\n\nQuotient = 800000\nRemainder = -17\nA = -72f725edd5a3dd6f20b5e9ca7da08a99f8ec9214c80588182c0d42e03bcff34b488b28c03cdf41813a6193c10672a8ee68f6000017\nB = -e5ee4bdbab47bade416bd394fb411533f1d92429900b1030581a85c0779fe6969116518079be830274c327820ce551dcd1ec\n\nQuotient = 1000000\nRemainder = 18\nA = 966df62c26acab2d3d1dbe729e48d0181c68e9f5eba45f6caefa38d60e34057d09fe620abb8640cec8cac755957aaad7c6fd000018\nB = 966df62c26acab2d3d1dbe729e48d0181c68e9f5eba45f6caefa38d60e34057d09fe620abb8640cec8cac755957aaad7c6fd\n\nQuotient = -2000000\nRemainder = 19\nA = 190790727c1514b4ef83a1c6aa07493c0af7087fbc8a675bfd9a1e97b8ef80ef684219d6c6f1a5fb5b919f105fd7717cdd5aa000019\nB = -c83c8393e0a8a5a77c1d0e35503a49e057b843fde4533adfecd0f4bdc77c077b4210ceb6378d2fdadc8cf882febb8be6ead5\n\nQuotient = -4000000\nRemainder = -1a\nA = -22d115ab02f8663d8c009960086a0275d301d358cd3b250bb9e7c16cc6ebed4a8fbe43bbced856d93be64a17377d95f5f9c8800001a\nB = 8b4456ac0be198f63002658021a809d74c074d6334ec942ee79f05b31bafb52a3ef90eef3b615b64ef99285cddf657d7e722\n\nQuotient = 8000000\nRemainder = -1b\nA = -41f2e708ba47494a13607223b08e6d99c0b4247436632961d873804e83446dc97139ffaef3e25969950bd4b5bb4ff73b1a25000001b\nB = -83e5ce11748e929426c0e447611cdb33816848e86cc652c3b0e7009d0688db92e273ff5de7c4b2d32a17a96b769fee76344a\n\nQuotient = 10000000\nRemainder = 1c\nA = e4b52f78179039499c2f6b500840f41103fbd60eac0d7082297236f25189c18a8301a92f533945047fbb83427dcade334336000001c\nB = e4b52f78179039499c2f6b500840f41103fbd60eac0d7082297236f25189c18a8301a92f533945047fbb83427dcade334336\n\nQuotient = -20000000\nRemainder = 1d\nA = 10888959278661bc36089519a215bda60f9ce24ff7c0ac1f543b6e652f94dbff1f32aa40cad2b4b4d676f16948551501c29f2000001d\nB = -84444ac93c330de1b044a8cd10aded307ce7127fbe0560faa1db73297ca6dff8f99552065695a5a6b3b78b4a42a8a80e14f9\n\nQuotient = -40000000\nRemainder = -1e\nA = -3ada453530a180fda58533ab8c62beb4f693a134f512e4d23e487dac3b575e5390c0a90992400e402bb47aac93d46ded55f54000001e\nB = eb6914d4c28603f69614ceae318afad3da4e84d3d44b9348f921f6b0ed5d794e4302a42649003900aed1eab24f51b7b557d5\n\nQuotient = 80000000\nRemainder = -1f\nA = -57879eb5d92d565daac3ac5173639bfe44b6ecc69ff770af57bd79c9b93841c5677042cb362b794f3d8b24b0d3b73ed1cba58000001f\nB = -af0f3d6bb25aacbb558758a2e6c737fc896dd98d3feee15eaf7af3937270838acee085966c56f29e7b164961a76e7da3974b\n\nQuotient = 100000000\nRemainder = 20\nA = 89a2f1792afc54467955839eddc9ef2e37d391ce7a1a4a205291220c1f49f59ee31fc7a7a7f7706c199bf5c8c951a0d0743d00000020\nB = 89a2f1792afc54467955839eddc9ef2e37d391ce7a1a4a205291220c1f49f59ee31fc7a7a7f7706c199bf5c8c951a0d0743d\n\nQuotient = -200000000\nRemainder = 21\nA = 1c267719338a4562e934bc57fabe6da86ca534a34244bd38c15032f01f47c2fd498c83f644b345c5c661ada0e586a096bb63000000021\nB = -e133b8c99c522b1749a5e2bfd5f36d436529a51a1225e9c60a819780fa3e17ea4c641fb2259a2e2e330d6d072c3504b5db18\n\nQuotient = -400000000\nRemainder = -22\nA = -250249f2185d4b428fa9534f03ef3cbed535bd31c56c0b273e6c3d35e0266f7777a6e59a99da5738b8e3af8ac60061d6716ac00000022\nB = 940927c861752d0a3ea54d3c0fbcf2fb54d6f4c715b02c9cf9b0f4d78099bdddde9b966a67695ce2e38ebe2b18018759c5ab\n\nQuotient = 800000000\nRemainder = -23\nA = -710b30c23c3c4e646ba90da33d2ce35af2ff181c40b02e3ffa607966730c6b6e274dd4c3c78e578e0b10f431f2d832274bf6800000023\nB = -e216618478789cc8d7521b467a59c6b5e5fe303881605c7ff4c0f2cce618d6dc4e9ba9878f1caf1c1621e863e5b0644e97ed\n\nQuotient = 1000000000\nRemainder = 24\nA = 877f1caf75e7166ef18484d0718947893fd1ec016984387debc55c19e378a487a5ddbb03a80a88316f6fca16ae148933e719000000024\nB = 877f1caf75e7166ef18484d0718947893fd1ec016984387debc55c19e378a487a5ddbb03a80a88316f6fca16ae148933e719\n\nQuotient = -2000000000\nRemainder = 25\nA = 1ed1b7d9e4cf3d44ee98ef69850e61a39f54cc407c6795c07c887374441fd9ec258c21193f8a8c55802fb8f8c579cf94cb0ce000000025\nB = -f68dbecf2679ea2774c77b4c28730d1cfaa66203e33cae03e4439ba220fecf612c6108c9fc5462ac017dc7c62bce7ca65867\n\nQuotient = -4000000000\nRemainder = -26\nA = -35d324ba37d2000f960ca1c9e1ab96e341a2ae6a5ea5cef014c73a39dde000d8ad9606b817ad67e4e4593cc5894d354854898000000026\nB = d74c92e8df48003e5832872786ae5b8d068ab9a97a973bc0531ce8e777800362b6581ae05eb59f939164f3162534d5215226\n\nQuotient = 8000000000\nRemainder = -27\nA = -7039477c3e0a6f415e25e9f9b1dab1edcd8a23f984e7e3bc149c206a3b756b1be001450af4049cd4535e4243d7032afcf6790000000027\nB = -e0728ef87c14de82bc4bd3f363b563db9b1447f309cfc778293840d476ead637c0028a15e80939a8a6bc8487ae0655f9ecf2\n\nQuotient = 10000000000\nRemainder = 28\nA = d6c59dd07409da98f7bbc7ee471b6e06c4d9e832e9f4d04ed9da63564d37d3072a950564cf549bb5d6e7dc85565d3cc8ba340000000028\nB = d6c59dd07409da98f7bbc7ee471b6e06c4d9e832e9f4d04ed9da63564d37d3072a950564cf549bb5d6e7dc85565d3cc8ba34\n\nQuotient = -20000000000\nRemainder = 29\nA = 14d27a16a9cf2fdbc85b88a604dd8f0e57b5b34a27089d75d805e05fbb367dfa61c085aa98b896e3e53b85ef774a3fa52417a0000000029\nB = -a693d0b54e797ede42dc453026ec7872bdad9a513844ebaec02f02fdd9b3efd30e042d54c5c4b71f29dc2f7bba51fd2920bd\n\nQuotient = -40000000000\nRemainder = -2a\nA = -3bd0119619fbb5b260c44050d61e6b1925a49713d754ceb06bafb1d730a93f199df654b153c40e75096ebbaf5a6ce3c801820000000002a\nB = ef40465867eed6c9831101435879ac6496925c4f5d533ac1aebec75cc2a4fc6677d952c54f1039d425baeebd69b38f200608\n\nQuotient = 80000000000\nRemainder = -2b\nA = -61a283fe41d965ee770704bb453f689cb82a81089422d6d904a91776a06d32857220286e6ef6327807b724062dda143b46890000000002b\nB = -c34507fc83b2cbdcee0e09768a7ed139705502112845adb209522eed40da650ae44050dcddec64f00f6e480c5bb428768d12\n\nQuotient = 100000000000\nRemainder = 2c\nA = 87bd03a64d9c56fe340137065ba36bd07b556119546dd1fc3ae087ead32bc79ca7efb5c7230ea7bfb00ad419096d9279fbe10000000002c\nB = 87bd03a64d9c56fe340137065ba36bd07b556119546dd1fc3ae087ead32bc79ca7efb5c7230ea7bfb00ad419096d9279fbe1\n\nQuotient = -200000000000\nRemainder = 2d\nA = 1eb7cfb197d19f56ad994eca52d1af6466fd09da07d68d63067602046b2d42d3063ef5eda6b58afd69fd92b0b727a0ecde1420000000002d\nB = -f5be7d8cbe8cfab56cca7652968d7b2337e84ed03eb46b1833b01023596a169831f7af6d35ac57eb4fec9585b93d0766f0a1\n\nQuotient = -400000000000\nRemainder = -2e\nA = -3ab858b3329e5bd0469118be52a867b2febbe2894d962cedeb3a5be1738db1cea106cd0710c9f6937348c2c63b109ae623d500000000002e\nB = eae162ccca796f411a4462f94aa19ecbfaef8a253658b3b7ace96f85ce36c73a841b341c4327da4dcd230b18ec426b988f54\n\nQuotient = 800000000000\nRemainder = -2f\nA = -6137bae6cf7573afcbb6fd5c066ba37648cba8db0ecafe9dbc66959b19deabf42f3083719a2268b7602bafa2140a1ee8ce7d80000000002f\nB = -c26f75cd9eeae75f976dfab80cd746ec919751b61d95fd3b78cd2b3633bd57e85e6106e33444d16ec0575f4428143dd19cfb\n\nQuotient = 1000000000000\nRemainder = 30\nA = d00fec043edadc093673e5f5abef0c6bacdf1f3faa49a831a645bf80db7539d657f69403b122a5c6f879eb8e63be54d35ed7000000000030\nB = d00fec043edadc093673e5f5abef0c6bacdf1f3faa49a831a645bf80db7539d657f69403b122a5c6f879eb8e63be54d35ed7\n\nQuotient = -2000000000000\nRemainder = 31\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -940693131e2ba7b2af531803794983337dd526f0d84d08d58723edf002a388d55c8502d88c2a2a6e78233a2a1b1c8d339a13\n\nQuotient = -611b743a0e2acb1043bb33de50a59eaa0405b37bf6b622075dd69291fe5b53305dbfcc377d1f3082319c153d0c1ffb3b3346\nRemainder = -16e346b6a4297\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 30c77f3380ccf\n\nQuotient = b9e34073d5e6e5b9e5d2d7250150f8ad86870faeb88d5aed5029fb25c176de216e2388e0f5d33f7c3b56102873eb40b06f2\nRemainder = -16ebc86eb88339\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a67", + "3426000000000031\nB = -197b6f6ad5b75c\n\nQuotient = 141bc8752e846cd63743e6fce4a22efc3eb5f0ce46ba81b8f578c94c516288ec3610fc9923f45d4af2b94c0b0a20b48ed0a\nRemainder = 9bab19f12d81c3\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = eb90162ecae18b\n\nQuotient = -381bd85c951e1dd775b0d7fab344aadf06b1b592c643b5852fa44aa55159eedf3b3e47fe0d9f399ad92da85ab2bfd18240\nRemainder = 1e4f817a2f52b71\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -546c109fa8a9d7b\n\nQuotient = -5e385a83b56830626cf8306acc232f955178080e86384bbcf92eec3a8961360223c4cfc1d8d118022972e61866cbfc46b\nRemainder = -292e149300fdd1ad\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3246242094394c8c\n\nQuotient = 9af0246f4b49316df43f61ae3795a764fe9b1d071ce227982ebda7988a7a7a98129c94a76635c6913cb15e4f75ea1608\nRemainder = -dd3b3e32ddc79cb9\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1e928618913898b2f\n\nQuotient = 1fe40099811c648aa4e84e4fbb8cbc19706774a11391fc03a9667d8dc72dd0b26c4a46d0bae56ba90fe4bfac1517d241\nRemainder = 16e021603d30dde2\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 948887c1634f4b08f\n\nQuotient = -3f4fa4c179dab02ad461bbea8f890292c934496db560f72878323a4463d77ae261363f4dc8f53eab145fcc3815d3253\nRemainder = 407ccb4f0b814dc5c5\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -4ad17434071e1ce664\n\nQuotient = -4d17d19f7f6861189a520776339a1e425876808111c303e391118714370111151ef4ad2e6e84250f59b0fe09ab3293\nRemainder = -36f745b0f421d16db7\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3d71635bcc25183cdde\n\nQuotient = b976d544af44e711351c6618106d3a002c42ebbe22fe939a2457d24e8dcc35c95dde5c7c77af6b4545344a198be82\nRemainder = -107334ab98e5099fec5f\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -198a54e35fa0cfa328a9\n\nQuotient = 1307bb8e89aaff7466bc238d32672fbbde7be19d15423bcfa14f9a23fe85af9739b72807fd4bc420ad0b0fac37a42\nRemainder = 170ebe9b83d4c43b79ab\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = f8e923a8bbc0242eafe3\n\nQuotient = -3925a167c1c4d2fae265f277302b989466e309a7211e0b7173031cbbb91ab7fac8dfe43c9d832764e222e9d8581d\nRemainder = 4d404e93edb435dbd60af\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -52e36cee22274556059ea\n\nQuotient = -4d5a6ef346a872142b999ff9a5429198b3c2a97e968f55aa2c01583efe30e9687c57e2bca2372db4d3d443052b6\nRemainder = -3a2ea5f9d204dc31f21833\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3d3c79a115d9071b573d2d\n\nQuotient = a49dee54430f1737a04543d5f549efafab25f0f28f5e304f1bbca191f99521c2c4be1b9927bde19e1ec2060bb2\nRemainder = -17d02758f8fcadca911a95f\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1cc65a75211f2826c9d0811\n\nQuotient = 1808ab7c0ccac2ff8f7cb61248bf4624fb60352a356fdd1408904f8c6fb0cc52b7642ec59183bcaf5dd89ca0ac\nRemainder = 5c95323f3b8861261dc31ed\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = c516e6e3fa6e3dc52cf5933\n\nQuotient = -437e04d7076794850aada0cb4ca7a1055df103e74e00766be6a2fdb2631bf294cdbf2695d0a2f8f9eb5587aa5\nRemainder = 1fc63797594c56160536faa9\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -462ee529b488d1db2b6c60e8\n\nQuotient = -5dde5497accc4575a412e7232ce75bdf7905936e09e382d5c9f133faf82a05ad9dcc94ad858aed34cc14c714\nRemainder = -15e79293d5e055f906381a899\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 32765b0a34c88864d39bedaae\n\nQuotient = 11ac52a9287472e1d3b8577b3d50c95076e190714796761322b3ce869d96b44387e190e824849ee345d0a22b\nRemainder = -a158ccc7c055d64e7df3fbcf0\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -10c061a37f6cbd11bf0c327643\n\nQuotient = 1ff5cda1551867577c5ca72c86516a82fb8fc5f59ce967b73c6bcc1b85168389872c9a747ddf044d6dba174\nRemainder = 21e766a0020ba429b330a325d5\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 9435cd2dc2a92c950bb9e69b83\n\nQuotient = -2719c892fa3f4dbc9951b2095056a16159adaf32dff902e20a800a0cc2e858ccae408f2161aae25d3e1f6d\nRemainder = cafbe9caa1f83fd0dd3d5a6881\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -7924e4dcf8f96da61f54bf83870\n\nQuotient = -5080dc99dba295f4a2d9a474c2ddfa3b232a82fe629fe62177514988983eff8195b37d3fee3afa343b497\nRemainder = -94ae72f78982ac1ff83f300cfe8\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3ad70d4b6b9b5f5b2eb65da67e1f\n\nQuotient = e475eebcfc53d49ffad2e0c2a4ba48fe7ce02c42ff107e01ab3fe5b26eee45c83c4f58c181d77c259155\nRemainder = -c83ac7582a02b47ee734e0f24dc5\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -14bbcff5423a260b21895327b18bc\n\nQuotient = 201308a421b85291d23465d648ad2a8d6f3393efc16fb675a42ea7bbca635ddd8c2449b1b34e5db30a03\nRemainder = 8e07efb8ae4c9df39533042362081\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 93aebb72a81ba68e8881fd1a56a90\n\nQuotient = -2584cc534f88f091fe471c652ac66a695906a7cde1fc1cde9be3ee09026b690c1a899378ff31f6acb90\nRemainder = 794801d9d5770a60e312b99d6b9f91\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -7e408caf387a0ce9bbf4309c80755a\n\nQuotient = -63f7bfc0fe5a5421bc0a19fa6c87713a72eeb2a33e5eadee8c2f32c20d14f403ab8bdc424b9e8e0c68\nRemainder = -24227c242afedee2473c1a66a5cc29\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2f622c665af7f8126eabfd90df8e9c5\n\nQuotient = e557e6d2180aeeee5d2cef453fbdf38e84cc148f4608ade8836045498be2d318520ffadcea6319432\nRemainder = -dd290149e0e159f9ba6bb9f5a4b003d\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -14a7623d1d9dfc177e913d3119d0d30a\n\nQuotient = 1651d852316d472b41ba0460566e43fabb9257861859ad0fb6ea5a6433a4164299e078f4d50c58afb\nRemainder = fb60aff5fdd2a2b794b0d973ac4d92a\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = d439da27b5e70342aa5cb365ece15665\n\nQuotient = -3ae357761a8ff43d3b1bc53eb336260342a39d22f8fac44eeeac96c2f6de32580dd6a688faa9c515\nRemainder = 4fa6f7ee4faf2f6be99c5ce4b65cd642f\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -50700f9c0da59482165a47a3eda2bf07a\n\nQuotient = -543b4390e4e254226683aa0b83b2ca176ec27a373969fb88f766ac72adc9125ff83b2652e46afd3\nRemainder = -12ff398d9a7d9e97a7f63a0bb293c8fb0\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 383c5a4f1767e83fc382ad4f1c7c2b7ddb\n\nQuotient = ecb72c14c59d49287fb6b2cacdf04619ee617d5f3f0f1b2890fd4e79746a4fbd848613cf5eb437\nRemainder = -1035512a2717a89062d48f1bfd213333ed0\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1402b751a1e5f3fc46e22b43240d6ce9b27\n\nQuotient = 1e800ddc5d5126f322298383f32fd593623eb88a91b2d68c5d9f56e20c16ffe2cefabe87357", + "0ab\nRemainder = 72935d534bed5ba557b91ea023601f50b1d\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 9b4df766c608ff3efe5ea1f65cc850fa73c\n\nQuotient = -2c2dc2378abceb983904cdf6728f361d279b4c821710ae785724a7251c43fe4f705f023afa7e2\nRemainder = 249f6433af4e8e224eb570fd438197af62f3\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -6b382f812816c77d65c94c0c660b31a69b8f\n\nQuotient = -5f3ced1e42fbd3c6b2c6f1e16953e0c1bb6efb4e49566f974a968f69a1a66a3d7558f5a802a8\nRemainder = -317a7fb1af65982fe4641fbb1e5837e6ea3e1\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 31bc97372d17038fd842b72eaba2abb26df62\n\nQuotient = af3fef8111c449b9e0858e7e53e1d00b764232f7a077d75043249c387ece30af351c8a40335\nRemainder = -a1493bcbf57a8480461d62796aa8f8541ece4\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1b076b2f7b78b4a0f0e24ba3a05d6c697efab9\n\nQuotient = 196734cefb08f09cb32ffefc07da8d9545d3451d5a08736757184bad94c73be71311cf1e01c\nRemainder = 273e33521f4d74840a96b3fffe169f79d32855\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = ba7746f4400f812919a3dc86b00642e1487691\n\nQuotient = -3c5989cf33145057a9c8e904435d12939db519cc6b9ca1c0a11934399cb139a73613950f2f\nRemainder = 456ebf56c636d54e37709b9e799e83b7a08cb93\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -4e7d4f389423f42e980eda55b4a6a45f6f4bdc2\n\nQuotient = -8432cf3338bce1d12586f83025aea50cff3864af3eb2103a36bbb0aba10b0ba4831641633\nRemainder = -4f62c678137df301c4bef216e6aa910104e76ff\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 23d4c57b5a8162aae8d937be12efbcfd7b96ec06\n\nQuotient = 9f94c4399eef16dfc65a1e015e0786c86470299865932c4d564b71c9b1551a9c0308af38\nRemainder = -168b74a6073b4a5b54fa14aacb5c3bb7897ed0fe1\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1daecf01ec633610373b79e04c22cd7499012bc66\n\nQuotient = 1d5b838dce6c0324f157ad125adefde6e1045dce9ff97cf8d1d39b79bce02128e3433ffe\nRemainder = 3aa816216d55fc3c910a030fd10fbda1e12f2ac2d\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = a1598a12a84e9cba42ea0e200e88d4599c9f615fe\n\nQuotient = -3edb182b53890ca8762f3039d2d71a8a27c36cc884d0879e0635e6326af0182bc47cad7\nRemainder = 4610b2b1305220bc0de584dd3f87d90109012a8077\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -4b5c2f1ba3a82047c9de61d47cbf1bec86b6ef90d6\n\nQuotient = -7571ed4c509630886483f6ca0923859e644063acb38cfb338bf3a681fe449501262516\nRemainder = -21c579846594fc3e5efc53ab01576a7b32d69faf41f\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 28550e1f7c6492f4cb682c37b105f92b049c13fc03b\n\nQuotient = 9ed8fb31327a110ef4377258681c5287de8ef9dbe62aa4fe84a7f2a94bb69607cbdb2\nRemainder = -1b7bb759dd0ebc346cbe216e56be8063f063490c17c5\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1dd1e61caed1efc07d21ce05d889de1ad65808cae026\n\nQuotient = 1aa716227d1ca6af68286062b2d6dafd7ade16abbd5d6fa4ada0365832fe18f73bf35\nRemainder = 32e714b0c4ecefb38735cb88cd5e07c21c81be858cae\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = b1b959a7b3262d7f4dff488315903aeaffd982b726d7\n\nQuotient = -2a9979a530046939e0b43a25edfbea6775784eb5cf346a9fc3a2d22e1aad473cdada\nRemainder = 4edeb91a2472e80068b1883cf2cc45d68ff9bbed1756b\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -6f31bbe097587a68fdf01d0bf93830bd03a23920ccc0f\n\nQuotient = -566ff76814e1c7d31ad53bfb9f3c0607ef1f7d1cf9bdee6e1cfb78b3ad7018f8bbd\nRemainder = -1eac095d6d84021c33aa9b219d191bd0637f20b5920eed\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 36ccf5bdece624b4f54c729a8cde13325d8dd764f44894\n\nQuotient = aee4f377611179d8b6315811dd94639aaaee63e99bddcfa8eee297ce1dc04daf8e\nRemainder = -59cb3ba7efa1637c46b21795872e8deaff90f13402cfaf\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1b157ad838684b45065aa77ca3238a4d8c5427f719cdfb7\n\nQuotient = 1c72d32cb83cf4a9043d3bb5002f61b03e29c34e44a9fc5cc4d613726f5e618546\nRemainder = 7312d11fb5828c7f1a0060a5152a7644fc1e6a59de28d03\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = a681444c4d47d829f7b629b561ffaa0c3be1232346c907d\n\nQuotient = -2702afc4095a0396215e3ca36e2a59725f743b30de0dd8d4ec4d943fef6c37162\nRemainder = 223dd3080ede3a64744b14df8742cedd71388b0df99073bd\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -796c9ea38ccf516a2054a1e584c18b64b996c9679960585a\n\nQuotient = -805585c6a7badc933bced6f8373ffdfe9796e963d3fc90e85b1a22c38f842062\nRemainder = -a6ebff3f651644915d5c466cc2915d104f0f85a44e08fd6f\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 24e8fb7a6a3057ddcafff92916c46f7e4038b98c3104ae831\n\nQuotient = 10383ff8feeb180d4fde925b534be97ec3d5f1f1dab5d8cd9ab5d8ea646cfcdf\nRemainder = -a7efdd0401c74a69cf74442fe3da907acf92e8edc51668828\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1240a71ed8d81e86fd9b16e1d64f438b35d6f8eff672494017\n\nQuotient = 195d95a520fd22317492117dc756ff97806c48c1aac67a41ae56fe503a60cec\nRemainder = 8b8692bee56f8a1ada9ffd8b3583eae33a0df9b73a7d8585f1\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = babe02063b61cb90634ac0493174073d2419e00728d46ad2b0\n\nQuotient = -37791adae674b866e4791c107a697363847dee4a58a37806391426ea48b8c9\nRemainder = 33986fc6a5f5c4f4e31458fc7de55e08a4e9320509d90299b93\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -5563bb852e7338c65aa21c516eecf47f498e5788c608ed46cae\n\nQuotient = -68a30494eceff55e4f54a556dd9b30025ccfa22c0952fd746adfd13d31d00\nRemainder = -1b511d0ab81d528d00a1058850bef48df2e9ae9357e779bb9231\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2d44e919fd27bb3fd2093062d11830c30fa77febafe0a2082cc6\n\nQuotient = bd30999592dbeabb8871b76aa04cc1c6c3794a83f0178c2ad505d8189485\nRemainder = -b0dbce286df5faccf0bdb40ca60f508d436f9410c5e49c3f1360\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1909930e2d16fc877c15895a3ec8b2125858bfa1c5a1b8776bedd\n\nQuotient = 2171694ef4a9d57b83b09357a511d4e11cecbab5e9387928b480d686a0e9\nRemainder = 29abc8898d5ef85f87323c2a6fa36ab6e1bdbcc0ca742b1a2347e\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 8da37bc9c7c9bdc62f49cadcd40e156e776b7f4c8f7ad543f463b\n\nQuotient = -267d470f32911150d9944e684c14e1834734b15475bee968748dd5f6502\nRemainder = 53a2ffef61709bd7143c4c876e021f20a99ba481f2b11abcd45da3\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -7b117ddccee97816c2ca2f1a612cc0d94ac67f5a79ed41744c8fc7\n\nQuotient = -5a21a3bdd3a3d4f1361a978706ba1cec409c296a5b3c369e91fc8317bb\nRemainder = -2cdc818f1e445fb3772d2a56833aefb2f5565a5fca80662e6fc1845\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031", + "\nB = 348dfba3c793f0018d7d3a70c4060c3148b4a3163ba60af9d6f8b04\n\nQuotient = b301b4050fdf4ede8f9c746b26d968110e1eb119ca42cd9c9bd8d4fab\nRemainder = -17993daf81711fe59204ec82e363d2b91971129af9206ff9506d3cb1\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1a76328184b9bea8770c91cfccf8ab98e75b2224d666af58022aca80\n\nQuotient = 19c401336dd43c221a61264f8b91791d250e6c99c61850efe6d1e3532\nRemainder = 6c9e547a77c98eaba1b021777dbd98ea88f7fd37c95a2b182f2b9067\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = b7d7b1f95f4fe2f267af88b81af88fbdf603e54ab6de73ccd000c32d\n\nQuotient = -38a77853de88a8db14612884b515e3cd7c673175779d4ab71ba58f83\nRemainder = 51851549cfa00dbfae388cc3b46fd4824268e00e12fba288acceab339\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -539c0171f48e4160e5c308ee9e74f35d8b6d032e946dbcf748b1335a8\n\nQuotient = -79a7eab82e5b65f4f6734e8803fa7c30852ea3ae56e801c5dd11778\nRemainder = -f89592eedcbcc68d5df80663b3cdc638d9d779707d4ae5a552d97d009\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 26efac15401a945ffd37066bc5af23191292765164a0f1e4fd537fd64b\n\nQuotient = d33afb58753a21581c5b2351a74f3d220599ed56ebeacf1d43eeb2\nRemainder = -f699437f44af44b3ddc080f5b74f753d35f70baf3866040ba3c64b30f\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -166cc6a3c60facfa0d8d318f26c6514c7eb9113f6b625c1de804ad379f9\n\nQuotient = 19e55bdaaa5a375c36e6869700f8677db563e5cf985be2a8d1b012\nRemainder = 7bccc3a653f29f3f45b52b8de2449c868c64d976666c01bff2dca03a8d\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = b6eae7a82b5dd1554795573cbf558d7cfed813eec270c326bf290adccc2\n\nQuotient = -297530094c3e4270ab5cf67e60fa5af6a32eb41b18b050fa6d46d\nRemainder = 62d8b502e172da7bce53fbb7c1ae376b6c21b3a3a47523aa0023406e353d\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -7241ae5f1aaee9340d437ad2dab94b70dd29fc6fff7fe31b100aa5001644\n\nQuotient = -640f3c38230962c6d6fca459afe0e46137525e8d62dd9b84da73\nRemainder = -16fcadd5155910764ecf0b4bd0afc3707e2ce49cedcbd5414f1c7d860e95c\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2f570d2da7a4e62097eb494ca43f7bde33e36525308dc864ffbaeb5d48f97\n\nQuotient = b3895ebba13c8f383ac0482be02e1f5518511420cb4513426bb\nRemainder = -21bc847fdfd48c7a4c36c778681ea20481081cbb7af6b281c8b8ebf2b2c3b\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1a6233954b3480af5f911a6bb8ad33967d5e0446c3e56f521e892c986b6b82\n\nQuotient = 243f3fbefbf842c79c5e96162fc42fe4f177a59d27681c54b3a\nRemainder = bbfaf15a90e744dc4a1caceda3cb339e5491e4507a1118613c5e9739f976b\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 82ae783b8a13e2e65d52dd3a6d6b057163347872f4d72245ff364dbf2421ff\n\nQuotient = -30f7cef2948c9ebed8fa3c5ea9a9bfa96ee4e9729c9b18e9d3\nRemainder = 1feb3fd887629cca60c664e385dddf538d9bf7fff2d34ca9e0e7614946d807f\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -60bba60d69093c0134fcb90aefdb9c190e7bf037ecc13dab3cc7915d7893046\n\nQuotient = -6b6f0183c1f598a68683ba7435c05d700d74681fe472669a1\nRemainder = -1f4d58f81a8c18523918d31791a00ea9aafbbb87792d90a5392273ec4e405da2\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2c17372a5128d7c403a3b94838072ecf9aff88d164764b12bfbf6261df957e2f\n\nQuotient = c4347fe42b2a7d9d5a650b72724369c5c1f59262a7be3fc2\nRemainder = -1103ec9c4a15373949cae4e34b7b42e242da41edbf5ad8362ce5e5426d3154a1b\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1824671758069b7660bad819f06c86fc76a9344ea38412058380363e5c5b4086b\n\nQuotient = 15e8c8d6847dfe974cefeef5fee93da9e58b74d640c6c413\nRemainder = 61dac240f2b39832903d5ecad9cfda5162bf8ebb0610545f259b75c3dc6ab8771\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = d83386fb9682576cc70cf84520c53169e391b414f5421cddca6e257bd77753c40\n\nQuotient = -3572711bf994e6ad48535cc4d65ac323ef1ccff530b4337\nRemainder = b5899d4cb879e37022c539962959339d055900cca16153da09b54c658753cf50e\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -58a05faf5c61f85ac5a090b6bb045c851ea17332d9bfad4309ce2b7a79ad3cc575\n\nQuotient = -6931ebfc6e34305e5d7cba5284829d088d1ec0abdde508\nRemainder = -1b09eafde481064bab3a5c7fd895edceca40b1e62a9cf953eae1061dfbe00936391\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2d0769f392ca9ec629ef1bfbdf08cd8cc9219330ffe3c05343df792dd94b1147714\n\nQuotient = 9a4800f0cb2bfbe8d234410deb510103b7da30cbac7d9\nRemainder = -971e4a529e439a1b96b942001631027ff2fbe40b8939e224adb7f2ed30faff64d1c\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1eb3d7971125a036c3a67d9f5ce580a4ef4c469a492be53a55bafd2eafd4032b5b9d\n\nQuotient = 23116704b7a1a86cfa2ee5707ee46268634db5d50dc0f\nRemainder = 467c6b64c8121e4f250492191ea36a27119a0a6d19af519bf7ccdc2436c885c99d85\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 87134e98f73470e23a96c6a9139af3d4d21574de8aa9ea1d720df8940bcbda343694\n\nQuotient = -3b7f72ecf4f55c02366c52f38a827f5773b7cdebb9ba\nRemainder = 194b334b2046a66be3ddd7c6df01c88967fcb11e97b8206d000bcf6043c6e9ccb13f5\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -4f9d0341cadfb1f0bc38184d93503faa196fb8170f8ba2b5d3b512c09d39b7f79a5b6\n\nQuotient = -6db1d69019dd4cb26fd65d5b88a31bb6413b30278a1\nRemainder = -2042a060391e181882dc0c8d91c3b03c1ea35e2eff01babb3ae876ba1e57a505d44856\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2b2e8f445c0c3aaef0285945e4ca37a700310e003086f34d02c891b94b117f3d3032fb\n\nQuotient = c0e5b9a5853bb21b5e2e37f469764579d5cb2bf984\nRemainder = -154669d4bce7914cdc8d79f2b8d1faa43e8cc3b20fb0767e1c9a47c9e1daed4b665cfdd\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -188e619dbb719381e701363de874fe168529c10f30d3ff184e4356991fdec1649f72235\n\nQuotient = 180054f8c36833d44cab9dd61e6d89d28605c564af\nRemainder = 59192ec5c6fbd9773b8b7dd7d8ab1800dfecc8eb01c29997d15ad75b79575d9e26e1fc9\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = c55b5eb165c63ac2794bfac21980ebacadb93f1e059309fd2b855621572e8d9b3f29018\n\nQuotient = -31412e97045c19ec38951b0e3884c66d1d7479437\nRemainder = 56f1425227bfc6eb1ecda7bfae0e5cb59e92a2cc5306b28465c8739e40893dc5c1e94cbc\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -602b8c25ded1ab3877f58cb048c733649c7dcadf87b2652e35c4e5544d2306107ebff7b3\n\nQuotient = -8da1489ccf7203ecead94c67a5750884122b6e75\nRemainder = -15162026586a1e55dda72785f31c9e6140d166a1fd34c87a7d8c78f8d8f87bbdcf8f75b1e\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 2171ee4a6f7f67d5a33d0a08c367184d70ffe39da28562655e75f6b66c866b1c2ac93e467\n\nQuotient = e635f8bdbf80e99723aa5718d3fade4e573be2c\nRemainder = -ffbd73bfe05f95bc2b135f12682288c620215eac3d6d56503d93a90e06f236e597d1df975\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB =", + " -149375d478a096e724b84faf795c589ef0d772c4623f5be38da99006cd833dc5b28363faed\n\nQuotient = 20f76f5c6d0c8284764a10f6936c22bfba5f851\nRemainder = 82e3fb3f7252dd87b5370d26d9e8b9e98c7d333701f0ce8a05c337054c7aeb343d04d7e342\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 8faf8c0a3ef94ab1069394998e5412a7d84f44aff97edf63abc46d96f897172c38faa0b13f\n\nQuotient = -382586dfe93872abbe3a504fc62a8973913f96\nRemainder = 4d407323ef56093eea2f3993334215950f4e1a85ba18cdcd77d819d92b8b292c3ec8edea425\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -545d81ed25602b158bc79aadf98a8f655fc399fb8652ae94333bf54c8c9ffaf8c6b3f2a9d52\n\nQuotient = -7d179efc493eaceaf46572a1f3a62bdfc4a38\nRemainder = -3de3d817a9cf7d529b5229a503e8ebbbd2c53215ac3c584c010947f780198dee16ffbf47791\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 25dddb00f65d6a1ba8caf7815a8063c5da656d775eae9e0108c68ce11dc925183810888dd04c\n\nQuotient = a9f7e5f235bae0e3e29393ac5c99d510b009\nRemainder = -150478b4a0df3eb20dcd1be8da283a00636c021c5c6337e7732aae9c4b49853b95f6d2475ea7\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1bde6cae7f5ced9006c0b1a61fb50982a433e4e2050aa486298f456556d8e909e96933e2ba3ba\n\nQuotient = 16de125df5936181981b4c2d0051a8b4d211\nRemainder = 29ac7c8a11f9beb9ad649257994216146b663bf4f237c561bf315d95778fcdb1010283475ebf1\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = cf24735a60ff5906410be5c4d98e3c9247919b57e404aeabc7eaefbf07bd64762bc61b96c9040\n\nQuotient = -268a52cd10ab4814268f66d9f44f71a98eb\nRemainder = 20293699f12fbfef2e391963866fc082a7884cd13b1c9bd8d5d203558feed2b889720be936451a\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -7ae7d548212830013b7d653072c33f0dd54a6ebd8792bf75809d29a8c798dbc67c3edd99a69b85\n\nQuotient = -8f051067ccb82b6a3dffedd0ff2ee97c46\nRemainder = -100dac0d3bf5aacc5fade281c071eb2399560a65349566567ce1c0c34e43f175a575ed1eeeb3b07\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 211ebb5dc59a051fdfa3b18ac491971e863f2086cdc099672c1215af4ec877e29950efa4f487be7\n\nQuotient = 9b7ee4c499386f922432fcb1a453ee2ec\nRemainder = -f410122a74386d724cdd45b2e548645ac5ee4a44cbfecb82aad34ae470526674da44ebbf557bb75\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -1e76750814dec1ecbb1af0fa2281ab3185e94e47fc16a77fed312f23f261ad7709ad7c9f85862c1d\n\nQuotient = 23efb26228d7bcf281cd45f54572e2b3a\nRemainder = 65bf2ef1c2f8e94d98060aa305f85e6cb869c74eabad99877010d30654aa2e578ef6aa3c5f1122e3\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 83cfc25e90a61cf8686e3d5857b2f958674d478622c54cf8427275ca5e9312ed24e44ed4a1b5e413\n\nQuotient = -2cfcae0e922f2d884bfa0a3346dc9812\nRemainder = 14de2725b11a9c6784d9608c52770d29b9fbf824ecd4890bf28f3ec0dc6c52e4df9be540332b8882d\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -694b057ff381badb37c7c15c81e74cbd6774e8d61c9e7d450811c36262ea834fc1287fa59708ee072\n\nQuotient = -4c0238ff3c18d4d58e543f020002802\nRemainder = -2ddef796c50817e82ea6f64a02a8c6b30ab40070ff5401c2d39ca14b9c4d99de33834bfe566a0c2efb\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3e51c9ab14f522b55e8f9d3ba995c0846a864dfa2d568ea211b0cac1463ce6a1da72d0a15746fdcc9b\n\nQuotient = d41f9102a7785ce64f76b7d7b870b0\nRemainder = -106eaafdd518c658bd371164ee43ccd915a01b513fc7d220900039ff840ba36450e16ce9987e08e7141\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -16549c5d57b531528dd4d781f03cf275b66cb94eba038b782b739c3ab30b8631c8706abac06004a942d\n\nQuotient = 1616b432b3277e774aad92b0cf544c\nRemainder = 2c89373720b834d718ff3df985ae47c3a7cde0e0309f682f5fd48dc97a1ff3d69fa0dcaa1245e956445\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = d6721300e877a8145d05f4f3d8085697c2ca5f34a5357fed0bdb7169f83b6f8d855232eeea594846b79\n\nQuotient = -320fd6a7375a42a3961362ae196d1\nRemainder = 5336711bf81237ea3449f4e9f4e6358dc250f8ebd86082cab92a8079f2c8f835bc783082efb0ed7e3f66\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -5e9e8e1d446fdd314d487cac1226088696e33161d923acb67d3c75e87e428bdbc193e02f53200610fcdb\n\nQuotient = -4bd06daed3f30345d269f51e4381\nRemainder = -1f3513bdefa40662f0f50a04b418a833aa2f85522dc6c399298b1b147662ef2164ddbfb7247ba9511b8ec\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = 3e7ab7ffe5f63a6c1e109b95b83af470ff820cdedbb3c90c398ec42e44a45e1ca894870a7fa51f17ad5c5\n\nQuotient = d6fd01a0c5b55fbe36e58bbe77b\nRemainder = -c51af3e8b430870388357cb366ea888bd7b4ccde09ad3a1d2ee1426af060245c6d6b5980ae87fb66c4642\nA = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -16086df3dd5e665f2631a294563c68931faa19ee67d6a2153d262940a648ae71bb3c1745daca5ea977331d\n\nQuotient = 18bd9a8f5678d28cefd955cf99d\nRemainder = e193f2fece67b7abe16373c3f84f18dfedcf654d951bf47585fccfaf67ee04f5037354d057c9f5eaa8eef\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = bf758acacd11f3f3e6665cd740517c9ab2384266f3c7ff9afd0888cdad2f6c9401c24d6c11fc3949aabbaa\n\nQuotient = -371239db55c79521206c9e60c0\nRemainder = 93773085af7582dd298b09d7098835787978d820289ea6850f27d0d77eecce8614785e32b228f46ca4b371\nA = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031\nB = -56033fd85be464301f10177b58d895fbb6df6154da5c2a2a7cfc3a24d83a96f5295fb17a08148a4e51dde91\n\nQuotient = 696d8e378d12221e2d970c53bf63a20ef381db8566701972c22fe067cdba99c57b68706a5c6e52f21bb3de861e49ed2141b3036f07d1fd0ee\nRemainder = 9f0e50ca76031b\nA = b2668f5fbcf4170820ed3fc9b12a61862acf8e3cb17175482efe23c5cfd3556e77634d407b6d1f98a73437a8d6066319a7a860afcab2338a1b1313037e30f4d9\nB = 1b1313037e30f4d9\n\nQuotient = babe271ea266bc7bc16d193097903037819f82366c7e9ff8f2cb14157b40433c6ee327038d5dcc44140b070d823befaefbee5e13419f6f17\nRemainder = 93d7c547a9ba0a4a\nA = 74b1a591f449377836f378e05d2902b29964df59c6926e5a9182cc09ce3111783cb7021a185340b4880d56635de268d6f3855c4d9997373b9ff8df899ee3b3f1\nB = 9ff8df899ee3b3f1\n\nQuotient = 890139fef28aa3b77814e1122b9c7f26e746ee3c507e6082b508fcbe380de83b06a01f735239c6847c30eae44749fc8c5e3bd97eb40ba297\nRemainder = 6c97aace900389d0\nA = 7e89adea82b4cb6feb41297b6dc8d948e72c3d5554a987900e7fae48cfb38fb5282b13d9a1f5793cf7cbf1ef551865041c3ffe0e287714a6ec7123556af55a48\nB = ec7123556af55a48\n\nQuotient = 1fdeead441e2d7a6ce3cce2389b2a22248ddca7970ae3f7e7d8453052fd08534ff7c46f6a4537fb6f28df6c5fc8a7d384336e679b74205315\nRemainder = 2903c7cc2651bfa8\nA = 9ca66de3d83f0a747fe986464522bde5e42aeac20e8ace1ea13fa6bc9514c58517479a4281d4128c6d775489b85dfd114ad184613f308f6c4ea484a22ab0ad1e\nB = 4ea484a22ab0ad1e\n\nQuotient = 12f16c8f9f898a08853982e2ac5a906d784c5ab8d74007ba3ab311e861d7c1ac115efe694cab7583f75a4a59ceff2887dab53b2f1022aa452\nRemainder = 4bdaf1f352e87aa5\nA = 6e6a97b358b591b78db43772378dc084a11836ddc9dd4607f263ce620714e8fdf6bf67387c163b6f2999f84270802b4bd5c0f0377e949fbd5d42fe145e66ffeb\nB = 5d42fe145e66ffeb\n\nQuotient = 14e0c06c8cff1f9f5dd8afb6fa6c340f0953a18ba7d2b26b22d8e7f946ef20fd5ac277ceb59cbd4ce3e8213803c3b5b0452ed449e22bf2c29\nRemainder = 55422f1caf4a9a00\nA = bc9c054ff568af73e301e0751bc1ee055e82826cdc53449f2d9f45feda2ba227bedd6df9b74fb58a85917d60b087bef04a156a571716e9bc908ae83784ee35c0\nB = 908ae83784ee35c0\n\nQuotient = a457ea94da3237c0dd15ee30e9c13e7b4ca1dc90fcd67951b8737872", + "06babaed837a3eb17e298d74cae92d1059636f9aefe11aef9ffa31053\nRemainder = 124768541b600598\nA = ea6dc82b1906c277526ed867fe8b0fbe32feecfb935dbab860aef59a7d72799fd4e952e70b4c9304c7b2a06af8badcd6cfa12d0b6c9db38d16d2c4a24099ca14\nB = 16d2c4a24099ca14\n\nQuotient = da0a37eece8972a0e2e8817c54e67c4d9f92373340488539d5051984bce0ae3300ef6ca9d0902daa4d485dec3b4db6c8b1ffd2c5d08b18ae\nRemainder = 1ba15c46023500b9\nA = 36ca8763e20e6ebf07a55cdfdd83892bef0bab68ac092093bfdac1a49c1da015541196a24249bb2262e70f7ed53e0fbae61f02ebac4b61f740548136ce50f243\nB = 40548136ce50f243\n\nQuotient = 3d8c433daedfbf681b528f88d610204d33bbe74d0b13978c34a617ae94177e07a757519b5a8f1a93a73d0751c7b5b72b4bdf475a9708fecac\nRemainder = 4cdfd72349c6110\nA = e0dd7e73b2a64dc017da65992176e2535c43b6fc14f2f7b0a7d894d768bbc77507eac0112b2dc3ca83d70989a1b949ccf374be6a012d80a23a74bba39671fcd0\nB = 3a74bba39671fcd0\n\nQuotient = 39d084b444e39c32f2883e9968301151802da15141f65893f37b8b834eb01c074aa1e1a978c5c99732c87ae106bf8db09e1728c8bf2aae88\nRemainder = 2950443357cd7477\nA = 16df31dc290559c3b6a3d192cf15d825cfe79f8dbd5c9848eac7fa90eea5d87f8b430cccf9baab3e8e4dc33467a4234d8551ff25e33af175654686ff1368e96f\nB = 654686ff1368e96f\n\nQuotient = bbead8f70c8e61114f22d36e97861f16037efabe1347613e78c51d7f539065421a66c907faddaed13ad2a0f0b00f8fd594e917799cd937e5\nRemainder = 3013136f5f728b68\nA = ba5e688ab4f8ab5c25592bc4334b6dc2b7a06d491d0f919b716bf1cf109b62a30d9dd59dd4bdf870dd2687894edab303277a5f3e3a537cc8fde3ee3bb61767d6\nB = fde3ee3bb61767d6\n\nQuotient = 42aefe467ff2a5614efef1edce25a1acba9c476b3abbcd680140a3aecf8f51c1ebaab8912de217451bfaca2842c0bae717b8a030b6318c0\nRemainder = 1f130dd2ead0d35e\nA = 17bd50b5322c51ac883852ad2a4446c039dbc210ca3aa0313065fc88cce6819b324e93b036bd0c71be58586cd2b243d01a4a918c10ea0cc5b22f9d795df09de\nB = 5b22f9d795df09de\n\nQuotient = 13de73dcd72a3638fe2a907fd7f6574bbb228698fa60e4ecffb082911c5f09c74bb4f50564d3d4035d07eedea38b634a3e3acc26c8e9aeff8\nRemainder = acb8702f0113e0c4\nA = e0327b2e59236a3f91ccf960490cc69b2afc854de9299ad2edff9618f9fe24251886afc65f5c581a9bc86013f356d599e98b8b10f5236a51b48a6b29025983a4\nB = b48a6b29025983a4\n\nQuotient = 27d11481f00519b786eaee96220afd45bc51700f7366fb5e7da35bbc84891aac3d9d2b709dddae371a6b78439fef810c68eef586e1d68350d\nRemainder = 3d1890c5e1555d74\nA = f3504d5d96c9e27a1527725ced337f1cd0a183531642051e166507432c01e8d44c4e8918701c2a05eb8a9d7e26bf04993f9adeef2826ae4e61c602477f849121\nB = 61c602477f849121\n\nQuotient = 10bdeac209c67b023044186704735c7291423054bcddc24b731ad601b49372f4d5ce6e9d85002f8dddf0411efce943f81a5e42cee2d0c9fe5\nRemainder = a93a0c5bd51004e4\nA = fa29e37b0d0410d19fd180149b14f94ec2edccd347da65f6832850aa06a61b7b78c96faf64dcb347893c93c560b8043466419864a382c6f2ef1412873b2d8cbf\nB = ef1412873b2d8cbf\n\nQuotient = 1c9b6cffe44241292320c0660b89f2f77aaadc8d36e33f5ac3da0f12b3c114a156870a92079f7192d237f8bf49aeee6282531c929cc56d75\nRemainder = 1ce3e5eb13ac7958\nA = 144325a641463ed6bddfcbd73e50620a44c606d71fac38efb1c9d2747b4903f7b51fdedacfb66db022aea09b43c7c2ad7b851035165ebe59b552d4f7eee617b2\nB = b552d4f7eee617b2\n\nQuotient = 1b4ad18dc0e634053beb3cf840b53e35117ea06309ea8ca22e37123fd7e1d391c96c792e5125e322c27daa73301024080d73ba3491484b659\nRemainder = 3286bdce6dc3a828\nA = e3a2b90d3ef446f6bde30d3e726cf3e78212324054b40deb0b18fe00645568fb0a6234b6bded6240977373731bb30d1349e25cefd54b7a9985735e9b78002691\nB = 85735e9b78002691\n\nQuotient = 28f5e8da6733240cc2f18e3cf4d42a50d92816062af33a9e1871fa89bdb39a0d905c49faf51cc1c1378741bea34d25ac2c8e522881a6f6087\nRemainder = 135784870eb40c68\nA = 593206f9367b72f9cc59b3e37d2eb23b2061422859162ee53656899c2471017474f500c6e23efe1f6b1e57852cd4229329dc182ba01a257122d76a26aaf9b844\nB = 22d76a26aaf9b844\n\nQuotient = 1ab276448d16c533b6e90b5b5ca266e13ec27b5a58c80b7657df963ec2d1fe4eb1c1d24873eff6408bcb3d0cf97c31e85240eedf0efcc1e5a\nRemainder = 27b105741264f875\nA = d84fde3d851b52ed3b2a1268e9b765ec6c09c5768bba709b3b799802fadac30a6c3184185e6d57249b1c34619f3c9d2b90bc0c348b22537281a39fcadf738083\nB = 81a39fcadf738083\n\nQuotient = 84a87678485b3e60ee1cae3701ebdf0a29ee44115a492c34a0c8e84090e14070eb2ad0abfe2c339f26b5099327515104fe3d1c5546feea98ed\nRemainder = 95f7434941f9d8\nA = f79a0643bcd9c28cc22cc7b4178b3340e4685dd2672792516d6fc08567d2de2d3e25d43f100a58826edb146ac94acac4213bb09bdf8a258001ddd0ab110b89fe\nB = 1ddd0ab110b89fe\n\nQuotient = 516a2ac26e5b3afa502c7f3c6f15376f7a380e5842c229443343b5b74dc3de84db3ae99a0c57043e32a504ded19943c0310cababb3e92cf8\nRemainder = 327cf78eed336523\nA = 17c0d5814e1020d5d69674bdf6b9df193a16c0c8567a589d014e8eb7f6c9c36560791f7acbbbacee7c456eb51a4cdd7ca88011e9d8d9f2d64ab08ad74f7be5cb\nB = 4ab08ad74f7be5cb\n\nQuotient = f0da0beebcfaa716f494cf3fc81fe65117c90adde3b3942e8e66986fe8050fd5c9ebe1c88c5db04cea4c4c14779555d70cafb53870671f95\nRemainder = 3b2f844440d7be00\nA = ebba8c393c2a22b094d824ed95b4acf6875719fc165f73ee6d359e1134949169fdacbb42d5deb8cea96e11e3aac985635b5bcc6c02a6778cfa8e03d9ce6fc680\nB = fa8e03d9ce6fc680\n\nQuotient = 56527f07593774f0fa642241400985d0bb9b41d3dc9e025ca069130d93afc972d75e3fe0f798e127c3e1b4e925000459a3a5a83b15186e516\nRemainder = b620b7a3b752b78\nA = 5d6cad9e26267abb480b2b9ac5ea323bc4c3c53e0de8ce40c89c85accf0499aea5b11703a04296519047585ff12f8795f98da0546c20016a115100eddabfb468\nB = 115100eddabfb468\n\nQuotient = 294dca3b56ce9529aed2c132a9bd6c0c61de7a58ac50582f396b4fadcf7873b502bb869f801a9ab1f12384631cefee72b3e6050a7f69eba4\nRemainder = 53a0fcf5486c7a6f\nA = 24aa73803f270185d23310df2cf3ef67b18d7800bc41aad2ca13f372a27ef0a9217194f3f512e79f545a903895def195a5eb9a1a1b6b3f4de340e9da9b305d3b\nB = e340e9da9b305d3b\n\nQuotient = 16bf4dab1c29bd284c9b6649de65a4ee58f21d6a8b51627ca133fa817872b1a4a9956662db0aead5898ed0eda08511be7c47449638f2fab95d\nRemainder = e7751deb047d98\nA = 77b04d93272491322ed2fe651044e28cadb2ae7825f02b55aeb0f73b8b8a8b336802416fe08c718ab681581ac04d87116323f61f50bfd2180542fcd4a46dcff6\nB = 542fcd4a46dcff6\n\nQuotient = 388ae1c243bc9111e663c0c80495c36e8767bafe188b532b7ac84b5160d902af1b638aec6e4c66955d16bd8ce94ce6027a7bf95910f705ad0\nRemainder = 7c667ea307017c2\nA = 52f357e9a57722a867d8199242e100f06e8df810ee913d6992bfd9dc03ed78bcf44d692aaa7be806df0c9e0802851d7ae8405f76114e6322177907198f85cb62\nB = 177907198f85cb62\n\nQuotient = 33dc2fcceef7dce92e3a9df58566c6e28d03b58ff6ecbbb31e43936cda6380a56788285d37b5e8f11487afd78c39cb2150cc98d9d78a0c6cb\nRemainder = 429a380c9f8eeeba\nA = d99cf9a0bfc347c9631ae8c69defe1f1509c3ecaeeee5dbc61317bb73fa5cc6e704f64c865cf4d898f8a2f63214dbd511f61aa6e09856222432376698f8d2f67\nB = 432376698f8d2f67\n\nQuotient = 18ecac9e5539a014cffd8310ceb1170577cb23aa9cb3c523d57ad83069d1609ff743cd3c275b67097a038b85afcd7105ad21672f9ecbbc7df\nRemainder = 37924fea665f5c92\nA = f87aa8b6e62b09291e0e9b832ad71d8f85d60501a8d89d2638dccd4022e89bc4932c186a198557282527dfa86dfacc2f90fe0656695b61429f8220509f5106b9\nB = 9f8220509f5106b9\n\nQuotient = 37c0649a53c8cab91a7458702870bf64cb1de9fc1c6b9a3b92444119d368501b62d3a5138af72bdb7752eab8af6bf4e3bdb9e3beb1805b88\nRemainder = de179463e3e91ad\nA = 995c04c1f24c4efe88393bab7a7545e39193662d5db7c8e557d6c554ed4367f5af82c463d0ba6bc3148620481140add5677937989e03fb52c0323980d8841d5\nB = 2c0323980d8841d5\n\nQuotient = a6d193cfe7d8983768ff29908ee6e07fee99927a4bc4ef41d01f63f3b4a2e7029630b7d925d0979458cdaa903771286af672253cd99593b3\nRemainder = 6bf69921db298b3e\nA = 55c856daa8110599cc4fde0a44acbd69a68eb177e0438f7d843ba0fb74caab2a7e0c8a6f176f5555779e65c555e9157a16a1497edf36ccb583a458f0372a57c9\nB = 83a458f0372a57c9\n\nQuotient = 63f379bef9866b59f8bfd6bb0120a75dc03506b0034e7440764afc8ec14d8d735aa6f03a568ea98d0a74ab9bbe9c6e11b288467e5f79a2539\nRemainder = 11c077beb8667d88\nA = ff1fc3ea60fb37ff23e2f2f4e207a86e055cca41eebcc5bd6376904b51fb3d233cb04666fdc92be33239b5ee552870e45717890e35fdbe3728d6ff55d5662419\nB = 28d6ff55d5662419\n\nQuotient = 285ba8cdfbf00b112e496ce65cdba2271c82a273b3d30bed82ef2d360790c5deb97f3311bd5eb9876a61e33b3a37782d00c2d5ffbeec752ca\nRemainder = 1672a8aa119c3a1d\nA = d614352268930d301aa4046cd38e2eda4dcfcc52eac984943f2c863de5c4f8a44473a8ecebf12cb8f4da4722d305e5c9c3eddc0109d416e854df334dbfcfdd4b\nB = 54df334dbfcfdd4b\n\nQuotient = 358178128648fa9ea28dcfe68b4cecc7071e129e3ce4d113f5d1e387f7e5a412e9d2dfe5ff16d9987a544004d213ade9c134cc240eeb6871\nRemainder = 44c3fdb374bc0c30\nA = 18b973dd011969e29a1f4a5b8f118313f715c2e31dfebd9fe0957cf23cf36eded89c38637a8d3512bb23324ff", + "2a3627d5b942300200c823d764b7a6c12d1c91b\nB = 764b7a6c12d1c91b\n\nQuotient = 19ea7212f6604d423b308fe3f2f4986f31aea9d6a117a3e207e38ce5bbd8d7a866285ac60433630de547fc84e364c451457fbf864a82c6613\nRemainder = 2718de2dd0796f08\nA = 83577f755a448d5586e19486b04de7836818223ea920465c4eee979a9ce5696ad8e2fd5253b5d5dcfdf355465e8c0819658ccc5580fd29b351169b54c62b779c\nB = 51169b54c62b779c\n\nQuotient = 13e0c5b9905770b60a6f978d1c983cbc84dccfaed0f4222f534df80c7d3d129f5e8f74f19581332a7f6d383915424c71db4ca19bde2591fcd\nRemainder = abf5f6c8ab6ed4f4\nA = e2bf43c91cdbb244790eb165cc13feafea36f5187cc9bf8aa8cf202042efd5441e3822a1164992da5be750aaac0bb11f09375bdfbd4a39e3b682c7ee6ab5f5f1\nB = b682c7ee6ab5f5f1\n\nQuotient = 3919f31521e87f90df3a4463d0c83fa31e3f569449009d307962d26f07d854e8d3f0badbf55311c206bf34e6227949327a93b1a5ada7a930\nRemainder = 6c3802d44dd4668f\nA = 2546880cc6f97fb379afbc4a2664115ba7909414f35a5bf88be2ed5187bd1a24afaf82eeceb0b438d4999ebf9b7ec752236669425bd3cce6a71d9ad67ff2ff5f\nB = a71d9ad67ff2ff5f\n\nQuotient = 121d5ad4115c2768b962e51d09f426d61624e0f203ac6c923289b4e7964e165b34f3dc1ff938a7cf37478d407de251c64db71d3ee629c1035\nRemainder = 660a35e1c1245910\nA = a36d3250c123697adbbbdf489e6cb40be57febaff654ca951c9fa0b396b1714c55ed6e05e468153ac443dabca29de9b43cc0cc4e62cdf24690593662c86fb5ac\nB = 90593662c86fb5ac\n\nQuotient = ad81debaa02f6e60da58b46e76ce041fc4da64138634ea7b3c165b8fbda027eb64b6b5339e70babbb83430d60383c2cfe22029e617fd03a7\nRemainder = 2e4aeafa2ad76832\nA = 8992cd131757ba5cbe54aa58be115723ea3438ddc782a4d1996980b7b312fa76e4483584df744b10340e5fc9e468690cef538920a732a8f0cafb4e30846cad1d\nB = cafb4e30846cad1d\n\nQuotient = 67a71b9ebaec91121a8cf6bc2932b6be01af7954eca69c5202d771c2c2d13683cdf90ec942a3445771ccfe484f947f078de825ea88b3c05a\nRemainder = 8395953f744cfb31\nA = 4f8ada84096198175174896167405b85cbc03fe0642f6b263a70f9a22f19ad6c9aef38da8ac036d409e6fd925023c95312cebe04eb653e0ec473dc8dfed98967\nB = c473dc8dfed98967\n\nQuotient = 9416326e2347a541b777a0fa1b0c35d8fe76c940d24c6f6806d6ae8ac1e280c16e480786478bda3f780ee92f3f3c361574efc2ed5ca98e26\nRemainder = b8ff45f31bdb58d8\nA = 902f5e48b96b9b1fd16c3b21292ed495987ddac4e1d92b2ab10378f2966c4399d6a41eef622a4991ccd1f647531dcd145de4ac99b3036779f9414ed2f4ba7e08\nB = f9414ed2f4ba7e08\n\nQuotient = 403c651b4e571e8301c4158fc185396554bf61d900708d2af5c2bdf495b3cb539b0b9b5acd0d71654b3aa68024961d5a7bc9e2788e6c822b6\nRemainder = 7856ec047cec8dc\nA = bdd6d846983fbf140173a26d2b709b9f31b4fee1eac9d25fdf0ef3523be0e6afb372acab470cfe1806b36d84017ec99302eb9eb5eb2862222f4916d8b6201d14\nB = 2f4916d8b6201d14\n\nQuotient = 1b6d967173f9777cb6194c8f69289b91da731456fe5a1515a49e4463cd906c84f97381cabdf9f358d97fad5d3cb140e3a3de397e7f9f683157\nRemainder = 83649246ade8bb4\nA = e3da80658acd53ada7c2dc57178e697f2907c5b0c64f4a87a794ca7521105a0568a32874207646df3768ee60964b7d1d2e29ea6bf7fbaa7e084eabd4ea553a72\nB = 84eabd4ea553a72\n\nQuotient = 27b8f1e49e404455cc68217a20766590e749507976a3a6de25a7cf2c32593aaabb04d84deba1ec6bbe048a2959ffd747243c396dc53c9c811\nRemainder = 3daa032278ce53d0\nA = ff3ead7c7b27f607d16f1ef4ffa91b6cc28301b9256cfcb0c22b6818371ce648ae8812dc50a86e4bdc0d0b1e5b0d55c6ba07b240886a6d5766cfb3ed0937a543\nB = 66cfb3ed0937a543\n\nQuotient = bf987f58700508356fb6274f64a9f78d455e4c436fc6fcc980ec0800287ab3789b91c29a8a72b16645ecfeec926b6f8242f3c7dc3adb40cd\nRemainder = c007da44faa80584\nA = 971aa67c9af10f70977f600e10f9278b8e66d2471956da38e5f4b3fedce9a5fc7ff42b800bb4a78314c70bb59394d0880383f5182b6c1960c9e5b47ef8e63be5\nB = c9e5b47ef8e63be5\n\nQuotient = 7332104442474715d7c4cdac15fc1731240f8b4dd0e6ff3284a15a62a8f9a071dedb87f2220efcc5839cb7e6933a8f65d767819db26e134dd\nRemainder = ef65a7789f54174\nA = bcea2ae4b1edfebf905a5820f0481b6c58d76a69df9dbe84764add3f49496a5d7005d645eaee3754e0ed105c13a114e6a0eae5cc4efab6aa1a3d3a0050fa86f5\nB = 1a3d3a0050fa86f5\n\nQuotient = 3f6182804a7ff12fe7ed3c8521b55564559b1a47a78e1fd56597b9470e7e0f6e7e48c58bc8841c9d118718ccd5e0c0bf9a08d8e244ae60da5\nRemainder = 398e30aff5bd284\nA = 2b877181a960c5e29ab1b2672ee22539256a82369e8f6cb5bcfb69e5e4a41f782e89b58fc0ef6ca336469ff929729f8492b44f12199f0e1c0afd12b2c999e787\nB = afd12b2c999e787\n\nQuotient = 1a80a681d2c42edbcbde552323dac3a1c03b43251a99b5549da6cb39ec6947daa0d574f0df68512984fa8e269b0b27a5576b3aaccb76ebc23\nRemainder = 378e44fdc7a5ec4c\nA = d37e62f44de27a1418f348139eac5ab9fcc1ada21ea6d7695273daf638b4d7eee6745f54b99a9678cf742d304736ee356f66d16d874f8cc67fae9be5dfd41a3a\nB = 7fae9be5dfd41a3a\n\nQuotient = ee982a63816d56758c29d284c19b9b984908cf0a9ae3f1f926e162a2cae4f88703aa477c5c14042247635c103494d11593c2c3839baf4d93\nRemainder = 39afe3275c01aae6\nA = 9a0b0476cd33861d2fc3137df292728e1f636f6fcba5105f384533723231a3104e7c77df46f7f34a4bdc63d5c67b418cafcf106b26ad020ea547d34edac1d3a5\nB = a547d34edac1d3a5\n\nQuotient = fb3f4a39a661e5c31228a6b7b4c27e6e52d1954e8ce262b98b61650efffd762cf2a1aec228bec5d5787683cad6b2e6e49a0de91c15c81874\nRemainder = 63e5ed36ff73a42\nA = 4453712f56467328401a69d4d749a0771732734a760a74094e50a62a030cb604e735bfe0bf0641754edff94ac0e0549e8c10941255f0f21f459e52a6cfe4d9ca\nB = 459e52a6cfe4d9ca\n\nQuotient = 7af60a7c0f995178be76c070cf49eee311e6d1e3afaf50c8c93ff200c1b3fe742b23259b4fc0b9ed0947be4fc9a6c212d86de9a0f7dbb5279\nRemainder = 19657d8ce516a138\nA = c9c92a31ad0f3cfb56a294c42a26eaecb77edf33ed40a7e6797927a0c996a7c0a701b484741163df388bb082e3daebf4e1b7a99002632d6f1a41c1d517238557\nB = 1a41c1d517238557\n\nQuotient = c890c55a8e2a3105b9bf9344a57a9b9fab5fa1fd57083d52431b695553bfbe7a44a9b6cd1f83958224f351f8511b14215d1648e88e938573\nRemainder = 1bab5b03c372daee\nA = 88341550e470016c7ab600b9f6cb410071a77f907a58cb6da4ce3e955d1e859534c2c1098fcfd91b9fa66926e51896733c36a824c3a20844add94e27f30ca651\nB = add94e27f30ca651\n\nQuotient = 34c240c42da400317f66f5151630493a2f200ee418d5ca3300cab10dfb429c2acd7280bf066fe19115f86db83d8f5b93cda714533b16abfdc\nRemainder = 18cd326996ccebc1\nA = 7e96d7b90ff09b114dd4393e9bdfb13d8ff517681126c566e18dd6369d87d248734d94bd02a1f19cca90be7642822b636369c51dee441a9d2663ec896e1d6c6d\nB = 2663ec896e1d6c6d\n\nQuotient = 10d18159e75efa8204e325e6be830b4ee8d2c07419e8276edeac6cc286488fc0c888300db3ebb5f935aa82654d3b932540f0093d1880e1d6d\nRemainder = fe9b6b8ba7c30f8\nA = 731aa6e2fb2ad1e1f80d7668c7b0642203af24af382abd207a5ffb588209e8b5caf953e9a96b478f39ec03a397d1433998e3c95e382d93376d80cf0c957788e6\nB = 6d80cf0c957788e6\n\nQuotient = 450d1f4a105ff8d1a3efbb12165ca98c67ae70404472e4862db479e03313b08783ecc42104780c9d57df0ddf19c5b4547ee9ba52ea82dd0c7\nRemainder = 169e15b4d5aa180a\nA = 902bcb1904b80183656dcbd51879e2982e2b46a547c9ae3119ffc12c6a003e4321b519289b7f22fad19d16480182d1d797c3045b2d29dcc12167f9ce5e233d89\nB = 2167f9ce5e233d89\n\nQuotient = a426f71cb3d75365cd076a6c35c10765bbc3f4bd317fb83a70083b0f7dc43a4e0b95508e60dc1dedb780e9b485f4f7a8870960de669b73af2\nRemainder = da381ae5c97a506\nA = bd59dcdefcbaecd9292c4c3685fb87d3a94c0f0ed01e43e63e1f36fb65d6c5eab3b584f3d1f76d31458c9f6b4c69869d96e943c61df102771274c5b4d821469a\nB = 1274c5b4d821469a\n\nQuotient = 26ccd4b7be090af22221729b0ca51a5e66435c2d33f8d88f94405f6c0123ccbbbbc8080cd8448a977946019ccbf5d267ac3f151ebe686720\nRemainder = c41f9e7bf20b376c\nA = 212dbeff03f14b5825f0d7cf8a7501db21b60581a01a26d522ee44e7fe69545cfcaaac64dbc76c7e3027ac39ddc2d80af6f3fca1824c6ff6dae90967d9ab48ec\nB = dae90967d9ab48ec\n\nQuotient = 801df28f4fd987b4e980760f4f2625276a2a7191d453095c82aa98a2253324ad2873abae70cd98c28ef3ce102fdd53469b9f01889f3ba8b0\nRemainder = 8e435da582e59809\nA = 48341b28138dd04807e522e341f74ac46b0449fa45f96d7fc586997c056a21eb3c399752a6a6c023509f042cf9e879f397a34af9aa2ec2e8904674f2ea3ff739\nB = 904674f2ea3ff739\n\nQuotient = d3857b72b70adff9b5dec3cbc63de7c90ccd7aab6595339b2de39bd6b9789045141d224aa4e6bf9a06e017aa3edd00e716a771b3f5b97771\nRemainder = 14135c686d2e9f70\nA = c1cea45dd46409d5e24fb7ed7d849dbb079247af2d312e01083754ed07f65f090e4dd50d23a973488702ef00936c5d78af603ec0fdf03dceea8f939c922b1e7f\nB = ea8f939c922b1e7f\n\nQuotient = abe20c90896e261e7d31bf40e7f3136d36b0b78006d12225a4dbef6aaf2062b609379eefe7e5af5bcec17126286f196f1330da8477096763\nRemainder = 230307c44cd55896\nA = 19a637e4f3051be0f7c4d35513bca4a91ca9b8082fe3c73899b70b6805a7aa0458512495cb6ee1ade55ecd5851be1dba96d65202f06bc7122633a0d905017545\nB = 2633a0d905017545\n\nQuotient = 5ed3765c4a777a903e182f7c9ce39d19c01460f389b904c3ce1d3525edf25ffe7dc0f4d9e24f0bc8b7e01bef19c83e74f17884bd7", + "bfabb2c\nRemainder = 40f5346f8775e20\nA = 546578393e914be30581e24508a33f6560a5805dfb1c675d1ff1d6f5eaa7ee638b9e0265f543413e04e3f1f3b0895dec271c9897a48d9ce9e3d7df32c15b75a0\nB = e3d7df32c15b75a0\n\nQuotient = ed73a67932746985465fb0606fb0e81595514f1647c911c303d4d31eb0306e3b2aece07320f6fea57a7071d73150591ab2a82a7d53968a81\nRemainder = 2e495a881876da00\nA = 8976445bc318921f7e12c8d4e8e50596849a1503b5efb65e939c291de136597c05a1fd16137f0bbbd7197df943cd612118d1e55a50ee097c94331c1cfb1e941c\nB = 94331c1cfb1e941c\n\nQuotient = 5dce24b7a16d847b0c43cf365ea20bee9679fa0e8732813e827cf6ef3c9bdb7fd8846b5689ce8b80a7dc0dd05721cb06d2700aeeb7ff04d6\nRemainder = d8ead1ae3126aded\nA = 59b99e5d028e6771d27004bc19830a5fcb347f7ae04c0ba7c49130bfb198c5b16821e425c979e6d2dddc14889ae58475bb52c6cdefecf2a8f4dd6e462bbc8f47\nB = f4dd6e462bbc8f47\n\nQuotient = 170e10b399a4c5fe354b536fe59d53602102f215d5107493680ab6e181f67d75ffd45bf49ffb23cf9269b856156b5ac6b1c5def4ab1abb18a\nRemainder = 57131776937c5df9\nA = aeb35966e2a616762768b7f63ce3aee5e81561080617bbabd7846b3ca03fafaaef83dd05b8d16cef40db0a56f3b0ef6eca5e236681cb57c8793dc0907d9aa30f\nB = 793dc0907d9aa30f\n\nQuotient = 1acdb88f047f9bf679c50ed67ba01dd24dca92103f8ea2677215b6142083b64f9fd2a365499dc8f2bc61e29fa176f7d76b55557fa58e34f9\nRemainder = 5065b726dc6b3758\nA = 15a6292c9fb66c6770a8dbc6fd431d2a4b57338581f78d0860fda90182cca563eb2272a79fb4f5a6fc72c90dc23e8a95713b65988b5b3f9bcec4f0466c1c47cb\nB = cec4f0466c1c47cb\n\nQuotient = add8127c0a27c961203ea0351aed5b3c75aa816e9c2684574e55f55c7140adcbf69d2cff843e5f53c157bd60b43c45c8b6658de72062fbba\nRemainder = 67f48d3584cf4fe5\nA = 4e8938c8cc46d34e3369c5d8536b18c963dbde56020678f77cebac5f8777e0afc62ca2ba4f533cf6cf7561bdce77b6f495bc1b05f1416d1173a6a288012c7c73\nB = 73a6a288012c7c73\n\nQuotient = 688ddf883a0bcc1ff9bd582119c2fea7c059e19aded8c048390a1d8fd7d769666987418bbe0d4cf4b67009a342958928769375c1c0d558acf\nRemainder = a5356d04b64ee12\nA = e0c9e32056977aeca72e229d83f0d320fbaf5cd8bf3e033289f46101c75ef59a854982f33bcbcfd200034e8ff439d669a03fa404e7dbfea822664967d67dd5f1\nB = 22664967d67dd5f1\n\nQuotient = 39d4d94587fd1445f31457c275fd6294fcb69ba155e7da3e6cfef38ed1272d6c95755bca49007ca62cc101b038d264876f18594b8fd4c329\nRemainder = a34980d5046e2ed0\nA = 2efcb12fb55c923f5c6ca7ae076765059e15d9e75240a6e5fc3db92de184143fab1934c7450c3a380a9851846c9f43d67bc199a314e82e72cffee795d695f82e\nB = cffee795d695f82e\n\nQuotient = 145ea82eff186b7db4b11fa1514674fb9d41c698efb33227eb1abbc4eb78bdb2a280c0c4c47adaf4e010a4336cbb5650becd1ef544e223e53\nRemainder = 36052bba2867f5f4\nA = f6a6c7e33fd4c664652d696c495df387b85b132cfdfe34bbd35759477b4a3c052f610df57e49e85720489e4bb8dc923696400a4a28dd000cc1bd491446a50b96\nB = c1bd491446a50b96\n\nQuotient = 35d0c9d870348b113868282aaba22b21ec87cf421519a23b288b150604729356f924090ba038d7400c0ccd4932836c65902b4d3c46a202a0\nRemainder = dc8c7d087bf24b0\nA = 22228c8a5966ebdec64007704a373b0596ae702d62e29e468653b21a890ace2f02c27f26b043f48495687ce8c2ca8092ead21aa250ce0f6ca26129615a2432b0\nB = a26129615a2432b0\n\nQuotient = 52fc995a486c4bfd17ed9722948e9ede1c4ac2fe80e6bd7482fc47944c4337a185a506a9ca473d49073e1b813ad742f19b13d57914888d5f\nRemainder = 75c703f654ad630a\nA = 3473041ae301dd2806da30dcf06b9c09600086d6873cf3ee9d5a0be638849afb56bce2664f797de4123f6f8fe3e12acd32e33a285bb7f493a1cc13a7108327f5\nB = a1cc13a7108327f5\n\nQuotient = 1744946730b2789977620f2e7439641125dd338d1b31fc50813b34dea70b83d209330bd17fd527db9a402ad9752c26b8823082ec9971f4ae65\nRemainder = 453a3d59303ec3c\nA = c0f592d83649bcafb7e2de1a8a71fa863c1f51b595bfa638c8fe30731c6fca36da975b6f19c657e3ca29efff6febfb311c003ec68189998c084afe4979b5bb19\nB = 84afe4979b5bb19\n\nQuotient = 468f3eece20aa9d6473f3c559760793e702758a3d9cc19d7817216392c7cc7c3968778cf2fe0c3f0c1424d7512cee19ac0717952f18aa287\nRemainder = 5904e71034e3a02\nA = 1f0c99a128c757d76ae6dfcd01012f0453c8f89b00476ec46321ecb872f99a48b4da29a4abffd0bbff2b727dfa182652ca85350b4ce100fb70a6a40ab6c41d95\nB = 70a6a40ab6c41d95\n\nQuotient = 12198913ef16c1cfc7c1be13f1cc5991a61ff74935e09f0c46d26456b7cf2825403b9851d07d27e0197c1fa2ac5e32e836979a184f14cd94a\nRemainder = 33431c3df719f946\nA = fbfbf5494a9c5384c7ae3df6c02a5e1f9f32dc31cd7f437832696bba164bae1a9d95daefb8bc08e0e8e637436fb747084460697b5ef5ac9ddec06757dbe61aea\nB = dec06757dbe61aea\n\nQuotient = 376c2f902566d83c21eb7c3aa3a6fa0482ed52c253f67f00d5b915d0183c2d9a2891c2ff837fcb426a4c990c48bda4f90e0bf69d13558696\nRemainder = 31540f5e05e8b4df\nA = 2527f8cafaf7e8319ca53104229199188ab1ca5fe592bde8ecf605e17ca6446414e06898a85e177d6985b5cc6d4eeabd6b222b5f44b4fc1baba050665c090b5d\nB = aba050665c090b5d\n\nQuotient = b8fdd5cd7b2d9295258bd99e2780921cb2ea70627a79088039fc3ab1c62bcfc6307e86db4a7803f18e5339f152063f9e41d370e97b1ba2f5\nRemainder = 4ed4f2d12e4f4ba0\nA = a25bd113c5a8c67ef65aa80f1512de43c9441fec0c41250048d29c406fbdae80912eb3970457d621c552e3af7ef2d6bc1b5448e7df5be724e0adf6f71df7eef8\nB = e0adf6f71df7eef8\n\nQuotient = 5421daac8cdeb6acc2b8b0dd85b592f255ee4fedb3a9e90f2a5bedfb0f9f033d7c562c96958346bcdda4664c67848b9d9fa7d3892bc4e9af\nRemainder = 7e5661558c345eea\nA = 490aef65c81b32f5df76dd58decdec3e3f73bc1fcbdb6aee0c93cd98725056153b572509e75d2cc4b042bbeb0a77d27fbca1e39efbc765adde41a7dfc5c3576d\nB = de41a7dfc5c3576d\n\nQuotient = 156a8a24e7804c5f576cd1757dba44cb4185bc13cb56603b54ee3b70fa35cd98db1992904d4f7d99a63b3a486e6fb31141a9d39cc0301f897\nRemainder = 29e9c1627537e5a4\nA = 5e4a10e772de8dd2c96acd714f7d3880ae8ab460095a01038f3aa9b8ac8165889403b42019a1e70e0e7f32e77fb388eae3579dbcb690729c4671868b0526aeca\nB = 4671868b0526aeca\n\nQuotient = 1b0eff2ff0aeb2c02ee3cc9e0bff808f4d616eb290293b13a6b58a84127972bb417d55e1d001a9720ec72562ef3ea688e64c4f32c7e26cc87\nRemainder = 664d57c57d4952e\nA = 806b8504abfbeec4d5923f83ddc071be88e11c4394168854448df96160b95adb1fd9c288852e2f3df3e36916ba5118815ca2e83a6a7d9e074bef9c961e2958e3\nB = 4bef9c961e2958e3\n\nQuotient = 2e363b13b0457a0e9effc2d7e297df78f35e5d24d0f8ad4525b573fb2f66f374871291ee8a8ee3d15a823b560156d474c678f79ee480bbe4\nRemainder = 5ba8f49e0ca36ab4\nA = 2e1bb261d98ec405dbb068daac5efeb0a51f08149181864e9dd6bf6cfcb617b76d8facaee2ef468807e0403bc550d58e8ad9e5cc0f094b02ff6d0277fe642f44\nB = ff6d0277fe642f44\n\nQuotient = 149a5b1a81b9e47ed36be76252055bb202dc25f8fe7beaa1ce59c279b32941cfbaf8fe4555867850b2fba43b10b74534db82398320f9786d25\nRemainder = 1ef621737e81780\nA = 63de892cf5df40c98de78c755c99e94e0e76cd5dc0b49b8856fe69dd0abcdc535bb1416f0d02b4eeb54e8a939cf7ad4edfb7de4dac87523e04d8ea8637e50920\nB = 4d8ea8637e50920\n\nQuotient = dea8a9211974758752d89965eeeb93cc616f88ce757ec2809f829cbb8d99b4ffdc3f0f643779fc5e0bb53b5273a5b15965f4a364863592f\nRemainder = 9ae7de3edb6c7edc\nA = acd5cebd069f7febc38c318867ba3a562bbf8ea9b19a6b33538ba107e49439f8ac6e880c6267c29b39141dbe2273d93062464de307efdb7c6b738c0bb282c3e\nB = c6b738c0bb282c3e\n\nQuotient = e9149b347cdea84d740be70060b239af000c4336ddf36fd5159083b795c4763588c87a959df0104212a04cc928baf60b0ea72e8cccc6d477\nRemainder = 3ef5c6ee67e6f5da\nA = 6ccf1b8b406e6a106160e73ac4122a04c0814ef5a47708a6776eb52002d52772d3fce3fc05398172bba191390aba925bb23aa1eee626410877822f27d1e3cb09\nB = 77822f27d1e3cb09\n\nQuotient = 1606c2fe44cd0b780ee474a9c7daf0b2bebf62db0ba8ef5a99fe22036019890a4c7dff73e678965bb0e2a6e61d00a74a1d33dc1106842115a\nRemainder = 7cf920ba2897f714\nA = ef9a3983f26237576311a871e4a3df0538593dd0cfda58ab90b889fdb35c700f7d158abafad127605057ca0532e846992c41ec06902ce58cae0c1fe238c726cc\nB = ae0c1fe238c726cc\n\nQuotient = 8ccf17de5068451fef1c2808c62e19997c7f920d5cc0fde1f5a247cc57c6d730df553cf33094b786597a343a0ce9e4bffef568247e904343\nRemainder = 2689c40a54df34bc\nA = 8435babd279b7a3833d01988c58005d4557f7689ea9b7168ef42ce2b31a1a3c32a982aff654f271a651085335496dd826ee4b3bc27f58920f05dc6676e51c662\nB = f05dc6676e51c662\n\nQuotient = a9e78c48c779140b1d15843089765ce9ece3855537ce88cad3eb7aa7bd6ec72df65adacba2bdf6c491066406bdc3dd3dd734a70e93eed958\nRemainder = 53da0b15ac079ccd\nA = 78550cb7b58b58d6878b615dfa25a5b90a1ff631740e631c7f8829962446903c686c810c46a1551b6c1f7a89ae898435bb8e36d1bae24a80b54edbf4bbc9af85\nB = b54edbf4bbc9af85\n\nQuotient = 1e3b41304ee07f6baf1ca061e0e28a3740991c6ca2749eba70d3ea1f9cba8adec45cb69a31cbff22784a9e056e884713c0812e8c7981e49328\nRemainder = 3d051148ec43a72\nA = 76b9453d315e7a9c592e1f2640f5b6b90a65e7f2ff8ac24b9b47e35abb76fa5d303be6d501b341a882bdd9d2a1c81a9280724673f87fbe9803ed5a2e7edaeec2\nB = 3ed5a2e7e", + "daeec2\n\nQuotient = 1921410e1a538a71d33d9c5de95593fada116200c399fa7590ebc374282570477f5f4abdd5166784ccee9671a1a23b96378df62168049f6b8\nRemainder = 1a1f4aeb882d7546\nA = e4aa84f782a65d376b10e7789a7d56695885aae274db6cb37e0a34414397a57b4a5f76dced11376af5fd11d31828203e685861a6dea239789196fe73d0e46116\nB = 9196fe73d0e46116\n\nQuotient = ed2afbd2e63617a651911017d9d02224d521e99275ab642ad1a941827983b17ef0f2067b5405b20e8e97f2ae6099150a1989df94276aadee\nRemainder = 4578107045b9cb81\nA = b547cd987638ff7e3c30fec9b728bc10c3b8cf16e7040bfe0fe9a26e44d2898c4c4d28ef525cde2b4007b2ffb3aa80fc4514a99b9aa2e112c3acc56b72ddbe9b\nB = c3acc56b72ddbe9b\n\nQuotient = 56181509251931afca3bb9dca21eedd6ed4226be67497d8d1bd0ec052af146993e7358f132e842f9b6c4934cf1b4501f5d6c5912e65c8d3ce\nRemainder = 1b9861df51429a6\nA = 32988a4e0769a5aca200f6f6f1498512e13b4904a9a311cd8a962fdd688de0c6e50b04f42cdd2cf8bf9b0a6922657f9ad195773e1250f85509672452618da9c2\nB = 9672452618da9c2\n\nQuotient = 1fa45bb973dd1d2df0002772afba55284a1e41f6aa4b0d1a6c6a4beb8ae00b52e88a9889037b8bfa9b7ee38036c57b713b48af156c3f9e8d8\nRemainder = 2525d52ecdec8814\nA = bda657ddeabe24c82c883e85822941bf64448b7cbb368468078101289b6fca36680b3884e35edc1fce5a5cdbdfc11359a1ba8ac0785c09ba5fe5cdbd30726df4\nB = 5fe5cdbd30726df4\n\nQuotient = 63e21f5568d07976aa81a2690b9e81b76fc3291cdeb010d1693d0e80191186815c7b2f83551a5f1b172640425d4733f06f4df1b2c8a7e6ed7\nRemainder = 14781a368471ecae\nA = 9f3dad0b3b56de15ac46cde1d79aba6a2f3b34d685cc810e9fa3f2d865bea4afb480d58653630319a258e9e8ded9be93cda3bc52b80a9359198221221724cc3b\nB = 198221221724cc3b\n\nQuotient = aae37878db016dd758003b85ef52acc7288b7b74c4723e3876a710baed4751d3be2ae49123b248f2b2c55a5be702c4428b1dba9b8a6ae8a9\nRemainder = 6c754d5c167e1228\nA = 4b93a98eb7b92cea0a4f5c2223e77abdfbd332b39f295b4ac40f71625d88e4add7e482adf3010082d8dd8854cf714a54fba0887de87946e97137cf7eabda038f\nB = 7137cf7eabda038f\n\nQuotient = 9881f551c4b7e67611f37df29e77cbe4e2d9fd5e17b7da3d013d6f3d4312e53dd26dfe3a2a12525cfef1ef81e6ebeeb7ef8fb4f918bf15ee\nRemainder = b14595005716bfe3\nA = 7737f8e7337160c14cfa8411236ca0354d8aeabf389b9fc4b14bb2ec3bb68286f3d82eb394dbd8062862b955e9fc8e86eb646317d1315d09c81ef51b30288cf1\nB = c81ef51b30288cf1\n\nQuotient = 4c8519d4d85ccf845fc5b8f31c27c60f0893ffda29ba86e8a3fd5fe67de5d29cb29362679abde996039b8febda2ecf71f6b9e1c1874361464\nRemainder = 10fae644af084f8a\nA = 900f7846e927760d9986894de6489e53cbbcdd59f7707917e7581422508f2ce79b77bd2c56d964a41e60baa927ca679faedcd9cd8102dde91e1f583ae834b092\nB = 1e1f583ae834b092\n\nQuotient = 16ef17b40bb73063f3cd0929cfe2405ca0ff2d3d426ac05f8a8dfadc85659105f7f728e113baab59247c4c7936ab975c08d6f1c72c12c532\nRemainder = baff11e6961c72e3\nA = 130b212cb6f3d854e4f17524953fd8592f5e59dfe92fc7d955e2899d1dde1ae4aa20d749caa349ca8d1bda7eeec2310532a7af54660e2a1fd4929335a1623bad\nB = d4929335a1623bad\n\nQuotient = 1cdd7ee2eff733b83beda5b862673177e2f2151ee0fd9ac0bf0ec5b7e05516f1d1b59ea754b0483d0e4bfb7668bb99117907a58a8ceb78028\nRemainder = 29e33e0c2a515780\nA = b0131ec2c1ffe9a523591a9453d2fc740bf885e7efc1a0158905da1e646745ef1bbf39b406564cb3da2f842bee307b36219bdee5991c969d6199279c25d4e380\nB = 6199279c25d4e380\n\nQuotient = 20bfcd06f9c54c537ae563e33dab31047aa30a6bc4e7eb0902bfbab3bbb7e65df442c46625c39e08c88310116348e9ebca2450ab463727f90\nRemainder = 11d8f2f6d4c1f55c\nA = cefafbaa2990eaa88184162ecb118d20e5999e5a8fdd25ae7f6248650ea74a8cfb92c58efecdd5d31eceb618f1596d7a6bfd31d092cf86da651f629975faf91c\nB = 651f629975faf91c\n\nQuotient = 37204c5735e4ba5e47e845d8b652cfc2b1dc715abf21ea0ecf5b1c6c8b9e596591fd7a7f41787be1a028c147a721ebb891b0abe3bd079b589\nRemainder = 1ee700ffb0ea02d8\nA = ce22d36b3cb913b32bd0e25cc14c7270d3f7b8e600a9b6732377f846adafd7fbd8a09d12fb7011f2283d988fc29aa25948dd4a0f24512b4a3bd460ee19887d35\nB = 3bd460ee19887d35\n\nQuotient = 191051194e4362bb201f5471d4bfaf92f79b6fbd119ca3dc1afffba334869ed9f8acd14fc42a2d8f616d652610a483ad90f5140e9a5ca4172\nRemainder = 74785b6874d8fa37\nA = f3c79f9a6af1c5bec72218d969620149afe8bf068cf7a7aceda977076665bb5a2c30729ac3aa976c9be379c6a5458f1501db8802652ef69d9b9f4f097027ddd9\nB = 9b9f4f097027ddd9\n\nQuotient = 6c46c17fdb03d192f75d636e1e2ab4e858d55f0f205cffd75550c4347726b5cfe036c6c901782cbe5a04f1985d9fd1dd39d747d25a6a7a88\nRemainder = 9a836be71a24e72e\nA = 4f6cf6e357b4985442a25b5c84e2cc0a5e685e2f5ff71ceba439b81f4123e16db2296dd4333fff23eea92bdbb812daf1d27c721412fa9847bbc9a0bf08879b1e\nB = bbc9a0bf08879b1e\n\nQuotient = -4984390f93e11c9a77880cfbe157dc41d43fe901c8895ac5091c5367a77370b16d42e8cc260058adf4d3fc8ee8cc6c0099804f4c319f15561b0a2b1caa7d703db82a726c9eab569c\nRemainder = -19374dcf21822188d720d6ec892bda2c084e8af84f38012da7029a3c3660c7e813fd4f7644ca80373575ff98ab6d743e939269c51bf62e04f\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 330af318ce0ffdaa92448777ed117de9c104e0f975651322c8e01b1c470f3cfb7a78b11f7daeea57614cec37d18b89155f19babeda0016171\n\nQuotient = 1a56f7d6c06a316a9a466319cbd558a99f06843782673a54775d859768a61933de3fc410068d00d5f6ab13fafc9228fd40ad41434501f8827bd7461441140eb6977f18d102d446\nRemainder = -3c3d566cd48a909292be2ce30f88ebb68e9122a3359f52d1d7b0189c467b829a9f226c0b64845715020dee12d179913ddb7f17da2db86d854bd\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -8e770450768d07ce20ff8f5f6af464b1ee5f1d0e8faaf927a19d3ff801f6089378133e822b8e63cf29c4c9ed721adfc91d3355a3c7bbde77bdd\n\nQuotient = 42131cf8f52a6a3f189697ce402a8c9439bf05cb3dc1cf8bc49dc2f07cef15b3bf0102c941b5b3bde6440abc6eacfbf77ea8da06ce932fffb226b33dedf001e9657464b0f06\nRemainder = 4cd483574fce075404dd22072abe61200fc455c15b382c7f2962ffd82c38ec1e2c60f71267cbc35fcf77fe1f9301d6b5f884f1c416304aa9f4d4b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 38caa64e74b29a7e9bbf341edbab112a730b17103831a9ecb70ef077e9660b2dd1fbf71d7f6bb4cdae2ed7cdbe9070ec9fde996c91b9bca5b83450\n\nQuotient = -11d6883fcd705ac97cae5bb7f8a2929d6f636f4f232ae9a4af9769183dfce9a9296fa0714c3f4fa1eea467a5c96a484a59d0cdd87496b9398e7a818daf89a58add3a39e80\nRemainder = a6b7984fd80d719ffe2e6eb756e4e3bd7ab51f6088e04ac8fecdc744b0385294dd23b5007910109abf40cfca814c10addcb5330e422b6f5eab6efa2b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -d25d50f53c694cddd56aadda2654ae5888603b39cdbace93d19c117af5505750aa24e615f95446862bd693f5b444e2a876eb2cf49f6c7acd007eae02\n\nQuotient = -3fa898b02c621915f44b213ba4e80b8e85c7a2f4c78df2bda7d99494bbca3eb2d9354965d83e1c9001f10aad9b3f3ed837a630b329f5a4b28935158fbd9d291a120b08\nRemainder = -320d41a3875da2e83ea9a83947f5abb1a7026c84020e983381722bf7aa87d5987ab088cb2c37fc3781c82c81bef3263fec560023e236a747030618e9d2b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3af2721aad4b18db27842b5e539d8cada9dcd7ac4c5b885065dd2496a6f76fa73c8a51b239b5c068ea6feffda22d8ea806fb488ad5a94210264597edb40\n\nQuotient = 179307c3e14de14a744d082825ed723b996a4e15f156ac473960583138c43f4275b4436c50ef8f21a7b450a969819b81c15bc355fbc5fb55cdd8e124d931d142851a\nRemainder = -9c8eabd36a25e995c1811b79a2a0357f6aeef4477cac0ffdd130046cb2a647f928a34d91d9b489d394965719cd58604b957c693a93145328e5568d33d88a9\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba46638", + "1056a3b92c35d9b8b71372b\nB = -9f2d3da1da77914df66bc889a40847a0d705d4648a11f282e09173d170e96d84b5a45092d995318fe7a954b54b88b784423402519a38bb521e84a4f6c5485\n\nQuotient = 6c0f316406afb4cc2aebe34f7948422de0b612a02dc47f4ae59419c579fc465ceae1980a3e524fdfdbdfad4862f168a9851664688c9ba01a8bc1ac156a6276643\nRemainder = bf52a2fb6493eac22fc8b334ccd8e8fa347620539d9189d535373f94503310a027c5423197c7279bb51ab8c459e27f548d57b55740320e80b753290d077aa7f\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 22b9e55639ad3ff4f071a49c8bba6bd9047e162fb31882421db8ec5ce46f28fbc35040bbc74ead5a948c47c43e9c7adc32fa52046b53f12b07b5224e0d8e93e4\n\nQuotient = -1008fcb6894d8c411905136fb3e05b38ec5d8df35db06379fc2d6d3e3579bcb34fa6e021b98b899d9d082c111b1a6ac8e50418fcd5968ade6aff8828d8e4777\nRemainder = 3d7dca387b00c677d855fc4af4d86d86331fe4309929039e828765f0937990bffa964d3ffc5d4f2f4b8bea978329e7cedb847c7cc341ee52217f903ddcf9446ce4\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -ea045323f406bd7ce25b3ab4993b5f6dd92ca80e3a02607a862deb13470ccef229fad67ae958cd87fecf4f08d9609595077d0d1360d9fe48c4566e237aa877e7b1\n\nQuotient = -42a50301031962754ebf9c4b1e125e6df3dd40ffbe09c044b1cf4b62ffb4f92d298b05933a450bcef65e86398da80740a610ba45928000a5c12d26e9f6a4\nRemainder = -c5485b82cfefb3f980e0fc7c6cd89b1345a8fb942299bdc36ed4ff8916016315a0da84ca0ee2824dce3c7e5ed49d517c45173c9c8e30b224940af6cf828c73db8db7\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 384e523d5a687bd1a90101e43334894b6a27e8c6809a8bf5bffabc34d558a8309997dd6f2a3b7c1a63100dcc0b6647b444ef7e5aa4a9c52c7caba1ebd096c3fae6f95\n\nQuotient = 1054439945ccb5bc5461fed04e364c7a36d5dd2c0428872676debe07654b2ce31e435a90c81f2bac1032143acb0c49ad101398feee8426bf270bdc0229\nRemainder = -7bf919e14b2559ab82b3c1bf428d083a4c851a7a1fea44718377e9e945caa5cf48e0b1ad727e251bbb330292402a75ecd96a56db4ad07146533a3ab5a717d0a25a3a7c9\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -e5cd83a644ec86b94f5e33d4dc307a2f14ee8653288145dabb2b5f894560c164470197fb9e37749656f47df343c245258627aeea17965fea10a57336bdc6b4a47443492\n\nQuotient = 62675274798218da426a54ed7158f8f737b7b3c328a9c351371f0cf61f41712f9b28741f187eb635ce45866762fb5fc5051776151d202e2556c5845\nRemainder = 1aeb5d1fde3c259917e430e6790b00484d0d9508391ba6ebab0f6299190d4b34f5f7d8ea2174974471a1e28ee2c15e05da645db971f699d5d0e80569b7eba7908ae579f5ed\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2622350611b486e6be7a7c1c073c230d604d782c2696038a3233ebcc3f01c6a711969094e47f49e294f2c5bcd04fb1b7c0934f19bf6e7aa519a8d4ec2c172ac59cc1a57b26\n\nQuotient = -12970cdd96b92c37787971cd8dd166999ff241be881eb9543ff29165a9c1a3beeb38b1910a5724ffe2b73ab95ac1ca88d3989aa531374d4ec6122\nRemainder = 627455cb555398150e5b4c1c53ee16dac8d80d9616ed1ef40031424287f8028a9cad1a10bdd8430f6f65368cfd00390c8d4355aa5ecdbd1ff0266a1ade235f33cb5309446961\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c9dac93cfb7abaa3fcde359e09a92ab0b5c06359bc09ae9bade3c6783064dba90b233b4c8d5c6236a13ef96c7a223e37bbdd931eae61e845e5a10088f75b3ff5f1158e833b15\n\nQuotient = -6742b3871dece5986d4e219bf5f43c101da8896f247521fa286fde696e0b71ffeb3b6a3e4f33710c9ab150b7a1f747cee76839c5e7f2509f62\nRemainder = -203b2d6eec9d485f7b439fe9d4c640bb31170af38418faf4daad577c30e44ca06efda55ceea4fbd959b3809fa2002b6e2cb891decb09334ed89ac66ff05502036b2155ff62f8aeb\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2457088096865cd052e9cd9349c6e5e34e46c89d6e860a36f8e2a0bb1e5d983e07d05e6f6b31edc67e4793cb4d40979c029c80a13e654b66c8acf6b894f615a3ac800bbd09ce020\n\nQuotient = 15eafc416460d757d0abbda8d094eb535262a71dd033c25e704a6df54265b6123247e5625da476e0c220ba88582a1ed94265135bf8bf1fb1\nRemainder = -64ccd9a0ae0b0abcb5507d51b2e6c8e52e67907474605c439796febda06eabd8a3185fdfc0bd088cc49fdf564b5b45890b07269c15b1aa2f993cd9872b97aa6cc37dea2f03444b3ed\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -ab34d3906d8a2b806b22c73d44948d703c1e05a9337f75cb0b5df5205c5e2d23f8a92d8381372f9398c9ac2f7b9302b83e48b26512ccd0b06e6b8ef1b930ec2678d71e2eddbf7349e\n\nQuotient = 3b22916d9fe3145fcc3b8872bebf5aee4e14235f618e0aed09199852c6bed80df39256d8407d334c06f4479f230913370b7d451fad99d\nRemainder = 1b02a7b97f9ac1f6306aa00fff0e59f55fce463ffdc640364a950df29474e08b67cdfcec0628e973d42fa1e4f98e988ec4c47e4915651a1731b71d5e36a10a0d1b3420427dbb79ba7d52\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3f74cafe9ab0c1b307cd7571fd442665fa3205fb2f45b3811b92d1d38b096a2025b8170663a29c52ca84da102e62048e583fba96a594c0b23952fec587814857c25221ff2cd0533cba6d\n\nQuotient = -12ffa4b6fc369404968911c17358012b993c18c2ff34122e06f450d3d441926b5f5638b40efb012d76d8bcd3c0012d0a0ce5d55c596\nRemainder = 64548684fd5f6c816bd296234740a4eed772570bd4a48852462f9cddf14f1350ce7c7c6a58aee8f66ad7df87927458db09e3af08eb5376de08444f35e5171cfa0992fb27f70b81574f6e8f\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c58383afca9e1c480ee75d3cb6b0b99ea42e827d39fc96bab6b0dddc97e3eaaaec02a74847f9f7d49937f5ade3580bfcd491990737d172d4079437067251ab403c36a9826e974b113e2d2a\n\nQuotient = -4964410c2b038573107b0151b36177cdd62495e0dbef536b59c8aacb8836bb45e7bb014e5022360621e8e82a273d0d462b8eb6fc\nRemainder = -1250c42f8c9b129a5c477be446b86356edd1b19409d362c3a5fb5d59c30f1c3fdc1424a88a0d6ce20bae885905d98c8a5a6495931f73edf4c60112ed78834e3bff6de3ed54c867fbf16a1cd53\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 33212ef4a8e80daf1049ac6f639f8e1990142ac32f7ebc97675ec90f8eb1a2814dfdd295ae67317253d0187ad33f3932a3a7efb056d0a3c87d28e64e23e9f1de751ee6f0f61c6f39d08d72f0a\n\nQuotient = 17f77efddeed52ef2e423bc2c10d2ae15c97384b766f4108474964c2a44789e61249103d9f5fe00b4d612772dc6ea12a42e395\nRemainder = -1ec95323b7b95169d5ec0667f3cbf683e98c15dd0fe44df4ed9de9586e43f1f69337e41a6d11d889452665dc0b03cf8d9ef2effe0b350eeb9f6468751b8a2c42608ba2a33192b770cb62381a966\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded49", + "9ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -9c91fdf2dd1827ed103a102db254630c278bf8b47bb12a342a92f081acbdd8ae5f5476ae194e24b187011ac25b19fd09e6e690777f9d3efb6b3a32c8f5905e1478a27fe4b1adf17a70abb4e7571\n\nQuotient = 4f5dec525ffc737094f40d27446ca0be5b7a2aff02d51d99609165c4cea0dbbc1d92bc0a8680782b616c149bbef7f5ca912\nRemainder = 1bc84ce56a9a0c74962681c02ac927051c81f3824d9f3f0f91465df333ecdb449473d9c26ae3abb9509add5795e89ba5eba6ec7c89b114c86e6991ca0c185b34d6e66925a14fd82809dbc4936d273\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2f47be01e6dc6a86097676fbd472c2af0c83a2f743fcaa885e44fda7e9f350e9fb7a8cd07fda59ccb7963f1e95e6a1236f5f94939decdc85afc0e523c711b24641c844cd3113c17fe35ca988ba407c\n\nQuotient = -163cafed5bcfdeda88555f30bd4cc2da2cefe2bcec9a7c19c36ccd04a45121a5a0dc28d0bf6ab7fa4b78933c47a5d5286\nRemainder = 93f856077f5b2907cefcddc4d767ffeb0acb7af64bb9dd8a15dcfdda6c244c24fb8404ff9ea2fe1dc337faa05930d33cac4f61e171d0236e222374cb3da76396ae1329a407fb4ac652fcbdc568d0fafb\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -a8bfcac452a5e48fee9132b73bc2fef771450143ab80aabd8690ce54c9b52c2b5a669076a7a35fa6d926268077bec6d90b722b5d074f28ce3843fb0147e567c45f4e91a11416c082762e71b5c6129c08\n\nQuotient = -617dbaeb8c6f9d584e8eae923c872048f9f9bf039ec6b50cf8f09c061bf79acc3311b37c2502e560848c05ab316fe8\nRemainder = -1ab4613767c4f1f7d127e848f2bb7c72a3a9e1dd6173b63198b80d3bbebce6a31494f19b53ad9e3a77248e6f9b26fc59060e2759a20dcdbe785297bbd912da9a1819527fac550d64bfd20ed1f96450c30f3\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 267d9397138fd0374a7a58593d41627ba1203a646ec2c04997acf607e9d217b8f40183d2f9304447d6f7e727a476e636ded4697a5ff30a9ae3d249baf97969658209c1b32ddc0edf920b0b278e9b5464313\n\nQuotient = 10ad85703fd51870306c5e36b51512341d6d39e0bac47a03732787b2f62e49c76666f7f49b2596de6cb5c5b2f31b\nRemainder = -846b4479713bb19ebb8c1f1b75d2be0f39fc1095a3d2ca149b5565146bc19382b86e5ab0d098ab1fca1ce701d582400190fee34b602845c3c0c498925710f0b9e3af2412ed5ead1fe03d77e9b2b407ac83823\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -e0ffa4e120f2f46fd1430b6022fd03f71a22f9b120f8d40e901279be235b32d94760fb8c2403d23cdeb728ae73e2b16af7322d6ebd5f5673187668c99805e700f1e997423886bbcb851448dc1ed4cd66d6598\n\nQuotient = 41567bbf616ab41da51108d7edcb5a8a4877c5a8663b3aed7559421b1fcf4b535a54989efedfcc935b3917fcd\nRemainder = fc026e554a0821e0d36b796fe6a676fcd7383a55fd6158d78ace4edfc3d8aa87c65f0eb41baa2aafadc51218b0562ff4b5c9b17bbe84afc491d9e309217a5138ad48dd51e1b1a9aa51d69963b608ec47d63fcd3\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 396e9b45ce43d3f89386cfad8ddef4b483ecb5173234530c67447ab74629d246c18b9da09522c77f598957e3fd2a1c0c9417399912fd547fb1023ba6b90d63d223bcbf3e7ba155e51bba7e8635aa5c39d2b9dbb8\n\nQuotient = -18f1f395347ce8df530d9330c61c0e30ac9531b50a0af2ae7809db1258285c15ba7a436121287990fcdbda2\nRemainder = 51417b9e9995de34316a66a2f70c146df8e36952fe64124819607bd8691a465f4fde98e590dcd56f0faeb95d1b67751081c2393626713c27ec2a2123aec2a4ec3761e5ace4aaeb612d46e52e16d72a186d2ec8a7ff\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -966dfc779cbf9c388a84e947d1128e2392399ff45d9491259c7cb19589154f82f41e852e0c6bb5a728f6e87ff4ff95abcb9b2b57af1b6b7fc125497775ecc1338e4bbcb5315f7afde4e283347184b908545211afb6\n\nQuotient = -3fd962e88dc1d501fe9335fff8b6b2d50eea967c3035a3dcbcdc9599b81f9a445ed5a6ae7413b8865fd4\nRemainder = -97f06f6155f8d0ee6850728192e0b4fcf55fbd9ba982c5f1d598ddcbc4e1c4be0e209fefa6ab3b7eb2b4c645e4dc40217202285ab0a7270d085dd9d4fd24e5293faf6797b4c3c79bbf3ec63fd82942549f9e8f862297\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3ac566d6b2d18572360fbdc626ec488aa316a74f33d71a17a2d0e1d2bf26395623eb91dc4abebf2f944e9bc3d669fae2e4332088e9ff9d9f43927a7888b1390ef60f05efd6e63ec606ecb3e164ed6dbdc9d088586aa71\n\nQuotient = fb5ce21bcf28490afb64e6746a1a81792c90eae17407c0b4c5ebf2464eeea43e516be2c615f84901d\nRemainder = -3d255bf94c3d610c32266fd472d070c0f5e7dddb88d32723b2e1a20709aed2faf28701e0d0227c2b33ecfa9e708e5ac354a97be732b786210d86f1f05d191513386c580b1ad1f4ac6890f87fd0d4270f23cc5c2064502c6\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -eedb64a6e204ee3d6df508830704f1d5b2d2e627698d38a114c07458ea0befd593a80dfd2e08fcb1893adf57061ec4fbcd3130692de7c46f5ca51361e9b79bb7a91963618b8e5b7591392a5f0e3be954e8b9978c97f12e9\n\nQuotient = 6933a3123d0b32693351a834751345300c49324b861a663e8700bdb3b70ad996747b284a8ea5c02\nRemainder = 13849ef93cbc77460c3c496e8f31f7e01a98c21cdfcd6877547161f9601680665b394933d3a0824f0d32854508c89f0e4a0873280c779c7ca636cd89cf6ee5d42a917b4f382be3b9654039f623c11b43164827f870fa0f0781\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 23ab6042240a7709d43de7ee17332a9710bd0d913c42b3591341527bf48d5bc30abb962482292d45a15cb03c9457cc8d78d1e00aaa63358427b000e59e4260bfe1e2cc603e175d7fcf02bd9f61fae3740cb8e10a510ea3d1d5\n\nQuotient = -10e67cbb33dc6e24765893a047252766c2bfad8385150689dd4fec9ef495dff63ede1fdf78bb6\nRemainder = 9dabe2cbc734b910fa1bd25616daee5657d25b6e4dbc2cd93cf8549715c87974a8336fc5070d86c11f6b670d4b3bd5ee8ae3af2bb321fbb4f8fade3f5c6c2d6c366b4d800dd13ce897f13b0d3fb79f1d9ca525b4e7286c56ff29\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -de093dba98747499f2876c8b6b7a6b9587284835ae35f0716dd594c826cdf5b9179f2c6b08d800a77a6936602ff2b64ee0b7c94493bd5009633f5bbe423454b7f018ae96c21230510ab4bf5db394ff153b0e9eda3ef90eb4c253\n\nQuotient = -521f5e35300b9ec2742ff472cf61235dfe2e449772afa638b1adb812cccf269afd164b7602\nRemainder = -2ad10e8758e1d358d4744ad344ce319617027107c0b8db195d1b58c6e6035450c9b377f026fdf9e5737750af5615cff2ac3ccee623c060d779373136d48a735b353d64bcc5f2e6ea1e46083fd799b5f57dd5ad0ff3e6df9764af977\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2db1990ba1e353a1a62de1b914ccb691380b6ea937c13621a29f0a40ecef460cea52cfbc77d98706fb3c9939ceaaf962fb8003b0cfb40535e0dee22e8e7d04b5648fce2e58803242c199421cc4b26cae776d3603f2ce410d", + "dd1e0da\n\nQuotient = 1d45aa6fe6837a1b7ac95efd55d1690b66487202949a286fc85da7ac0b50b860215e44fb\nRemainder = -7984639b596f1d4e6efea9d8b4719215588620ac959034b303584679a44fa84a4be0c89fd2e29f54e62959f9b7a858c06b0cc051176af82d4b85e7334555ba11c39e6cfa1829995c383ba81dbc220e527e90a1d440c1d069703cc1370\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -80316fdc405bb002990d3ef7d0e98defcd1f0e370d1e51db2d21ecbd96230baf69d00b168afcb7b8da9edc3ef7f6621ae5c5a0d7797e5c92283342e42468dba1036fcb2ffef1f493ff97826477364f6b5a41dc56d6389a01b83eee041\n\nQuotient = 3c0c3f7a777e611d1bd0d17d669a1ef7920b72ea8de06d4b415a73b836e37d6cf0780\nRemainder = d8c77134a75584ecd5ab29e97a909ec139464901f9cfcb1d3d9e29a63d204615b6845d466c8710873980f107c40ab54eca9f8933ef6d726f9bd0f3e9e97eade5eb1a9bcaa7b01b6ad51ff3ecf67d6e4d345f128e990494a2db434fcd3ab\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3e7dd961be36c0c286eb9e78bf3b33e6f9bdf2c2137a0c660f1d21dea31ac9a044e526bf47ec8190e137a60f1f55e947046b9cd04a2485679e48cac80a1bb064a915208889289d63a6e338cf7069ad799861c31ec6eafe02a4ef2c2641c9\n\nQuotient = -178d749de2dae3a2ea4898c59aaba98ad9f340762040f5aea13cad45a793f1256ef\nRemainder = 6c5d9b19aed9f099255b6e3d251aa50d1e534e6c86d82eebe097dc8dd0748201e48ac62eec070a999c21f5c7684e5a700212e9079b5fb731321dd1e16ca82ce80c1f5c17fd1720f1353bb90997f47f5fce335a43a6f59facff0b3724423393\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -9f52ead13916f9807d0cf0c6699578af52c54816828f22de62328fbd7b4fd6c3740ffc82af4e24892092c7ecac44b5e775944445e6615fce25610984030a345731f944128f5734e6e315a0ea97aafd7563105695d026880d065761687b75e8\n\nQuotient = -4fe43bfa9417839ee408b254603c3dd176653b6915a89de5b781b400162fbed6\nRemainder = -1c15816e03751a203ae23c48965c8541849b09996bc81d28e28d7871fa87d1c3b2d383c056d3084d7d01d853bebe270fe2c0839e71851e169d417c47caacab2aff8a8e05f65dfb20eb17ed8f67475702fa83087bd868246cbb885d52639797b85\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2ef8419306ebfd215d9079c7a2b959a53ca2f4553845e3cd32caab2635c0e77fee8c5c016c121e3cbedfac57f810c132486ba78df9e719a976e0112516893f14cf9b89f95a89aaabf31cce509ac8e7e62ec3833f0be4336afe6d7d73518141d39\n\nQuotient = 127e8c06e12943017f9dd57ca24dca0ead230092811d307386c81b6efe009c\nRemainder = -24f3431858d5aee412443feab243b465b849f5dc97e4de4db88c7adf774d9bdda65fa0a28cf6b18eac6078b00cbeed2ac406f8426aef868d4b59ab045825d4b0a18af6c9105e32abc72fadef55b221278d329ff6fb9019630411bec143c4156df7f\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -cae6399216401dec0f8ff5eaca884ab061469082ee3a18e49e0b4d5f9cfc98a598c373249a8ad2374e0b3de71370e93a98650684fbb931aa5d8b4482cb0be142492bb71743c251346df66896806f926a4a5dd4c16ca3294f01bb998835e6583d29d\n\nQuotient = 3f180694e59df85f48ac02b6d4faa26278af9641db18d79f198da5d802f\nRemainder = 36cf82dcf8c7ec783b4de68e0627a4a4b2a508637c176de09feef62dcf382bfa5d8b88539b5ca2cab6cbbdbbd0e54c092f00ee13f4a352cb570034cb0a012cc0fbdb6ed32967f3b81d146f352139bd3d9a5c27789468b7d79b84d6a8f6085f859532f7\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3b7983bfaf565c5ca444367654a07b8bc2bf7fdc04ef12128c392bef2f6b67d9475b4d2f0ce1c380913aa98616fbe1d74dc5c9d64df15f5c9b87a8bfbcadf335a6e8f863c7a01ac175a7d79645ababa5f961fad7d1b9926f7284e254fed33765339e0c\n\nQuotient = -11f635baf7b7d613e84dc38978a21ade2f4cd741d0c4f6ae592d93af9\nRemainder = 4317c686dfd56216bc4865f8dcb6a3446e13d8b33861e74d6c4a3223c387ffb8caeea0141049898609ed1abfc2adbd21756cf64a72272aab6c0b8f2177419abcbf9086635dfbea80a7b884181f2f2ec9a402cb0505e8208909fe062d5e6dc7094d66af62\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -d0ea50558197566f22704e66a70328cacd6f4b7ca9b00c16b7c4b4e7dcbd47c9b2526b3858ebb4de7a571ac570872f3b44ba1fec655c0778a8a87ca24851f6072c5c0b7591b5e67a8cdaca78fa46f201e02379fcb9a8470e4a4971acde36cf501d369751\n\nQuotient = -64a078497f85588d3402355bf3e83d25ca1f0ed2c24a395ef6de6b\nRemainder = -87fc31ac66a24ebd629a26209ccac1b2c85e52dc83c5240269ae5a27333f33d31152c9470efd41472af034e8536bbe94b0a49e892b1d23db3c13fd84b7395d7e3f19d7d4cb4a4c07dd1860826696cf7202483446452aed2b4980388e7eda0ccac792d77a33\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 254a85bf512d9159b00a70678239902ee7e15ac2790ce5747c4a4743c6a0851e6a179b64c75acf312dd37a7b82a729246f79196b8a399ff476c48a05f89c29fb106bb06ef0300c4b330a7b2bcd4ea1e82584c7a96b99ec2131c885c5851343cfa6ae4d384e8\n\nQuotient = 116a06b1d38067cef9f55875fee1254c8ce39b42c19fb232a287\nRemainder = -c15a797fed3810e4f536e9509564b2142ffbfc0c961ee5aa923d43a824765c05d2a99fef79bfcb6310c77a91d9bc6d0762bd687493865de270c99989e891fbf6da7ea5c7c7a1032449457eb73222a011bb755ff44e4bdce8e86f8aa9f687840c0832f7fd8ce48\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -d77c14100d19fbaff6334ca6aa504001a1d56f274632dc89d48e1d517935503c26b60c047cab9e186a55b72439761c884f63fdd2a38ca1acc653f6ccbb4b7262e6215e6d00c8829b448b7ac8716fe0bfdbf8088c8c61eee8f8db43b7b5551f6278081ac2eb1c5\n\nQuotient = 6fc9533f6d0e6c55494cb1b319ec47bde8e621aa92d91155e\nRemainder = a1a70f674cb141a896c4adace0dc58cdcbe2503fd0ad36ce348dc5b8afc96d0f2f8c65bbbadabf2920012798b7ccaedbe8d896dd2674082ad3cc75b54c5c190ad56ff34e8cb5dd29c031656497d48571295d6da396d5f4cdb652732d874a79a674d06a1d7b979f5\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 21917f48bb8e65646c618068fd9069c06e22ce8c679a845f9c4ec843849010abeee12e2d3c61fb963297abca30813c446f2ae82e909ca6ac7839fb58974fa65f3b5d91fb8b3f99d948519ed56653d50026d694060208cf48e3c757f64885b4ed4328c6f071e9f5d5\n\nQuotient = -1abc689fd19523d2e295f260d248041bd00ad3009cc7581\nRemainder = 1ab5af1478fe7373d012befb319b53ff9e36899c1749ea763fb74f7d24624e70ee78faf3115c2a423629528f45295e4adec7b122b993b5c29260558be4831df06468bb1c63e8afcfb1b9b533ec6acf754563d2ae25e2adb4cfe5ee3024611e03a156484a130ee01f3c\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -8c5a7b6bc8ed6ac015ec24efff607b0446c1b736dc8b409e2f433e69d0ca015d70c64b4c924175d0e0102ebc3e1dd96dd4d5bb01cccad229e699f9d8f9ad0e04339d70cd113e93d50c10c03083a81264396", + "f5db2d979d272798ed30efa15d52289d0c72f42582ea56f\n\nQuotient = -4aa210fbc0457fa7366a8aa9a3acb3f9fce812303ec9\nRemainder = -737bc4fdd3d5496fc7f936ccf14bfc3d93f5b7caf4718c444db7a3228b41015c67aed304fec7704ea8238ba6cccb1e94cac3bcf4764a44bafb49e5fcb0339ae44c0114cc304b9c4370363657cd2bec09bf962ccb21f6091b081e71d2bff8556600576e18d4f78fc68b12\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 324774e49bb429553c10156e8db122670d6dcaf6ef5291f515c517d7ffaee36ec5ec5ccb4d12dff71ae7a05bdfbb03ebaf4dc6c4e8bfdc165b77cae20153c27d53bf27d92ff25643b4888cb586e773955a1c02ecbf0fa6958a8ec0b832332eab2e449be6e72c48d2f1ad1\n\nQuotient = 1c8631a18d189f1fb689f896005f2dd2098e0dae9e\nRemainder = -1a1ac9612fc3354056a5378de5b315f12591ee71f0fa9d8a6b2ea2b1c4eca9947e5c4f5ed3d4b78e69ef7a1f5a9894b9c7d85f6e2244ae76881eb06584eaa98c78b60b46084b517f4882758691f91d9e2acfd580d5e901dae14ff4a4fd6b0d7c73450e4928fc6f02fb5463\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -838df2a27bbb033fa0e581073b879d6e8747fff38539801a1870f2e52d91bc84cf10f2560e93784650fba080304244dbfe9da679f207b6920be46b0214a1e490537e56d99beef3f58b30f311a12283501ad79a5407ff209d19a6efd0421aa144e0cd427380d89bfae5d1f5c\n\nQuotient = 4213d04b9f0b30026bd355404bee887b22b2cf9\nRemainder = c2bc097d1c20f050e88912f066b658446cacc7a4d510343a8d88ed007a8c0cfd5d44fe5f067a0e81536d121b39f2d0feb8dd053bb5632e3f9c04be5f6bf4091d646860cd38c96271cdba466ef8b7e2377a51d5669117e664269fe3c08a51b10e1e019ac063d670a3c7db12563\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 38ca0c2f03a5c56676a2f95cd7a69d4aa2085343af6b1d2a71e0d1c54157ec0e8f9125df2a499cdd484c04feb23b1e0042ca908db74744584036c79f21c25c40401d551a65afed0ef35f1ea000fa1a99cb29e6307f6ca0304145f7e483d008cf9efb028ebb654115a8c6b87a08\n\nQuotient = -134e043b3b88b31f89ff4bc709cfa1bd2c1a8\nRemainder = 99c1c846cbce5e9a26c5afcc0186bb1e43b2501ab3205d13fdf01dccb9b1a935bc1cf8adf74d58f1c316381577366b6d126da49991a0d5e02acaa678085f335ff8b8e975e5bf2e52a05488ebfc21a3e0d0bc5bbe67442f77bfc3c1f0c03b7f7ce42bd0fedd8a498f018d8cbea47b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c261a6c562fcdd56e67fbd2b91027f17c95da43175eaca6e4069c16d240ebbd240582dcde953eea739a4668fbfcdc6af8ff3ab58674c95de90fdb43f64a61108b030d644a44b0319b912bb563f61e520dca9c88f411b32e99c872cf00a01f5badad584636352913b7429b99ecfbe\n\nQuotient = -448c4922b7a7d5e1efec2c3f41d0264b76\nRemainder = -2599e928027d10d3a11056eb719768e5edb1a625fc0b8a1dd4439ebd30a82bfdf89e617ac7c71622058cc64ba32dc242d96fe3ecb856f1b146f831334af562cf88139a99410dcb869b9ad6ac4826563b400b59f55d8fff262dc920fe525b12b2fa167ec237028a098c9117cb77bc3f3\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 36be11eb72832f8ae7b6bdf689f794f62cc1c885e64706d14a77a11df9761c2e9cd81d8f6a0ad0cb1696c69afd80c8bb992cda5100cf1162d600515568b9dc9c81a518da9d240888d4984df65c129ac0b4c557b4e63ee5be79a27473ff5bca58e559cb04c4ac93b61545e7351bb6514\n\nQuotient = 152474a1a76700598c18d9301866ec00\nRemainder = -274a2f9e2bc5f9d75f9897b28f840b71bb10a3e4e7a35ee1dc1150be61130b4e0e987e8742c5edb75a1ce3158eb8bdb7d657b8ba39436d7c88fbff160c7488ddff2f13b3b95ffe149a3d0d2d406b1737a7671f69c0e5d7074a151cb2776b2d13ca24bec261662f2967fd22339ed6c3f2b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -b17c79a31d5085b49793b6a6d628109a6047e3b1afc947e5212d0a9ae32b1955cfd6fed07fc60634ad15f32a9e402d7d5f750fb6d1ad958211f9e8ecda8990689e5212cf72b24e9b51bd07a6e0477dd4c02381d0ab6c0ad3cac1f620f723ab004880800736804751349f6bb19d3db48da\n\nQuotient = 5665f53d5a7405c83a5ff382ec376\nRemainder = 252d055186ec896cb3142c9e4e49c441e2ddad365b86ad21ae4ef1c522d3306c2834d6993a5e1f8c64a1ed582bad8ab746f7e773fc004b1c47814f73560db72f7237ef6e2f671d3b19a8777be2e4c662a76db87ea64f32c48ea371b1ffb15df26726854a417e18afcf49054c6d2e0e337e71\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2b6eb2caa3ca650be02fa199e9ea6c48646a76434e268713753a547e49571f9817ad396f2cb7b16d307801fc8892f0af3e7f93ce08f7955a8acfbc0b56add4b4c7ef7351f60e402b9a8ef7fe02ccdcb4b00b7ffe78c7009268dbcf1d606c3a1b5307d9a8ee6121c6a635a742b8bf36b56cc7\n\nQuotient = -eeda035247bb13860f228d8f2c\nRemainder = 3976edf710ab42bf069e5829de7e16962d1b765f6ae6ad0ffabe723e21ab01cb9f3f5f4edb1d8c13cafc0556c0aa93d72dbcff754ae9260abd294647b71785bb049bbb865a26bba22defc458a14af019a796e942e77d03484028aac2b3798fa730ae0193d89728bf80a8728715a0807b3c497b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -fb5e55f261aa96f54983869d58b3e9f0757d363b9c43aca5580b7c0380096f396ec79d1b30037702c19be5889fc6376793cad51975100f33ebf43e0897dfabcb9adf3adf8d845aa7589ba1f6d155b25f73dae3b2f835595ad6050401fd4e6392012d06194af415b810b0c10a53bc56350bfcc4\n\nQuotient = -5b37eb0c3e3f8f8d9ac6f4e4\nRemainder = -28fde388257b9a11441c592580cd38caf2d69e2ba57d43151c77d26535226e05e08a9e6d8ed470d4354e9f46b7626e5f2b22b652a2d78f817bb51598c727a765941fba63510b58fb3dd5f30717f237da43b42d20bc260b06d488c9c912bfcea1e7808544c58960a3e1355c50c889cefe75d4d9937\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 29232a3fb059242cae6e0b419ff13c479048cfe46a9063188706c6a3842674b16a1aeaf771c5b0ef401d2dc8a57f6fb4fe1b3c7bb545c18ae763e39421e6a07c4469d234f9fc737ac21ca67a5553c7ed693eede4325dbd132dbd9889d815c02f426801eff1f46e7a52f72845234acc6c153f34065\n\nQuotient = 1c7ac058af2e7bfbda9484\nRemainder = -54d7aa6dace87e61e24d87053b9d094bd160916b720d7cf4f740a4fc5a7f03909773d0456c530ea0204427146fd44d3ecec51d8627b5768de1494bf42081a8a4fa97163b0b93b59e70e533f3257723e441cafa4aab471ec4086601021c4462e1f74bebf298ef45fec98fa8e6ea97415f84c93c12633\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -83c2cdca7577b32c20e9e20fb498a2bceb7174ea9aca09d4dd2fc7a1d3b922797b4e9640c7eb9dbdb4d93c7fb9daadd680c1c7645d8102d77e9c877a9f65b13239f9a650dceefc1fd41ea9bd2b38a622bbec99cfddbc6e88f377cd51cc29fd17a27f3d0d970403a2aeeac6ff9fd69c3bbc5c2b0fe7e\n\nQuotient = 472df5f4393f33cc382\nRemainder = 16579a289cc776a47611353e158c43dadf0a78833396f8419fcbbe47d90c7e840e2c90e73e563e6c505bfcf691120ab0f1e9ef9c31db608cade70eb8e487b1113a46e2b5c7f4a172ad99b502eacdc0f91c295fe608389e61d030607a94d09d349fe1a0cc46d1e07c8db533cedebcb4a3b89afd8b924993\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932", + "725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 34b7f6780620246f5a0a92a768072185f02e57a52db1d865c21c952f4386ddb7e2dc1df076316cb4f2f394397cbcde1af0197fcf33e6428e6f5d42a9ccf623f75fae5940873097d4591d9b1a4cbd00074d134272700ab06d901742da695c3ca9d4f917a808113336f883e769fa8051cdcb0cad7cabd1cc\n\nQuotient = -12b4e74d76bd306d9\nRemainder = 8768fbe8ddbf60b548938d8b4a74c4a326ef335257e5f513e65a7d2cfbe9d456425ceb719407bde3cbc74c9c978970597b5663a0ec61962e77eb351adaee2d2d37f1fb55b5d2ceccf282ea3a0d398be1dd1b166d55dce04a39ef434fa392893618003adcfa61401276ce4e599051ad93152e3477ff524f0c\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c898a753745f0fc178227a7004d917557cf3dcae2e85e95aee51e137b29c895755853ce2d61f214b80070174cad8ebc2795a7d070790acd335b383f9dc88c01227eeab85f1f29d76c1136ffcc7b9fdc073a3a03d8812c7c561b32d8e69754fff64acfd64994b7e9574d2a7cae6bfd5a6fd61dee7ee993bb7\n\nQuotient = -548c97fd02eca7\nRemainder = -939e90e281f97a433eb1c6510668d0fc448f03d737d92693b6362c692167add7e4442105d60ff3db29c03ed06c3121aa4a53c4625906519a4092e4821c918d2264ed0cf088b7da43a222877f3ad9a9fe8ec06fc66b9cfbb44e0fdca1dbe4e461dda9b85231b5b9733e0c78852da83bae557755de3680ab61d4\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2c61dce04200e725ab0ecc5016f66044218391bdf650bc0bd31f3749ac06c24707e79526ee459ccfd4bc22834f8d23f391f2e99135f92b5abd0b04079ab75a263c0e98e46edfb440cd865269ed7872e8c1ada312df1bfd6a5fcd2ebf548d7b7d1d75bc36f62e5e9d15262bb8652a8041e5c8f4d673eecb777d1\n\nQuotient = 14622572f311\nRemainder = -6d197a84d2ed486327790059adb5c073218c56345f48c15caf6892734fff0aa7af4782738bebf24d984bc8adb3056f67e57f9960001a67fa462afd8c57ac9d60ae6517d58ffb4773b637ebe6bf2473a5490511fcdc576a4c40ed03b3afcb2fd27c57b66a26f6d3f9b2bb101502b1117ba3ce7214c9db6302fe20b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -b818674faf69bc92085b7230d9335d7bead0413f2905539a54e8d1233843ef13f07cb5538e0787097cb24f152cf54a92e62ef143e31cfbbaf3c09650b14229a4f61a783eead26430949c88a87f1618788abab9728aa52dd8419f5d568e6a109f278b2afdea91cdedca43e562d4bb8fb7f1b7aef13992fa7edc320\n\nQuotient = 5cdbb03ee\nRemainder = 1cfa68d5da7a600a7ac598b9ca1a0759f972fd9a46ba62e5e96d8f6f00fbccd0ab26ca03d14470b43793411ea9803c9409908625fd74ef8f9b2d7c2064b2e3439adcb684e6f01432a1feb0f492fcdd2b8b5a6cdbd0bf460272218bcf763974be8784e5306c219ee535baf5541b8580952e3690b585fd99f77c46d69f\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2869338cd16322409d3efbd328b27e2ba53cbf71816ff5c093849b1d866b8cdecbd6bd8ffea0b7787251acb760f85c277ded21e56acef05d29bc728cf44f55be87cb4c8913408a01a1ad53461058a1cf94538f05ec14a6d3eba804264df957de7eb1a61b794a1141218966463dd42402c260c229241ec46afdb5a06a\n\nQuotient = -f16da1\nRemainder = d8b66b622b5a54963c2c84aa186bfde5b67a3562e07a23a5f6843bdb615a3c5d4f007ad8b275ad7e4c5b1436252efe35699cff2e0546e6dd8c7230d6ad560c51cd54db6d312be32ae4c708e9047c3a25c211e2566c58d6b9291de31612006d4e847c6916702be99b3f7ce40e1ac842908acb7f03dc120aa8998c60737\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -f8af8fb7002a9d2218dcd0f0c139b8e3dbbd48e25a5c910f6d0b6684bca224f62768b64955580306bac6bfd45b99ad77483563fc7dbe015edc06bee3ff93b0afa8f5866c23c7a7570b366550490c97ad84062c2495cff30717aaa965a8e15e270b504dbd4fa943be4f97a7fd1f3b589bc9fcf4f907a7690d99c978a374\n\nQuotient = -71bc\nRemainder = -13316e9b053a06520526f579718c326402d2a9686d51a340375cb53d7cebba99c8d1ae93388db0a41cf55d5753dd1174014ff3305fcdbd5b02de9e90c45ec0d2900ebf6ef847c2a045eab7f80f07f01c81b9fff093a779a280ae42239df79de8d2ec4bff6723788c86786fe276ae6a4dc1472442b552258e1e5b597305187\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 20fe256859a2e4c4f77db6adef78b2aa4758b29ad0787ce7e277bc68391d5949bb4dd07a9b1a79fe890c8a760871d81adfd3858e27d1bd6de33fd31b8aa6131fef9130a50f995c3be1d615d1bfb9878804b7f6494237d8ad78ac219488f17335ae54b494532f03a3fc8e9576cab6facd90c662658878fec86db66bacda3a7\n\nQuotient = 10\nRemainder = -23e09736f469c83f280052ff01071b1bdb52b7e2b061e8a1a8c6a4e091fcd7ca0b33ade885d928a11a3375599aedfe554d1c2289795daba08f07327a19a8adfc219592bcdf9fc5aee5961a48b3b1b5fc380eff5ed2ba7d7e564462397fb6c6187254ee41c74602b141d7adba99205d2e0b35da57efa96397b3a5d112751cf7b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -e849bc0bfd9560cb90e42c8e4e88df175133c14466e530716d89ad0326b660b0e617b4efe8df6b000f517d3cc24d9dd4cafa2773dafd4c6bace0aba54e43c17e8e3ff9497a97ed83e6408aa0aee0e6485dd1d89d52520d1acf4d587422b0c5cd2d5e7e81fdcf842d6331779e800f96628206e8be020ad4021789008a641f67b\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 22004040a65f9b6f120bb7243c638cf3a4cf6fc58c230da932c79568f68e31af7a7b8569aae77af671f8335ae68d6dc1698baa9d6ba9cd633a662101b45bde51d55098b50fabde8546f317ecc2ae7a39521bc075942e3751a349f51ca3c371f3b8a6cbbea3e11a334d677c07612bcdca767194c07fca78ea8a06cc3b0dc6dcb8ba\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -cad46f410062dc33ad4d712c3b743ae2b7613576b2bd7c346a8479ed679a08e3644c7ee4f23b95f1cc9111905714b170abc37ee1003956f64f0a7e876b38d524fbb2436ed56069479d8d2e4029770f7801a7278fff99b3dc76280f35c7d43ee594073f725554a92eaf4f785c18a7cf6669dce5adb0995233241f3294cfb5bd8f4741\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2fef69f9745646aa13e0c38d77951161a1f881a7ceef", + "032698da3fce00764959f11140bec7d7f53d6777c3622453d4525fb068da48047609d18d463a8fbacde1d21035963b668ca11d5b9ae66db13de7a7a5b66a40608dfb56d9f9f0c8880426641083a05b5ff9e6ba0d6da3a04af1af01dc218e9b4f6ad7b1d3a4d1d26a5c906093b2c\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c50a24e5ddafb768f64677233c5cf09da1b4f06894bd68e194b23feb5c5d6844320a12a02d13ad012f13b1438eedd6313bac9c1f9bb4548fcd314988d8fe0ce6458306735307afe08a96a0c2bcd9cf126f529e48b7ff4b8266caa28c40b5c3d2a473ab8805c860d27d7ee9c032423148d96fad019490ea019d40679de7a2a3323e80979f9\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3a8682d0e5a4efa985dfa8bbddc2c0d72a4400b8b070a8cf7450aa8f831d8a91c9ae3542641b7a4ad793e232a0d301b82664fe2c7f20bd9bf8275828a2a20027d6056b211638b9b0220fa4252d058bb485dd3c4622b1eac97d54b9634b558ff1bd5bd11085d4f3d288f7965af52beaa922b23ac0207d5763c24c085076128e0ef7370eeaa19d\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -f00fb238bc9383079c7ecad9b9f6efc622d58a76f2d5d40ec7cd7c3c083c459fbcf3d128df4d20ead5f585505515aab11c36584ca622d28e0cf037419a649d598346063a07e29c61b7a8e76d1949dbce3720d45576763aa0d391b39dd6b694c7cc60a1b4f4f107d87130402985695e1847e82cce39b8d0fb5c88bcf3b37d6dbb90baf5a8553c3a\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2b809f6baacecf61198856d9edbb768ca2df2abe9b7b8ce1669fd9259732c8569c0cafde2e32d253094480ed281a8db230f84e780c6e8bbf3657c0b0baaf19ea973fd8daa2870c9d79f3695d78e063f9130fe07ce806a088ca267fd2820f10dac34b5b32aebec20e4362dce26eee0c29d2fedc1e020d452bc2499234d07a2a6e54314e3fd6dd85fe5\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -90ed75629073df816ec1d6dfedd1cdbed9239661e362db706288dc4d774d806bfacfd4b32c3013ec67d8c2af133b46989f12f809fe202d33d5ba53659bd2a9a85d3fa542de4a5c656aacbbf8899aa66ba816b809f2629f37b0444cd3a6dfc99103bcf2a5ee87790b8401be806b5d7fb7064ff0a6fc8ec769d0ccbddbc3d35f7dc4d388d8d28021c95b6\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3f60052c9dfe0bac797a674ca7f11377a24c28a1396ffa0f46acab7909543086aee1995cf51852ea4a21ff4bbf6e7309cba9848a7b2e3b33dbe660bdc58d513d16bc709f1f2253648b46daa7aa037332552db1da81b4ab9850ac4ec66621648fc856a71eee3cedc6617071600ecbc5ac8636233f288ec249b7ae0bac942a5fd539d03990c4fb28a46653aa\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c12fc156d9345cdfcff94bdd324429530ad8caf8afaaa1a82297eb3a8aecf2ac021384036749e489fae05e8776da0deca7e4325436bc8f383bed579c2d67a456c4e23871489780d760d63d0bc0d1d0ab41f06a091b44f602bcdc0bd4e817202e39ca6a934c0c9405adb5a14d24da895c58a81d1c7ce52734183e00d80a414ddd8869998822364e029b3f42cc\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 205dc6227dbd3adf8ee49dffd43f835882822b1c94f92cf38f5efc62f943075d80b33588973a0e0a8ff5e800ede21d394736ba98d4eedc53a9122f8c262cd09fe9e91cedfd0237003b0124d757797ee13cd03e7a3a257bd8df756940a4d22face9287edca00ca23e7d5e629966ef710b07e54241dbace041aa6d9f82687c3ecba818203adb376ec0b201894a500\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -82c30a9ef6a83d81b77825c71ddc563939b8508f1b7e44c725ae0f61006646ba9b86507ec9a4dfd3755ecd8bfb451c2d43a61599732b8aaeedff7a304ce0a9327e2333f75e9a010556ecbc3abaed02214f25e1c8373bfafc2c288ea36b8d5f848b76295a141d8f633609a6656c07f3d98177f5fa83833476dcd111aad179001f81d6013ca3a54cddcd8dc0ce7eb24\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71", + "372b\nB = 33aeafda3cfc20710f0b4a3d9ace4817eed80ca57ce6c82dc2e7946058a40983c9204ac95a1399fa633bc96cb10af3ddeee3ad2337c64391a42dc7794fca629e3e1e4e03a2ae24a000e7113b91c1b6230cce9592e45b6ee7984680b45aa0aabd7f56cab1a64ec310cefe5211821a75deef2e0c8e43eb467dea79dc8c03d2d523734498d079d5493c904a2ebfd8a3a9bd\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -b897bc87a40211ef8f93645b1f6c981fa00ab3b12e117a89375400ab5f4c64bfbba01d265c7bc6f5e3a8e26de5de9df3b8f70f4a39c0eba577db5e4b7a68f751b4a69ff4a38915983cbf70dd7e066779405d572f5bbe0719c978b6865ea1a72d90d3ec8a8c146f20d98595036b3de88a7500d7b476644913e4b63e85c4e2632048e9600d553e560759770a902cca680b17\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 20604e080549e1c503049ebf4a56cf9447d90fe699a9773915b0a65588890e15bd58f55ad7b52bd7b7992a8b24704f1dfd5fd07c70aae4ccba5646405ff8a9cbf542dc334cc0c27a790c05420b552539fbf0a155861bec0e4d9e3fbf045720ea3aed58307d5738b64252a963f3fd5ecd0587cb4d7e159b4980dcb112e26c9c34f10a192e090ade157eac1d7a6f970871eaa69\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -f11fc9682601cab97c25533b2599f50edb1ac65d46f1969bd9c3cb3717461627621c8cd401a0a0b91f3645b8804e095aecab31c1bab0c26df556adafdd7e7f4f0510e0bceefa3619e26b8c9a1bc613db03857f53e9eb5d4b8f75a8cd1429feb81edc705e5a779d5f95373d2243368ce17ef22da79a6a2672496bdf629171b7973fc4659c8eae9ae867cf38d6d7617029bf59d2e\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3cb0ffbd9ad21d0e86e4e4dab4d237e2a17d97356bdd305fda772fdd99acefcfb8309d813643c852f66e1c6c7fa41ffd44f8335ef7333b2b3e846139fa9be2c4ea762afba4e11263c0b5fab18c5efff2a18d83ee89844f5f4db2c1325f0f55e066a9e01030c07a85e2c9bbd37b5e767ebcc9b95f474ecff24df9ae52a19edeb66546a3a28980f616eb5a351cd399e5f8436f17faf6\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -b8aaffe779855c6ae51807f8cba780aa64bc22e8fa5e33f7f1dcb084fc476791565bc33eb37b4f791ef5cf46d64576f48b5fadc9f096f20c798355861ce5d24a7be1450bb871f9821099f98213d74a5e5cf83b895ae65e0e0fd096698463906a112e6e169a1cc0769df7a5ba6812300fdd33611761b6339385e1a70f8f8b2be7679ca216f5b183140e69586a27aaa9f2fac118118875\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2b7ee3ee34347dd89ba4a81415aa1269d0390346597b07444f0febb71d490a01b6fee174634bd88e8aa180409549b2726d044b4690353de2fb2294c8f69c612485aa066f68fdb89466760a85901cbc7312bfe5a6f656e67dfd2d4ee099ff97694b01d6d5b8626ab1650eac5267be53f5f3ced5dda1aa86bf42ae132a28fddb94902a515da40e0fd0586dc8b17a34af8eb03d06f70ab89df\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -bf8213944ba785e01b8d37a12de77b2ce1492f34bf6f67406cb51da89675b4f70f4d4f314f30ca8d65cbc48ee2fa1f0a3e4ac0de3a87d2c4c589b6812e850623d78ef2e46fbb555f6d3c69b211892c11a4a2dc3d8a9a19e96a07952602ed5ffc0232c140c3e828acf990e5425d8dd9ce0c1107ad1c6f96c8fbc90ffa457abab0d843094dca3c8a45ddad81b7850190625613a4851485f38fd\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3083421e375f0722b9397e156de47f77635d62ba1d51794469371b473b71c02e3722841bca2ca06b5d1cf1492bbacfa0abfe394dfdaa7bb8787550ddbd953540e9c97631d9a1efe0c8f8e14f395c82d20245cec6d8021f8564b4d66e7779c3245734c56fb74481172f4e349d9a113cd0ee5263c69ebf746c5285cd4c0fa91d9531f769fea3610c2972ccfe9a22c00aa62ebf52b3a4c6135f3069\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -d736bce537f47ae4797faad797af8cfeaf8a4fd42df1f7e61febf8ebf6e47dabc48252ff7948f3dbf8cc369b6952dc58f64cf09b4c53447d135c7a753c21b6052a9726a47a61e13628edf0f2bdb357f2e780ac1ae1f28f211296c8961c2955b773d7dc2904dfea96780b2877af133c9591a0dd54cb20884f014f363862478ee7ec45236bfdcf0321af0692e68f744af28fbcca827ebdc7b210da38\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774", + "ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2cf1708f1e675ba688c0d19eb61a05d2c8642528ea6b1512375faa732acc59ec04ea0aa55e0049144be09eae1292b6cba6db7a9823f1e912df6a5032bb9674f4f26c0c8244ea0dde7acfda566574956cdc33e4a27bcdea25fe255c19f218cc4316ae8428ea61d1bf865197a066b959c5fcbd7c9596207997d05fc38e32322aa189ea06cf5139522571661745c0d72b740dc6d842f1dd8481e318b5792\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -a9180e44a284b5bbe72fff46e55869f749b626ac33c8cb17be1fc260d7c6f460f24a89e1367112e00d0da4d213a821d09f103f35bc4eade5605bef23c5d048b1cfb45dace8b9c637af626a85fc773cf51e6602a7a5999a030030cf114ed6a4ed7583465b9303a72e7f60824c12329517c6763b0f64abd8ba2b9b26cebe882a51f05ef8076e527d53a213db910a5f42be5fb78729a3dcd08d69a709920a2\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2f26e156b3b1117f7cec542b20fcc06ca66cec03a19b6f5eeebf22b4c0fc265df5ff06fc9dcac569735135bdc142b526b295225711efb71577b10aacda2fa446f5208487c725407c2188b3185237740c813e4455a6f1dde4f62916237f23164a3471aac0fcfe24ad1ce1dd81a6144f5861ad0cf22dc337abe10fc4a88b36116dc4929602ab48eb971fdd7a5ff747d6b9e0b2bff75c59621550991966a0a19f\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -9fe18ae697576dd36ebdb621d14cac1cfdfd1f5cbb7cfa8962c5a7dace96f9f54fb4f4cf2e650dbec5d1ba89ba53d251ecef7dcc1cab8c2ff3d77903f5fb5f29a4e8e3a2a3c05c105d5733b5132f2f8d88f99d17de86ca1191c32ad8ed469bb649ef188306f69f183bd0fcc32759e4f855170f88c0a3f6745aa98f6225536821bfa056a42b37535a622f42b009859c974cabf2e14f75c749d0fe5a01fb3ab0c0\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 33ab185854b20a8126884eed85181b14e75d4ee452958cc1043b099bc16c24b9c2f3e0b792744f230013907844496e600389800e45fd55133fff0cf19c9c152b9d031039eb90da568f9c5212a3ba283f4d1353ff8ff9dd04d292c265bdcb77c3e411716f471930bccbb8ddb819ebb0e0036dc1a18457cd97f4f5909a725baabbd15e8ce33875895aa8dce77a4dbedeb0271a2a4a17f77f5920c3776caa4a75ac650\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -e7ca0c037bf8bad5f8d9c5a2737e044d9f7284c616156d142612a53eb217f57f4aa00b6daa424e6c0d9163939e1ad0510a1cd64fbd576f3e54c59d7aa6228fb3caaba7cdcc951e00ed141ac3a68abb9780bf46bf544fe0e347f677288e962fb69782741df49b27cbbe8720c6f8f2e769147d89df6e17e3c592bede2e696d384b9f01b99b31c505d67eb6193a8844f8c4cdadc9fe45dd446a0dc572c9da6e58ed303f2\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 22b76d6973e37aff4a09216e57662f186c0a0748c4375d6bed370ea61d1f6fac2d9bbe04487a629118b6b0b0c8cc4179fff7bedcf048cc529498bbd9cc81ef3a103d6cac49d58bc41c83f961b6df7f00c7171fb7d9359e03c76e4364cffae5f67321ce646e9b05f9c04aa16ea65389e940022eda6dc740ddc070bfc7e589b86fd1559dc320701c39de20d54d0483fdeef6c4fd012850630b982c2e243ac1ff918377ceb4\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -e6e4d69a82b83e26ef8ac0f4c3a211153ea6655b7ca12840e7b866510d114693049c5b8b22c3a097eac832bbd1986e60564298e54dba3316807ad64bd6c18903a0f22660c9e8d5dac180f57cbb90b176b842d5b58d6dd9f47499a037833a92a18f397238a8bcdc4afd129382fd6d200d3d267ca1e6bcc2cc65950831cb8e30bcc01665c8149b874c9f11168153c187341afdc43e4d8652ce4fbed9f9eac75db40d64344ade\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 319a81f052db21ee213c536db2cb8a71e0dcd0a9b2ce780a9588c38b717c5e487a337f82b5223f638fb552e92b826192e6a1c27771d1e86584bc6c7cbc5d9a6ce6edf2ea2ccf6939485959ccbf3183b40e410768c4665adf90a0ae2792fb4b5d8aaa06c6294e31893620decc3bc72fb4eb68f1e56b48e39c59abe869d07509b7564268d0b7f178ef09ef5dcde6e7dbd2a20fd1d4fcd707943dd63adf590a117ead1ad10ff85cb\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -eced809145e696ceaa0", + "ee8f831eca67049509b31a1b15e7fc86cdd97a73a2ca05bfea5f4b283d287e49906463ef36f2f8ea23c2aa12d5534c08e9769055e04822be0f8ac85f404f5c025a6833b4115f78da9470451c852ba0f24062397d20385f58c5aca10f3f09072b2592e5672ffb989a390abf86cbce74268aef1f4ffde730b3b962df1088bf8745105a7462379ce142f819c2538d9bba99e094ffbc4478625bc54df16c5e1a\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2c1ffbbb30e71d5fa77b5473392f95297b489c85f83013262abbe948842473154e00c86b2e354278844083f960fd746a3b7cb9baecb9c66932774b3a28f678d50dd8fe52fbeead43d8c8adad7c0fcdbe5e02664b0feb0ce214c5fa007c5fa2d08c5fe96787b95639311cc4b7eb2a7217c9c38c6d93444fa60c1f52ddae9bb2ec1a49a593e210e47377d3623cd2c4994ad9343863443911062e12233176f4a65ec715b3c9731c4a0cec\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c3bf056b905c0392a7b5fa57446ed350f325eb67d59f1784c744b04c7f4d8f5397db913407aa8a7f1dd0225c1a9673828db0d8bf3d4908ef53307131bf5b5c4c6068ad73b874aab98e8db33b0a758532172acd8b2c830d0679a8226537090166317b8eea91e8ee4a7282c0ab0ab6f2b7b63d728d22b534fdc88294c376a8d036ba9a644c2489bcc84f6aec83afbac08067a7b93f3897f8dadfb68c327b751841927a728faba47dc44ec4\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 23fcf9510caa531a304eee8d0b2d49050fca83abbf287b6b6dea06501c5afc6d87d2924df1d45b1bf6c4bf77b563a3013cfb4ad9094f8ee9892d33f6ee1c70131cd5721c5af804a9da7654510e8591aa185ee723f8caa78046d9e6fbb891e6024d2ec70110ae61c3969995e35941d2c7f3779d5bb71ce5b693bc9ce4b087068adbb554acc4ab23624e060f7cea169ab512a06ff3d2a36c2b6e3bd9a75f1a9ad30a6a16b0256c42eaff2c3f4\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -c32d5e643b12db6616554116299c1da672efff1eee394378c5e9e5f702ea4ad64f0dac8904bd2751d2cef91adcb283599f6c661967dbab27059e94dd50025489cf74c6897a22e95013669aa3063fcdd4b73aa6a9a1ba5cad3956bb26346e22df6741cd0ba1c0ab87fbe74035618a394383823216df47b910cae495b8fe7ac5feb3b2cf0d0ef6c75db477160b75324db8eeac48a0fce72b9abbd7079ce6f529a89025a03a3777cc7d1deaf3e4a\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2a8f2c530342bb6ce683a760540e956a1155c0fe065476e400caec59861ca97ca71e51a11b3213b2baea1a41a29449998778e0f533fcc181698d293f05e28bff2750ef4095170de98a19a36ddcf59a65f3789a3808ead51680245070262c9544e446f23652eba47065a2bc4701c55378bd49733619ed2c213f8ed12a4a317c465f37efe07ff2df8e88fc33d3eb42cde9408dda28215702bfa607030839285a8bbf89b5e8842fa7d7f50d83fd4ab5\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -bcd2b2362aa146cd120b729e81c98ae598804006d046a7ed0f9782baa10a85e37c7c22288dc61c24830a1b42b123d63779e88d7555028292fed5ada1793264b35e961b608bdd7398e421c5474c33a65059ef13787e0cedf4f8f032beac48c4b5e5a67417109142a43b198ab617d1de1a38d6fb4922c6ef70a5aad3faf6f8d5da3af9679c94cf61ee760ba792d2972376425e2ec9c4109e969e3d9c3dd90cdbaeaeb7382cb7bd024b75a1fd6d621c13\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 3940430ace4b5b87bf4baa2673582db3d27307ca4cd8e55e976ea3e10da72b6deb7de932253bc9228c85cd4ae7766cd0264004c658a66d81e60bb9bf4dd66e2afe11057b7f7b53a1ec222510748be53a93970fb056e8082631b2b77413fccb6e61cdc6f224b7903d75345afed8a4f194b4bcedfee1f16dc256c2bb9f4a129fab6a9fe752895a93937a3d087ab7ca212991ff34f1bf1c55987a574674af43986312bbc3bad3280bbddf4ab0217440f851b\n\nQuotient = 0\nRemainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -f0dc20b88450f45381791e85d080e4f2cf38837391e16e608b8cb5e0ac0ca75e9f72cc04bf2f56f130d46aff31efbabc0ab14f0c0ad680d6899797297152be85ac012644c8d0927b5b6c70dc3e5a8d79ef92a0873ec22af3d9683bb5db1ffd5ebfb698c5ea64cbe2b6a8b9f14d4c18624be1b78b19eca14942ae9542012692cd0d5289ebf75fcf5486596f92659143e9f952af3622137e633376fb95e628055e0fb1ba3a37ccdf0af69a4c0d6b0793078e0\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = 2f2135850715f623909e41a745eaf7b37593567fa8be2d1ccf76d10b93a096e244b91d8700cca37a2ec1bff7c3d21cc3211ea8b03a3594921dec32faa185e7f3d9d17e98cbf8d881fd2abb9", + "44181659242ede21df7e5e8784f541cad678df1ef6ca4a5fa91f7856c62fe593c4d24436810cf4fbd11125bcb571f6975d82afeb81bd0c7700e053fc175fb5fc7b329c438479a863b8d5fbe6b4436b67355c51d0306e8847a27a30c9e61f0e08232673cdf0ba4e0\n\nQuotient = 0\nRemainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nA = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b\nB = -cf429f101a2e19a65af1e238f6745215cf476ff2609c846f10289f1ef21b89af2aec53def3f4ec07ea42041f8b5862dc37fd03b2df12adaa8c9f1933cc69b526d47797b40f49545fd093b8ceddee3c55721d1fa19b336218de0cac56d410cc6cff4e620578cf820f5cdaadc367dc4d6372aab1e0ae3831a6d153c14920b1dcf09e7629b7442a06385420d79742e409677e3b82ec58bcbfa668ca072e981e20728a983d84a432605389c855a6668e0ee0d2b67449\n\n\n# ModMul tests.\n#\n# These test vectors satisfy A * B = ModMul (mod M) and 0 <= ModMul < M.\n\nModMul = ae2ca2ce7addaee2e2b7752e286b2bb6a58b51cfbed5c924f00398e59ec36fe6341cd83da43a33a12410f45f6228079c4aeb3912be87e2e81fa1799151bfa0fea29873097475b2c3efa312145d0bf7e51b2a7c9bc961a4f4dcf0c883ff90b919b87c21099fba40257645be31f95a3a277\nA = 6b18497fed9befdf22a01d988d34213f6687d8a96e86c188dea4172e7c6095a0d18d3c86c0f5a1af9c6e3aaeb6baac2a510930b3ed06ec78ec2e12b\nB = 1a058d99397db0d209f01212dd4023ae01b15da04fe62d1f76f21622b2695558c67d706c535ca7f19b36f8ef2d508ffd6cf6fcf25e5\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c462c7cdd79b7604246a0cd97b40ea5a9a77408f13cbb548b56ee713c690dac0507fd988bf28e77462832f4307b08564a51510d4a951c1ad7564316dbead2b53540090827a8ade8092a6133af0e5fac7310f787dc1472836178ed6992b9f71224da3e884bef8e8379a58e6d4be0fbaf59bc520f786631857213305e23fd5ca65\nA = 16c92f77c139706430f396f72ec7adb045745cd9f5899b0074d9955bd32de66f57c05c7929b575312a7f1c04f19e724d64744bff7b31ad0e6171437763\nB = -8734c4a2361fc530f60b28a5f1c7e93136c5ff6bfc7553965eaca54c61e6befb3c0f8cef4280e780cc5940d21a740debba31f863ded75\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c462c7cdd79b76042469eb41a7a83115eb84103da4ba438c3e33227631dc185054ba4e607141d1e60990d8aad4e0bb0ceb645ce9ccdfe72d4738cbe1f6a73ed3e070194fa4feca6001c4a853940a227d15c1f1cc153d8c96e90e24805929fb11e0665e0c41c77d5a97fc5903a8b215360e26f6a19922d650f460f7056274ee92\nA = -6715098ab2ba3ea1e6341e89936e3ae913cdd450dc831c8534071f3c362841e47d88f2cd29c0d1239aa0949f3685f12f8519625bbf10b2c7a515e6d00942\nB = 536d4b3e4815ae5ed55bae6950f5a8a61d52439d2800ef1b5ba2285b85ed0f6ec4af9fa0e364a6b14f6f6b8bebce9200467804e787f9f3e9\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 309b3e30f74c58beca8b2c23f64fe1203830db8a7e306e1fa2e2022f0d6d422851da509d1b2936f088f0e35effe12a7463f47ca369bee2f2980bc48dd8e696b2d8c6f35cf55fb8baafc2e613b4c684de26129cf196741aab873f81e498b1e03018a539b5eadffeb5953029f31f8579df7ec0ff3f752491910\nA = -11fec955948e007b59fc50e729941ee9d43d552b9411510b73f6b4faafc0465f261f8381d96f647267f72175883172918b5c866cf1f1ffc43c55f3c96a60c01\nB = -2b3792f39499767e0a8b7a6a406e470a78f97ebb36765beab5fe52e95abf7582736db72a2ebfdb2405e3954c968b350a459ff84ef815dbc5910\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9143ec3e9f74a8eec476cab17ad8636eaa7c60e108e89ae0702dbdb2b255a217ba2530c6fd52658cd931b962054a9c20c8713976ef3b7989c40611cd25b0a9ad0635d61f6dc95dba6e0c4a7d53ff539b623b97ba3d66344fa324f905abb861c6b1e830c4b0fd5f6a4b01f09c8e1408941291b2285c4625267a108c\nA = 7713413d87f1e50840255927ff27bad79e5de5898725a876e4647913158cda9f5fa031dd7fc11d2e8130a0ba99e8706341c1a98d5fee3218763ceb1d131e9cdcc\nB = 1384e60753dd4bc20cdabf398525e7c4aa40065255c5058cae0b2ec90a3821bea8de672a712431aef5864eab719ba621cbbd8b46fe86fb31286091\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c462b3b4a0432890d141c0f46a28190a2e30ebb2e4ba90ed132169cd72316b290dbf5c261984d98e63eea6525fa890bf52185ad7f164cf49f67ca91c2f35511f3bef6eb7f3da31a602a78e4752e326d79dea729f4ca6438f2aa65eff44bc60979b42e44f6a301cb5de8fb42abb47bce5633c6ae9479d39c9e8b507d96161e0fc\nA = 17d806d7c76aa8acb051fd9c0c782443f1b1b6387455f7cfb737c41658d0459bda5d13587055eafb87ad8d209bccac1fdc392aeca0774ea48799511c1fb9141cad2f\nB = -d7c9b6574354e131de4b8643d766641e98554a03238ebfce1112c3da5f049d6c410a7f05758571aa2625f7190b936a214797570539317b32fb94cfd8\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 16c84ed15ec6352a8ce6d5c2bdc0d9f13b333072fc7041146e944a29391f83e346b8ac0bee6dde98a420ba4f8852801d7c5bea6f1177a6cbf799edf2146f8297013e0e796917cc967786788ff12d9c1d07d9ce4b897bd22a1b8a391d3b4ecaa5b5c85d0a03aea5145db6350c42a964a41ee5f83e7d35e14cf442e5d99ccd0ac8\nA = -6d84cdf18a2f53fe496248fafef183914d55c42267af3dd42a39515e80cf29211fd58454986f5fb6afb56170dd9865d3158249090270bb9af341c830522a4dcabfd494\nB = 6f6f3f74187b7d74dee92f79be864d0a2c56d4bca3283742e9cdf15112c8f4208e3ac8ecc98b44b4ad74b0671afa4aa9e48dc31d34224a1f66bb2b4658a\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 8fb782e4883ccf3aaa2d3e020b08993d580c69ec8fe66ecac152c5babc8aeffafe406736cea492450fe6adc25dfa2e12723a3f9baeb02fc0f785b3db760ed28048e1710a78a2ae0c96b67c109c5034375a512b6fc7906847253f66316baa0ef90facc9ab992235153684d49d6939ab9e91086529494d7386f604ed69aca2f53\nA = -1f745c8f0c8fe6ce3f893d77fb274c61b72b2d9f9c5a2eb2467bc00d1f496d0ad469d76bce318bd64ff1107ee5fcad4469f84d658586a5789c068b0cb9b866d8fdcbcac5f\nB = -3a2347b491813252e8ebef1bd181534b074a368d076b8c80bde2e54ec3b4ec99001f43080c7857427e069d99b1b65cff998a141ca6963aa5fad1ee632986ad\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 7c0c1c05ae1d6420bd93596a01aa0153000ecce660a8a14d6fde7d4740719cc495fe6681a9a08163b2dfd51659b3ae7db0fbe09504370bfc695457d7b32665a4df53e879ac817bf715d5bd6ca0e242b1ebacb1ffd6698ec90c442910a92b35ec103b345f9a9e5c7b005f8028da4dde80f36f6f6e5675040d19e46aef06040eb3\nA = 4c09264420a9452c6f0b55baee42c076aae5a73697cc6bbb88b7c922f236ee4c18e477f88e2c40cee03f0bbe87d3ac8dffd75f635315f856a3881c6373e8b9a286c813325d3\nB = 10474ece7ddae5c53c4df5b594439124370932dd94aa5d5b4ddaa233b1a55634fb7d72e33bf1b02965fa9d1538f97e1cdb5ec0477cec8ebaf202aff8533211169\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5", + "f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 481543f1556df756ae2e422ffe35aae020c9bde9e9b1f760b43043a4654de363dc67f381c0df1c3c1b90edb4343c47ffb8345a1aaf5dae56f446fee08a0b9ee8c42fff57143e10846610a9925be96418c4c957b4e92af734b96fd6f21974877dba52a0db1fec4aa97640e357434f95ba74b6b8323cbe17118dc489552844602c\nA = 11bccd165d9fa2d8b01a48c0ec549a6e600396cd2023f0240056193ad27e971c604eda8aaed6ff6be8be1001f3dbdc8655f1ae84eceb963938ae7bf428eb5c968f584798c1bd8b\nB = -cfb6629ddfc98a242e3290959f4d0726c0b1770b52393bc7488a471a90f7f0951362c03e67f443c9ecf4987f5303a789bf65e0fd59cc5eeb9f5d4f40d3e4a14080c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2a770ccfbcb2bad207d0e2dfaeed04b6e7509daef00a1df88e57509451739a8a0f15106ce8b53d280a4b4e09900420714cb6961ebb0e00e88567c5df50d2f2908b4bf8e0a9a5a8b3c6120503c14f16a99297459543c467dcb67915e0a10e19f72ed5b6891a6121b66abaa602818801d3306630bb04ea57e6b31b2c05e368d398\nA = -442c80289bfbf00db06eafbf06109b55f99786a323fc2c6db5686f99094cc24aef50475841243ec3ade2a1e0ff28b4032fd8afb8bb5e28f3b2863bdb9fc8f033adbaeb5f2ab16fe9\nB = 6d43e3c46f4a55d49e78f40d34033a7f5fcbe50873930e7c5452b6b3b176534e6e70033868c85b4d63052964093214dfd0bda6a84e893b1aae3cc72aa83d039e51c014\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = ba0e8c91a86af1001b13deb115c77609a1e7a3736a6b807255aee898e3100f469ef6222be532dedb1b8d3db4b3b55aa4b5da5629c83e9b2bde76bf2f2a4119a5378b5cde000980b3e58595d988ff776f0388fe025625ccf368e20914fa90dc771c826e4a836b2890e82ac2274471d586b4de5dab3278f0e70207562ac6e6493b\nA = -14be403d28c8451cac4dc83fbf895a9d2b74f730c39b0fcb33d7258f99211dde31a78f182ad1d27a559031d67d6f2f94a741f141bab80fc692afb452ee2d502099ebd5760ccec7f7ebf\nB = -2742dfd02134594edc6d3025aba5ca4a34dfeb43821ad84164510b43be4fb95748f8d0eed7bbcbeca14efe843fb676882784bb36c889be29bdad9270e0956286552119561\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 20c691d6544912fadfd9894cbfd42745991f39a29cbe3a1cdd302bd0487bf70c0179b9579b77f8481bee13ddbe42f32d734b6118af92884c946ea8576f6dec867c1c251c73777cad7c7c76e90da00ae07f96c8d6a751e5b18157dac4468c05d32eb86e74e0e8312bef85905af8193a3f5c799c5875badbc9eb7ead1258e56d7c\nA = 7ae9b4d5151b11bb7bd4d1569a6f4804f3b4d77948e0c6300e4f28d51c9a0afed2ae7503e53489edca5359e2b3d0c82a9cef316cd7e1c1275c31fc9c51a8c1e5fdf23935484e467d6460d\nB = 1f46f88d39fbedffa8501fa1268bdf3460aa98e12b629da59676e61852a4d3f8c59f72a2fd717fe2faa09639bc651ba516cd39297e0cac67444ec57c0db47c2a4e250033d02c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = bf21b3cd55c0df8d4d568d00f757b10ef3de782ae71b289cb2b59d36df1341382bdc1825ba13199f2cf279a72968b3bbf5f7e3d13ea9adeb96d81132788231fd988eef04828119dcca21ec1fe844998909cc95a8d01720e883df27f07ef4dc3f09081015dbbdf019b96707c18b0b1db6e689e8f86466a2afea4a9cafc576e10c\nA = 1243b14aa3d16a55935f6f8ca49295e35e7f75b03de7192e1e8a479abc0a430e0d340acc05eb9a61a5dcbfe3ce3a4c5c940699f5043e924f282bd21e341edf8b7a6741c6ac72d7587a9e7a60\nB = -bcf08b2153e8ca911096189e35dbdb21b77ce89685484f574c89f1747612f39340bf1b204a23530abb36b2c5e195940b86ef1252d6729393c25d4c73dd434b6dbc3057b05d3f15\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 460539d96c07e72acba5b59c88fe904bf7f1e1648612908444b0b08172d05968b31b43456918b4287dbe01afc3cb4860d9c2fe549a580c989b6507094f6c241eadff910d2603f747f8e289e7a8176ca4a978bba89288a4cf875bf3e03939af966c54e77c28119a39d34a2b7055465f58ef2efe7c82ac547fb675653198e4b504\nA = -5a44cb669c055ba7c28d49f84bf8d12179aa30bbb9db2a48d7a6b09e44dc0e0f7471e3629cd2fb51e5a53346ae025fb49f9591ed1d71bc79daeb3f1254342d8a2b091ae07a758c1555efe59e78\nB = 646cc0f766346aaecbc5147a4488ce157a6d844045b80884eaee9d419087285fa71108b5ab4a05689aacc8d2e3dd0e6714c55eb8f77487a3fc5e56c3c2df0c4acf28a457051118560\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 79b536f4f30f9f7483f90e65e6456ef8072d9a7430405cf8c9377ceea2c676afc338837643436d55ac6af2326ebb362684bccc5092367209822581700d641cb8d331432b761e4c6e22639a27335f45a25ec019d180fc53dfb53d69216d7cfaeaa07db8288adc35b7bbccf2829631c1eebb821e4d3299015c3d462dc17aee5024\nA = -167529b1e8668938ec02a68bf4d76c22dd018c41e19be25e2f821f63c2046085d0af30d8b4212ea0f3f9943be1c14fb2d2a944551107cd2bbf8dda5bf258957325f06277036282977db4575b0deaa\nB = -378e1be10a57e03b197bc2b1287d643ba6d89da4bf6a6170816691fb6529c602eced237863ee39659be3729825f032a57eb5de0a87b0894d1a1244523e85b6f50a3d9976dbb038490e46\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 658169197ddd0bfae101c10c3e6a2b10dbb456048e81160b47b197fef439b1e0ed710399cfc80ead8e436f1c0399064f92da50afc335847515686e055fc7bcc0ca721184435955b896b0af4f4d96672ebed2f154538d49fa507b945c0a6ae926793751231980274213c80046666c28ada213a2f87509d1466b8d1b2122e93f8\nA = 49136d37ae8f3da71a6114327833e8aaf3dc8b5a9a27e9d04c953988456e525263f86ba94397321c2093803b789f8db3ed7cdba19c4b796500b979e02952e1625246f8e977e01fccc133f94cb22832c\nB = 1dca005663385fc00b4fd58c73adc7589d15ddbcb8cb2fba03a737a320c447a2b21e576ceda73811a31d8277883fd31e22f776bff3261a098ecf8f40f2855b0c723d1265eeafb43f85323e3\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = a49fc8084f3e780537b4038bb769b8db3653a3315298a99c2ede6739a1732a636e9787f2e8b09d0b9bea08fac43cccca71a315e6f4a7d6417d171b4693dbdbee8cd9f95be0847ffd40ff027267125d67b89737e1d0365bef6c4429504d13cd8ddc7810f456d6293c0c57c14a307b94010d79d5c13b92a907f923966fd3c5c8ea\nA = 1e7d8de2061cca59d1cc19b356a8fcdf2ccf917e0d81598f014167c5a8de027ccfc8f2cb8c37c396ebaac83ba862c146bb2d551d10ce03de9528f97725804e8a6de57b9d9da811200604c2a032462b6ac1\nB = -e38592f3acd75b575f64ced439d5ef2377d21c61bc70625639b01bf755fa2c6de803ce155744993493debcd4de40860bbfcee86d0b117d7f8c3f8ace68b67cb6fe7a81a145535553896424f7a\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5a99c8a6afaa97d8e7d84f4899803c7786b1bfd2ecabdbfbb3bbb92247ff91ac213a72f6d23c24699d60babe91a7d9cea751e686c027fa1c954474fa5680f0059118426c71299462b11de5f2817d190599cc4b352df4d2e80605f9ad1e32eb13712d3027a2b6a19d52151e37e7fa057d8fe59dfc8a943a42a1756a38f103a75c\nA = -7df29221e6a102e32757c18f87927cdc90ecb012ab0557e0ab855daba832d76ddf595b9c5a62988ca968b64fd5bba2a147a5991810c17cae7edfde38bdbb7e13a1fe5206724c05a9fc9276c8d4e503a860c7\nB = 5c586d1aff7dafea3b8ee42e0e8854712c95385374b5bd1fc8ec41a72b296e070940c4160509a4a1699a678533ff3d12299338fc441b0f01e29a48677bfc5aebc644555285756e97c74e1af6aaa8\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ec", + "fa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 21fd2d881b6a52332dceea42664aeae1ca110512c13bb33e25ba4ec0f39f80eb73b1fa0834c998c23a2453dbff971eadb183c51a30ba78d593f23be9cb6b2b33a554ef31e4a36e0314fc2ec889f18debb956b89d1bf8172553271bd56d89ed0b30abb70e68abaa2c76f73cd5a3de93433747d09c845b5f8843f9fdf9f6c975c8\nA = -19fe3bdddcf08190a037768b77666de803ca4f7f0d7dbe6aaaf334a486dd0da7ca024d1b3df11e0406b0326595a171be30b04574c1a7d04f4d2ccd334663690fd20e4fd168386280510a00a70c1a11e99483048\nB = -33b2400173c057980b0e0cfabbda1a5cb5b83b7ae80708c199f28142237f04b071c6eeb63d42e80eec04b76152250c9e4d4c4f19a048cb9815dce6e66710fad1d27494db5c31d9af37d2aa779d12d7f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 1c45cfacf30682a876cfe253f05b393a2cd4dc065ce73126508ce897a99a723cf5145187643ee62d746f6edf70269ddce3c348a1432316286a648ee9ac31ef87feb14f25c42f2dfc2e84bb5bdb4ec0124e249c526c55ff2cd0ae938555c5f86d856eb181572ed01dc045f1ababa52d249e56aba0ecccda905d7d1e64bf89bfe8\nA = 6a40d948eac2fe5bf6db15d7f6b89fdc0712e32d39a881c21859e8f7722391ce05973efc7c40e2c0d7f56c217d8a986bfdb08bf87bc0435873cfe4d01967c46f7d39464bec411d0369f6f5d1d83f42596fa47451d\nB = 12529775e8253ba220d890d4912fb95f91e4edb59610e889431208b6bb42b089cf2aaa12ff9ff98c2482e7f4cbf35b22d15fa28aa288217bf766e937a706fe1e600143087b0a67f668cb7b762c9b9f38c0\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 3b3b08e8eda8be3918bf648227eb0d569dd898729d9cd54deb32b1a1dc69cf7b2c4184c8ae9641f0f75950df263a5e236f428ca86244e617b14a04edd0f31c02bd4d84f25bacfcd4a2786825f0361251475eb6c7e99020dfee4298a1f1bc260d4e364a332bc6f651dde7ce5026dbeb0e5aa75ee98874da54c7930108ad28e3a0\nA = 149d36918fffa682cf90c4d3f3d48e6408e7ddcbeb44e78b9cc7fbb08108f65215761a61d79f37ec8f67cc51e0a9b4bcb3834b0ebcf6734985153f29a2778473b80147eddc813b4fbeb98843f5c1ae6cea68f88dbb4c\nB = -ca87f66182e271a69c0964eda92a009d438078b584c3eede28ce1a501838c5f497186d305c09922f32ba858fb55f2a0dbfc9cd0f93b789c1f800cf092726d6d33db19e4f26c7dfca69b83925db14544ebfe2\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = b199655160d88b6b4157ada0e5675f82b33b5592408bb57c46e2f7d8791bfccaa51436dc3b772b83e907c20ce7edc2835ce96595b78c0647d244e9bad6f4184e0003eb0899e7a47ba0be888b9bf795eba95e5073a85c4d20416fcd4a8d4e1e16b403deb38845fb8bf9e9264d68807acf02d579e8cd104cf2bd555e6cf73d0450\nA = -70ccbb73e33a7cec30ef2071f3b1f2e008e70fd6d00fe8b7aa4b9146fc6d0549c57d984cd014c7e0a4ed6d33376998b7c2c9778fb9580d8ca4ba795c88612721c153c186740c58df3fa63b6cf7a4de76e049217218c05c\nB = 6cf4168d44a8da8e8446b4420466fefbdeeaf9623a40e10b77547687b25f36916f2c18cf6060c03b3b40e0959479f6aad5e44dcff0ba799262ef53e280f4a7f667d262d472b2e573265774deb5ff8f25dc1822b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6ff91af444c61d2e2fe8ad73bdc5377d5becd55074eb60f0f98eca3d8f4be8c02f196b3afea12c36f78b78ae6a5ab677ffb7d9c0bd58987cca816affe468c7fb4b56055f5d2326532d6ed1c00ca2d052ecd103994e8929bce04e067082b4ded7e1973566f99c514b4e0d95b9a8a931ef4f6355066940990fead70208a63841f8\nA = -1c924bea12ad6f8b65abd1796e381fee2cfbec15138191bc22d57165928794bb080c83878fa5fd19a5d657b2fa91165459966f50aabf19440f7d75f027b32e999ff4d3f7a7ce878fe0f33a847d644d86ca19713ca9968d97c\nB = -3abd4b281b8f25f5957d1f2fde904457d49a3a7eeceada26b454ceb4ae0e879135d376571f08b5038b7b3d73a9a9fecbe265b72375756a715a523ba66737085e5ef7a4ad988155adc93eadd5d95a0faea56914983b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = b9076229b1a1241e8b4da3fe143ac31d060785be6ac1e841c2fa9683d2bacff2e2b5dbac33f58b0b1718ad2053c37ee55ea54a9d258ddd8930d2784852844d85db24e4721762839a5c73cfe588efedc8932ccfa585e1b5975083919be9e32a86dbdf5cef84d3d4b2ccaf7a006c0cadca1e35fff2da9da7d7e779494d8f85bf4c\nA = 75eb0fe6c07559c2b0c7b2acd7d29b5798f6c4cda64a504ebabdf54bdc773ab28b218f0defc040016178958d5561796230b71edf49bbdcbd3f14494859843c8ca7a0f777cb05827f2839f3982832f4f3e3c5e50af17ecebbbc3\nB = 1b8aa718d61447003fdbaa748a9d86befdd2675a677cf34a1be7c81e4577f665d71135a8a243976a4f6ffa1636695567bde522f8fb1948033a7e0941f833d827e957781cb4349a08c6be418befc8959960fd5fc1b288c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9df82b7c34ca97a3a5d4efa28d5ed4f35484914dd73af9090c4bb31ea3496ece8ec650f4e7b07dc779c97e597e76e43cdadbfc6e72b61ea718c073be1cd204f8ad2bad0df1e530e75705f3d3dc285e9d793c8d42f04dc20773d3fcda8ef3ac1cb10d33d20a91add0358ab8658f49d2fe51d0d2d72684e31c0eef85e5695bb4b4\nA = 1fc2a171445ee6add5c2e4d29e50b91d83338f8d63c111e4d3e95f16d2a33be02bef24dcc3d6ce6bb8f1ef980dbf8fed409a0232c0566153014eef840aff58ed8c33e8d463d408f93e2f5381a26fdea63676c4e5397eba1d39f928\nB = -bdac7a177c77451104852bb99004ce8e617036906667258d85adcbe8cda21ab7d03aa7dcf62cb210a9db8fc750c7e1ad290b35473be0fd607fcdc686de0b78fd9f258f5b25e2ed43c2ad1a38859f882b9f6b293dc258659\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = bd9f3d2e8a1086b177698f87a9860e3a5f030e04a0bf4ee9436ac55e005bda01ff4ac662cb85d39e98a41c723ae542a83a936c3bd0280c6801ffda080ec0aa4230b45dcd0bc5eb41cfcf272028bce3572847637a92d1543bb2b8408e880f5b776e1cf14fa28d15cfb584f025596ff10c9f091c837a3aa622d9e5c856db8ac207\nA = -7fd5357cbee7c5e31fb62ad03bd47b705b574d915200fc7f1013d836b9cb683db020b152ae9464de6aeb8baf14999ac7025dde6173fae6ade325c60ec310eff6dc4130a8efffb15ddae90d760cb7f76a27d0368175d4a44a22f7f223\nB = 5894a0223e4aafe4efd4572752fbde4952c8b09cdfc35137e7e6ed650f8fdcfce9de673853dbf73730b159b2656047e69377d7c5025a6b346fb08831e64bc8bc34b75765012460d8135a4f7a0f41d768fb85abf17f5e2f5c3f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2c61867bca70e8662c7e5435a5aec020faae86fb079b992bf49d8497fc5f96abbd38a6f04f6ca8510e0160e546b3f68b7baef4ef0f404e881771cc12ec5ed3e3787c2d2ad6bb957cc59f8d56f0afb4bea49cb671cb42f4e8a0ee1dfadb6fa14f84a5b3269dd33e20d658ea4cc39499c7a39a4b5650ad7018d32f97954610f676\nA = -1bf5ae15f24c7c14eb59605136a3f679f303cd5b81e4a27465281d17715afdc2c231d7ccbc59f80ad176f4e0326eb757b52e3695e27c6776d7936da47e3a8a904f735b151422029535045ef489e61ec93f02e6d588491c8dad1cc311f52\nB = -3238dcafb85ce557036d19e42e7e7e473de9f9da6f920e18845dd010546868d2652decc94596cd2c36bd16b02c02559892b9f573bf21ab18c3c75591413d046b385d08aa66d849ab8adc9fbf788e837b047a7ce2b9c63f7fbd263\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c1d04b831b71", + "2d0619db462c3f3fb5973f5984e9a48493ff273a5abe17a548e185d751628899e2851e425a7d4b2c72d4d908dc813cd122b8f497e08e299dca9166f19752ff8cd9840a70155ed9e8c063a3840838b3679f96f1cd5f1cbf0e037d222029e02769dce7fdaea0bbb5417f85497d77c76a387c6b970eac15dcd128ba\nA = 7aeb60c134e84f289e419b74f99a5ce5b4aed5fc630d5d591ac7643251ad32d6ca7f052fdf8857f67138262d221de644140e9018f7b84879d74883f8f251303f65e06bb52246ec6a912772cb698b47de41c1826ddd065359f6b9f1ccb0cdf\nB = 17f81e53d9fa6201e4d3eeebb32267929cd5258d10f053e7c021c4afd17094f8ecf433b1ca752f8740f6d6bd84f801b1b9fd64bc4787b9ae5e5aba0b4318a63dfe27e92d5a3ade192af7563c74c9d6006ae7701240efdd6021a83cf6\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = aef89874854ed34deae1b77286f9cb0e3017e3ae77fe050bb244acf4f30dc03504c73c1a4d44b769709bdb53811a5d0f8a76a08e6a66fc2cc4e98537ad6a8049f02494305b89a49a55e71fcc3f5fc42d6b478456ada9b19ec0a03f5ccfac5538c0040092771660312be5e51996073ff1a506d7460c57d54e10dc2991c028606a\nA = 18d3af14bbffbfcabdaabe44074b407d69abdd80a6eaa5954f0e45fac85af7ced1715c78da872f7a8fabaad3207e31f12b7195cdb25abef0a1e54d3b13349d997f207fe130d7985e2033cfec899a0af310c9827749cd22bd062eb0b1faa254de\nB = -85a7d9f08a60031e689b0e611d7f7f46e1178eaa2e6459602e738990c77f4d3783ac43fc04d53504cf67fccbeb02f9846756f8e32fa4a9316b6d3b45f644254077bef096a72bcff17ffa17070a4355121cc5daa2f782fc0d0bb48101db\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 14a85edc6297763547702c212b1a8274b8f85d53ef35cd1b01ed51039bbe030d0a1b9626ae2f571a43f1224d723847a1c6708f2238f6f6fd75db6656e6c703a5acb57f69717efe8ed58a3713ba2720d8c001d026d83de0ce5e24b67c41daacedaadfe404aaa9b672f00562e6901fbd0710c4303fec41ee3338100beb36c9b1ed\nA = -44414ec207060d105f599b9a66aafecc5b232b55214c1a5e1922f6b59439b3ff77cd3a327bce4f7406871196b90350e6dca9aae147ce03027dc4de7563c734f111d95171f489105de5ca80047cfa43f7e932917b816ba7d41fb95b4106745d700f\nB = 45f2cea1b9b75880ac3ec206740cfe0ecceb488c9155cfacf5885a8cb49be78af8cf221ff8de2328f4880479c031f830a3c9eaebfd83f7de501b7c5cde03c4720c56a676d331b2a13c4689a2e34a43fc11f62825b8776e75d31225ca7ff65\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 7670c1e2e141d8f8f5466de8ae2e0ba2eb3eb7634699eab8415d3a37f8df291d00def88361e9fb64a2f116433dac3ac2764fd62f3201dce4e48a3b7019e5465f82241ffda29d5eb0462fde74dea3168f8993ccd4d090b9c31a5a6cd7e05f725bbc89479836b89379b422250ab049f31c860110df5ed69089716877fb0ad7b0dc\nA = -15b4a2f808a85a5bd466a342c4853c04ac0ab73f8e53a4a0477f73dfeb8d7a911ab2eb5d3d192b9b084d0e38db491148947c66f838aa5f460c37341b129137614259efa531c0e6ffdf163ec6851737037a5299060418d96da035e6f583e6ba79d0414\nB = -3e94fdf22004384f7881875b1d8f58019ed8afb1b6a31f5d591e77b0998f3100b34174d6f3466da44b4c7fc8b92ccc5679c26c146b704198a65a88554d24291adcf897bd758a035361f671a82972b5962002c6a828792980f86a64547165327f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 35b49beccd8d2010a8d777c1ff69e28e01a1bb78c6466e717f0a934bb62f9bbcec5ed29f9cd2c14d240a6c33b28c986eb9c8912a4927605532483dcfd31a50876e1819f3d7a0f49bd276ced5c4110470244fca52d2611ed7e31cd8b73e749aa70743b39e92810b3b52320342a65cad3180f6e2966059d15f79e5574348f5f66c\nA = 6fd078e3cbcda6a71a710e99204da640edc71a65974fc765999a74ab50a0e4b090d57ed0ee869c8da2cf694b6fab56e87c4af62fbe73eb8890bc066ec3460beba04dac3b8fae7e4f316e8f954c6e8d934e946dfdc9f4cde0f26bb3d40d5c444b03bfc65\nB = 14d8041a3b83468d2f44f150ad8d8d0a1a22035d630f2a17b70d5c3d557d3abc7e4d753e1ebfb3a3ba465520b84746073d211a67e079ec7f47c2cff9c06da69bb5cbafcb6cabe7e0018867c42e07931d6797d4499463e3cf786c6d5d6c8cbd600d8\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2f6e0fed8a9720fbd83ce950d7545d2c6d5b271582194570424f90309227a51777cac974bca0ad3c1289ceb91cf75af73b0645cc20d71e7789144876b8c1bdd550328d9907accc316189e8ad81310848cddd2dbe362c9398d814a048f93f9368fdbec0f19ab87ad2a59d4066d738c3da3cb71d4716f2cd2336ad35ea1438276c\nA = 14bda9e4aac85b0ab7abece728f61450b7779d3b5fb83be813758e742d2ad76597f132aed91e20a75c554f0d61ec4dd118eb733d04942b2548b1efdb4dd22fdb543d9bc1e4bf0574ae2cb2c46fb98cc4835b6a074d6df1a3bc5443beabdc784d542e3349ad\nB = -efd765f8ffd72d041ac3244078b8dc4482233e9411b289cbc2cfc26fed2cf28e286835010438ddc9e7021ceb098b10c68bcc4732608ec1f4052df9362176ee14812bbf09ccf7c2882714ecbbf92bbff61c06e9dc35a368208a05dde949fa2cd091ce0\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 1f0c436379f6dff55a59093ff2a0626a9b959e3e3e59365afc33c7a7893f04bca863ec910c446957baa8de4e35a1f4e9c4a776ef41b053f03b775f327eb7e5fbe68bbb478aa4339ae703ee4b573d6931e47e09271d40239d527fe77098a7fbe519f5eda1f26dd6a7d0ee6833efe37187d8a85844690fecf9fdc3a4d80b921130\nA = -51eb34de29ba24d2b1fbeb0a1c324f4ebc69cda2dff971a315c0c2775d988b03ca29891ed0790f3dd507a1d26ead461dade9284613e45df338dd83aebfb66050465d8aee554970b43f7d4e0428e1512289fa1f9b23867b67095c455b66d536b91207b749189c\nB = 55259a1122eb7eb611a69118d3d42c2f05dd228d71c0e1e42ae3a8d3d180a95b74150d844e916ac85105805126e4b995f2ed1cd3fcdf28e1fd241dbe3125dfb3e4d90556256eb513a2f7c9b596719c83b26931d92bfd3573560e8bf054138f5d6b9cde72\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = ac321a272d2206df4dcd6ed8ca194a1049c1e3a20bf325fa44809d302170f850721c077bb5d792f86f7ab03ca259567397cc2fa1429771190bb632ac2c92d3fccf6e05e13cd33149994cda5f9c57da155439663f6a13c66f9da553f5038fb92fdba186ed9ca04b8ec87cba4c5a68c8edeedb94e38a6dbe293340dee1a4ecc768\nA = -19ac99d7d51456b00a193b3b04693c7e5436e05763f0154768db078ea5111cfe9eda3451091af213b9c8cc649d341de66c12ab2803ea39655d3d7de182a77355ca444c5d2778f791d39952a7a11839e497f5dfd8a703df49ec4d7628bfc25a992e94a6477e6be39\nB = -286d1d436f113308be594f0f43d7a05120639152b7e2f93058cf602cbdbc016512bfd23f7aa937fb358b7b602d15998ecc150f2b9224c58527c0c1267739e065e24236771e2c683957871637468181e6e896b513569bd004b9845f0f0e4c26a5ca123365e1c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 3466804a1b7d1af8b6060aa93a4c325d9cadb33ebcc8bd991f9e44cc2cca8918411efeed0f005790d649382ec40278c8cff903cf3db177d24466c58cf6a56ffc14e595c36bfefaa2327d37f616b1466eb702f5c49170598bc361d892e18051b8233dbc5b3fd6832befd9a995bcef3b0f3beda6efaf09f7306ec203172e78264f\nA = 6710c19330d3f974fc377e28039e0c0ee0a558621fd67fe724c326537c18c66dc5eec60980e07d401ad5556a05688d2dbe7b271f9d5eda3032bf7cb7c420e7b5d65a195bc037090b6fe83064ac3731624ce2baaaa62a6eb07156ca12ee51d4321988026cff573ede9\nB = 137ca18f47a151363a3e8c52dcf024262ba525ec8852e8e406f460fffc2cf88f1999b17a5821849317fcd84d09c88ebb6eb0340120f113d7ca5fbd91c6a40cd790bce7b422552cc0cfd2a6417add2501db1667f2802e5d0f4df824adbd033a90a155cebfbe0b53\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304ed", + "d566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6f248a70b2cddd9627b32fbd130f05a604866799365f94d97f1eb582b28192959692a870be7c2614536a8de84cd8c1364a75a3927ef9dddbb8c6c87dbf526f2d3a7916384f2daed96002831173fa4a51863c28b4378f99b1b201010581d5eabd66ad1e328cc4e647bf5e0588bb775e130b4a4d029eeeeb5852c5742862ddbc3e\nA = 1f014cdd87cb33ffee623cf454edf2c476e91df279b4f0879637eb6e8e5ccab305186de67585595d34ebc195fb150408c4620cf6c7a0b0d9695ba0e0e1d7552ca7d0be3dd678b1cce2beedd11939891a6804770f1c843e16dc2ea6aa8e4043940c37fd3d950caa122845\nB = -8d8d9dedc80994fc5db04d8c935301e47054250fea9020bde8d5fef01f2307cbf458d5afef5210a369c396287c5eb453637a2d721085af3de0d75a5dfb5dfd22fde3b229d438439af7b296b9e68ffc982efc6c825556c52a735f8be12a214a06c4270824d5268fb6\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = a35ff7e232f047e575b200b9fc4c9253de6ac04c612b8a82c275a951075eace5e7d6664fe8f78301d554cebe7b996c1f4ec3ca59d8d12d7196eb3909223de94c220f0445d24233534af1c93433b05c5924799d2c781fdb88c4537bb8d442e6bf76b2d966827bfb4f40378a3f135103513da056bc0d375b1339561700d15a0227\nA = -58346cc8a9a1e5b8babaed8e7f59415388e0db654ea7cd465d96781c57faae7a8af8e7578e46f3a8de7bd1027188e1cc32fd1c0d60be24fa3289a12cd822a6c9a77dcf8799624856c27ba88fbdb047473274e651760581b44457ed048cf76c166d38bb9b2afd3416ac7e45\nB = 61951a16dc6466a9fabae99df29b7229f1ab96b476092dca1e4f8fc8e7404e2fba56ee66486d1f27f89bb3f86f271307228d7d6cbcff943961e177300b6acec1eeb46af1c5725f745a2d2af0fd9642f57a09c9ce6742114be0aa6e939e638bd5c7a92a7c206b2d36e35\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 90b441d8277eb1ed454964acf567067925881b5db0b446a7d554dc61ae87ff979bfb0e58ca1706123453e62ce31284a5a2db1228d259e27abc7fb5cc5848dbeb9a6808fa1b4afa844ab39b652abc41423c2833e1209a1674db518b6df7ebae315dd7f416df54e73088762ef64cc2cd0a08b1cb01c49d9299d149cbe84145a55c\nA = -1ebb693ea7d18e0ff4a9a51124ebb78bfa3a4635b75a6387e9fc745a2325409f927324d1289be8a4f5cf2d5c04adc7ead20564f97e453287f03e5ab59a6133584f970446652d05a131d7d382c47b7cb97580ef6710a532dd4f5a0369dd3db500ae5a3c5efb587cf0cd2638382\nB = -3916ebc4653e7d6e0a4f1e234d765d41e9e948b5acd7ebc73cb595559c1b20b037a3c8da0a7aebfa5fd327bdcc922551cdb8db3fb0a581fa0620ca2d2559ccde3ebc44542b4d80926d061e2a35c08c09547e0cd587c396ff2959ee93ea64b1e6b7e2b624cdf445988e1f42\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 3ac61c3a028f4a2df6645acbd36818a2f76a3229d229ce22471760807585a909727411e8b68bfa4e76adc459409a101a1ce83900d46918e8d0903a163de87c07bbafbd60c7f536a62c59370ea53b6cea4384345343146bbf529334b4201ebdc7585b6e5eee42696400c9be9f496406a4eb51d2fd1b40466224f1752b181774ad\nA = 5a16d5fb9047949684b80805e5d962bdb939d0d0368b48517a2a826679c37ee0ded4fa83e657192d9ae84294e450f7e2f2773d1f13395169582cbf95860891b9fdf8f3240a16aadd1198e884f22b2718219d478e2410fd4bb98ea534a3626201959af099fa55488f5390791bcc7\nB = 1f67066dd06ed4a49cb556dc2fce22814754885a7cf6c13915d974b46b0e6269c0fafd688f45ed2deeb026a7cbb772c080dfd577d21ed2c81e50e7537a70dd550eb94fcdf626500040da88c43dabce13c82a93769a9e0ef66a471661292dfd3b3af07169e2dc909e43678400b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 7087dd62eed6ccffc7e1370cca9444dccc4ff160458941aa9f49dec1a2e9ecce4cf50ac2daf06994c5010cf225cc92238cd60e1aed9edb2befb0fb354ffdde94ef5e8ad0415bc95851d59095a5c4850ec52a74c78eab58309f395d3078dc481feb9d30bcd9f113af7a01611b94d085e32193dec738a64c5fe9bdfbf5dbc98cda\nA = 13596eeefbf06e9ead8d883113d8ae6cc3da8b6fa13ab66681db5a9c083ef9e49d905ec19c39b149cc09452eea0446b29cc92d4e865e6f681827336945282fa6b276ef552363229a976c503b822e6e4a9862d3fb30dd0c3627ccb97a7046a6a679050a39166388a9daad5ec5555dbf\nB = -a4e574363f2e5982cc087b38110d257019962fc166c2d6e6d396220bb308a8a0dc7d90c5cb2ab85faa19b07ed7dc11eae9bf2abde0a5fed279e77a717b43d35e70fec4e18445e37741262d0b0c20dc4375371d87d839d39934f1dc41122e815f3f37352d04d0cf514738b351f02\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 8495eeee238164082240ae1db1e3c1e36fb6621e6b714c9de914f9de8a587d7106b8dc5214f7c60c0ee231d7441e03cc26462e71adf8e29772ac95d0395722d2756f9f64daa8ed41d7ce824a572d7f9fd419112ae823b5b48b8aaae09fe093e9ed05918c4ec88ab159890910837ad0691849b44be95993682b2da2b124de39ec\nA = -403f21e1a7911806747bb78a4f20c4e6572d49c6c4ce071db0c8c91ee985e68a16e60093e4628414b2673d25c9f13c4c43600633af95017e3846512197c9515aaf9953570ce5861620716b3d80eae7de0f033772fba82652484cb3ce7cc189d1fafb14e044e07a88da302547f2e623d8\nB = 689d1b4a968b7c00082ae3a29c8571f826c4630c947a7767fe4a71af43a5de84db9b5baec0980eafd0019e09de1b5c56173ede68c9a6acf260bef3d9a03f4c83a33106c94ca7e1a8615b3553088d1d05a62ddab0f1e5a126df5d960f67e3b92981022e1f0358c7970bb2fd5dce7a7c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 397df584bcd3b2e1ec7ed89de624e9d104bd6812901e38c5740755ce91bd54155c0b624c590ded199590be5d98bd1ad4acee56a62d05d6b5fdd1ade12f7db8e3eb08c4a5996450cc1204be7ba61b768af0efd563ea478033324731e24fedada1ad6e564238c891494e85ded4feb2165fda22f75bf120856034a9206511885fd5\nA = -19cc480d1e07523bac502872a971d78bb26955c5453386f5d51767150e229daad3ab2dc85e0fa0cf6e72389391fe627fd2d9f263f105508642eae5a095ec4d88545dc9d0a2c436907460e1ea7db174673000eb2e0b60d57163ced261bd0f6cd8ce54133cfa10591f1fd27996353110060cf\nB = -39c45512fc7c9620194fb7ad22abea8f6dbff4a137dc4523115ad7e262934143cf1f320892f8c097a400d4099e787ea7041d0d69b6269d191fcdc8ea28340ecacab71058cb39a9c7362c848826b35ab560c27113fe53c497ca452397891c81365b6e7f07f916d47961e50b8c7c5cab38f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 263ab04c98efac12210beb66b13fec7c260c5b1cbc20cd732a511fb3786b917a617d6622847f4eed70f25982ef5d0b0d13848c62dcf447e3a1d491f4c80e69cec03cd318f6f93134d582210bfa81c1790562053a71091333348c6624d4d793fd6ef971d284a4ebf0be0771efad302015abfaf3edba017907f10ea14a46d9fdc4\nA = 7a354753e39b9ad1c0ad6b65575fc7247487f3ea320fa82d1d333ba8dd5d0ff925331994a6961c9c603be5775ef1842159551f0bfb34920b93d90ca60e6abd514650f77ee8ffff2bac0eecd0fe8ea0fffc6ed0285c9f3c3cfaacf338043975457d62f9c8dda8cce1e99f34529435016fe2ed4\nB = 1a4384f9620567c698ced05870b4dae983d8f0df6aec888353f9dd6ac8ad54340c3ba8346bfa47bac38897f3963fce972f6d55f3407ae03f5c7637be1a34e483e50dcc27148b76ef079f117104162beb191d146ec828ad5c5bde5ee1683a031d554c276d837bf1f2f622cd11baabce10212e\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 91cf4d1899e170bf75dda0d51a6481f79eb94c333b876382c9d04681073e949191223926523f6531f0a45765d7f382221eaa080d7bd05a3c19220ebe18802b15d8009714e8e4e9872223049622ca02040eb041707c7e525f698cc", + "361847c66fe3673a72e4d701466bc374f55fa5437216eb59375c0e2c4f7020149d0118ea72a\nA = 12f35c48024e8271e8f9a60a48b5a214bfb6595a837c041b230e6ac87a4c1d4b3f93a2d3a193c750c9857c8627d0f7c454d6c4f224dbf14a865eb83e990b1d9b8bfb729b8d3dedbbe9c95032e4d60676c2baa2aabafa698392590add3b83b521a7a5e7d6f8af207e44ebecd735374acd01ef5822\nB = -8fc18f92c0613d085cf3ee6f586b39b99ecca864bcbe60fffc63c585e5613df68f3534ad46e244916b1f9188507a3692526c9e403b8e93480b0a5a6297f65215f1a5d8e20631a9d559fa1acc15a98c9397761ce18903f393b10444ba51bc92ac44df90d4cf0852da9d75902230c6de6f26dfdb\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9af562a7b61c6c84c91bf979f32ba5d246d2ee2050f07ec2dd5cb3f9496bd37c3922ecb2b5b17085a13e93ab2dac6022077cc18c621cce3a2d2247e5e89de8692a36f596e5dc7a6969a4f3ff0d1580eed380e6550c6218c1938caa2b7ab401ae6f520063c811088504d60a19da3b5018d640ab8d340f35d1337a2ede8bc64bf0\nA = -63bc10b8fbcb391dea305fe61b404d3bebd035514a812d0e1d38daa3d67f9f1bb8f02d2979270cb9147aa51d66ca73d4b5787e472456a13fbe0d568e92b622439d33ad3c357a56dd26806ebda7b3bb592385ca5dba7e5eb5d85eed0a1746441e8d56e22decdbf8f4296e30d222da5af17c427e832b\nB = 57a602bbdefcdd00f42ed1e2cbde2ba858d171804da56b0ac87081424ad1569df1308fee7c9ed349eb496d5409c4c46921f09ff0830bc9f57e920e17df16523598fd90314141955ddb84a1522ff3ebfa812cfeb6670525123476a739f64ebe6a5f1fc805a880f8e5a71b908c483a121b38d05cc2c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = b395c9f264172a3653af6637e72c4c8e564d1ce68032a5d761bf546e0c4b51b33cb026bb4256fa639ae98e54e5ff7d8921ae411497272b53d97c2c44b5b9ecc5aba43dde201f64f1d033056f19ceb0cbd04decb486a1d07ab1c64fd213d7eb6db9cd11efd743462e137f368acc4ca0b49a7f85587bbb5ede4be1616889e2699d\nA = -1e71df5f04001f6468c3a192086bda948aedd19c5da9a5286856f30524238d95b0ae71940f2af123315ab5d2fc61964d3e970d5858b7c1a78d0f2cfd10cba7ba4830a8c19a09b59794ca5d7da32cd8376b5ab06079b51cd9819c0021ea41a9e43aee147befdbb17a92cac7c7767705fdd908bcd291fbb\nB = -394c187308320ba1b14d91d75b8ff993dfd57f9c84e8185f12bf9924e046629ffcd7174879f9925bb643988259cbe9dc9277fa83a25012f91159b012f1964aefddd5a94ac6c2a55a22bbae93085dee079f84cea1d53dc4771901db9a3db5a14eb17c25aaf5377e2beaff6276cbce7cee97a9b8f32737\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6602ce0fb5002eca37e85b60cc871b7b2eed13d38c20a37a6e0886ee4814f3ce2515f8714c67ad81e8c3abf6a00464e6a51b15e55b6c11296ada43cf459e15915026d3260cce8fb796241fc2b0bdd2b65ec04bee3b7ab6626e10597f3b13b43d16c34afd5b43a219917626c88b24c6f8392bde1b2e65a50b7f1a8dc5eb096702\nA = 4855ce75a3d7dbb72a257f6291e9f6ccc158647aeb2f8beb3e8fb32f6f59af1a46617b77440798562d6f58bfe826d3ea7dd28daee8f5162d7d24ae6c24c2deb2669b15898689ca789e2005903f3a94e991e7d3c8f3ae6181029d959bb15e71d7ba94d2dfd3ddd10f6fc49a65798b5f6ffd64682c78b5d91\nB = 15b3e9992aa3f042fd58ff97a8c04aaebf46b75fdc38caa9224394a1805cc26e4311bfb498d5a04d19396e98d11c8810620979362df82b23a115fc1711b57c7a56b8408e2682a2edca36cf9311addfedd2d0889a78cc1ab170d1379245de6f1f6f4db815fea9130463dfe5283f195e6e81486a1d39634aa\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6a81ccd82f00d829bac186fb38b85097d52afa3ca83a026856bb83f94d6af6f6c6f3141d433f8fc159d11397df8d2f44c769f255cf8148249d8e9fc4f59ec3bc8e804d7d5189e71e20b8d0e540b59a2854ddd7feeebda5a95f17605e8bd5f311a63cc2e4ce23a51229d0a49ca04982c1bff79c201de6cc6150b690c98106a39c\nA = 1f1589c9b5ad9d878631cb03c23ea7e94680220856285668838452a63b726e01709588b38e578da8a4845aa5cc2e4723beafa4f81a1a2e463f67d9a3e432de7064ba8bfcb943cd9efb0e5a136649cdcf5e85a667917075804991b997f318752304f4946d69abf161625ed0c03bf9abeb4ef28034f818e2a643\nB = -909dc7fcbd27d0bf7d6a3d0e2937ce725b5cca0acf78c103d633206cb431e2e2c785aea4bfe2042df32417143de76b71d21587112f36d067f878e556b94ef63d59a07d19647593efdba7f3f5324d64c55f93a283a0dafe080167f6576053f9beb326994f4a1d53e18e3f3e770e69450bb70f276d128e48ecc\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 69139f2e10726f83300505d15dcbad5b5f284d1c06789181683b7b8caf35dff063dfa4968c35facf32a3628dcfc19b3fa4c30ba0e030b06773832a2631529fe0c0c402e05a0c4e9446a8b6c22754c70ef540f90d903d83a2e3592169ce6b5edf939ac5ff25b8bd48aa2425321602a9571661a1109e275a3b3039ff0c2f430b18\nA = -5d02cf3969bff8789850ac898c00fcb3ff1fc49a22cb243ad18703bb8fae25f83502bcdd885417fe46e8237fd0b444712c4fdb8f4972dbf9278a83eb305efc7a8210ce55167c069d1c4136a9b66d0c4dfadbf036c079d12aa082fbb42bfb0098006136a61f3da43aba3d3bcf2f5ac2d7884caddd0cfc28681d33\nB = 50b369234d993721288662d83298d99b9052a0a66336a5a31b76dfb20ec2b5be3aa76f78b2c17c63d78402a15aacb585be5c8d2e7083145e316e71e111fd34f5c79363c4591c247b1a94b20ee042d840c42a3001d6c8dc7cc1e1348e0e3ea8c6551f9d24af2dc2d0c38a54ef065ff048b148ce4f11ed2b549c50\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 87de406a6c957e85c759f8ff684023a0f98e93ad4ffcbc6fb0038c7a7ceed2486f15f36555d286338aab3283aef677118f7cc3f88a7ff0ac9fed31da6786ce895c3c08d3edb652bbc9ac2b44c4cd24ad281ca3a8e8e6e4d730f4f0c25487cfc1b2afe222934eca8b1e1572780dcc149422a88eeb1bf31065c929685a0a97ac3a\nA = -1878e0497aa1c2942a2e6956957c876dac73c4bdbf42bc92498f29a006bc92f788c24a4624b87324a7c8aedc6b2c0c8a1a442aa91557aed9bf2c02b6664979e8a9a21330dd839f4ba8f84515fa6f7db9287f7c20f31732b98fc09ee7796dc524870dc35851814bc57e1a8ac49d8935fea04bb08b8760df33a98149b\nB = -32f4e94bd073cf3f70810d9af7a873996a0510109bc6fdebb855f27dcd012c59507491152d30849d75f95dd868992c6fbbf29b1d899cfd401e9e7f4e0436732cb4cc9e6a6d6b0cb63fb0bee21e422b7f7b7b14dc5d2b6d10447fc4add390fd3c8e7b06f1d9b181adfa8d04459ed051bbdc9666623b00e3871e597be\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = b456ccf9d066dcf4247a21c7f3820e324ac9cf004cecf8dd1f6c3aa40c2a33e24c423e97190fc71bb9fec21d36c5a687065a7877237a2a05e64cabfb3b20bfff0b1f5ef2e9adb7edcd7140d1047b0919a2c770579ab44a08e5ad9f63a06f90ec7d5885b91de5e524b2e187937609b4b81d40a0b33e31a48d7b9868add75286a6\nA = 6c484e3c6b530dcd3644b19fee66c41c7c2c1dbcde574d87ee13cabef9dccbe5b41e25c32c6a56df23f2e87176afd28249e5fcb918723707fca94d7e2c9623a3493d395db802a1b49d550f52c29666f785652fe81afcab00a60a5b50cbf523cd13dfa06d5a5b0809c68ff7264a2cb35b8d52284172c62ee658e8417e6\nB = 1b4fc753d0530bd07094bae09a02b1ea684fb4e8519086b1e2ed9d59af011f61d1b94ffca6f354a5b428417b328bb1e8af3f6c7ac9121dae58de9f1dcbaa9c73a357f408b870e62b0c7db1a72c4c440f2e6fe90b199b9dab29fc23927190d3f2bf8a7ee926a152e64474283695614ad696c85ea547f5f51d02d1b823e3\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5e7c63276f350f04816a6ed9f98507a78314f1d99081fcd906affa3b8395fb58d029ec657af82e77ef45611bc988095bba9c26f25f8fd404432fecd02398e69635f3315a824d6a98b33eaf6a91f12957a5e80cb48d5b086c795eb3b1e04da5432a7e8be3d683addc586a44b62", + "43ffbb7a979bf9664cc7ec41e75f267d58a7127\nA = 18efe267d4c62576294f4ba44c67a058cdc0bb44c48f4035682b2d6b8a63106081af43d99098ce133f8d7f9cd04d4dd7414f704e32871d43d6e5d73fa9f447873168b43b32d6ad19378d74a967f92ec7629a690d29a62a5a6e734e9ccf5b84857a00d97b9db846b057004b03d88b827dde717fc30e6a5246c752d65dd625\nB = -ebaa580d3eef5361547c692e107439c8391ac0a2d1cec0cd275d0be69133eba8a94bd186ff9a129af3f5a015d5ebd30215643554d7064635dc11ec7a8ed2200fd637b099e534237f0495d2b629abd4c8f84aa1d925d53e98490d02f9fe51bdda08b043f67f0903c0195fcb886c04397d3612e4501ab8c7b7db69f781e169\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 76fcb39f94dd2756e8266c025cebe8e801524a757b976e35ed45e3da3db720061cee9037fdb34776c704ad2059ad8920e400bfbf10eca9bb157eca7750cc31fda06473bd22d4def80189c47ba32e2824c721425f225563df2a2ea1edd090e01c0bf980677db5a5dcad37d21a68e2832d1012586f506480e929b2fd9bb4aaddf0\nA = -75f903ed9bb0b6db8e3be16e797258f6c18f6cb7b16f835f04e3045f7e4974d7a86a63f2ec351c88fadc0635b6dc83a797cdcb5cce1a1674f89e44190991e0930575b19e2aa1512bbbf2ef6f8c3e707b17516756fadb635d8c6bf9caddeba14834b5950a4d1e98bca79a4d15e5fa5fa3c1727d7a49b33d481d32fb14ae4164\nB = 4ccc582c8460f7def2d26167b68788a681c41bdf6dc805dca83127a18bff6f5ebea6db75cd959beb859637b200ccb5c7644d571f436e46a357d027edc9769da226278f7ab947963f7caed1e7e70e572980e960e9764a40c6db67bb526694b084976142471270b2331da563a10427cbbb38e76203d7da5d67487eff701d75188\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5adef30c67aefea4da3884b8a1d0ce6724492bc76b477f1053621e7d19f3cac15448e9401d34e05ac4b508b9d1db9a8d323cf43722e0af6e3c3b6d463c6007449c3bc3236d156cdf988dfc308a1b4911554ecace52938a7b10f463d14f917ec3d9fddcf6d33081745009c59b58aa22bcd7dd8c3bbd489997d4e0bff5473ab9d5\nA = -174e8e057a1d66e22eff88de26f43fde1c8efe5611f6ba4f318f027f5a5818df02ec3f014dfedcdfc8c143c5005c3c5098d409710967c93474f5854c1113fe4030e6682bd56d389ca8b9a4587b8b9262d146bc92fcd81d75c3bfa4281898f394f45d5dd11cd4c7344ee7a933ee346bdaeb6f5188967c388b919a0ce6730c0bbdb\nB = -22702bcc4f9d5bc6f803af6af8072780ff7de7a346d6b9293ca751d6ee3a81493fa86738c44cf2b7be4bf14a55a4f8179c35c09dcb1485f4c08ec5e9f9b1efa91f4b5f15a31a46e1ed71cd934ba6bd271bb22bb5703aa468d297f360ecbb48f9fd6c572683e83ebc3d432203347dc62e19fa06f93e087283347950829d4256bf5f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5c2f67b1607776c10fe2c30b112e541c4d8229f5f99f615fa02cf715d3f20556a28eff5c233c58994e9c6c1fcc37b3416b0875b9a62fa5a09a4b8f9e216487203b387ff97fad1f39f674ab19c5e34cb2f162e6b0b0b0084f0618e64928423b73b189c744e3de9fa50d66f45975f68b14866cc16c8c6c722a54420adf027880aa\nA = 67056e93b69e8a7b789f1f8b835d9c6ecb7762f844d656b26df9844a60bfbe0d55684f61debeed31a24ef4246485e8a1d43d49eaf97ed9e7b9f2d2916a8d85b8c9e8ad5575cf5a3fea42392e5d1dfb23f7ad41a7b56a4f21e2828aab38a602d560c99783a4f807120292ceae366b1fbfb4be8e5d4561bc8944e7f17ebbcb0fb6296\nB = 1f874f244ed6cff9f910ba9a58db0dc0a7435e8d99ba6412e976b8f64d4106d3c5c57ba079384fced1c261aaa538e131734451fe84fd3cc5cc8b3ab46b2031f888d95084cd3a35a61092672a9118eee4ed1a0df0409e3613b3ef45a8b16b71ec892755dc3f83c5492b67fb9a143ee6102d053078f4875636b20b536d5cf851768cf73\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 7850019c6712f18eab877faa8489daba23cf34b512a3193852508185b13cd5a2e9f503fe8d61b74b5d3930021a5b8c38322aae9b9b1b4814fa4c2c5bc409b58f11fc8fd7854b17baa94a6bff5f234832f9468d90d148fa2bfed774ac03f2dab6a506a70db4ce363f932adcae202f04fdcae968f632dd674416c23d4e21345ef2\nA = 1e378a0f27e6259763890d29e112e3d8d2bdeb9994c49fb67ab680b6e71a52fa0a7db886d3baf52f36d943b5430ae8bcd82e229f4197239c35678eed254c5816722b995e9c311be942f8124e2f80c1e59658433a57f346adfcdb83202e55457308161d2f928b60efc39538a6469f90f1a868cf6077568c8241623896ddc2705cf04e4f\nB = -f4ee37e39d4cadb692bab5483ceaf0258b068f2c0354c540438803780c983469ea28324ce7e209c3bf55b91f0a2f4544bf318585e4514333eafb9b8c2f02170c620e9b5280a828ce1d8dfc64ae9c28577e15071825a85a59656c5b47d9a382af6b78a5b3dab1078dd647e0b473174b8415d401543d30a4018cc3eddbfa546d0fad9cbb2\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 4c8f8b671443a3af5ef5749885ce5de8e2afeadef9051bc49c0d7e72922d049b1accdb79d82288e472b07578e8b6d2176d6cbdd7f0caab593dc0fd9224a94920235410501fddd6001b62a7f7d8eceaa7a8e4c0de52029fae68656e8120972b5cc1c2e909c2742e836f2fecfa51e12e4f8a2ec7e69eab061c81785374ac607fbe\nA = -5769eae759dd6bf94468eae94189d3396886d4569b0ce264c22d39b623be3abb01bd5008b9fc86701a3373f7764118becadcc69481cbb134c20f669cefeb376dfc489dd4ee91cb333d06afa391dd322abe2b3b715d11ee372666473a473e29dd90fcc97e939049b455be52b3f288db306999019c1177ab5820d94859a9d2f050b7ee1d4a\nB = 44adcaf1e2afbfddae19b23cfc0f0ba1f940d32945d0b541db23f3a0a9d06fb1f67ade9a8e620bd96f4005ced99430c7a55eb7e93a701c829fd5b9e55dbb4d3833afbcaa0d9c946916b1a86af4a6393b1155c6439b8b82260e09ccf0ce5d1c4856f4d524983e4b0fa123267694a1c6118beb8be26113a02721a02d7b0ccb01ec6e9c0f9e19\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 51e25767b8d4d7b2b0c2652d9ca6bfdbfea06acba543b1bc8d3d25b2fe5f2998febe1a6e742abc3f482b4267854c2223a5918a9b5c84e0864278283bcb5bace0c046db1d0240443404fb62d70ebff3ccc655e5f5977958df4c878d9859a69731744f3d33978ac31551487270bb4fb56ccbf59402ef9fee42cbc329420180de08\nA = -1966812979042198f70b3f1238c93ac5c6e5749f1108c2bba869b1dac7680f910e56318c9b59be9212e713a348767ba6e75917fb599e929ea2144880d18d4fbda4f4663c7abb49b02245169f385e09098a4e01b56dadfca8c803acb7cc244f3c98bc17440ab2afce318476b80e1d0b4ed9a8d6f2a0be64633f8faad5eb48de2681a38a633ec\nB = -2e4f5eb92fc34c753c61dcc826abab6fc4f427c6ac7e73ffdf65b1037464b2a9a0b0290e713d81ab57c0e1dc30e76fdf96046fe10a34cc4511398319ee34bcaf73763a9042fcacf59a100c43d3333ffb3743048e8df0dc61fd0da3f935fadf882ffdfa9f0f42980c1af6edfdf161c4b16087e2b14277f655abe54582de79c51193e13169b55e6\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 33539b5f38a9943b15801d449adabe02da6e21651d96acd9aa40e866bf65015fa40178399254e8af6bb082d021e2a05da0f45b699d193b70112e114f0d25287476dc0c733c5cf9df57667ad0d3ffc4ea2f85b43cd10459cdca9465b0974e578c00a6e275e0b97ef2a4c9886aab7b5947b78a88f84a3f1d8c5f26bd07bcc59886\nA = 531b891fe9e8db322cec59a2115574c7a304c423e6b11516906b840542b2c608785e2c18033262ab9cf68f63edb40ad4f073ce8841db602cf8fae0a6771d741c6392976c9b333ecfcd0c8e9997da40616ae2a9e0c6be93fdc7af0dc0668ded1e42a9f729c70f74500ee76a91d3d993c075c2f645b35792a20edf17c157459e35c0a48da6c4c6f\nB = 1a6fdbfed1054a0c5758f92f72db7e5737b0740c4d8c3ae4713366ef6709b21eaecb6b74c92541a9a0c99ae18ac6ef7de79d4c84ce39ad59cea9c203734a99bbb895916275e8778cfcf7fbb7b7d081a677769e4ab96bc7bcf23303100e629fa8e07f5b8fc2e39c7b5724c72907eaad09d3088783b3118e57c9c8ad1799b43a13f73864c5602c478a\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b92982304", + "9d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2eab6018361f557ab06725ad90f6886d4b468ab1a193f8fdcfb4ad15fff781c8681329a27aeb5f03a81d7c404b8017b12fe23165e941ea767c733513a07e921aedf20596763f6f977316e37bed70f6a617e5c2757c229c59b3d7b1fe8755b5f65f7f407f13634aca7c8a267e661ae2f77fc5a95f56cd6c8458119df587478b1b\nA = 1cc779145b2b7bf9ef4c9692845e162329940f96eb43e04db8728bfe736698082aae6b6a1b3c32867c293b08547a0941cf4059d2d567840ab6ea526e3724ad59e715a3782ca656cbb739dfdf0c113a18f0dd62423d4edb60057fcaedbb852178d38f1b5a232842b4fc645cbfd97a8cac0b094b870064302dcdf23df2c9e9f736d93409cbb8ce9ab3\nB = -cbba16086b51bd83d3460e51cf193ebc79b826e4f30978274eac3b2dcb04e9d7b56a1449b7cb128bbfeff5c4720bae45271fcc64085d3ee501f0f21fe73cb7db5f275d88be55c339f9180ea21a8cf3755a875331931b75d23f57c2030c89c6f9c1ead431cb4dbd4480564c83f8470610e5673c7eb6c0fe7351ffd7ee460df5db7872c67041aff0227f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 96fd93535728b961b4167be8b304e570cc34e787c12a9a5d76e099b336ed6b837cfc246c5bceb04b0f4744c5da7071fc01d70e342509473e5bd7c60d6046c9b4f21c5ee71c4e678447f837db3a7694fc3936ca733efdb7d387f0f6e263b3ac0b89054a826da9716691c9d580ad38d701d08ca090b6c59be466e1b9833e75d820\nA = -6791fd686f46c3773fc8d7f4753d178a93f6fa4941f4305d9689c2a305bc67840bbef80ff05c7bc6de3a595f73846609327d28540cd705f5aa94a3ae5915ef55304c37c4c43a4b46906889331ee16585629bb303673d439de9c0236f708fd19a977e6e1032e0576a921853f7dd328979ad1f1aa945905dae93a82b3af9451a541f544c18ed2546b66e\nB = 6ae062b39c77bebc2fef05743e6d35e14a31c6fe1fdc42d8de2db94ce70a6d60d66263c7414b1081ef2fa6ab511b361b8baa9c71ec628dba5bfd772c440baefc2fbed68d40897878232d9715c4b7e7c9bdd41cfe7b6986d825f68be8cc16d04afb0cf593f3028f3dcd91bc94923f3d7211aa5f0f12d3270e8df8bc191808f0e266c4fce2af97ac7ce06b0\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 949ea5f645ffe5d0d03359d51a663c7dd6e6013812a47be309575e036503126f48677c68c4ef6e7b3f72d76657fa282ad5881263e649b5297da82e24298300d032af3f5e8309ac7eb597b16e257a6f7af3476a264415aa7783433e83be57ffb3fdb404a9ddc3527d6a9c297f8cb7b6674961b3af837ebb65f218147a46c39cba\nA = -10f59ba073126d92a201529a5374500612bc59a9e66322c6706b422d35a4f82d97e668b268f5527b4641c6099c80bcea504234f3c1e3fd29eba0f161da97c50aea542becba499f29d4ba5571873d4dd9eb3f48cb26fa6c929a704fe8e49791b2ca3293c2428d9cb453263935c9c90a4a2b39d23a0baa12535845f907d42b729033a0a1e74d18da30a88ed\nB = -34fdf9ae6760d4f434d09ce2a7760ca2dda14bc256015809745524dc49d841b07102aefe5a1d0182e3e09d4d45b415e46f653185742b9b8ea6960160752080e5c9577a12182ccf1a293407b534ea8ddd33ad16cd19ba537d8db5b542f86a2a292423d452bf18d82361240a7efa831518184572c5a8b73b108a81d5036b3b530d98bd47c7fb2123418f12e05e\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9ab739ddae55a0d71b39974628d4601122ba6c5035c3ad0439691317f23dc33c0014f3e870a105e4dc1432ec79693bac658433b21cfc218ed411e003990b94ebfa87767f3614ec19f5bc30704adcaf85a9d3d15ea764c8f0bbd52ff388659637746d39859398c79016ace8c6f97d3a5616711a235b85f334fb889b9280ccbea1\nA = 76b15a0aa0f59ec804a5e9a627e1fed524320b29120b6789f8e71b1ac4e00a9a8c826919035b84f87d291e2f35460bee181342136dd9eaeb99ed00c6328b8e44c49ede3921d6275f6e7f03de179fb2374ae2fa6c58852fbb2649e214691daef945ead6c8bd5a53ad2b130e9eab6ad046ddd6b80874ca6515322bc171ee32749333669de0d9c883058423579\nB = 1fe2171056ed4585a143b6b2bb5f44047664f64d710dfc05c18be5840ef9426ef05b6e92e4ecb5544ee4622e9030153dd9827f2f01ef38e62b88ecd6c46b4457d16644ef6d863c226acfd6928a40de614a5853137124fe69127a7f05463eaa49bc742d8f7be300d06b302dfb0ba86801119bcdc01b516afa360aa8b22b7c6c1839cff859ca1bf26e3f7e030512d\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5631048ffdb2767aa04d59d8a5750016b38b983a2d53743ba4de5d93bcfc8ec30183a84bb1e290ef9c72c7ad357728acecfc613a6f9b3d712456d545ed54a337930937f4589fe41e66ee930db3dc10a4fe41481008c69eced65b9d1c46b8574c5ac8f7d94025d8fff00ced17a5e17508527681bf94c2dedd51502a2c4652538c\nA = 1aca12b1933f25ea081e12ff4a4f6f9ce379f96d976da2ff7b8eb8ad791fabe31c1148fdec22dfd67828e540c955a1e13f40c5b125e1c7e6bd839bfa84e5bfb58bfed76058c6db77af7a34ffd25fabd60e19f65e1faeeea6371d7785f2e5bddc8650a7492e06691d61f997483661eeff54a30656f1daacf31182486bc40647975151fc05d2f64b50e632f5d5c4\nB = -88ed894287043e7e5cd2eda3c1e5c97f85809f7a246b0c20891fa9a024f3aba4ec1f3d112580fe6ba6b0bdcaa1325ac7ec9508aa88c187af08e4f37631eb6cc97e4481b18f747ce6d35ff355e425a4833834ffb8d34a818bdb015fb818ac9f58feb87020234243aff912da5590ea3f6cba74f1a9fc3ffa2b4aeea25479c55a3b572621e75d86d8c8f6ee4f587e0f5\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6ce341aa4a571cd5bc110dd436acaa09f409661967de0bd096c77c60db58b2b0ec95cda50acd7fa20ea4266b2c579eeb6ac214a75d40abbb70845db74c4d6c93f8c545add269d45fb15d985e7e630d0425565d06dad4a3ff9835411e51fdd9780c24f466dbf29244cd1b8c3445af181d0928db399bbc8632f7ebcb9d48c0b754\nA = -52c53999b02a92d6254557203cb31a21dcb896495d1f29f3277d19129ee43e521ab9d5a297204a844a9537d63b74686eceba72ea2e7b98ee8895513395cf7c44c99348f5c4eb657874a8115f0027d6a416b8a04a1ec0e6809b7701ee7d41e99996e307bee9c295ab3df1faf674e0067d0ab3bec4da998580203e33760870ae472a3045bbd66e352b8f4d284efc00\nB = 4329d110504caeb71ce0453b0706ff675f646e70a6bd9575791a38f672eff226f4958f8b1fe4123c0001d8f8595d8030d0e9798232942725a9b9d654ecf50546adfba7103fed796b455ffbb4c153e70f941bef7953c8a210d6f2f4ddf5d9a79d9938503ae8f24d69d5d7df1c988630ed960e12dd877bb80a1ab0bcf6db67e0c0578fc0c40408f72b19052534da8d31ed\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 4b9fc1e0eb4be199427c48bbe1b53948d0135bc1965b8aa5421a4ec704b13cf934c650405ba02ad611b0f29d46d82d4a1fc5a84651a29364524e37be2fc7001cbd3c792aa477802999841ff19620cf66dd2453c9b05aac349b9094d43b40e358f32805d87cea3cfa98e05240ff95ec57d88e0a12917628ebd34946eb1ad6799a\nA = -15a223b691d8b3696306b0ccdb52c1d62c7c2d1ac71e5f07cd8fba960417b42fb5ebed5eb9469be67f231b5254bb0fcfadf5ac5d2906769e8bf8292f0442986cabd88805a162c0c1f60f9ff0bcc2029ce33452d05f754375c0bd147fba745bf8a0008792d4f90d0e0f2cf391f2d7865705544f4a220ded44732321473c0ae7870394d4e625df11bd0923340cb70b995\nB = -340e5ccd644849d982bdd455ddb3b9a23ca14e168bb87256bcc370ffb6b7fe78fd062b3bcc1ad3c8c3b8cb549f2baaf1b7f0f6522aba02fd35b651f7de52b3aa2e0e40352bfd6ed0f84a2bbc3b3a396dc8512ca1db01cc69611925f1037794c82a418f10e0d994f458d1f19051e8bea32b90ce744d46718f42e711c094ad0a1ee96c88920188078f1b044ccf307e4cad7de\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 31c090e5160faff9a136a7a482b42a43ae3c7d00c215cbdad28804be0e7b12b0b3af820c1350b1622a22c8875f24d48ff16231c826d1a946c66f70aef92d4e6582e3ce9213d907267251ac74fa3cca9f1c8fd53fe9898aec19936a2b797fc345d68f0791cc740199be39c05053d5591d874b415e62653b04a3f41e263d00f230\nA = 5419e87e50b28b6d24927934b541d8de548a8f4ec7e9b00aadb6d23f2d33406177d3fc72d29ad2c2e141ab2916adfd30ec4791c626af61d8d192276d632aaf3b54e2ffe83b44f", + "6f1ac441e6823b6b58cc08fd7a0af945a02eabb5aebb2c7ff0622a17b38077cd0cba906ce23e71ac7f4da40ef6066565b4cb3a62ebda28f3629eaa251dbd9979b123a5447ea20331723e\nB = 184782ba4daf429cbd13ac13fe93fe5833f09915cbbc707feca3293e505ce9cf0b4b12ffc8b178e0a4617f809be53d4895a4182e7a8a65043361e654befe8b01429ba4b7420193d1d7d90930ee19cee0316f33a5795335f5fa517e1ffbc99b95101b0f936353afd3bcfec34851ebff1ef02fea991a01b587d28640c935ec91496d1aa3ab8d38a6ac75b3a4198ed27b9019bb3e\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5eb9f3ca660de481968a3c7321281f22fb9273b16fc10d8eff1fe34842364dabcfaee4993c1c8ddb7c8d6e509a8d2afc005075d5fd3c4471f0622753c7797aea900e785ceef905e2606f64f34e47239c40b74f07e2ca70bd5a18cb0a88780489f3e98232221f65ac9c5ce703a256b7b75eb1dd38778d8bc05a37ac9ad8d36b35\nA = 1c73d8e3d5db127a81477a5c4c6d61ac62af446981773ca15a9a01fd5175a2826a8763f91d68df28ee606e8ffc203305875a238d2095345556f12f3b5e10c5bb6ce3f90342ac74b9ac057195c863c4b9d28ca1d958a98649c7f8897bc6abbc39becae963f61b33bab4fd20d9d0e5464f21c2cdf06d00f597dfde45dc5919f5124f26888b12d72cbd2f57de3f2de7c014f891\nB = -e406fb60e35f0abdd313b8431f4cc89fbb034daf71fae0cc727e9a93cdfde53566fc74e48f4cc2111fad158c63293bca0b21b98416381b81d2443d0e91647679481cd6b6869b37112d3b6e575eea7fbb5bdea422558d817b49ac36a829926553202cf9dcef09423c085d26176a89be741ae20a434ea461def090dbffaf2e2ef97bbd4ec779041ed69ec07d125c7b85a2d215bb0f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = acf9d363fc9b76ecf7e61c33270031340e66595e559dd1c9dd4d2243819b660183521a4124558fd4b216dcf5c52c4127fe517c48cef428b9ee0f1bebabab487c968a80b9815e82c12e807c096974ea3893a8d5597f745365c352a6bc6ce92479176092f02907538c5e784bf26dcde7672338f402753b08de8aa21b9480df6955\nA = -7c03ba6e3939ebbeabd35cca277eecaec31f326ab75f1a29e05af50c4e62e0175d4d6a57acab87cf1fa3a51791e9a2b2d4d5db570ec3941263902b0c74544c323c106557cd5139d2a25f3c3ef81ca009d4e3c16f1abf6e2b5196df1b30def46d61eccdcb3741a6dfc8e8c5e6db68ec29c82b0adf6e35ce7aacef8da806b3b58bfa489d319869b20768f8eebb604a9624d048f9\nB = 4e021959da96ebeaad17f9896ed53010d80ed3fd4c3a826a266e82b80ad81b3032303e7c0e58034a652b8aac00c08d42a530039de60d74ad349438f5ecca1256342ded6f30e3bd2aad5bf2b49124cb27f45f697e157550dbbb37f5aef0f04839aaf1ba43bf1e77a1529818d0fa91d940904eda6b748e5c86cd1b37592542c43b7b4afe2b8926fef6dc01784fa431d43900edef27f8b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 24124c69aaabec7a7b4e7a82245f6cb14b199852a8b314a7b8d9049cb66096d5ac93ac75eb58a2004de8b0fc8375638c0878fb6a45be8bfbcc292e3571df1bb8d6e346d5595fa395fef983a365e4e868154fb3e337d47771419e7f1dd5e4220900c564d7cbe8e7792ab288f99d265aeb296c5ebfdaf08b88d9b30ac660cc3ff8\nA = -167c959417e9566c93e7e05d2a410f4850e3a313e516ec958c3d2fbdecbf58072d05691c68981e176a867d7467091dfeca11f695f750c8c44ebc4d08e39e679d96c4791ceb1ea3b89fa3ce26f7ef214c5368c03ba694f7ae592bcd8ae53a66cb3eb1e0cd3c105faae6eb7e7a8fbc88248be722406f2d35e46c751b5ceabd992091eeba15191ccf6dd61a7ee0c624d43b188c42b6a\nB = -343940f3b2a5f73a51d6f609e8af306f44ce7b5c2e79edf6f4dfc07866dc5c4b2e0ba48099b5503af87762a44ae451d166f8914ba25b3cc41a766583bf73d27e40784064582fd9fe952fc00e9aa2d4e4f1ef35818978e725e69c1bcf267fda4d635d1d292d54d3ad10bae9763dc5d7f7226f371184465695f2d384d749fe07967a1bb64df22f294ed88b13600c7068d881f713cb8e3ce6\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 50cac148215963e58cf6d2ebc36fa518c63a0ab8fb136ab84c9657fee459043ee9f42aafec89e8ba5fd1cc5c4495a41e80590ce197e12c087ff7e6ea88ed798735f55a1634562b82f8514488ada526e5dc10700058980885000e266cad55948d1e080f6343f84b12a3698d9ad5427fad4017d931df77ed2e45e2fb8380b7fa39\nA = 6a9833d768a22ea46aab1a1619f30283a1ec254a2de5652981d73146aabe31041ed04d271c6f2e5e2d090cd615518a06563a94ee2b12cf9f142de3f15599998a712974d0ce9b122a2aa65bf8750f54c6324f12e321a888154330f0f9e1e5b7999acd70d4e6da95c2df1da2d19544b7abd2bd3041e3228c7cdba44f7d1cbfbcf968f8fe87fab523eede0485efaf5cc9e56095cec8983\nB = 11e782e2b3f469b1e3d14ccd1b8301ffcde7e371f6e9afc99af5809110c6d70e1cca5c0bbfeb95fc3ef8352581c11ba75c0f8c445ce2aea903769a24289581c95ae5ebd9553fee61a30d155bf6011278807833eb2ce7ee2a98fececa23fabaaa259409e88e3c4f4eb1e04176d44878ad3f6961e0615ade2fe86b6eb02adeaa7c9019d63231a28f84b7dcc8bb0e71e2a717db09301e1dca20f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 7cd49d72bcf5ff4fa2c686f21e1f0146c4f24b9ad2e900dca1c0a5d2fac5047509064e65ac582946b251a3f04850c9abd8b80c92af0fb11ac13debdae8b94927f1de0e4bb217e78f5d04897c6a0762667d3d883cb754dc610442c9dbd44228a7ae4f14fca145550d813655befe3bfeb52f1c76f989ea8a1dd9c10fbc7e9d6574\nA = 109fe33568598972063279b71ba0efdc2e03f770cdec331428fb8ca084c9b20d0fdb5cf9ad7ce90c8cb8f0fef10d219d7dfcc6b4599440db8cff9971da7852880bf004266886eced8763b3569720df3a1fb0dde2717ce0183f2250034871146628430f206c12f5fd87574c206b203d90c0f2c705cad3484c73da8bf4e9f7e1bd433a6f7fd27df63079d30c490aed7161bc594eefad4bc0\nB = -b95da952cabdebe0194b7fba519768e1b56149353cd12023b97397b59e0d7f4dd1d27b65b833948f58e66d3f6928cc3140cced835dbd612cc82a7e9fae1621986f71ddb6707ad57926b03e87e165d30fb145795a70627975bbf9d9ac9bce07492de5227c666663cc28b3e70b19dbaba7f16849535ce5fd61e91cd2875e0a534a10c60d21f919d566a3469d108a35ec3f023210efd5d318c7210\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 98a89cb3c9602fe503c32c44609bd4487b6c8323737b3376dafacc3eff96efcce7a31f1b61ee6799dc9561e77ac058fe5195cc013e72a2864f7e492d9f35244b321d46270a582f6f14f15fa8203d392e81b183a1d64d48b51d70e38d49c93869ffb9d7509f15ccde547d2d9c4dccd50eba49190b6e831a9f4f9000a95dc83f3c\nA = -67d7fc8f1766c40bd476cdb65d4dd161c3d4c2c5860a0c559f0e87ada213c9ed33308c36bb1c7d615fa69ec53656bbae6b57181a0134af23ea2a75f8fed3290a2f483392a3745fb57adf2121738c84f6d34325121a702c8ccac0090ea27fe9a5ebb6ba9d4f397e4a7e3151850b3d7d25643398bd3e4c1da081471389799245d986cab825a2e6ca72b38ff978a2753c835299ab4597bc65fc\nB = 676ddc4d18960817ff8fd2adffaa68c87d234d62d445d6ba3847ded849356d929d9e4ff01f517d7b1c0778bf90f475923517d855956f17ece1e032e2fd474d2133d6b8a591995454d8b587cb4f6fdd0fa29305f146d340cbe6b6efd28a926c73735621be0c5decb792083b3f063a43dd9f635e03f78c1bb56389a5cc993c8f36134d755a324d4fccc2ac3bafa270df67db0a4ee6ea4497aa33b5a8\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 76c31404854006a7d55554762094df6e11e0393f5b0451d85de2e5b104432df72023a35f44da10dbde01cebf77b8f9d3ad582373c5d32232564729af0d03c5450e439045d96a2f0a38871c922af2bd38c545d219adce0ec80fccd121d6a733bac09253604a8a0b1ecf0f24e44b818ab9e9974181cef10e9eb17684c57d72257c\nA = -134e8784878a8f3cf49ccb952075f9f9bcd24a20f8883955f262867045c11a9c566abee00638927e5de924872fb98f6376e321ebf3f567db6cfeede62e04f839617d78b7c9d3487b60a0d3897b3fa49b14c12511d04854bde4a9dbe5f31424a3d05cb75d23b46f6c0819536020880afa5a2c173f6881754b56f82a2864c99c820156f96b5cc4665d603597331d98d90a52f4a30c6215ee5eaa2\nB = -3c5c0d35de5fb21c84d2db228829f43b31132b582556b92b495f59df5", + "02a6d00584bb5bacd9b8c1a8c7eab91db0ea24b40f07e62a712842d5c2e1d208a6412a068cd5c6394d715260b67fbc03e3ae7eb4862f74f4d7484f747774fff03830c65fe022d579adb6737f6dfe297db750e6a58d1004e7e2716838befc2ea97179ecd53b7f36e3540e1c3a0f3e044bfe2d0efa9b89d2d308cbd0bd88ab3706\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 5b704b3181e5d0494937b4d6aa8172eea82919fd1d884493197a6a85ff047a7bcd5dcf072bdcef0287be20d4ac49918d1df550d184f86d7220f0a84fc4da3ad05e131c443fb529df01fec9fe4fa6fa2f36e791f9e16b4092759016d2f9b1ae7c3d071c57edf26386aaead767a3109c12a5004c7b9fa595e6d592daaa2dd1df04\nA = 48a0ccd2d14e14e2aa862d306501efe5de239e8ef36ff6251c861a0aee9f739411f402491bd99aebacdc26c4f30306f9137ffe4579c2f13efa81b979ddfffcd23675ac6307c0aa3ba8ee77a2e3a3c8e241bd2ade6484e6ead32ce8d752fb3584d14688f223758c5cb8705cea9c56136b219d87f9904bb56be2ea1c9a035df33455206e6b7972cba32ca4c3db41991117d88da3521780fe65c4023\nB = 160120a35ae3edac3edbede9ff1c6f317d95481227d87785b7ee46cfb80fac9973e418244884caca3211a3f6cd3bb419cf70fbc22d82ba5ab98ad80e1f6c2cda753aaf7be78613ef25577107a47ad1ee3c3645db85c4d29bd77900e99e1f439cb23c6c68662c05322f94feffcd9e37d8665cde984387093a043447de590e7874e6acfa37ed302040df4d5c3dcdf9fed91b3d17ab5c141d4494d0f301b508\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 448c3a64958b82ccaaed3c74706ce0a48c5e059c3610cc03a6b5a03a7de5d4f1d1e4b08a31478fa8edd58401f0171697f0662146ce2b371e335d695f9e4a671255f29fc0b9b7d1b2eca4cc7f8357aa0920b5942e31bcfae84e909828fbe5d02251ddf10dbe4c15351f675e96e2eae6d044da1f0858ce8ba9b7aa146850b85d93\nA = 1b2a52aefe44170376df29d17ae2dc1501c9c296f72f271c21f53db71247e72c3eb2b780190c45343bcc8f548507559ced3bd4a6fb13f9174dbddf965b9c4a56c3d88727736d78be9db2268cd02382e50c6fa28ddaf8eab9f44ad45d5882a5100b3027c150a7f3bb36f29d24a76e40f3820ba116d645800459f06c20679321cf5be72450879462f0eac99ab6ff8d26b464cd0e6d78621c9263394c15\nB = -b7d9bd08d7d8e0e9596851b7e03c78973a502afcc7b5fe5b0db6034ebb8a11df1ef7ed0ae1371eb4111cefd61c61935d768be3e3755e481daced219874cdf0d07a76e7144be626cf1fc21c8a0e9db4389ee213193775e95d4d86741d8d8fc820c239b7a90937000dc3e89b2fcd61b44e1c38c655bb3d31aa7e422b4406c9e4a88e6a2c18ec7c048f4a6b5b270c90d9fb378f64be3b5b351621db48a6c18625\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2192157490ae044a26c23eea6da51d3a3dd08c7fb67a9beb76d37ee24ac0089863aa7f00849b81bab8259f3a0e1bc744d841e07aa413c286e4bef2ff3356bdbecee756026915894584b4fcef7e49da4012cd9fcb5dbe3f3b867cb6a7ee959a328b0fd56a9eac1f4e40a22bf0a30073cd2d48f99245ac03c373810c54eaf3306c\nA = -598eef47b40d1fa1ce260edc561bd1c1ab286a7e068af412ec2baaecd07c5b9cd596505ea1bf0370ea961c4ceeb9be76baec74e6952cb846f20e5da406bd01368b85d59569b403b7a305cd7448f331f10a34def43c738fd633df9a3eb194c32d53aeb567889927271d71d3929d43fb9338248b64f7d23cd1b053239e09cc2ccf5fe9c9ce240f1a10fb151a8583e4b4cbc70ec3082dd20a9962d564544e\nB = 559fc917de34bd7dd7a23a432142ed79e3ac4a6caa357eea21e423eb9af7fd94f1eca735d2588ec4c2ff013520c3a0e209627217cc69bd5a07ca46a43ec1f1bdbee5f09ceb1b2c18bd388d3852e51070943f16152a73da624be680c671057677356c6f281a4ba1f7c60609125d7fd9086c907ca5c191820d80e483886b70c1074e2963c49996ee92577334881edafd88270bb967da795aa4fefb739e4367390ae\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 3488bf00f67b852592922fbae64fa56d2e4e7081678e789bbb3b4f48df62576d537da2e99c9bdd721c725b9a828194662bbd51ee20ba73d4ed5562482540880686d9fb1e8ae62d08e39fdbbab1d18e399ebf07b3a6559dda8b043fc25a8152858d39b10ff64776e00a839950e7a9ed5ea95b594b6e9e9d4348ceae08071ec5d9\nA = -1b135d8cec9969561be396323e2f8be0c60903ca59b6c418cb19876e9e3cdcb9ce4f5251eadea11fd6e785476c70822aebdc94617063d161ebe55584a8a774ab230b8228a2b65bd5a6c873bb6b261429eefdc7d0c64c7e78133e739efe57f835ad03ef8f84601e1a2310659db5e0ee706f23e3c5c38c9f8c36e5b15b654d1cc528f1dd392f1b08921af8be6fe4e4e6db774392441883ef867bc729338943b\nB = -34fb63435c90018e5843098e379c76ef3ba0615b6b500854b3dda3e77fc5646228fcf3a6e1cd87a506e4959ab05e24474990ad98ad0865942737734c03dc289307f1b1f424b9a8c2264350943449b3d2b0f71f989039131e23095d122ae98c0089a184dc530669e804140134e5b602861a5e61c030fc3d3b3eef0a59f8c0579fc9b0afceaf16698de3fa07c43231312254c04ab11ad7a29efc4597780c2cd1b64b43\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 8ea5fcf7fd41803606c95729d2d910941e43b222f9b0c93a1a803b197fababbd653a92ee34e805906fde29b307a962a294aa4dabebf0d181c046653ad0fe6da1295eef817f3289dcc6579cee8869198c39a9f79992cf6894162d35d812df327a64470c935994aca4985d0e6a783b853ad762338dabd575ca71034e29d768d014\nA = 6858d029a62b0f75e4c59f3ec067e3990b2304c90a097daccaf554abec49a9d297ca14648471dba08f22ebbf8e238c89ea06f188203599aba56611eb3d4df09ea795a7e28f91f4a9a582c6b949c6ffc584a076de653446aff9b24e87202037974aede37aa9a121b5b70a3e9b5ca376c9056c2c91f5d5484baebb64cccb6a09b4f40529afad1ed64b4cc4aca586892693fb5f92edb6b4d5f678f7a2441e51410\nB = 197d6deff7adc30b025e7e418cca0a641e1a1b35f78fb56b9d8847f0690313475e6fbc6f73c3a718b10bf37434dd9fb1eca33a99bbba674195b20d35e3b34ba9d7c8438eede24ebb48e6d39eecd93fcd7dac44235ad32f208919f57b261da70ca378f9b03ae5e5a733f97f0b3f4102d971272015bf50b6f3e50c7b36cdaa14a8a580366c9cb0118ceec6e627827b0b8f614656292675ddb66e1c55355d5a1d78e69ed31\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = a25db977e7a8fa4578fc530995335411432ced67e131fee2cd7ff56970df64a6f0f4a7d225d2f4ccec8e98273ec9a0f1aef01dc0b866e425d64e09cafb9ebe3f80bc0ad71c769f1ecd5efdb4a990ebd3a94303f52f4a97e3a1d615918f8b2df5321c4aa9339b4453d7a710a803106dd0ab49c6cd9aea431f97fea9fcae0bbd90\nA = 13f97ba15ce46ae32147a0aa4c1639b6b555f4d8a1af15ede4f1103f7a0b06b4625bf456d667720adca0c4e26e858f008b012fae63cd89322b33fe51e87714519e7dc3cceea27d968b46ebc04024d063b17901a7ae978591ca6ca41afffd81769f04b714134cfaa6700cf23bfda6ce67313988bba5fd3782bc62f76cf551d140c978dc002a779ae37400d34cbea013a5d1338b203ff267861edd88ab8ee1e4c4d8\nB = -88d8a4c8c680fb01f493f73753c70ee753951d4734627da14962e36449db5490b8c575729fafbd203a125b500b96364e6799d9cfcf0efb4ec877e86865eea5e99e2fe5e7655c1ee0eac641e73b71c66d7a72c2934d1ccfefcf59781035b2c7b89e5de3f7d1e9128cac57947d22e7577832ba374492a2f53be37e17733d8bc625fa77fa5cf093975049a5c477f792fe75e85da26cceec820c8b255df0292824b4c3a8ed455\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c1f2165a402fe9becea284dae60453965ce327f540bb8969562485fd1bb60372b8689d9c9c97c91bcfd699dc370117ea8b704f06cae3d972dc6e5eaac971597c69d4dc24a68b256f97229e643706aa6d2d844078a5fee2d08270820055ea58155d7bc754f09d0c6f804e55ebe53e3ec418747d4130cec68533f6f0c2f8fd2409\nA = -626a1580e52ba52a877cdcd62b34cbc7f949148671d4a61201e03e98985d704b2975b9a2d9c4557deae065becd662ce8448171ac582894bfa2c59d4ed20c6d0471fcad1d0fed1291df5e4556aba72f3645486580c8bfd0e3c8f6cb34fe17ccdd75fad4d4a2db4e00bb8c2a23ed17a31e95631320590f40416c153efdaf897e3b278a1faf1917554d9292f90c4edd5992748b58492289eecde1af34976ea8ff507fb9\nB = 44c336d77391", + "18340048939d6c198f73f90e13030b69be286ef920902391d87a58df3632091d0ef25340eab395203e8dcf3389e95debb7432165147e145735d2e3226637b4b8cb7d85d68308be07f217f57fe439b31fddf3fd469869a20f1f852e1645b0d4903432ecd1fb6397db4c11f6b6b9c0fd25778b0ff00bab9ff576b16538a6b7da40f01fa7b987af8ead41ecb66b8940c0e8a1208d0026773e711153d99348e92303\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 98eaf476f11168bb63fddf7dbf3347e619f9b580ea6804ab893214e94ebc089cb652e307f1f37ea7ab9052a352e260ff7d1e8c17461bae68c52a8a8f1a57a84c79b2c8fcc2d504ac4f553d2534f2a776ca129ec1942d83c8ae24c772f6a8429bd61949ca1aa714cc3881ed731497b84415c88ad4b9be34197a549737edcfeac8\nA = -15897a5a986641fc2cda42d185d72aa1552eb92f788bb71cc74c0e424bd038e02c620d0686ff88ebdf0bc1632093c0d89e724e7d5b526b0ddc4c7e145aa90b36be0d8574901fdf286df84a6b52674a78cf21ae4865618b4347bd905461d878537b33cc41710ddb290964c48e44d4d2ce2ed82847de75938d23ed418bb9ff1caa03b5c1ac5d65692dd1defbc6013b3270c4314a45dc67883762fda5509b915e8277c1924\nB = -3a7141f54a0bcef68cbc3006166f7e15a5c2394892a428fa417a485981316a537cb3ec757d4a2473fdec2cd61010a9ff865852af8f43afc79a97d394bb6c58643858e2b4dc5cb958c33781b5c35aced7882e8b8d7b4e4249c2b82150adfb0c8f2bbb1cff3d2ea27ed24eae030ef468ae4d6b7462f0b072cd2a2f02426b3290b87b14d14b34e91a94c5bd69e9eda53335cdfa7df90a57f97f3d023ff85537fe0a8bc5d8fd7901722\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 34464b7a50713d17b01b5940b5acfaa7006aa6b9b083bc17e0535b08783761391eaca8703af2edbe13dd0fe9036d38aecfd9faae08c0861042ea1a25b41fa8a15b7721909783de3aca127e955e177987518dd010306a795bb66466fccd55bd9e2bde17470cbd36b1e8f8b63805229754387a5fb40f3ee9a8afb2e51e25c8bea\nA = 701ae8c5bafab7f41c999e492f04a7626b2b1054e6dce1b83002b2d3de46717225b018733b0fa8fe3f973202da8a090ae3fd14f48b27097513ecd4ceb1b9729e7783c17fee9be5221fce4ed3860275b3b36b7416594d2b65e198ff564e82301cae23756c878494e57b5ea8fd22ad800a582cae32fbc985d122cbc6e0eac77c1000d3ede45ae7aa087534adfdea8e9f924efa1b19c43dfd3b7bc83d7c40df7c6578a320a19\nB = 18e0256543619a750384d30b6a7afbbcbdcd9a2ce644dbfc97a8ff699e118032558f706502c9b956695cb25a46d7526596b3d0b67b69611009265838bec533a9488d24583e7d7f2284e23c3cc4ccc5920fc57e24f60da0d479d41f5b9c6ad9152903a4f37842176c6257fb1e3e0681d6d583e704c1d1b24cf616fe638106638fe9d79a0c74f0df67cb2df9d99185324ebb037d01ba0066ba947d5345cd3201b19769d438c43292f572\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = bc57cbb3e1051d3a3035f77c2e375c7e3221dd472edb1a5ccaa7521849fc0ccc7568238aea9335a733d839e89ace6f2b66ef238267e0050c065c3d9553cf50cc5cd93d34fb43c3ea1c31b8ebf0b751f595a7e5e3e860b366229de4286b9d3f0267f78c6888ab3f208c55d9292079116ea0eb9f4ec2934c97149aa132c03336ea\nA = 1ffb0aac11f6d1d257ef7aa997a030e2a12b0615fb11ff04f344f6ecd550e8e77e9883c246e009af33a51204e4066ed4249950e022a61337848dae17c88317e15ade5b5499c0d7597a69a02b6c18db0f975c19c16d2167c583571e947676ae9c15be60e69d76e78329aed5fa57dc5e616795b5487f3d52bfe74b54bbf93ceda093c2e14104a6d2f017f0d200a9fc89deaa283e04b0bd9015ec67598425312868eeefeae9c996\nB = -9de2d82e25b449b8ca4b02b2d2fc0a023fc5804ea553aa84674a815bd74193a2e549070e2cfa0b90a53070646875282fdf855940905f834f5a07f073093c658cd1813fc5cd7092af592092d789ab5481bfb14b6683139646cff8eb1c5dcdb6a33113d1c97d4b587f15f972c06046730b7e712a8e3dd5f4bfd07cfae289047de31776f222d11510ab6b70a200ceeb6802d6c33f913c509b31b96e2b8dba9e25b0d2250c3b102d814683f1\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9f7f4e010370ec1d76fa83f73c80825c3b71521855fca5db06d7ed830c910d0430375bf319671f6a83bf6b57d9d53cfaaed5bc5d615c5690df0067b18791c33cb9f0ac9fa5f0473e4f4eb7840b0b660962097606b3de5744089ffb37d9c0df1123a91a5896d4deeab8aebec469b099a3a9a4f6d822030ec2fc4d11636706fd0d\nA = -7f56093243ec2399548ed95df79363e6ff09de211dfffc314b7cee526535def0f9a8eb9aa6f1736528ee7aae8be55c06645708d576111766ea33e0564c12103edd61ede3128a7a642f968eefd0d7f3768b1325c2dd910d459b15e54145a234225fd29932234e59d3ff5099ec4d5b5c6075f56382ade1101115c7b94e1e2a7bf075dec210fdaf2357c735416dd5d616335002d1cde6056bf7c478f810b78c661a3dbe6e54084bc9\nB = 4df1a6296428d06f51f31a1b0f66d0b77a04db3bb8e1b80d64da649899a1a55d4041bf0bb47d3e3936ee0f3740e1e8c2b235e1b8944d28c7d617d1f968abcde9dce10d6e3c27b2e3607d8df815f5a39da9b5569e95eee1fe5532c0a80011e7415800d8a9ec175fb1d13dad959becf04964b70dabde6d37072dc9f6d914309b850cda33a565515dd6c0181fc48bc7033b314ae0bd5872480e02ffc08dac4e3030d83b33488cf149e19b0021b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 6da5fcea305cc6eb47fb17190889e6a39c339da1bea2d7c95e997fc538b4aeec8b0edf7c109faad7fb6c656420f4afa104ada7a0d3d14d3ef0fc6774b59aa2687c0b4efe7c3fc83194a89c832f7168346cadc2b1fa6fa9a23a67c91ad731b4cfb9943738c7f9951945b2eabb3743473d9c0444ade756291f53fc7641501597a2\nA = -19dfb98f9f7d20fd331ea749d2019d8367935fb75ecde45d6dabc815ab9e593e51178a72816f85aa678304e6ff3a2c24079a59aca253d76c4ac633fea1070753ce770765bce47428f8f5ae40c26a3ac91ddb551b3d575bad9a3b6fc7954acc93aad2131b78fd212fb0db7cca4195b41651a5311bbd4d8c64f1c93e6520eef8e6308e98caa1cd0d3c9b4041182cbfa131c4948257f1200b1c5351bee77ac8bc8e44680ce64ed0648f3\nB = -2736d5038c60553927f389c0650bb1355b0ce745a7dc5f52c9909039465344af910a5f6a9cc4ec130b9877c1cbb52fc08b20d672e42b853d26a02bc07eabb9e3f91399db8465b6a8b1c9f4a4b9eeeec6e9b6180f1a770c139c8f29ceced61cc7ba182884ae01d14dd85bc924391333e8ef039b586b6a0ae18db3570aa560c2b0226d5e23e7e753873637c25aeb19e74997da4f5d0755571785bebbc7dade57446e0df4cdb8df23c1003533f60a\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = c0265805aa8ab52da5aec06ef7cad2026fa0b18edb27b4903e3c068ca6464465e34d3f3bdb4bcc10a19441040deaf5569645f7e09b36c56631b3a6144d6206d39c9bcac53b54210db6d484cd6a2780bc68c07272de03a9bba7e51c9d86cc8883cd2e1864a2ed711d505930143c883c57545e9c40851c6df8b3314a8c9a0d201c\nA = 5622f906b077d243521325be82a43fce321412bdab1f15e4ff0c11a7066a288b7939afc01d30243c8a4150e74286611ac1ca4daf457aa23508a7af869d2d55f54f2746afaec477cd7df0d5711dd636802ae7f673b3f730236ac3899330f89cb71d48c2838322fe856d9d8b4053d9c1e66acdb5e43614ecff954dbe37c5269d7ffe00b34e682c0be3d7cf653ef212daa3d55dff92b329126636e440b0bab55f4810a2849f77c39ebb93e\nB = 1ebe0d1800b1fcfb67d7d54568e45dc604450c1dbe103ee21d48dda300c1d9b9415dcd9f5a56cf12c2ede3c862e895efb83621435377387b29b882b2acac78386895c7daa90810092bd3062a3a4867f92d54622d7f0b89b40fabc4709fd507d4002ca80de231596630c234fa418611ede0ae4a9616d570232c1b03329bad02220ef64e455c164aadc16190ce35b78060a6b117b4b0641fa64dd8e8cddb5914e7657573804e63dc7b216b1a9aa175c\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 606d2b6f756548568013bdaba6e811dbae88fb01f5f36d30d15dc1e099d86bdca9fc1eb3a785034ea14cb7f4776586327d57ca5a52ea1b30f26e2a76140bbb0e930c7780673770fe22c5ed443c349510e1494ebe402f2621b1e6bde39b8691edbe5c7242efaa6634553e6af146dd40666edf4a3db5d1e7f9347fa1189c1e5168\nA = 14ea5e6fd612945c71fdb17ec44d95015773edc908a85a6645a8eb823", + "d11226545d05b81791401cefc81ce9765eacea7a619cb482f29d38988d355ce731bc9009969b7487a3acca2d2065c1faadc5d6dd8ca1dcd3f3d4ff61d0a75ef75272e62193618f6b802f70795041de26d6ce367ba996dfb91167cb1fa16c8977f982e1718de7d60275a7f66e4ad72ee55ea06267cc4e8b08f488579825cc674b0bdfd34a01bed08b62004fda15b7c\nB = -8a542280f6c8bf4d9fbc96d5bfa6ee0d16a09dffdcbfeaa2dfa1097a760dec7bc540a0b5b2020bab1eaa594117a40a9bb99c3f16fc340c262b29909608740b8e77fe4706a88dc0fc3bcd47998e88fa02f617062393978ac1bfe14235d43f3d5edbdfb9f140412f4fc2dfc05a700f47b1f0f90da7ae07ae781d9ccdbb951f19a8b8a9a7dd8a65942842cf207f3baed3a0b2f08a06ad0d9ab7ad0110346293d51ec53ff8165b925c0e7906be8b7303252\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 512220042f151479a6a8b7c743ba83366cb7733caf37164e9c823422ccbf78b0b83f426a7230f559d50bb0ed3d9486c6a6e25f4cf96c4fdcb2c861566c6a73215b6d08995a14569710cf9e54abded1d77fc7722d06fda4557a3a99862e5ce963e1be25336fb42a4629391cde3aacd47ea5f5426e7185c5df27d9136a6df26f54\nA = -4d108217b778694931088bc255d1f69cf8f5a14252156163f948ae58d58f2ed54f518177d668e795474952c930052c1bcfcae11bcd15af168ec2e881e6ddc8de257d0cff90ff3ad409bb3a080d30fdfda99078cc3ad8302a4bdd77de66ac082b40fddb3cb36c75a86bacaf60984a74a0fd575d751ed2830650d85844aba9e3f781b2dc6b515bdb8d9459b083e1aa653ef177de76282e86c99e97dae9c0b050c9e6456a051e7d99adad7be4e4\nB = 7b9079504c635655a588ac360955fceb10cdea5f3de548ca2db681da38c17a70df5798f72cf18691d14a5f400ac69fbb47e64115cf071466c54bc7077a228249209542683ba57791352ef3409f6a947865d8f234ea9d39491b5c001685487b32130bce9aeade97d9537afe3f2f87e8f3315619ef7f215a73cb724f1adca99b90912aeecdc81485c0d00a74387ea99c965118fc6a9af1163e60d1ee6a1eeb12d7c2bb9a54f747a415beb5873d616fa0eafa\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = e36899d83a143c82e19e11494ba18478c0a9497fc89fd83df38adcb6b33918645a416626409a156899c6583ab9a4426438d9c32cac54b78df579cb7b6b1feb3f39ca4a6183743a4b823082896a89f9f1722be842cb2d2ceb605f84a9f9b61cdc7e184593fc2f9ff2994fe6cc4860d255809d04ab47e154eaec9ecc807ceb298\nA = -1422272d9e91a14b38b3e81cbd9411a0cafca23addf4f33c94a1bca70603db879dd8a9c0b95f5986bcb447731219c4f9b32a1e3253b027b7963ce40279dbf4008e526adc0bd7bcb2b533392a105c6e8e1bddfdd2bde7dfa0d2e3b1c6ffa07fea07ecdb9fc828283e93b0ce4861945562478b1a56de32251b7d31f9a2309488f7cbdcc38cd6b1c951570675ef0d61e1df69fed78979dc755f160d93ab5a3e65dc2944d3333cb85aaf87a153a90fa\nB = -2424fc1e71286ce3be684a10dd885e4891b52e9009c3021d90ebcaf68b6db81130bdbb74869cbf142e0f44ae72684fc12c85abb5157987428c7812889beecfd7bb43fcac2eb6298ebf1dbcd2e70e4274841c2703b8685df18f6e5bbaa1422004797defc6ba843e77f891bbb46699a863bc1d77c5e3cab809c247e2975e8170da00fd9c8b232abc3fc6b16951ac4e6c96f9503c1ff2d6832ff9c35b2c8aa408645849c577d2b8599ef520da57fe2a9eccfcba6\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 4e8a59476d47ee2cd0217bae2981cf25a2c38e5f5d5c30c2d8bf95856a6e8f42429e565f1836365e550d85207246514624e7ed932d6f5802a50ff9f15d500dd84b27729c1717a3df0f2d6dfd40f0094208445193ba6500ba03fa3f4bdeaf9251aace8729b32ec3215bcfa170575e26265fe523cf44a071470e3b1547901e9227\nA = 452cfc78cb9597e67aacd4ec83e5b473ab8b7a1dcb6097fab37e25d5a6e25c69c73a6c20de0e2a744375bbfe7f612036e69c7a503255d9e17c6ec1dc6cc6f634d4c79bed4764496e5c7c026fdf9408242d3b234195e67a5681e7d7b861f58eb631ddb9aeeb0e5b3ff7a7657a7fde5975b8a9e1f643893bac47debf7918c7ef8f6d7439320dccaf63b80ec9761559078baa8e35d98fb9dc242ba83536eef7ba9901395ef02b19990d8312203df7dc1\nB = 1dc222e7a737e6d97a703fa232defc6c0a4fb2bafd247c8e547b9c474421cacb7692ec98f94be19a5e40269e1f5713d06a6d081a943dbc667bc867e481b99c55e437061cd44c4482649faf870d9347e0252ba9dbe116fb4992dc2c2a0583c1351e9e01e71e9324f5fa942322485bca93c2d95cf304028e68224fed446966073ec7326c93ae326a7a533a36e053437910418bf1761abd9c4c5ab7e6f538e9bf963903e6c80f21a0a38a683e8166e4626a8d8b743f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = a4d5e9fb7f0d75ce41ffecacd2ee1e4d15f82dfd4decf5ab1bee75fb97792d0d574fee60a30b15af80bd38e6a25b1821e61628dbe456e39fea3f8a9ee6ef3d2332412be1500fada0c1728a1457656eb3e9d94c64fb2d0ac89f10f2b9ff57d73207274ae7e8c7538936cb7241615b830cc9011d4363ef88f51c7b3ed503c25179\nA = 13eeef030b3110451fcb1a258434aeb51d3dc805b38c72ef7c79d4b0e18d600e5dd28b552b59f3dda1898367ec7da5dc6d9089a585cf52002eaf8f9ec64b8d3ec50d0bef7dc3faf203c48583ec89757cfeaf888ec4a91470a6b8ec9f26a6b07f3311b4fe972cac2f2ffe47f5c11d2dca87c62680e2229120cba4de9cfce9f7f5c33af8398c07ffabac1675de1845e05a32536329647214e54e5d9216fc0cbf2730898eae19e425688bf184d16bd1d655\nB = -ea324da99252edb03f40100e528d9a5080c43be97fe4b7e03d9563ba48040d328e57d0defd4b7ffa9bef3ca0d2682aefd2a0ffca8566e755b11f2e3c6c1b707f1b9465592aba6181e583babd5c70588e7123361a8ae77d8c398e33f894ee288babea1d7eb63e2f3de469e502b5048417043c5a9a9a3eb921cea1533162e3ce9c79e6caf62bbe7e17b180b72c59b9ef5fe1a001b733d909a8278029fb4a63077ef9b3545f1159ad73dd75030aad599ea4884677e01f\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 2f096fb8fe2156c41ab695956f13f0fd9a084f87ea5f5b1acb6b60c62617b8d7079f4b072223ba18cde474af3942599fe070ddb0ac1a99f42b9506a2648e1b8f6106015aba0bf7a824842403bd3f4ac8b6fc4a9861bf0e8ac59be0322f0495e4b515fd579dfef273160ddf96e453f4ab663e703609c709fb1f016ca919fb26c\nA = -4212bf679cc00adb2ca502604b71dd5dab99cdfaf55ae92aee6bcf8b3b6354a384656c09eec6175a95c8cb4591ce118e783d6344525c25e5b356e45802ea3ce1fe764833132e6b7bec434e4481c9cc2986904988bd8da7dc2e31cdc481fd0e359674bbff524124bab1ba4379885a6cfc1b73d953e6d1aa1b938129d74fac9dc597c31383f2f7e02fd995f7065290a9812ba8e205316ad5bac6fc65c6c7310f1a6b033503ebfe85bf6d3851bea1b65b9c15\nB = 7ad83f97f40d5be508cb394c128764532f0aee9a108eb02840ca1c635860b6d751d5f676e8670e2f61466397e1bc68f97ea52d64b335d07aed22f20bb1ed19e3e42e4205d650e6d37714c2f80d39b111577725e3bc7ce75bd7ed5e44f8377d5fc2b97f05c3c1ed5ca1ec90ba3ff7935a25a8acbcb15fe1fc7aeaa1e444cc2f06c1e6711721d24b8969d465e4958cb87924b3e0fe99ccb371009b5b15747bf6dd5d0fb73b8fdf58d955c8773a55424a34c741406f6f904\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 909626a69c803e9acdca97c56781eb672d6fb31430a53b853f467ca26d4ae96c182d71c0212894b776c88e773acbe9602e3ca56584c39b5947724290def7dbf04c6853a108c1282def95dbd5bdc015b68daeea0ee959b35bc5af98a4ae4cc7486e627bc9432bd009b21ee9af3085f074a3ae1bca879e321018e991e7898f2897\nA = -14eb8e28dd04a159c576eb10578c24fad9eedd3d8b7560b681002a54a4bce2167de05cd061338f63c50b86327a79595a2dbfc1d3f4e76aabaf88cfedb69faf5148c61f8cfb2130511a3bf4a17d846ededd4c08f3b635182dff1854e8c4c48007af028e06f01235fc2becdb32adcb9e2058dcf8f8655624bed9915faa06be972282cfbf8530bc0cf2de5b2057df32e4a6cbc3c772feea0a511cfe3408a6dab0e2714fc4cf15602ba0da03bf0016f1f3f5ddfe1\nB = -388da160568aef9f82fc16f48a22e8d7aeac99121cfac9b748c815e5d3a823b673ddcd20c1168f98ba204df5e52535f61b224fc0374092f8c834321949fa0a812b5e65c492fd9fe8246b74143a943bcdbeba16024e311d673357a3dd3eaef9ae3a72bb06e03e34e091cbe5b6a9eb9fa3d7f36c03baa5c3e242f2c186b58db5dddbd73f6aa54aae027529b8f8f0a536b9b283ab08247b9977a2ac2d0d9f162ad03a2fe247d2c589b1a2d14b5f90d5b9c0a95918ea956e261b\nM = c462c7cdd79b7604246a0cd97c017700feb25908656", + "b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 128e8844a2f04704a4a60cd33e85cb7ad373ff683abd167894a35a1daf947f504c0abd7a614e293ce10797a5330147c88c4d5e1dad1bdbeaf74095e3f5a515f2af68b7bc11ee1f53b493133905b654318dcfe73118ef1931eac47deb6c4958406b704ce027d9b027803eb8e639b52d5983094b8ff4b54e86a7dc6ea169ff1af4\nA = 75e6b045aa44dd9b8f4b434dd4bb1346fcf558a5e96b00fef9b6cfaca72fe8b1672edc2a64beee8b959683b1861138b297629b44a0caec6bad2ac05665728379cffaf66a129f0ba40aab7c6b1c3fbdabaabc87ed3dd580ba80ec7ee765e9a8fbe845c0d207eee7a1a3a0c39650c75ccb6bcdae2e0d5149991dc3bf899ae9b7626a2baa17b168b260d82fba84a12f10e09234035e08b730cfc230f0d2651c03e34d4952fca6409b5c6ea5d8791c90466bdc4adf2\nB = 102fc193633b0e60a48dcc17aa76f3e52cbbd1012f179736a0ba7a102f8dfadaf434063b0ed1b1528a018b349eaf192fe62f868b538cddd7e8e6fd98b93147727d58561517b2836e4a373bb31fc8d5e42d16126ed80b880c1a37940c138fc1f7255ee0b7fd39b1b799c34e5178580cdc076ef3fbff65fdff7497398fb1cac75e5c09cc7df1168a20f88a16e7b3ac78091a90f1169bccd48c0d06b4707ab79b741a168deae5ced5d48bb5f5dd3f465e43c82b9db7edab24569b2\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9aa9699d1e5d2c6acb21e31890c1899f30a925b834adb5b8bc8cce83a1718944a2c90faa71b34379a21340457478c0c43121dbd65d62e290eda2ba6230bce4e6f18555a1380c7c95c1700793157f7c1cbabeb09460ca28dc596bb17851ab2ba6dc6bf311ea69bdb7fa8eb78df74adf171d4677a154b8536f8104d919bdd58648\nA = 157fb9e1b38f288db78a1a0e22fdd9f48a59779487a9ada2774a094d34536b85993e7b9ab6e24f081c4cdfb64a82271100a054169e4f1c24e3957ae9aa8300e85eb2a45a6d5987eed4f0fba6fe8557cbf6128e018c5f9df028131bbba6c544b2c6312aeddc71405f0e4ce648fbab9e5d51685949408e4ccbe06fe501a36fc13ee65c31f062313135054b7679eef45964c77f5a1556ac09b11c496d0ba8c6057e283bdaebb4e6d9e5c557d975745f9f98a288d5bbe4\nB = -82cb6334479bd997c771e894cac1ead87dcbaf8f5006be5c70ad48ef94303137bdc45f261af91a201b276a17d884a56ff27af7dc06cc5b7b9c94f7c4d4a36f68f8d309c477b4969a6e7cd1b2afab9deec06555cb753d8a0eb00965359ef865a84bfa87b815a42b2050e1635d5ae5e3743c007bd79e820aa37a968702a960fafbddecebe63f022553cadd7a4d4fb27b4dcb981e8b490e80bbbf13af8c4412d158775db71f5fbc9986e7b8a8f9299574abf7bdf9ce7544e8c4e85bc\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 46e401989fbcde9d830dc6e3c42768999f153d44d270d4805c5beefb470bc1e82706aa7173b359763c5e15d146eca91a32a36f0a80802871933cc7f2ed15a5472988849a2d2f57543345b531538db57ab9bcbfbe787efb0a82e61baa505aad628df5f9e881dababb35bc2decff267eaed3d3671757ae1764ec5163b792b4db3a\nA = -590c16ea2cf7fa7f63b5cf74804333f22fd2d0e1da7d226da8425abad2b39a4672fcebcf5cc15d220b0ecfeec09665e682fff0140f16889f7a6ade9ec11aae3fa3a369b3fc133babe52e42b7a8bb9a24777521f4d9e0efe7d7977dced9e40784c24d2c6056b3b668ada7856da71af73d2dd33d2e481ddf40999d86a6e236d0d73f31a67c52cc8b38203bb2840c0b92c2612ffe5fdb6be87f9a787d70b3dd506f9a63d144db3417495f0a48523c812d14a89710d95bc6\nB = 5a2865cf2254710a1a51ee3056b0c1f6c5f77d22d7aa8f939e6f48ecec529a169e630c554bbe682a8c4de9ce4daca77a278d7e752cb678141ddefa75ba42e661885a82ab55d699414ffeb75802cb8f4e7583bec8a7ab58803b378bb60fd46f476ea490c9aaba568ec17f3a6afdd6f20ec54a512f7aaf62d2f941e35b4b72dea77095e863dcb38bcaf8777707c1dd437ef2ac6b6a8b2b832f80ad2a6d6f279c053d02058b1a657a1cf5b6b269e15d29087b0cfc0c2d4c3fbf32a167a3\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 1c9649f4540556ae82ffd71b2c71ea8588aeb845c50dab595db9f8faa01a26c809d30d8433b6c0add465e164cda2b6723c942ee87241eb7baf9944cae08babd8e22a0eaf35c09e9efdfb9f8bfa65d53ee6eb23fcbe1d12a66ae05e7592ed788b231b000f895d098a24febcfa4372d249575926a5faf966072f29a62a401ec51c\nA = -1bc9ae5fc2f6a3f1274584bac1e145f02c5e8c4779f4df15e98dd34344c988c1437ee4428485a09090d81b18606a6ea5c1b9136872ab5b37373fbffbb5b3fa8fbeca1e112b9f1643658c2f38b9548cd8f0f271779ce0acad403177057ea0a2af2e7435109879941fbf463488a2522b831b95c1cff21d2d816d70c25156369dbcf04a0e28e1d746afb8a77713703fefa512816fe73e203bb4c3428efe09b946b750199bd7a03d30feb90230c219a103ad4528cbe0de1e5f6\nB = -39cae179d955049f830867d4115d3bae25127c945b1fa0c16fa850e8fd77c1b3b9b7916b9983c1659b7cee77b7dc72abfff1c56681b7931c5e58cfe4f1bf0168ae32df0df8f652223885717a98f858a497b1a4be62a2215c39316c34451b0d957791f49139921d9ac8041899b8fdd5d3d443547a26ddf5748147e4c3e93f5043ede42f38a9baa628df65d3d6148ac2ce182056700f0f94029be05d3ea3a218b40f65a87b4baf097fce107c080de24880259f1046175db1297016af76d94\nM = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4\n\nModMul = 9fcf6a47addfa336557749821a88ccd2573a5ce2c3094a17d9a29b33e043bea165499e89fd2c939f17a670694aff05e9af46836b62c96e597c83681092d63ab9d6e22751aa8fd4b9ea94a90a373876ef0f6514304a495edb5ca1795c9ade7965c70f9aa92f8ea460ccb670e9a62c81e9c\nA = 71b93fbad39b1c2755f2051ff7d532d59c985756410d58aed3947d6ae737ace5aadc35e7e0d29c684b9d4bec9c0fa277996bb30230f70431cb7b905\nB = 167be8381a3392dd4df62e150025e13b388bf366922ba8632614928922cc290772135857d1b5234d51c27862cb1a055c1b86260b6ec\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8e2ba940fc5165c6c5f7f4cb55cd89d1d5f59e90e78730bd66fb120a814514784879dc43ad4f355030ddb3486a59bc34b601474978a94ddbceafdc0ee23cb18708bdbd824d37cc32577802ac6057fef29a71f168e816309fc80cc46f251e7289c6a57fd222d5868263360af63dd73e7c8b1dd6b3f3b6939849580b9231940a4d\nA = 1220ac4bde4feca135268550ddc79d8b05ff72f483b39f77436f348c4f5360c22c598f7dfb76697bf6d2ae86c68e90748b8b729b25f932b2e5fd33f3b5\nB = -bfee56cd412318cd62e7b6cc49217345d3a94e7fbf6fa19053fa685efbc0f8b320b7e43883189396781c49371dffe7d126c032d1ae4b6\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8e2ba940fc5165c6c5f7bcac0e449b64801e75134a390f120acc58cbee43888f50d07f7aa6dc2b33643c025cf745434d20eb1aeda8fcee5fa3fa5baf10d67c21390297857aa50bbcc4a29a6b10885f97fea60f1b88fc72512c111b938142ee8d67545efe386622162e8fd50418b09769b8c22efe54fdacd652580d609f0528bf\nA = -7bc53f6f2e78628678ebc8e35ae4905caeec61acca5c64fdf595689cf005bde2265cd43172802fc133dafd933d7b48def44256868d202727a4aa6c0cde66\nB = 74147c93e729707111d0d531b1c135453f3e59f63a7e082b43dceb8b16cc5debdb6d7c0ce0c00ec9b5ca51e7673e411c3cab34938124db6a\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 43c47d7e319c32a758360dd726a1d91e2cf5c57f73cdf9ad2040e61a9c282a2962d96d300e04288461eb1ed37df19e6b88f104a250f9885898740f6487b081515314e0a217df2d4345d3cf81eabb2bfb346b634b9c251624748f6e9407cb677aff4c53fcf42cc027de267e6ec011e14bc7f3bc6666f693d21\nA = -1e6ce0b44105047d0da0eca7b936980267db41d41319dd5315889fe8fa2329023d7cf54f71ee179b5bfedf442cdad1920d311966f7175cbb953bb42ee105393\nB = -23a330c7e06cdef4b6b121d15a9c0bc774eb5e432e72d04c5f03a0c588e55e010b61f57c03c51edb1211685d8dfd2a35393091fd0e3ad2304fb\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed45", + "2d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 768293c84c431b9c8dc6e538ca3f856c60ae5e1aaf42325865418b7bed16c7fc2589968319cf41cb370657c8edc7b969de10e0566b64ec796470b630e22477e7aafb38e99b6012f100c9d23d5517d486e3cab1fc60c1568c0228c9b55d2d77d23b1351fe37ad4fbf9c07f29330a539de4a32709d043dfc9e21aa1a\nA = 6bbaeec78b6a41818b7eec42fa3be7d639dfd86fbace2bc14e0369dba6dd3f04ede8b808743d809f43f70f1146dfdb1d649546441919e27f1f7a9760da4a3b152\nB = 1199dc2f52868a0cf440f6666b576541c7aec1e9cee14c1d22010ab0f53fe8bbf3029c639ff78d89dce82de85fd8eda4e67395d435df60158623c5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8e2b90afbdafa02ce68d537ae807b4e7f3e05a66b20b84cff309941fc3150f99d083841ddaf6f19f5a76886ad5d853c73051a0457e95eeb0fe3776a084a027ee77d14f3825713a59622ea163a679cff904db33bf6ab23b06eb4b31f4e34fb122c8c170321164439db783e7bec1c265eed33f33bd9cb6d1611c00aa18a9b4b90d\nA = 1c4821515167f7073d4b7cfa318ead1da1131499c12497447846caa84176a9d4af576fe549fd8b0f77bf8dbebf6c395f84dffd40400101bf28b1dda0bbdcc5da255e\nB = -de60cd639044e863c6a49c73213dbc2ca84e4225aefa5f880e829f2d9cb48ae92e3f2680c462ac697dc34da38f65fcdc1b4d8c3c99e8cbe29660b539\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 33e8e8e193b4b99d8bb382c29c1fc5403190d7654f43cd77e28d1bf77bc3a728dde9de9a89c6522ebc7222d25f46833fd1753a44275b04485c77b675d816090280b3541ca61bfa33921a79f7286830131d6eba13acc46cc2c449b3a359f1cb49d67a4d0cc1245f3f8b59b1684aa0c3ff1c928b8e880a3375ed811dffc991fd1d\nA = -50ff3e00feeb2efc6df6387d6409a622b7a8297a717b8d94d0dc41c6ec6f29a8455c3580019349660b31dea1e4f66b74147de93535e671c853b604ba06a9b62d34646c\nB = 49ff858c7081392defc3ba12ea8869fd61188ff15d9339be72657b00530b851de53b1fcbe16034816e73251fe1ec97bcecd8bccc470373974287ca328af\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2c88dc40414969e8b614bf8db05fbc38fb2b7ce144d7e707f9f8eca40ae2309c1fc67e713a8da5fbb20e808ad20aeb369cb72a77fd285e38a7895ec0fc795ade4ef1f1680f3a3b3cee4569cc9d5e699984daab3385815d2e515ba5d67d21dd1defc12ca81bc8ea645f8f8d103b4a0a9cdc92eb50690c07a037df274bbd5217e4\nA = -167ee0fa8e5d8b569d7848b068df06f6baed80f6fa6a442f9d11d9712622b512249b92c7ccb821ac751fe4ec0a7a47e04ea5571c7cb45a7985749ecdd87f0c0faea01d232\nB = -2207fd8dbf2b8e9a5e3cc515479cde241dd3671803f9fbf7859459ac66705be055fa759c85631ed2a61139657eee7eb08fd963b49e33666e60b7e75dd26b5d\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 674885ca3ef617a53eaedb9564cf96bcde131760ac541a81f4b25c174a6fe1444c2c206f7171e343e1bb43f81610162994c497419e75aaa25b664c122ed2b27640b45bf646fc5da1703fbf1cc66e10a3c306eb69ae5f937081a1a18dfc8db376ea18f4c1c499109b0cf8806eb32cb1f28985da790047bd7b32c1f67bffb9761\nA = 413cbcbbb5851a4ae12555801f7f80ccd888bb82ef1b5c31b99e1901d7e0ab91ee489c84044bc21fa2010f11aac21d0531fac09feb482fda579cb9f224c3149dd6249b0225a\nB = 1b6bfea70f1d80350eeb45f9a5cebda954d72cf5cd27a299ef5a42e1ed0b50a541d1657b70e50b0cab69b22e31d0944fd735957b1ff764865d9385af302bb802b\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8d74ba5fdc67733ced4d468f6eb6ec4c1ebd79c97682c1d4daa06105788ed9c5144992e555d903804d7ed0dd9b29ef2648568ab7ff462a03e0bceb5482485afc3b91448fcfeba435dc587db6f3a022428d37fa0e85392d0e48e7d4ed6b21253084e653da8175587b3b709e28426cddfec8d9dc582d4ac2f3d540305c0fe17327\nA = 17c0b7f0e2cdf316e4d32f040e26d41dbde1e6689d98f0652da1c380daf5dfeb6a511b72d82f1b32d3852e9aa2f594be10776a8fc89a8a35c160e8e41b42a06a342fa1c309fd82\nB = -d7b7701340c5a358455ca5fa314ad83860d9f765978ff652d7f542de2e123bb976930b8fe84b9608648324450d8ed2bac4e44f2fc71711ae813cd8793af8d3796e8\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 57e60f79b4e156ccec4c253e70df8d86e4aef326150d612a5ac4dc285761e88ede412d28d9dfa5a6f5c073d3c91a65ba9c86067d81f296935f0d0ebd2af82e7f6b5b336422429cc3b8427fd8d3f5a6fe936f4208362632093bdd3cec1aa8f4b176d260f605caf4a12cc011f3d1b76135ac2507346674e41673eb16c0f55d8010\nA = -4f1568c207a9ec970b5c26f068f3cc8019e8cb483525d251cd2919b368d072ac8f40017a19fc7437cf88e927c9e7d6f539ee84865f0af24be0d6d98fb33d74e3e0d28020c00bcd61\nB = 723db98a78f42aa45496f31cf78695583526d25e167da48ec310e447ad3540be2636813a2c2f7b8c622795ac451992e91bb8e43e5737f0dd95623282e729d815b08ed8\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 237eb5726e2c628a515104bafd44348dbf099569815784eca5d6a415d3c12421c8c70fee23d6d82f7b5b136b70ffed3b6d9e98cb47854e79239d96c26f2ec955e4ea8dabc29a1b0765c9b7af6ef09ca673d1ee21c680e4b8cfebf47bbc74c993d017ead6cb6f3319ce4de9e9765cdb3ed8fcc57a1b153327e1a6a965e5dfa89\nA = -1fd1f634685eb1470dd9080529a891253a28a0b31e15c662733e20d43fc4cd71f4cfe83c3774adf8293a0fc3bd806d0b31b61c6ed0b4414ccdb91e2994e22797e5771c63defcc0887f1\nB = -3ec0478afdf54c949a097ca411be41f931acb750ef4f0ce97d0f0fc77cf15970cfbe24b170aa332de04836b7a0e6c5d456814182d27c8310d5fb662a818bc421587d95fc5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2f1d500443fc4f4b86e7ec93e4d0dfd3faabda35a6dd31445021928373be14c37fec369ce80ebcb77aff2151b7ea94d21592da1823ebfa0af196f286d7a69ea54799573bdcd4d09ca4f33b8a3a93b35de5ff7f65099d59367914f1c79440b471ced6773b0802bd8ca99cf531b62892eb1e78d67f8210592208859b0aa1754b14\nA = 572de2984fe2ed0d5ebb5bc3f62b197fd592795d91cb16b48a0c898991ee3e884e5870b92405f248036ef9b3898c5ee6100a09ede5a48bf7edf3a067e4fc77e7e6bf6a6e3d4f538e3d66f\nB = 12c379402b18a34dc8b80c0dcd25be16c99d6f76d5d64b6050b90910cce594bc022794640735710c7ded857ebd44fe5b2e51574a2296f7d7a61b59c0123051bf2ba4a168cf8f\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 4001c734e1391a88640007893f167eb79ef61e4717d5eb14b8d80c25ed59c753be63fc8e54bdaded22c9c7d3e49753eb49efa010439807dba0d90ec4f9b498aa97f109af542bb41922936223213ddedac4d0fad8f1446498f4228b758aafdf1d9692f59029c76ca2832125ba50e811cb95f2b982a7a4d87b4726e6dd8b1963fe\nA = 16792909716b581a936287d0a8550a1f3e840935f0f3ddca75aa32e3489269b078fd19a16f8d6b2326eebaf46da76e90890c0ead3b35689bfda8c1ead17a4f672588f982cfd3da2c2b9bdad9\nB = -95ab2c47f85001aa852d6999f29644a6a55f9e4e12bf905f911f90d29cd1e4fa4fc9d1a2aa6c215bcb5c5643561499aab8f2678fdc5fa9c6ec138aeb2d62f635c45f239e46b0fa\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d1", + "5896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 1bfad44b58d3f8bc987116d4cc7ac98f89f838a8712d81d726189e9e1469cf46fe04675dc0b82e6e556b02c350ef4e30ec6203c7f1df937ea80f435af7c10f48538fe7755ba78993f304e64ca0d783b0f46f61bd14fd3fd30768f233c59018ce911a94b495f58eb96438e416ca3c7eba5b1bca9dea5a770c1d2d9f2f62f821e5\nA = -78a6a6ef40e443c52036e75f0b35938d632bd45aebf45a1fff5c2e1b6f601a57382b9a82c3e8b2984e643eb1570cd83f3a6be6daac567ddf9f37bd96785662bc3cfee6f47503d239c77781a8df\nB = 4920f870cf9f371050e64a419ebe07ac92dd3525b41e8ecf6939a267e1ba853d54862dfc95dd21b3526eb0a0a7a7f8fb67df2e9472dbec81e15cb13266257177c5f2b92fced4cea5d\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6b0b84505907a5ca37abeff9a5ba169975792c69b5751d9845c0f09dea833fb679c8dfbf3895bc470529e0cc736c9b4a0d08b75d709a1d04525ae583c5ba082d3bca1355055c7bb674aa1b92689cfdec4dbac84a96e81c855280e417f60e7e4931ef4f428420c0b85d2cd11c1030a47788d6ee6af0a76b5364fcf23b270e9d4f\nA = -143d843e3b12431fa0d873815a757a214cf731c298db61ab13cb87fe78b0a6184bd1fdcfec0c7661b10775b4ee2c815dede0ed497977c9ec5154f7b24a8a786501ddb8dd257bea51b9fd9401ff760\nB = -25d4da7b64f439987eacbde66abadf0da7c1653c1c1c6d9b2092351fbc714a20d2d7ad8093209da371150b69b3602480595533ecc1f3c5005a8ead10732272246d8cdfbab87c49e65223\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6bce40524278ce242b0b5292d27751a3dc414f962d9c1cacb45fa3ee693ac6890d2ff1647abe578c40ea8d4b326a2e0e2fa7cdec28fe2da089338b5fed91c4277cc5be37537eec2f17edbf48a45fbe38f15c58c3e733d408d001262dbd40c9d246c323e7978df4fb7207aa9270a12921743cee2a483e7e71b221b09a6b2c667a\nA = 402671b0cfe14655bc650bd35dd0c36ce7f65de274a0cc4b708c6f6c3e84c2125ab2430e702421904950b29aa8a03b049910305127890457cd0cc97a3e05df67f29d28b0452969986959df02f59d207\nB = 1648c29205f19fe4c646eb62e8ae9b65260c2cb8424a526423c6bc04ed55870cefef9b8ba808f8ed2e1ab170e2e411f68b934abb1a22776969f79f9420f8bcbef28417582942e26646af60a\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 40db38dcdc201648da555f1062bbbb92c632c29b66902eabf90d98dec69ab3f3b28e60cad1571e7246f4c9e6aa62ad26a6d0bc08598c7a8571fa830cae4c2875c5c95a59f3295f998681edba7749b7e38cbece8887a7823b4752165e1a897e638836d408f439f009d0fb6c196e83e83ca3289d2bd0f0eb36b721331e4f9f80fd\nA = 14361ace8ec5223bf0165b78913b77ef921b7089bb5e28891d120bd3db6513ddc90404a4e6cd027f9b51fbc02e80d376d59e1f2b043954199ef8218bf26cacdc5e749f668ad3b4ab35cd796f94c06307e6\nB = -851a39d8b0101fdb22ea9e367286e572dd132b8a77a6a14dd0e995131467aee898230f37dc6224e35bed2eaf459aae579181a161450bd7ebe6b62ea7154a8a0ab590ca4a6c2f05531c4e24650\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 4b085796665458b798f824d1c1a88c23ecca456fb88713b433228ca8735141a616633ccec4bc53ea4f6e0c74e4aab6fece2e4cc4c4efb479638cf54caf55d4addf75908076f5fb487ed00d540e5b984acb8f81cae3ef51db926a06382a288092b352793de721c23c371fd0ce7a789486b2e8b867d35f47b5daac2d339d22dbde\nA = -511565611538828ff7dbc45c273fe46f4f5105d41ccf5dd343b41e9dc579429e56a9cefc54657ef0422960d1375b72411a5cc93ffa323455e006e242580358d6cfb641f46b9c36fa777a613b17dd4a187454\nB = 4f22597947638b9a9e9b9b7c2a8d37f77259f1bb1c7db65003b6e1a1c807469c84c89a75b80bbe0324fc3aeefaedc6ad9c0d9e470dac9c30bc48f6abbbdce9547ad7624f0ce9ff3cb6be23e47bc7\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2b90a57349ea94ea818207fe15c164f9d3530c7cdffcae178557274552f79c4ab56acd78033a570bd6c3e45789704ef0b0ef586594fe4cae3ccfbf9ceef46e769589b084adcee3ef8345375b7103232465b991273df724964248737d5eccbac558e35e4190112571d3e7c291baa7aa8b1800121bd573b8419f627c0091e1bba8\nA = -170cc62ad57094d307ce1b317ae5e825c2f2e317ad6060437afa105501caea00dc9a86af8729e2f3c3a854387dc3ba368c0a84aab1a527ab34fe27b0a69bc71c728cca87be728457c65eea7d7538ef3aa282615\nB = -3d9da1377a88f647de57ade46dc7caf71b4f42bbfaa5e77f16cfcc90f00b5d3e9e9d82355104c7cd0db4c1dac0496be3aa35706cfc0a30a1329755faa439694e8e9b41fba8f1ebb46140818c7008e27\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 4cd4da762c7576d582572d3427abc4b4297f740705fc14a32b46347541b152d0d1e3a11f27213badcea1e2009e34a63350c7a59e4d43654b28298d2757d6b54c4d82f580e98de4230cd119ba350416452cd4b8adff29b9f35ae0c533f666cfed716838e2b91941dfbea8d6a978a369d5f27554ef411f15e5a89850655d7f3f5a\nA = 4f4a28af27b926d8ac347503d6ac0bfec388a6c0b38a577501c3ca4aa709c69601824ddeb5eba4d9e437a97f3e4477e1487d5ce7b4a35b90fb863657a5b2d901bb8c3c838db40b89b495ee9875e8eee607d7b8013\nB = 13ca192603bc8b2da29dae67159e4f8d32f351a503434ed9e4e24f74abb5908ef7da80781c71b1a5ce64fefd13a16cc1eab05a370bfba2a97e6cf90cfe98d3a487ba72dde0762c36c10e1da175f1c1b5fc\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3812e9e835ae355fdf328b29ed8b86dc3f6895e379b8b5d65a5de41eab5fb20ad3e2290c8ca69f9500248ff883d9715f59d0db6257d13c5cd612211bb1fb99867161daffc77968bdffc1fe48bcde0fcce02ca93975b3cd9e93b56974ab4beb59582c3d0ef2a65957f701549f8bf858de0c5bc98af3e5722f1450de391876a2d9\nA = 14ca6101af00d67139b985ac9f149accc260336237dd2dee802b5cc6e506e217b74c1a007ec10c20012f071ddad34e7407012669109ec1f385566ff04cf1a1ab7562353c0af1ba1be0baaef920a188c60db27970f64d\nB = -94b683326e9de19e414f653aeb2cb4bd7b17e76a23de6a4d91c43d717a35e08f2155b444a9549dfd01a8aec4dc901ea9f629f16bafd2c84828b12d2f63dc154323eb2d54938895ec4c9efbcaaede274fd4ab\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 5ad7411cef0581b2e675d03b0ecb9969102a283eba5e779bdcbb7646d94e843083a07269c932d18b973b57abe54eaaad0aa76cf7b61f30505a263bc95aa063efb264ae829eb1d1d5f7d380a0b4db59839de9ae6230ba51901e71b3e3d59e8c34a79678e751c8b7ab139123bdb2f04d90a18ed81d2046ae86da1a73c8dae4fc4f\nA = -469f61cbff01f0e4124ba69a860ec6dbc75cd758dd8ac7cbfed97645b16488a329adee62d1a66e90ee4212569d56d58b61676262f49dcb68296bbe5d8e23853e3fefe8a304710cea568ca65c183531a992ec5b4d82e226\nB = 4a0d48e31cb8c24a3b2c9c95fd19edbe46823032ef4c97fe65d0a30d5c2cad7a4fbbe89e0ebc9940ed9f9ccb8ab18bac269759a9740a7985809d0f38259e680f0703febe7fa012d1ded47f0cace4a133f59a721\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2b2953981db406ebc544c39dfeb08a8b089064533221536c7fa2bf2a7a0d3a1192859b7dc0ea5036eeab5aa371e3e0070c3980433adb3e3a5202ff257bb546bcb9550423201a35501fd717ed4c0016eb3a675ed399340bac7f058a04e69c1774590fe747ffb9c27e78ba50fcee30ce533a1659fc49dc080a60f21357a6265d24\nA = -122621d97f42b65b060c84df3f0c0da097b5e240731b77a37bb9471e7e398b242db6f1b5e25062a9bed702860ccf6aaf386c1d6fcf60fc31b8c190d348", + "6949c5772b9e621b863a7cbf29449ddd68b7e0c21e669492e58e94a\nB = -33978406dd30ec2b192c416e422428683deac210017cac9e4355e8446d6969295b0fbaa8cabc92c1fc0068da70efa047f938a419bac160ed6f794a9f69f53a88648c9725610d5f309b652f5462bd3011cf68ea859b\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2104dfef151526e072c09a4a277eb981a035379de3b1a55a88cb060681706f26131c388f5572c5646826b119c85ed450207f32733487e3c4e1e9d701a65058c4b4ef0cd1db090495643038229ed177b54695ac32110619038f1c1cece14faa693d88476e3d70329b0084d0ba5d547bbaa5b59ba1ce1fad5aa2f1c11a75bc7c0\nA = 7b79e6f1330fefffaf8521089c3348593e40ab7e8d4da3d4346571b43b12740958336580afd13619be3dc2d42eefd9e30599405da3e32e7f3a5655ece8b77a367059668021aa092460de75e627526da08e6206b0f8f539ef40e\nB = 156e234931907c0c0970c1fe6bd4b24225ed94d5f5b1be4693c8e141e9a6032425b4a47b6eac6265afbeb9d796eb230efa707d5ac4a73808225181cf814b319142e9d175ac461c75e6d479bb6bea53954bb981062eb16\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2a392c5fc96c29df2f5ae9eaf76e7d981dc1e2f3b47b43a98eaf556a9465ae8727c622188123c64658053ec50c25e54ac5c6c8bc279b134d326e911f14c873357647866eccb4f9038ed0cef5082c2058ebd71e1619f7c8f8f2fb80871ebbca3fbfb7845bd855d307d2efd853f1bfd467fbe030862f165e53a9cfa633d0d3fa23\nA = 1e0430e7cf15173d00592037e83e717c90d7dab4f54a5b2f0f5772762fb5f56bc0b2a53ec1bc3b960afc35e7b043f9d85d0af6c29288486af3e186e52bae6300b58917647231b40a12648cc8c020a797683a9bd7ff34eb6d41b928\nB = -e08372fc766eba6e0ef55a9149d700b503e2e3f978c8a397912e2735d5bcff69c461561ac0822c44160c7c1bbf722df421b74beada57462ac54a9bdcdb42d6a27b86413036ed2282abf62800fb2518a32a4a135bc948053\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2608f68632ef14dc3979725c8cf1a0db10a1651f17d91247edfae9935b53f6364d233b030eb99871a87b7bd876ab2cfd5a643387a7af9d337e81770db04a14f4f8dbda2cff604838c9af9a31e8dccf9277d453176589ba33abf77855b9501e63370b2e6cd22831e1e70ff1815302c0a026c70042957d08e74dfaff940a91a7b9\nA = -5d3568858c05a15bc9777af949eb01d33dfdba58439fb3f7af2ba792efe8e78b16d7fbc2a303a4c4c4be7c9d43f57405e88be54d6ab55268a4739945ef582921d2877019659dadbc76e0939f4b2cfbc91e5356ba2ed531526ed5b9b3\nB = 47f81f65ea1af04f702757c02a175a299b23cd8ad551fdb67020c50cbb4110b5371dc5790b12484e9ce647eeb24c0220a5e62aaec3461a9dcdaf1a22814b6f22d66372cc5ee31944bef33469f905458c172ec7871d9dc9c301\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 5735109bd21d31b5f54e9221bbed78c54cf387e39c13d31557e8173e173f786b2d2f1acf3966c3bf4552fe9bc802d0868a5a7632404cb91609a7a45fe0fb83fea8d83b0319666c1b0ac520169c15be708343359447f2fd37960c1e96d32799ac9394e839b391f59dd347acfb79bcc4e34e76490880d163ac97ee69e3a0a6e68f\nA = -175011349a0a1ceba11756bd528f2bd631c106e709aab223032d08d52d7d6724e8c5b055b6f97b48261f4860eae297badc1214cdae9b2500a7a47b4b777dd7b8f1006757754ff1143b637d2a3adc555f38eafbd5478cde0b04e5f46d3f0\nB = -2aa7f75d6801b04ea9f690aa0c5448906595fd28b53775059c01efe54b463f1d87c9fb4b39cb038e770f99bb995a2118b86ff8d004bd964e958c2af82becf362fb0b927c671cc3bd7185990419d26a827a2d81bbc0126e1029556\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3b4ad19b75e1301d19b57ba9b68e0666c28c7c5c99df1d5fbbe0685dc1d3489ff39c919222719c5d8b7ce2d7ff967730d776a02b36a86064ed66a02011bab82eb575390f85f0104715f6e4954a1bb28518450182a8ef58af35d00e2fe417f07ba25dd9c85e00c3451082becd22e3aa0c9bcedaa96e6423c7df6c375b4c799c65\nA = 58e1ce4a9b512eb0632b02cf1207936d6707b802140540fbcbbdd712e5ac1426b4f36e74a9a9ddc812e572855d4fe4fca8a0de6644226f5698fb46a5f2a479dfc8b588aa8e02ddb15acdc79ed3d17143e290f1317274f425b869df54a4807\nB = 14e341cbb5f5a7f3b4dd864172b82ceed2887fcf20aae7d0598b3d8afafd2f10c27bc7456c1488abb570be3df04f43d892dc6a8dbe7621f55bccb0ee3acb1ade989a510b4e0cbe29b6b93968f323f0016d87944c908824d249769f8b\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 7fe0bbbccad6032069b1a335b3f2dac16089051cd9321f903181fad23be6853e2d209958e8c48e008be94a62c6206b34b4e994ca08b8f24a2df0e6394ea65b3b7aadb3bc43d04dc9d35a77e673c4476dedefd4568b4ade5d16f9d89486f3d5ed0566b1eb428cb0b688f10fe3901037744f278385754fca481f937cb630f60308\nA = 1cc0e3ed58090db55063c9ba11401636f89262d6ec096d361f448496e05181c5f7f2604333f26d511c13534618e90637adc807d622097f7eabfc03266135cb626e1bad20997e72da71bf2b3f65a4973dc27d2a594b1fd96b7bf7ec14b9e4b983\nB = -87871b2058d33cb67d83b6a56ab27839c6a6c771bd94e55f200a1257f2c737e39c4a0403fa410ea64e8f442d300df1c19c2f03d07fb74d94f86d26814fca23d4cd2cd3718252cf0cd8a0e36726f6e68827a1dab6bbb1d23b884381c702\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 35d7ac5cbc7e6c262ffa41be168b02a3bde9e112c512d1f68421d705ea34461ce3e0dafde67f44d44cf31d91b38d4d5f2fbf8c6c6a44ec3ed0298dd58f3d45c04346c11e57229dc3d2cdfea02c802732d9a811d7be5e81094d72172cd04caaa3c9d55a951c09f454f42add6e89e2d8a98e124aac86379df377606e7af9bc6baa\nA = -4ee01518f6581c560a186fa05c6f4bc26809c4822cc74a0bb74d5a6b0a368aa9bd0108f26113443422b8c589084ad49f919a9e7821d99127bb210670e732b7cdf610e464e300a39d3dfa7c82f90cf00ce329bc6763d7b1d4224a020095112fefa7\nB = 72dc8973f7af7122a05c90df190bbf1e39abca908c197590dc7ac41fd0712f48f838ca62a72a177a293ee6b2afa7a10c21e7993347c3df4f161a5641ff62ba123999bf1eabef29ec0d33ed0919818f4b7c35b5f41e654759fc9abdc0f80e7\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 5d83a9b34631dd6c63c05a0c012adf97b4d0f20f61907e1c2145330211e9a7e38128517b058e0a85e993c385068d1cec768deb814bea1323dbd333de091ad2cad72431f20c1e70ff7e1b119768ba44e14292c38b88dae7e55ac9e10ff98e9bcd5f0ac05af499196b4be0c6222d1a63227ee895fa6a8221a4a182a1323183cd7f\nA = -17b3e0c9288be15fda58c8fd228216bc466731d631218a7ddf1d2c9cc858c0219cb0757d3b680bca1b1964eb15031b5b9d761a8bcbd160db89be339067a2ea35e1ac3cfed701912a17ef9ea03999d92e3592e893183ddc05cbb98a656983b54590c72\nB = -269f96a4634eb37cf8a6608408128587ba45958405a29827d0d03d34816fcb1a2297f1319485439d3e8594532545086efbe4d21d31d30e2daf09b74fa8cb27df54e8f9f993630cd9a292c977eee70887158bd3fa3cfef321ef900a0598ac8cea\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 7fc1c65eade94d9de7440eb8dfaecf1004905135efd4f98257c3295b1e76ccf1e2ab6808d158d360b7419c6210c50efe960610973d9ae855c72ec0e81d423e5863c80b542ad455700d2d0dee5fc403dc01eab460c24687401cf6a3179642e59f2a30268df95fa80dcdac230702352bbf6b60acb9ff5d45c5b09a3403b954d173\nA = 7906bd8d3bebb1303c1df1fea0b2503b0abe9c69b4f4f5bd01eec9e314788cb7d44b93428adbcef570477e8ecac2a64822e481bdf520fc381e1bb0b2cdae2fe94e484cef5236dd524e4dc364b72", + "f4c06d57f29dd3c5079e532b1ab1e71dd6a65b3362df\nB = 1479ef2807b9c23c094d0416f513894cc92e023b134f44a5333360dbbe98b8161ab899302f4fa11b470b97dca0c4e8ab7ae47e5fd0962834e6cc1763618193f4ee027f667368da580c623080de137b5869c3081128e6081b9d5e2dbafd791773242\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 730c04094b1ce944588e8291f7e6cf763c70b79cf362dc8a1bc63bb8790cd4cfe4eb51cf15a45a8464d69ddc3e1b9383cfbfd643f317108cd9ca6a6eaaea177c5c8b6747bbf40108cbc0437eb8f11bd2a0939da59b70c0c6129e2c249823897f2ee536b0427bc45035f121d2cbe7441c175899b97c490e6c3ca01539bcd05848\nA = 102cf23cc3b81785c73ac3613c816de47fd585c7d5f175185818dbb4bf0bd47d0dda9702bce97b29d66e48bfaae0fd07b47b40be2b48ed702ef21c54b10bb927f9d6b43604bec4f4b2796b44aa6b4e83f8bcd00f2fa3871dd901570e1a32888d8691454c40\nB = -cc5349a9c5280a933e87ca38ce458a711c71ffebb40bb1f7612b42b4684afc495e99c4a5f32eef1c9564c2b7612ea4cda7a0f5df6b3ec9026447dc565ca08563d46aec7ced9fc4cc5645960210d44cdc3944149051d569c9295dc50862f8f6d1f6cd1\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 1cfe1842a53d00e4619265e2fce7cb566ffbd912c9213925d01408a956af304eacb85e29fb6edb812a95e90769bf1c3d62b0cf6cd5bb8f8992391d2ad70f38a14fb9d1d1eb522aa7b7fd9f1b52790beebfc887193882377b7ce567d317d8432e1d9a908d6ccfe8d2de7de497d77b023b3959cc042ae30aefcc0229617fd2a146\nA = -5c3d24fdb193ed83f5f6a825c1716f98e3cde6b32e09659f253ca3fd2a39402b5bc3a6497ed7bc908838e93422559a13cf59156254bd3fe1e3b8600b2a777943cdb39b9d42c58043f1d587424425d3ef5f5538ea157112970ce3e09a87fbb5f7c96f1b5e65fa\nB = 675d9d2a05288b438ddcb330acbd59e4639375f3f14ac2d0e9e8b72de6ffc1d217ce62f997577f7eaddbe4603541b132cd41f2f2740363d9c331ef22df92029d143fc8495ed0152b918aed7ff22f564c7cd94fd3fe4178c90365ace43def8fe30ab05c0e\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 83ed1948276d689bb7fde814e67fcea72c4e3509c48873c3e7349a8fa1c08ae11ea4d814d8deb1021eb8b8ceec342cba5002a2ca45d5f340ae1aa500af4c7db120d0402c6cc8a840404be7221bbc46ffa10236043e5ce4415d3ef1355bde26d2d26eb7127326d4b8d671bb96a08e38a2c1dcc281830ac77202903a5e4777ff02\nA = -1be86e7c87827922d2e8a06e3cd6b64ac9a280c525749bcdbfac4856916321a964c9346d17465378251e6eada42dadf38bc9d7d87367bec94ebdc21af6b1302e520db08a64ba6b39920683725ef02b011a3e4ba46ef0eefadb98582cb911d0cbeae9c231b5e432c\nB = -352059faf97b433089a688c702b97adefd0c91d51a0395647f822c6762fee3287693e302fc5a5584a12c048dea1a320cb96fa70b5daff7c2ea21d249467d14c6bbee15a1e94c030e908342a939fbe8ae0de58cb6d6eae7758485e392ff6d5d64465b701692c\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 402525e19b6b68942253d1a51fd9b2ca36fc84cf938d80b3d52fd4302de142b9d93d1663e89340fff10c2b5efc8cd47fc3b5cc5ccd49a6ea3038ead6454bf190b7f88f52c56bcf00c6ad5b0f5dfb7615915ee8af137dd99cd3d21172ab772f36d291a6856a8e7912750139c09aa024b930a0a6b9eccc83c2c5c0ee2473ea32c\nA = 65e5db532ecae639bd56dd63045bca39b33b4d70b2db82ca3d0ee8ca436e671828cde80217b48eae7487fe110830589ab1be889f1e1463f3b0757d529b2f0cdd2ac92c35e8ec141885bbefb6040a3b5e00e64a541913a38fe05824a929f8c5a2c46568c61989c3ca7\nB = 1d9c73eef8373cbb1e8393feb26d55c33a245c33d7031c234abffb2f06a1601f7f3a79ef1e8664c51ce5dba5f5aaf3b9a9e42470d381219b4616ae93c7f6e64792d23bae523b6a224c1f714ebc82a11f9be42618922b8d2eb7b55e4d45572e68a19fb0ba72228b\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 7a9cdb5dcdfb6e04351057d731fddb9e85f41eb432f01c0d980673d294d05ba9b0180133a89930e74cfce78ed54991b494a19e7f80f310b85904784cebc5639bbc631e80751807868e7fe16719e8ffcd1f2cbd1b9f303c3ed488b647670be3080668b5fa0e53b6342c33c87f0ca1efe1ddb1c877bfe2556aeb61805b06f41343\nA = 1e412c3d66aea2c503f3aa5dbad368a61d969a2951c0094f9da32d2794e47f3bf4c481ae23636baabdebdcf0753d431426b1865e62de8eae7238a9245d62820ad7f17b5380d701f5db776cd4e1ddbdfd542901731ffcea5bcdc247fa9c83f7e08a9389e5a76d38be21bd\nB = -afd61df72361260484fade8b432713eb740df83a401d73492883a5139c918d5c911ff5dc00140637da1c6acfbab4b0bc8fc1f337243d90beeb1c2a083ad8069494c73a99372bd38712a5b5393c779ec1915e878600e0b48157bea44ca8e97c6099c4ab07fbda57d1\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 712580a1ffde78c8cf98ba71843c8130e835fee3afbb45e372d04c04cc388e403c9efac742611d7974bbae982c3aadfd1893f5da280afe0c1db1d81a9ed73b6ed9b7f05a20ce828316103259112d7754560d66733041e9470ae0d4dc95fd0484bfd56d66739f38ead7efa4051187ea41f7bea8fe5d958a29af41328246e2bc35\nA = -47c5755ca61ca8b7ea927f6fbe347f1362915548ab38c40f0418f4c9ba4ad520c3b2469d9ba3976669dec0b278461bae80eda53e9d11447512963e797f45460f74678acdd69fb9efe3897913b6568f8e03a6d90b4cb5bfb06af132bf118574b70e6bd2f6d6cb4d0089379d\nB = 5bda68c0a64218d3609d75eb4832d5468298f19498507d7d515f4c410f04dee535947571a5e75f1af7f94a5b3b05fb742fde23e7cf3f8b3dbee0a569e5a36d7a3d31a26c4a48a299044fd72339d2cee1a68966c851e76b93ae34130b75f4abe4f2260207d2254d23f56\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 4a1a514aa4d1ada84fa841d0b668930c904783fac521377a7d622201867d773ad23dbb667e0d4181616358f3cb088cd157c8e72bcd03db64647b37aa1813f870cbb0318ae0a3667f8e6c19f6e0706217646ce633f0cc8bf4e8f0f4d7329a8647252ca6d376416d545e73cb9a3cba40f8f9465d85d57c2481b84b6d95dd42d50a\nA = -1d68bddd8c3e6b78daa0acfc63a6f39e97f19527a43f6cdec47568d57b47f4e4b7ee88e4a28d683b569e406ecd2510351dba25f10b9f7c82d6da16d848bb970cedf7675e67937921bd334eec4bc8fde83d67aca57eec804ce22bb342167602fbff452d5f0f2a7f38b576e1e50\nB = -34d219765916a4c8ec843ebee9a7aa1162974d41cb4d6b60532513608452da9993749455d9701af6b7b6c7454d7f2fd5c344cc938baa5259301d4b56ae8d25b6f6510ae6bca114cae6791fa5a9551e8a405f5b1c0bbfc27138563b2d64f9a4d7a8f42a23bfacc3f1ec9393\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3fe24e66e381eca525b24cf767215837019f44ed4fac6ab118d02cdbd658066505ee5b0feb7af51859992ecb97d727121e38873f748a61d70201cc43228a7732156a80dbe399e05764be19e37dc1b93222bcdcbc45b1a4817460f7021dcf1d70e632bc6a306628790201222bb522f4cc80adcc907463a539b02f74004d42adff\nA = 773454a43f495959dd55b8a064d70b1b1ffe45c084f5f9553582e24fb402b564de68e5379a8d9d02af101594e717a6c6db2e7173e557a64d2f28fd45c4e06041deda040705d99acacf8086830af19c7ab5e27f91738ffbd937dc27e5b7869bb6caa12c2d7930366ff75eadc570a\nB = 13d884a2396268f1a8186748a15722156a172a56dd3d8c77b9cb7001b6ee06720653507eba9bb9918f2f699cb37f3b5ae514f5180108a704647f19b0fc075826153edda66dc1105c1008ea8ec6f8c10057f8e8e479e1a1274edfed9ef719b30827a30f26da78820c3696d01aa\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 715bab8708e53f76d2ef2afbb", + "845bdaaf978b54ce25f84dbbf9074f16d30a18733a02a4ba5d7b092fa6c25d3b9b0d8243c743910f1b7b785d9cb02343fc6d59eb0817bcff05646030ce4fbb2b9ff76781cb1af66b46553d365d02c61e677ae97defe92d057d4378dadf8cba9824b0022c086e0d78b5442bf3d3263ba22c643f7\nA = 168186208c734383d472374fbedc2d5d430e85690a4881b740008623120a4f7f83b2cdf85dc28bfaae5870abcd7ff1bc782ef11c78a75c99d41f8aacb52fceeb5f10266dc65eb00b0868937340146d8850887686d54218badb97647a6d82c0c6650ca1f9078d73fc6222aab95c2967\nB = -9711e5b3965654bd9427f79c89a0b3f3cdec1c857f4451eec236c1f221bb6773e5dcc30e7381a18a813ac2b03ff4a4ba679aad41e0e5d7181d4627f682ca2dc8af9a8b4f878771446fb225a979ef9c7e641cac819c307c8dc50d9c1ebadf912ec7c844e416f95b546cf09391f9f\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2714b99dcde70d6c3be8b671d78abc155793f13105fd4b7c5d760a4c68ae89987311dabf2a9238d18299f983b8aca69a9ce398fdf2c9775d90b11b3dba17bcd8edf661efb6e9c50b4e37553cbecb54eb214fed1d0847287732810e550a4c86b51d4e5da1cb7722ce4317e69644620ad806d6d1c94e1e3fb4d87de6178a997453\nA = -75231ed37f1dfa4487c9fc79a6f7b36929fdca086e42ed41f79430b2dff521919236fe415ccce590e1d3b986e16dda866f3f0d29ac1adcf55d87fa5cb67dbf4693293188516e360bac513303769c42181483fbef7abcbc4fea1310c916396d29f37d9058a62aead94511aded7c4b8de8\nB = 5aadfe65df0e5b877fe45d42d7ca02882cb6c686d486374da5ece6f87771675153c84d74b6f40df1db567b7e1e3c60c41d21816f958f5576fd2ce2f84a8c3be4749dfc7e5561266b7c9698c7581292d0d813cb77955458d63bf94ce87472924c4ca79504d1ae9d5f025c7a2504156f\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6613b1c8ccac0cb8fe2f59e76fef4dd05acf1f1b2bfc20aa3f193622ce3e9d4c7824ad544477553bc68f05f0b546e7c1ee87301e111af7929d1f40525291b88e211db7175f4e5c0953141914fcb4fb951dbf77442e7cb28fde495704f1b5141de1e50fbd0e359d0d86ad709c8f564c84dac81c7602717c269219ab1cf12e809c\nA = -1bc03897b02d1edb633e2c019e40c20c1d89a210b0733412aab675563fae8bd75dd7e65988cd8df4d9b343586e27f548becdde274f62dd421679554ed9eb127e527a69d69fa8b17aac0424dfa2a7692d1e63617ea45564b55f01a70325bca050862d583cdad96c4a2e123d0ed827348a745\nB = -3d5239dbe7bb3dcfd8027204eccf5e9444e68d322a0b0c535a203a1d0c054e7dc1e588bacb891388241462a5d2b43e6cce34ce46a23e6ef29670603d31001374dfa347dfcc794988e58945d0d2d17da6565cfea559203dec119fc357d396f65b296deb07686b0ad2d25a13fd4fad88d2c\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3a7fc5680aae875b9241200b9f4112a82cd624ffd9044138ae3cd65200631ee9d7b918fbffadcad7e598791a9f0bef3e23005d6bc0048ba92461283492df3bce74c66e417b082ee052fd8f808d71f3ab18f9ffc40f8fb51ebbb936d09c26a3514bf868141f7cf238c1abb3d88e5d50dfc188902254f07d63fb8cb611ef8e4149\nA = 4a30f32d467b29dc83b40bca2fc4ccee5f08a64069cb87f20e63387b2219b12aa312400c4ca59608f50a71d2535cde40a6d248290793fe01693ca40b93a5cded2dcfbc9aeb36e187c9d650782d12bea917daadbc6525f266e074037803e4b2f300778ca8dcb304658cdb502c93c94a16c6261\nB = 1ca5e5218dade077fecb81d579e1c9290431b34df5ec84aefaaf233d68f17dcf60ee010db26320685af13a821b6daa9d73d8f3a30826c3ae7b2bc5e219cadcff826283cd7dddd04cea7a5e0585d6e7c9f23b27f14ff815fe53bcd75fe700b1b91671bddaba737fb43bfecd2a77e5b752a206\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 768d312175ce7d2601f30bb38339f046e4c2ba5c19ae5f7ca5a562cc2462c579fce9985e9e8afe2578db542c8d9e7693e0c74ba161334b249ce720d568e9c18f09c87cd701e6f2080b752362f2fe6252a1d0caaaf1fa18199776e4c6078d89d520b9c63db159d5fba7e0838811e68794b1413c248f3f7173ef29eff28f15b656\nA = 149353e91bdb70cdca8f06648388508511a64d05221305cad7187ea40d9ccef91fe17ceb1e79667bf66e8e6b7a57faa90a83bad119c02984a8f860bc1f23ffd33d4ad84896610301cd2e8e80a5ca7e8d3ee63e7dfa459793c9dbaef3569eb4f8a021c6a3d032a9c94d3f6b8278274d0088a98228\nB = -a7cbbb6a434e4b022d312ecd4a45fc7fc4d3aaca038cca0fc56e529fe7119ccdddc8e76d51a2fb862ad3d27a16ec8a51e5f66b9c7fdfbddcd05a0ddea14172339cee340c8c651eb653c6aab6551c99ae94f26116e15dc62f2c2e63305bbf84590fba1327ee721150d46464d7e22d45d53ffd44\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 763912f4b16549e6ccd60eaf7a0a1f64d9c3bc83e4a9b87e209a3959ba3cf609cf47183bc543f08e346b6e12b8bdd5d1c07c603f74b286ad432d58d7001299ec7a4dcdb56ca875dfc7ee5c75bcfe2aaba14959bf3facaebf8df92bc12937cfd4a4865b3dd74b243ff62ba256d110b01b4089730cf48efdc66fe272f9241014e\nA = -4df3899b40d51c83dacb442fb143835bcdb550136921df78800f0515a6cee77fe3236dadd2a0800b79ebdaaf8cf4aba5ebb60cdff3e4b4531ecd0903c1674a4559339123e9f09158080fc53c4c6ae72c961c8da2f357b7c05368157b4956e592c41b25642457651abfecb4fed5d9fc1fc3825b772d\nB = 450eff382e73f2f38bc3a4abecd5f8de478f80a6b99fb6252173c90d7099629afe859442bb1f796855ee9a2940f21d1f9dc44f462edd74b479e1f2926ff6faefeb55adbc6152b5c97967b1dc8c44dfb85b5e02e870d2920b75422c8a427e99e35e2a4be92cb0ddc04cb7f4044f716be97b36f045a\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 56ef57d56c6d1b94cf0fcdedd3611a8ee444c2e25522b9ad175587619598da341916b183be03b1e73be300f9969120d8f3a23750cd8c4ffdb87124a2139e8ff2c15d8dc944bc3c3a066aa16dbe6dba4a74925e16acdb2b2e83cd7fd5cedade6a7f7409a509c00dadc182b2860609cc9a375cb8bbdcc350bcb2c0df9b3bff882e\nA = -143caf995b7783b1316b5551978727f06512fe114b419c735b3381ec351275fb7fbd6ca88b848c3e8c9faedebd6d084cb8a231636f68f6803d14bafd90534609d4a4ac0fb953417be7fee4e4cfefa452c5ee5d1e1b97ee75f83cca8691a0efeaa8bcc1f1e0f18c0c5d6c7684c9da6c9495d31a32f40a5\nB = -3025fa05c55826c40089b12741b7d406f748cabf692bb0227519a124653160142633700e3c0676000943556f97551171d231c1a35f7b7d8f96b0366eb74942466ceb4660f09aecb2fb2ac050ef699eb05bd8834a2ba959ac71550b5c026b9093c8cbbb7c5fb9390a7818db682b7c11e58996c9d0add5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 42f363c34c20c443c1ea7a1c54f98c6977b6671164a80308000533b2404a7f280adb1f3b98101cba25249131288f7ac68b0ae2572c7777e7381c1f4d05fd82188c4b1ed5636652e0bfca4d096bbf4189a9358b79f6b6333b99e5c4b7a940c2f7d1413bf9f47a2ef66b620b5e220b2c3dd7267452eb1b9d8d9cfb17bbfcdb6abb\nA = 499d05de867bda3118a8cb82b80ac91fc505e0fbc6c7dac5fb61713cb6e715f56a31ae8af4b400461d7ad1687a2631faecd90d7829f67d1b9e36ed7d55704b3f2aea65eac061172d698384daea710ed92cf1140cd4da427174bebd173c2ff1675b2407a84649b0a318602f33105006fe4d5ed8d0e015b99\nB = 17a426a12a0175bb46bf7a7e727eb5238af383cee6f4d5e2bd82b0d29b9fed35f3d8ec95cfdfcac49bee47b25d3b5f375a3340fa83f8dd9330a593a974d208debb7e567e59dbb7251b54e42dab2cd50fc63aab050a41bd88282373f8195c94c35f61bb48aa921f574cb4ff0984ccedc070efea8c46e5cf8\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2f03374e9596cb56cbbd89794090ca7a4b437f4c05fa38a09db60e5ca900b208fb85b52f71c29fd35e62c9f9529d7ffe46fcc54607ccb07f6f8e13fdd4ff1185033ba4fcefb1ed4bfc42c3ea9f05276767d8dc9b7b4aea4c8bc0ce84951d1f590cec0751f73667db19060e2bff64da30fc048a", + "1f5700fe3f489920675cc3540a\nA = 1073531f678877ba854fd1e7f857659614c526847ffbe8ed131dc9f2ccf69e1f1e917bb44a7b905f7ff758f61c06dd59ee09567d9f0df2550fcb98b776ed1381ce052988aa08fc5153e31c621c6a51ca61b386e3a9163a5cd69608b3e200476a8ada35d906c41d044bafe71ef5c6f732935f15b53bf36f7ef8\nB = -de3563925474e5408e245184b57f328e265b6cb62eedcaba809d8f257eccc0a457eeb82c451f93af93ce9f36dd1aab386e7c02b356f31c2d170169dbe15e70cf5bb9073b35fe0e7c7fd7faa91c5b2b0740734f12eb741a9d9ac6dcf7cff59f6e16324ea39e1e07dc5b9daea27ac674dfe5d0a5790abaebde9\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 1aa22f9013bc1cdebbdfecedf710c1bcaa41c696a3d7dfc1c8c601fcfcc1c85c8cc24be7df2cf3c7311b3b17a4ef2dbce545dc467d2a92d371e02a196a9977cb9042b236acf99d8c0d34a1c4dd8792d3497cffbc87c397ccee5d01fc2c89ef051324a7061e423720d0a3821a36739797393bdf7a45b5fc600824a17043312bc\nA = -4fb2e3fde2a0c653104c077cc6459c9234f86cc2d7b317329b68289826d3e2b975f1a69bed1a53418a0dd86e1b2723f4c4c5a29d003161e667c2315ec24a36f8bb5f2eb0a94f261e791bb829db685cd0ec9e1e301dc140ea57cac1da228124ae029e2b8ab1fa3ab99c55a9ca94dc7b767162c0a24af851fbb984\nB = 63702537a07971e399aa9a1a0795db052d6c8185c79107216babe11d6d8d472b61e604cecf9eaa6d44a2fcdd1ef0b6b52226ea0c6902d929b09e16576e6d1a6921765b2134c5d23c69ed61f36ea9a5552e5819350366240693558fac7a9d09ecd3702076c8c758a4bf6843fa843dfd688bef3f73515db31bfc26\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6acb23ea695d4b60cce53079390da3cb3a4bc3a6486c238c421f3bf6c93c027a0475f656c3e5435f0211e90458ae81772aa956ef284093020f7b58ccd9373f3fdd39fdf4adb8dd64590f4a7fc05238ba20017bdad07f5f9a6f076b71554a7741bdd8c98ec68f8fee88396cb1f47c64d6da4c228caa3dfc7a9a1c032a9ba4fedc\nA = -1b2496ef929bc673042996ae80f27c6bbd33fa7c20580240ef8fba985d1a6117d6e746989924e34f281e7d2509175d0773dd999bde16662e88fcef52978d19cc45fbae3997fa580a66171d398f4f0e7605d9f4aa4f728902cb886e6b6dc9f0161e7cf1ebac05a09c5a1bd69a92273280758173fd2c14550ec221275\nB = -28399206ae2820d26a5aa0bddc4903776611d08fc4cb34a22a8bdc2a19e9f8cdab94217f346a8070a4145f989e1dfb49cfd100267635af0e062872cc879c534ff138fca603b5d45a6860ea85b6de37cfca000c81fcda3d14ffe81da919b2a25214209b085bab9cb511889665fc845acbcd038711533da171d8308aa\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = c012c4d17ea4c95a360218adfc3363f6d89f5aa524aec70049ef94c2c05e59a66ce01e25588e164bf2412f9517b7740de53d037e71ec3a1d426f05b18b128c41a878da75421e8c8ef3ebd5effd40735c00818eeb1ec63182b44e817403c9f1f6c1a0155334be63a3a15109be6d45ac0d1b1ef5cc99e9b284b00c487d91e5472\nA = 796fba6276fb7129eef2d1572b305f63d7b8c49371cfb3b2c67b141071e66ccdb5e321fa2c1bcf624c77317e2aa135e1137dfa46a34c3ffefa2fa3e316be81f45614d422bf86fe4518c2fdb7e416bec199de033cb5fef7f193a80c0f0e6ee924a12c8f705f5ed3793ab770914924b45cf2578bdd09c701169f0a881e6\nB = 12cf934763127284e642ddc232b1c889cd86617307b6ad72a9fe0d48befd7c5c5370a0062dfbde2add256dc0af850813b22320ceeaeed347eb9319bf22320b2fcadeb51c4bb26a160f7459fc172c27a91d367d5a232d00cf7bb778fba83afb744177bf1ddf45446baa035fcd0065f9b493d92eda37e9138f4fecf3ec55\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3de123bbd50c35805b943e76e97b7e664eb9feb99860750bf97e275029e836217375cc1910c13269ffbd0bd72bb82ca445ccc4b693742a96d19d3dc23f78e5ccbba46d9ff5975f239551c36403ad5fe86997536456c4a5ce54807c24e3b5317b1c7b2a1661aad85b63859d427f0703b460cf72b9acd3f87e2e69d7f8f15e972d\nA = 1d0433d84f1de082d2058475e0168ceb369013a67aa9417f066c29c28272a0b3f8be5ac7190ab78591ae72a1dc8ce628c683281a9ad563e134387b9258b9c96d2df288fc118a8cff068ee49d635343772c2fcc252facdfc93112358414e1734d6948b909b53e46263e9a0cbffa141ef77bc98e7fae8ae2bd85bd875aa7c1\nB = -a31a574d105305e47f4fc00ccea0cdf854556886b524901c22e6f3b59a42915932ab209a8d5da29ab70d1472dd5378d9c79a7447d17665f9d1f1edc1e545e417cb65415cb8a368075c16264f42555d26e83adc704b5c126c6129318a8f394af8bdbb32c8114470d11b2acfe806acdc7b96e1e348a32ff96a988de76d4623\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 770f0c3104c0f3395fabeb75ddfa2c21a111d23438463941239f7c63e4b6e6832b84508ebf3cde1d90cff0a2801beee05cd5118f9a726a987eb58def6780be899b473ea71c697557ff63a4c6db894e9438595acdd98abfb529d75bdf3c1d619d6165a9edb6aaab8ada50b61a3a84de654706a9aedb7321b0523558e8f18116fd\nA = -5fafbd498d610e9f29c38a5c6c262b71672fe9e9c84f0f071b549390353e4fd0101a059b7c547007e27df97761767302458f1936395142ce5776b0959fc5ea039429d64ac5d50c2ae0ee45d60c0c50b7ceb4ff9853d57c6e883f588017ffcaddf5a1aa3e23ab068877a114d9a2cf742f01f5f5d611424c8ec0d082f5c165b1\nB = 552155ef110c126afcb87dd20251220c7a43bd0215ecd22249a21c93583e120ba6f046c6fe03086ef3c97311c4d520110a450470a473d8633e3560d2cb44c25559af07516aff50d6d176e8782c06cd9aadd3354cc695c4ea8dbf85e01dad479c8e8438154351fd5fcc6fc7e9d2162ce2f0179247f756f0b9b34b54be74821c5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2e9ed66317734668c4c354d720a011fc65bb67439b2ac9203dca65a8f567682be40cbad4f55a83e836f1fc135596b624e4327acb085a61b6398237fef5a6e6560b488d4a673b5ae7d734b896d9647d71087621cc81e94d58e01fc2cc2dc775f9ab1b6031840a672fb715b77bd636e3d87b4949ec7bd60721bec8f9907b7c072f\nA = -1a6b046d691830d33eecf2c53953676ed3f6fdd20c2252f6e915052ec28ad1fbf7a5f264acf87ef8ecd515ed921ce6b85017f3d8a8f1d14f269f31e3307c6f935ad468cf012a912b0650a15106fb949cbae7b36c9cd496538bb0646a7a28989dfadc719424519bfa43cd8833d3a748c758f813881d83c98f7cb2a63c2a4d06b8e\nB = -34f87db0f839af6e4c4bf146789db36b3d0bcebb9bad81db690ccc3a35070d8830c9745b2fe730a1f3a252612e7026bf9889169b57b8984a5479cc4cdd6844ee3e150a2e7bf7680eebbef30e0591c895cc8b2ca488d489554f2339e2f55598717ddd8ce444a060cc95cad9eb478491ee8d3b8358c3762a970224abdc1068af0bde\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6455ff7c12bf3bc37120fe3f1302a9916a6ffdae6ee6a37fc23ca2f3a7ad910dc0e1027d4dc304a8eb4eccbcf3c87cf52a13dde472c07e2df2420c1d36bdd5e88c3d76e774ccd2ecaf6a0ef55b8c60231b1348a738f812a4fd9d0c158fd5a9fb19cc7cf9f000860d4cb6509271c8e43ae4193843324db02a029beb58ec2955ad\nA = 54ec203e2ababdb0348135c0679eca2a8e778ed46e53f195331a48d3828e5e40da804ecf95eed819ecefaeb9c5377cc1afb1fb220175990d347981353e7d90637adf8cbb16812af8a3783dd312d967a490f8efe3f23746929cf2a5a8df58e0b878367f6c5e4d3c086f947fc2bf70bfc3a0008a8bb1d7d83f002930640b6ed94c334\nB = 1311b88a05224e15f1465c8da26784dbaeae84f818e029301ea39a982f714c64312f9f02d094c401abb6a89e8537d64c178637364bd261f4a27beeaaa901cc7b3d4e36ebcd9453cda33d47a53c6dd1d121dfb83a222cfd16158eac23482c8abbfaca59e765f6c1fe871d884d281793eb19f6409dd6bbe4083bf762ef24c24f0127613\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 64104f6c06e563ec66de4442d35d88117f2535edf9e012897f44daab5a1b8a8696f84db7a68d64ae24a394debb993bf6734c", + "9df542c7e473b2e497396ce39a064789d5d7b339b65766b002a18096e7fb9f312ea5997c2a85463fbd6fc18f25769ac2a2123ccb0e72f14b0608c4c22add72bda138b83f986e78d5c9da31b15b9d\nA = 145f580c2ebc6c0354ebdfdbb1d3d7fa17f0b55493b0b9a11b71001c840a967dc77f0206c3dde161b5a773a6b5fd9471fa08b205cb6f728e3afba440b55268d6a9542e234ec313d53583c580a391d8da5943f4a900b279ec9d8933f2cfbb260b74ab714a8b9a1af3190d914b6e42212df84f933a237728a5fd5473ce2e272eb82bc83e\nB = -c67f9b9295dd5844307b8fe3cb9c1875257258e4be6229ab097e148c0175ecd0de4d84fe03c8da6e27153c709c2526092b1abc73b5fb40f1d4da9e0f3d8d2fd5f8a4e6f3c30befd80e189b73fbd77e8547b34010d2aa57072db0f00537cf3ced95eb517b23e0c854b4becce128a575a31037c3a9e106a476d8b0277d26dcee435cebedc\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 11913c40d577f70a5346ff1cfdca492ff52b640eaf257510d311872c8df7ba9756973da5b9206c6e5254bcbbb4bcfdad5fc4594e41ee44e77f168e2d20a4b228480a9908b102dafddd039ba7f7619eed7057e8af3a72ee491a61dd049bd947e5b09a94ef94d5f336945f47104fddb8493ef22fb648ff5376b68e96c0555d74ca\nA = -5537630b7cfb8daf76d14e617f7b69f7b75b472801a9a818179d83ef2984d0abc8ea4214ed3d3d2bd785060e9c2819e861d0df760fc1daca8340e8a2c997c9ad201d6d2f12a82ae3883cf9f5c51ff1c25277c28175859a7b8e5b6cdec7cb3875071cbe415bb698b85cb19f617162587516f93c728ba8b2cfc19f238e2cfda115b8ec0431\nB = 597296cb27080f33a24241c1e98fdec32f7a4013a7340d367e4cf2a521cd462a2803109c27fcec353a30dd20053a1f744394fed75829e8396f8de434399bafd6cdb6e0ee81343f0cb99ef3087a7c69bd43bd722745a46cdff0c2c837fd87543c3c63df3896ac101a145b478dc224644996fc72460a89beb5741b91a42f2fbaf0d62c099b32\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 42f420adf5c6b32ce53fe23af4e392517e37013b8c3a7d035a93f6ff45142b0b0bd5525cde85f9b7bd9ce219bd3514617e89ef4d9279cb9a3e89e44f1994d72febd23ffbdb0a4f19cb76448199b31c5cc6d7ec1e46fdb67be1211c0ccd93c123d56ac0d9cd2ad11f0c58c713165003495b75b60665047ef80f6a393474cb727f\nA = -1c6ac9565d1950ae6c55025f76e0a040eed0462218e97aea87208ba879acedf413ffd5e63a92dd8658cf5f49d633ce7b126091a55701168ee4932db004dfe8c35c939887fae3a892b0b04d8eb74191bf8fdcf5566b4d3796a5d2596b1e750f64201057ae60aa705edd58aba4b48f6a2e511bf5007a6c44a27e3efd5bf2708f7046c1fff7864\nB = -244f2a90a57e5d066fe22f4d52f91b44882b8ef76d1dafc3387abcb224eda4a2100239e729bbc745237f8129d457e98eafb2ede2f3afb81e63520493da2a5730f1170b31fcac21259e90c894f8bc488c5e5dab2c2635bc7b1ff56c3685607f6fead73a09f83a7a168c4245729ce5b06e482d7d3d72eff33d14cfe2f32f72175484ffa292a9af6\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2239459025b257fd0b6659f54b8874f93f07f4d6240f8ad761c9da288cf1537d8bd001eced284bddf78edd611c7f28f1393c6fb879aab6e7df8eefd347d63628b1ae086148f488b01272f67ca19db71a2b284eb17e17aaf1e3e8f23ea253595de474d5cf47c16aecfae360eab7855868b8af361491f6ad96f893f9d3eb66d07d\nA = 558613de283911aea1ee21d6b926f531f778c5226e978ce329860682b5375fe5e5328ae27b00f504f2a2d24470d16c1edcb8e76b4d1a740e55538e79ac7da4b45c5299993513ec3bba7e7395dc829a00d4e228618dd348fbf838eaf0bd50f6c70253fb1c1c734a07d0813915be25d3163df13511f3675022cb85af7646c14ba5d13f615ded8e5\nB = 1f3c3c468146c29408d9207e15b25186d3b06b3fbf9556eff7ed7ef7788032d87ae1a4d2a0983902d4c70936c615d8c9ee26c89af8b58d60231ede54e859763237d5ac59af686300a3e92f456484ce77700557ddc0f93bb40e5d2e5117f2356ac7ffca26dcafb3ce7a5573e07ee97515b6b082fe75fcc9dccd76b4fd416e69a247fab2b30965d9be\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 7650985e7c6e5461268867dfa9782cd8154bd6a4bb5857d6555e9d9746ee79b37e44638940bf8d5e974911327f0e53bbcfda0739056bae2248015c35839f35e7e359e93d3a339e7af38c0cb43eac5b41e1406e34cdd4afd458a5d126f70b5d683415b490e0ad61269ffe7ea8972eda6addd447d97e60891e5099ee920e18f233\nA = 184845d3762ad1a9c925c51fabc7b9e15570a84a06ecef994910845d56869264273d75fbb84a31c97c27eb9779e8b39f6829638a78b266326b60546507f65128caaaf36d4e7f85939b75cfb3145e2b1bd8372531cda579f59efa0da9c95a8efc72faf326d35c660b4444627d328bedf50a919029dd164de051a4c0c924103e365cd640b9637d8244\nB = -977390f52af784b52c1d54e82131b072a1c308406e9b82587102e67c6f7145f0020952231a5f0ce9d130677bb5a7a37d5a06dc570a13a29673c8a9068f06242ac438806c37ec46136e7c1c1487ca2d330fc1f3c1f42ea51ba2805b74c44a61fb2fac109710dc3dae78a07057a753898d4e849b910f035bfd807178f0108812778345b256c7b59f8883\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 35d48c3e43070a10dac0e256afb83b219aacc0036f554bd998b9092ce3bf87bb5d3b00947f2c86fd4e7ab830502d15fb2d4e47ead087f5c779a9ba56e272ea86116e2c81345d379dda6b581e9c8f4df8ea56c78f04d4f7412d245e00ac645847af6ae97d5d2ab27e48cc878d8b510c2dc753f6ceb1b9e7bdd923e0e065a6c11e\nA = -76e575cc79d7f0c313a489b255e85d114f3933383cdfe75cfef649f639921eefb9b3b3184351fd0ad252c6e477e153ee586a0ff6da1e1b2bfd7e953e6dd778c849843fa5cc355b31f5529ca45aec81ba67a1e364d5a74a4656d266f7decdd47b2fc2d81d6c298afa2d1c39b5e8eed519a9997a14513537cdcddde0b5b41314476264d59b7d3f0e9a65\nB = 6b7faa437b4e8db8fba56c62eddb8a81e9090d1b6655a2185d656b2db0e85225992297381d653e707aa15f3017880b0f07abf3dc455cb09c4e551b3df3516c6db4ead79b88339fc33dda96bba76ff7c388363c36b67fd5dd0ee63f92f67549dd77e37e9902ae51cb58057579f03286fc48e3b7fba763fc5844c222e6a1eed9e1634d0bd034cff222bf147\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 445039f359b55eec647296fbff4f22beac09cad32cae79c13d591e314fafc2b77839816aa4f641250938865b0a2c30a10e23da71a6dff5985ebf3df4429fe64c327557b12d987ad9e9971f7c7b1e4ad01c94e1e5322dbcbc4707a959a401624619029558fd6f5b14564469b13146f9a2555916491e4d77caa70f51716b299135\nA = -18ddf976fec2090f7d1f4d41b8f875e56c813c04338f595d6e591b3eabf9e105be792f45354ee9beff997e6c0e8ec3fdc714c07b3466ad1a949b9d30da0115f5484c3b9e00c7cf0c117db57c3c6cd7434371c6d9ac7a5da1a0e2d705bacfc22f62785222d59bb5bcd3e3bf2df8e845953c6ddf1b546cb75b1698dc8e20bc611294ff288056723f1e46ec9\nB = -2cbaff39103570df7d85a5673b50fb8818434bbc19ab4e33bcc8289a4047d85de1b7029a5cda3976ab12e1d891b7efe3d5576bcb3713c597771f93532853290068761bea04200fcaf9b05d8553b960ef5e28064de89d9e5097d12b26af0b64beb40b33ff82a55af7c5838b44282917fd4342e2065942c724f3cca515d9142fb8e46652242e8f0ee5ae07b6cb\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6727c0d0ecb4a375d0fd1bc52146da1242099d445ed9e87b1fad4daf8369fbeeec49027d88bd98efb425c1e3f73e412fb327680068ae57d4a53992f3759af0ac1b96a92f56c2cf552e6682d1fa90c3910bbc5c0b1754862ee13c5ebd62d5b98bfe8dbbf9bf53bf9ed0b967f3c9da24d4334b9f3f75314b429b05b8e27142623c\nA = 5cb6c49efc6767cf956885690ef740337aa71b90c1d4b9b0a9e4734de0c0c50f2358fd45aeedaca6e1dd0fb510bf097bf46513ee09f3343bbd1c11f507eb61d51ada40c5d6b730561756480063f60caf05141bec9a769c241d367cb92fa8e229ba2e471fc73f48812a25bfc7553c395ca77b80443ccaa82fbb7198f8c35c3b5a2fff977d8b2a29cf9358ee1\nB = 16ff229a0e67a410555dbd4b687f1470ec854ef67db73a902f2d19953c55071c4a26dc320baa8571586f1fd54fa490b0d87dc83e5bf20b78956084275518b307ce69aa4ca1079e3aa753d97fa1cff62e0b5f3b99d96a24e411fc3a3e375", + "ea21b7b35a578a72df68d28286fd9a324c06930905f696424780083715f77961532bad061f3901ed276a9eb6e81ad4b4\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6e9947beae4d934253e481d27e854a59c4047eeee4fdc7df7e174a8f045776109c148ba3721685195b8fb59263def88891c5953b5a0ae85fcdbf02abc76f4d3c0f5d9496327d063ce8b3ba875b4f119dcd8beefb3ac884c25955af61c35a69d0670c3c349564e5b84f7df4252d6d3b29d9a75f09e9ef79f0fa9f797bf75b8ccb\nA = 188785951a3befcab56128cb6fb9576bee2412e6cdd7dd1bf5643babae83c8011af99aada405e119c3be33653862440005be994bf37d3802cb6c73cc312824c56841004c8e871ffb560e93a1d222c93d63684e90a91394b9c8ba8cac27b414bf818ee0de7217bc2faf099783800485ce2e93612ce39fc7e2f1db708bf9bb032d92b66159073fecdb2e0257058f\nB = -8dddf094f30284c213577ceb7f1b2efb1e4213a548e6aa840f801cd6382fb6d4995908b7827078dc3f46fccdb9e071bb8531ea8971de0ddbb714d678bb71ba9d961e58cdd5f41b8472146ff9b814a5d1d6368bd94812f8d38f235f39aeb2421a57499fe7102c1ab167df7d33b32a6dc7c8eb8f4babdd6b6c929d1ebd9bf4774aa40cefbf136feda7b6e10ba4dbef1\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3f4a8d90017dbe8e77205e65fa7a0875a1ace6f3f215c2974e47dbac779804143da3dbce92db391c2614c078997c7d1a15439ffb51a5787f5bbaf98a4dcef576a6317b9b92dd8141a8fadc05d3be7c150630668e620a4e07b4b00519f34e422610a160de112f1ab8adf09a9169ba95b60242c89196ac6e155021dd84b3054511\nA = -65ff4322f8e46e03aa6c1fd10a207a5e51db6991bdca232c0dbc9d73ba77fc485d881868be7b14c25b05bb59b7f5bb6c4b2a7d53f35d2d7af282a0423285c5de656429ab7d3af7d92837e41ca701f527845e98c2bfcb51647512e6abc6675cec2a7d34ce55ea4dcfe9e7a8397d45a7a3e73bdff06e303a8f04ab6285eeb1bb78b1455931cae203078eaae826a6e5\nB = 4d936b603eba3aeec3d3f1f9acff02a0ecc28a8ec64b6bfd9b153b1bbacf4f1e186d3deda8c1c81e759237921cec53251250e3e838f5063c4a1eb6cc93637f35aca10b965533d18b713617a312e74c446d63eccee93cc97e3723ab27357ae9b3cbfcb3e2bfc589a1bd582480e776198df047c3ad85f611ca6fa480c70aeb98af02f57d56dc9659b2a6bee222dc3e0566\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8a7f3cde3230af1f1fc25e0c0e9ebeb69161d3864fa5a03e5d7f8c82d9940ded285df35c008f61cc151b4578e2677b2f2cff3236935de5bb1d113597eee448496fe29bb18343687f6e9f1c783863e949a0954de2993d47a03607423b458bfd18c844ab57e9e2a43930df159ce8564edb5a2a37a06425626502e3ff9363b73c79\nA = -100f2984dc1451fd7b71e5d290e4b7de2d26175a47b9bed524fae02bd5abf96faba06e955107329559bff3805689633a4a57275732bc42183acdc792cbf7b6b24dbdc8921b73c0308d0c0ce5d8aad75f7eb16352e67116e859b323deccfe5d9ffdd1f0265297bc9eede073146a06acc3c330458b07b8fd0bb652c7325cafdcfa165f69cd0de8b145d49ddd576fdde15\nB = -21ac4953e54347a56800d75f6feb6ad660b0442174cf3c5dcbcf6528e2b5da95a614d3a8399da14507df4b8eacaddcddd627b10ec2dc5fb8c43d96a38e6dff37189ba275afb9484df800587f4953e327af71dbd58780bd5885b4cdab15ea0f2864f961bbfa9bba6b2d9448443af87c0cf178990254c1ae6e19003b1621f3240a6e5d0a3be2deb5dd253f5e1f88dbb60b522\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 76f8b44df8d8547f8b3d8537393d2805c699eb37d19bd115bd5539adb6b6a00d004def3b7793d5c71e0ccd2b7e9fb87103c1a5f56a8f18ede1bfe1607a346297166596aa78dc584c7c32832e11b72fb4f2d40ae1591f341919bc0157080ee8febb7fee5461a918d2178fa407c37a8243e24206ce2c19c3addcc2b7c3c1912b6e\nA = 56f4d397530f5c90203df1ec799f82a0096888fd370d543e33b5a2c8042108bb75a86265204c40fa5a9a44965ad2fb41896b134ea56c79699a230f38c0e3fa4e5d346cda70e0253b9993c9da5642f4e645a0d96cb732f8f04c99a83d1f1360a385c6e1a972b89915489245ce58830788ce23b9e62d6b48a7ff9a486614d6979033f7914a0735d201c6f29e512374088db\nB = 10fe818f6af7a95cfefb0ea0726f9a3e0e7c30dc9785b1fdf6e2b810515448386c7efc656479794d389e109ef3efe37fa6124c5a7db3164268da0d98538606c57bd2f7df9482860e81f272a27c727d7d81a66fc1a9bc8c385cf02b7ca6bc7ec2d8d6ba1dc992caa216d02c9bf0fba8ee754af77567c6e275ac1b6b1b36b065760761300d156e40da8445712b8fb206c0df346a\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = f580f9d2438b22700c3ebb23d1dc296f3d33deae2d32dea51c7ed3a0ce7b06af11046bc1cc279bb744bc31e7f822c17ffcc5dcbbdabe213bf97bb85c7e19ee71a513bf59b25b3b5787e42e9f3ef6aa1acb8705d69924a107b4f88e0cf9276c2c7c47fa4bf56c4900b557aa5587418f0ddd899630ad3ff678b5b907c07247b2b\nA = 1017a4fdce8bf41ce804b7c9c836d85ff6ee899807e1736bf0357b015b701b9675297e5ebf588ac6c295feed3c6a367987e192be0d89523ac7d64b0b9576f311b5b2705c5398276a52f06085027480c2ca72884ad7be34967bcc6c8cb4ec4fb761e88c16866a2e284b40180eb14536810eeeb180ab701ec47ece62af65a0753f95ca657e7d04ebf3c3a7db02993da9089840\nB = -aeb03379fcd4e87cfd18957a72fce42e016951a72b673a9e81f666b3cb20d2bba81400ecc2b38601bc3270eac46a633a1a6b55c50f00e9d7fc8a20176b93e971cfaa4f41573b17b8ccc498f8a3230825afd0d7f102daee347a9d59cc0914ac8689c1d8b39ccef1f3def44054307a7cb7706535f0cf4007231ba21696424c3d5b42c8e85c278f7c2e8b7d1787effa601ad357eeff\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = be05efeee19cc91e30a9277a6551aaea63aa3861b63f6061efbb0b92296e09f4709529eb849d9f40406fc59c526a4697144cef9661b556040458940ffd6a87ed56cb073d2ee0e6d1f05936fddd1b9a8974a3088577847ddde6bbdfb3d69158d5b3899c13ec78fb5cb6aa7204efe308bbe0b52f18381fe838536707a8a27ba0d\nA = -669660e75eae9930dcbdb99c477c980869417ec9c0e8c4053f0bd8ae62d496daf7539f37af96fd1cfcf3149bc02b8182a46b413e3397b49d4b4d204491440eea65505cf5d33a8e797af08f3da41f5a0804214846bd95d730260c6545d51126278181719ddd396c55f119e84da71f0683eb6db8393b098b3a0c5999862644e073b4918b5c8aff17efe860744d85bc94b582d45c\nB = 6045f903a750b69b709cfd6a1c8ec9fc0d7da9c53a9d26fdb0ce9a17c6a0ed5ba633d6fc01f004f4a48cf247d61f7df609008ca5bdc8eafe06dcfa06bb67efa6a584b5a2f02768718a908978edd475a2d2926af2a6e523549a5cbecedc78323c5c295bc0b8d3e14053078492e82e339ea2c6301412a5dd7efc20da0aad0577a37d853eed820776e672bc6d23dc821b5855eabcceb18\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 705bf20b7d92e68a69019cfd721b27373c7ff22f911066907f556321371fba70dbcb9774d3a26ca43e44ab20c586a3c1546fc3152ce011be66e04a59c6631bc8bde18efb7bf1743b9ed75a7a6c5bf5a4117368b81b112a3cd4e1c44a621f534a11c426451ea5fde880939ee5bb28d9843730e284520a976cd9f60c94751050ec\nA = -17c1dbc1ad1d2d33dfe1af7b4cdc7b69fefec5a92656957e111aac292e44719c7c752ace33dc74a6568be38b576a5ba174bcba77a034af5fe101699c99ca39f8a3b0a20679e6d0180868a232fd8fc775089e185e5eb81585403f32619a2f4d857bb091a824a89de2e84529e5b0702b45771a5816c5a823d81ddc89f8a70cc3d3a0c6bd6d85e9d72b69d2713b61c46161f7f4700bf\nB = -2252b54c602456c5deb86a0f249f3982c3836b70a946f636b22fe00c6e3b91b94e19200a33087fe734ce9a3f92a6099ad03a95ca523b7edb9e1ed3464d38fb96c470464e1c54790cd48769677efc5e1d22f5be4c15288bc5ea1dc184a05fddd5e576b3b4962f37437b4f9709dcec374377db44c8ba1d8611c0c3ec35f9bba213eac59a047e78195ebbbeff941c7f862e8c80eafb72b1e8\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee", + "199bc20d30af280fb\n\nModMul = 7306e3172929c00c29ca1db360eb4ce82066f237e9cf6aae368d1f531620e9b61eb64f5b3e2b735a3b565587d7e955d052df94a20e4aaabe493dba2c18e85fcfb65df166cc48733632d165129b112598bf5e4c58dff662e558e5f71b25f36708d3ab6536b1cbdb5aa2ee56d9e019a9c3629185b188af909831629ffceab634fc\nA = 6b31ef80767a7693e7d0a9ecce54beaf5848120f036923d80b7a0245aa6a46135e32314f3b227268e0bfa1f45b4dce83bea890526c7ac3efdc8e485189ce2c51597c2864c2d3664584be23559c03670622a53edc2c17b3f1a92640078ec35189dd7953e55e4da0290ff1e2996d164d69f1bbe6f5285ae89209d611a7d760e413e23285066eab8e126c320bb6130a91d67ef26d4dabd\nB = 183f06828033287497322b05ac08f62dcc5fa67b7a10c6c5a319c9a1e642754230c6d9809dcfd2de4bb9e360d6e6e1180f6ec6e0d4c6185e34ed299b6171e653521d0f7b8975ed5e7d2c51d27f9784a4b6f9b5e97379fcdb42e4df981462cd5bb9d0501f93f217d954f6baf70343ec710065eacbd2b778430ddc36a7ef0515f29d5fe78d8708d8ffb6c3391c6f632cb1bacb4ec52972ce0a5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 361ce44d153f4d251952c0b90681a19b7d2d8df7a6c5d459691a80c06107b2e818f93f30f8dad352d2dd87b01530d51fd1c67cede9b1a6167697098e41bdc5dc5e7a3c310116aed0c7b5fd99dfcdb3517c13daaba6ad10879f600eab846cdc110d392d9bdc0e8ab34b317840a725a7a12ceb48c75e8dfeffe2947aa85b2a5158\nA = 1e1f2e44bc7c79a00afc3b2570d5cd27ad5ec9f45aa94f63f2ec3fa6b69077480212a1cbde25ded7ab1c6cb1ec26d5905948e5c1d6d109bd5047b1e038666054606b42e880b609f6f00a219dcfb504d481d6fe709f4362940f6c4b6f2e05d243722cb32bee5508ec94eeebb53b5befa551d3ab5dff9cba3daebdbc97179e56cb778aefdda6a0c24265728ff9e59ca3c2d615398d97e66d\nB = -e018708df037aa2918850fabcad82731487fb812213b1c067d0688462a4d518e5ec7c4c84f2cb2017aa6bc960e2faabbe361ad8f66355366cae869d366f06d7cc32ea08dc51631e7f36a4c775611095d8aed06a0086d0a471749246d7157947a1eb5d5503f207723a7062382b3e45bb84c6f555e48f6d63aaa1c04fe13c0108507c0ced669a5296bcc16debf18e03c32eefd177bbc1dd2f19cd\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3aeb3ff6e797d271fd2271499a740a91569f300d7392a7b5898084012a3c5ad379a57d5169e43089cd58fc7210314758d5368dabca2f0ec5cf6786801bc99b45cd60403c732d9f98936aed76da724bd3e7d4b622dc690778f11fb0310fd4cd980b220627f7a864e107f93a6259081c6581e5dddba4890508af8057c1af29a745\nA = -75e06b47f60edd23148c3736c9c125a617beea7c8fd47e662c9d9be883ae925b7801a0030df3f4bdd3c9fc386f18c4e002e5daf4a6f7fa27b2f71252c83d5f1695e50d62a10b99e1900987b342290decf681a064f789e11bc3fd75d64e2e78ace56e7491fbe0eddd6f9958a5f95775c920ad6c051ebe7750fa76891ab00f42c910550a42bbc1c1e5aea0ae13b7e6f916a5d228bd57e854f7\nB = 434c8e4767d0d7df2125def75a978bb1509a26bf8305cd03df748c6c12b6dc580a2c1ca9a4526eaf3936fbc4ec797d0733217a54ffc9e1d7c6ca04fb39679859d5bd3fa64cd0a09cf1a056094b9c20ddf1f00e134533ba9892c2ca7346ac8d0655250eb45df9f0b7983bbf71102c6f1a2d9497e7a45eea7b3095cac037b7aa755beeea8a6191da268780179a652d94a732a2a5c7b626c0de3145f4\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 734a429c91f5b0f06fd47725ded06222c0193dd407e9daf136696f203e153c9bf6df59016849284cef93fbd35edef2cd31c9b956fbe562d2a22100f177254144718ac7d22c99783fd523b642984794bd7beb0d0b363e28d3f3469ee332ee364faaafef25c1d4a11b5e517e44a412ba717a113ea9e1e8f2d6db8fad6f10d06950\nA = -18dcd213e9938fe4b6a64abee3b9867f65e47e5b0365d45a8dee14ddf787f34072ce32f38d4d48ccad236005a23c5fcdc02b72cf27001495663fc56f428072d3f1bf5e33ab2c5f9dd9facf122f7225ea03c2f67321530a642803f65a2e9428f32d0d974e68a25f705e4f8140568f7e4b132942b49f9ff53f04f241feaa29aa353925fcade33a0cc192fee2628c2111da1e652cace9d304d0f1d\nB = -2e5397658a5e6db9d30f09e93e67a30dc84b1e17c25786e041fca48ab710e1d0497ce615264f1abcb23d5aae8412b58430bd801775acdce06cd362438898697940712062b611c92ae6ad10da31784207c5e7b9362b20d7254da0df8caafe0736002dd466d76b1a03e91a8dbe8a71107abd5f07b00fcdca2017391c7c3263881a3d02a89b0e16a2a765a32d24ae6584cf44a88975c539402db9a301dca\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 427609751f28edb62c717bd98ddf999cfcf65128b652be1b5aac0dfe1bc0f7687c580ec70c8290455a9448c69dcb550c0cfdd109af561ece2ec8707c1d02e8097e780f32ddd932e706f81f68711acda0e7610f4dd0fd55f6ac7ca3a3184f655b0b29d2d62974739b43ded96b413b9e3f0033ca1edace24b6bb610bf06b5d940a\nA = 6576c31d48daaf7d6bc3658952c4ba18095f1a0d73726f6fe59381af45a2a6b592adc79fbc3b597e1eea711ab295cd991441fb5fc4ce5f047e571a7d949c709e0d31156184be4b8a6a49691ef93d7d3b120193f6ee82246aeb896b8b7b4c74c27c02cb39fe0335883a3f088a71ab42b947a0cd59dd2155c65a0274ec0836bb8c2fe394500724ef84d869bee40291363389e7012d672b1eab6696b\nB = 1ba2888f30be283b588cddf00eb3ae3c641e35fc0bb3a9fc85d7fac1e81052129f499afd3e8458d4cf893d51fe4a2bcddf70f28c8edef16c7bbfb791daedf1a8248faebe36953560498af652d1f1c7aa0e9a5a667d9c94f7d9525cbd5a82147d58b738dfbba5aa162858c2c66d0dd7d8db38d41a2261e6efc7d0c8b2dd2d6962be0fc796705cec8e87a13092e4a3febdda3d4dbed9d11a1d5f92d7dafcd6\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 533d6d8d7384e6e65569ba0daae0a8cffbec1d20e417a6edb42d401a59de0a91a7e6854db081ce33b76faa63f6d866993c245e69ddbe6c86d339f7107a4807856cbca23cee2bf5496388ae8fd8d7c78767d0775acd7bd6202dd75451b424034e2766185969b5663b638d539f718e50a9f752f406c224c000bf1ae1fdd60a2a82\nA = 111940235b144a42a13201a41a3f9e4ff02948f8e9127d9a3007906988a50b36d7622d1221155f2516812074a7888b1d8334a01c02ee33b3164d761d02b36729c299ce2455a462bf18471fca42e5b01615d53723c3fefa5aaf4a039a6caad35c348a0a4dd3f0204f084f35c0b93ab233c4066dc50c5fd3897a769a7c5bf309f7a9c30e905466c8394d509b79d62a69b58c73d8d3f1665ecd9a8a4dd5\nB = -e2633e43c38c0b4b8713c20bf4e2b8ccba680ecfc1139954fc42724277beadea438596942fea1094091671c2060dfccd0351b2fba8cbed35dc963cc18f8e8835052da884799d88ec1887712000a0726b17cbc4302421011d5be8d234440eecc363f09e2c04bc9cded3cbbac9a5bdf0b6d418822fdd90dead20e5bbbb3566ca94ab85f3a00d32842eee6521edd18b9aa6872340b2f47deb961f58bf231e01f9\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 33960d7ceac73f342d46275e04fed56563decf2fa4c0e9307c90288e911ac8782f8e1354fb051a9da8e2db83d7c710b5d2b611495e72ed42259ce783a7e7a8f601c07061ec749481d39a082f29dda1f9c7f444a33ae1c1055d37a677b848af371cd3bd41c851d31a07e144d7add66df39576b8200a8b918201630b3da8e664c3\nA = -402034484e499a8efd610200790d443c5d3be35d19d8808da85954d42dca3f24177de48f55fa2efd7e4f7f624d806a8d461c3bbe0b626fa1f3cad2145746464108b367b13f3537ff395262256bfccce5f0414e1f98b59ed29940171d46ebc4bfa1a27802cc30d9221cfbceeb92abdfa6e84ab4a54965568aa10ea631e82067ae358a1a93a3a3fe3a5ed5636a0c4cb373b4d49f46f8fbbaa665a19200b7\nB = 78ec7dbfa2b28e268619ba6db34a23adab25e7f8690aa9464a7d8fb7c6b87d5dd9d33d4c023bb665f2d96febf2638fc087ed30796fe7517fd58e4120c0d319688e67a32bbeaf62a987a9764be75384bd499b0e00a850f27e303f615031299c631844d10abc571f9f2a0f742cc0e8df2fe3c244bd825bf1d9134b2f1059e2a1b61985ae8daf9bfbd9eb24ba268ca58553891945ff1a314a78fdebb5444677ac081\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3a1ea3fccd6f336e6d444d68af1753b83145131954c20f1e3c433a8", + "9eeb7e267425a34d91f67fd65191dce85769ece2fc7ab12d032f3e30f8509095ecc05148e47a85391b21a18257c338a6a3ca9816987abc8143fe443342b34afd8a52fff00dda2e42b1b39322bd38c6a1f711051f791d6cad2a47ebd423a9b933485fd5861\nA = -1869c53f86755aa350115a9f49d6248cedd42a339506b8ff59cb878b7745956f142fc4387322c41f369773ed375b72665026771d4ed1b9ece08f84e4782d4c3b0177853cf9ac3a55f7e52f39c1b82aa42b30628a4fa6a838754ec6ff9809308f675e455bca6f44e298394888d85fee29d8a0c8e9cdb9aa08d68cd70e13a243b5804a3ec199f52ccd462ba6594d856602cf1d5efa509047633923d31f78da3\nB = -2023c544b6cdd8d971bbb345300f7a101f6dd44dede6bfb5f4e6b4eafb7a40728a3063f6d4bdd0f606ddecf062828cf889b2f632d0c9254c28f36dd974aef116b73cabeb2bba98635841c2b4d2aea833e35eb1db9fa9a9d33bf7b51c49a14907dbc6036b027a039192b47406bcc56bccf375fbdf40b82ac4b3c660a43d5a6eb656868d383cebd099d2a73506f675cf29649617fe06097a46de93c13d1e590ef2cc71\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 4331f18a94c169cf0253136bc4eb7480c9fa4401c18db1194371dd53e5f7b75f07ec2e1e1c4116a5d2a8b2cded4b22925b67a88af9b8479c6e821d58cec7ed9f780a4c41e729982cb33f69b87d01c11cb9a8f7952db1920b6eb2124fd5d820555a99327117d7e8e26d18e748fea3ebc17e1d07161fda57a21a70c7f4e251612c\nA = 5e7d4ef7d6ace6cb106e38d96085d3f3505983fd952498af3c1d9b2af61e4ba10e14961b339c6e64e11ac758d5fa18c3222138290866970d67d0a4f4e19f453503eb8dfb85b44d1050c86943e7c5d6faf7851bedf7d0cb6b13d2acee25372243591d37dd230907457fb440f83b62395f80f59a2d02b87134887406a78efd77614f3193e517f234434ab3be084f1484d3f2c1f68c67c0d6e863585a8a5ddd0be\nB = 114b6e6726433ea88a2ba965f0881beb3ff4d377526e4e099741f069abfaf29e129a1f5fd243c6599f725a389728f755f9cad767ca1d6ae5c8b3a32102e47af211e86d67574bddfa42b2cb466d968f38b47333b1b55211fd9a315acd5ef62cfd3e83c13ee9d3fa20a06b2292177961dddc7dc39abad9ea31ead1fedd3d699f651b656edceebb0bace11bebd0cfa581dad577b8b42f0a844bcd8c8227880876dd7b0aad1\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2468cdb1a26eaee34db3d2724e37f023c8a1788526b3dca99321b574685cc8303c609c85401a58fe6da181daf4111fe8c6d4b7428b1cd301cdb9bf8cb6f33140756c8b490d3b2e538ff294fd6471c4d17b9d9e4adeae0df088cb9daee18e825a368be57af4a096056b9e76b94c8d3b911b6a074ed41082926773a585007752ce\nA = 1e6a59efe0b14fa017c32ffd0962700fa9752242b06ffd0b604b9bfd125114d4e0909534ede704cdf1c9e88a6567f4a2989df752510d087d7b7afb515ad594627ece54b8a8e539074386121c9a3e1c12eb2641ded8719e56d42ef50e2f3b5d7d59f8a6f897174cc00a7449d2b91f33e9df07902a95479731a44fc4ebe8048c449bd515ef6cffed70ae78c832cd43491203a247fcfe0a403862266777947fc2542a\nB = -8a9d3646831dcc852fecc8e2335549e8baa2e2d82fcb90846ee82bcc715c716d4a9f62be29d5e1531db73c2186a4d2f118266de33d966b78f989600d772ffc55b1364117d6750cef67f4bae851e7e3f8fbdae7b79de7eab54cc1fee56e25d0632b2929e352c882ce78fd64dd0a1473e80b6572f0d4eb67f6bd6e45c7617314219d6f7de5e505a9b395096cd36650d23e8d57d6abfa9faaf0ddbff90d32865bf5ddddcaf28\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2909d3aef7a21244efc9b5b16626e260907ac11f3d00647f2170ba37197e47b9767030195c2f6d5eda717a83a152141bffed2e26777417ecd8e27aed8666698c2e85a414dddd52b07b52b0da7e08b3217fa6a331f84820d21086a4424974e1e8cfed3501eb054242a9f8bf0803a94981b7b81776eca6d07cd50c050dddf81d68\nA = -73ecc8a6a1507fb5dad40677dc6ec75f0d130ea704d1e87b00d2bd56a6be21714bb30202739170b8dd3605f0553ff57439051efea2a97def70a6d2cc3fa2b9ec27a00c1338bbd588513f0f320272b8933fdf6635e585d1e79203efb5c95a454fcd7f33aa2aeac08902107e9bfb29587ce8610d50cdb7f2033c5b726742fa9f7f20b4780cf9244e6abf6b812171a64b870c3ca4c9e898d4c15e9f5b0194ae736c3783\nB = 4049ae926bb52e862606842bbcb4a5148bd1063b6a56f331cf10000c524b4aaa80b3bd914cd697ebc98d68bd3c2bd5c87fac4ec68606c264c56e25b19d118dc9f2eca19bebca07269714f2955e107b3fbf85530b1fe99c42d33031958280b8e8abea5a918a41cc7e6980149ad68fbf1c0041798d2046d7f88a395348b295858c61c2f33d8512b6fe75aa8fbad62e2f9b0b7876ef95af8a7b7338a2d6b25ec6355c276fc6ce23\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 22407e4fe280ff5a10eaf46d8e1f5a1e77a07410cba4106466d703b11764c60124fa355733b47327e952a12869476306926cabbd797fc80b4a6dedfbec0b7718ee754d447825cc405a98b85f1e09ebb9294c4a4636aebfc61af4545b921cbe759d3f389beece3f29c2c7c07691a4c46a1a72ce418a239fdec80df48732627866\nA = -1e165ca7e1eabd2ad1264d5ed9c3d2b687f2db5b507a0e4d21d9e042cd46e93c2444c6aea8491b5caba2d8146bac656b7754b7b1ae0f6216029c7167fd3b1c3ba2e20469d386d8566ebbc05cb51bf1f1eb2cad9dc4fa454b07cc1bcdb9b8f5a43e354c4e0f4e62d52798f667080a0e0a15414391269fe8c92f06da74f6209a3b215adafa1eb6866f8b3e419468e2e5b4db0d0ada80514249320cecf034477977bcceb91\nB = -3f314681eaa4cb41a3feae8467f7d76b8b05939731fdfc943235aa4d67bdca30e64de541d17a8971e829bc0159384643672bdffbc93b3eaded7844d824604f46aa58b1f1b9d788106aff53438954af015a0387268266a6ba262e2fe7a4c51b5af6ff7f918674b7407ce8282f66e84fd2582edd809b465e4401c67e5faaa9e5748c06e3bb8ddb23fa649ccaf9657dbf79b937eb8959aae8d5bd9513c1e601c0e536cf60c4fc3802d\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 385ba217033463cd9cb882fe30373c2d8e8475dee54aba1ca9713a709f40844905c2544ad792784cc8eafbb412dd68de6f98522dfca1c3de8e3bf4cbd09bee4656c4341153b17c98f9ac09411d16ec9880835cae772bdd8eee51eaba7c02ca6a1034c2c5d2d48e7ae3eb0e22f59bf69537ab6f1e49e58a71c64b8934113eb069\nA = 5137226623f4ce4dc9b80a783777ef4e53ad3c2ec648264db472c517a96383ba1173e52c2659a97ce36341a11e832f4ad293b89696f91a051c35bb1db6182260d4a276d1a9b4be848c206899f87a361d318d38b4073a7470c5743b816cbbc3bc1b20dfd7971b11ad4e20d947e352d42760104a5a3cc590b985ee3b5e98c779e38d2581413a2208d31873f9644ec979602671c9da72fa6f66c603c1bb6d8e690dba8bf4933\nB = 13b45d4105e3f5e8e0ba36c812faeafccea2f1a30e2ce8ffad57ffe0dadeae3a23e813758f270423ecda3da083b42432eead7f04842db8865f9f1e2226a3d298ec1895ae69adc55d1d338c3fb787f0676664564eefe46ca95206e81678cf1a2f173c52d809b1e06641a9b467f191ea09fcdc597271eb43da1a9a856784972ce0eeedd49ad363dee882438f09863ba5af063925871c525c6c0ffdca428054e039e149a424c6d1b5b2b4\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 7865f718cb30026837ca006f5cd997c5b917726ac6d9bd8c3fb9eabda0854d528d6cfc10e4cd3f93f6848582690c6a83955072daefc6959d33192fcf42a111650e50776ba9ae43d3d26e0ef2c6b60c3871aec33eda8c56353903e7ae96592fbf350b88d2f56e03f7f327022a2aa9b7c484a000135b85bbaba6f8836cbfc81901\nA = 16978c06a03276fa2e0bea45740a98d55fccc9d27321fd0a5b8522298a2a90d391c06c5c59e7eca85efeb9b4c91d4a1e9178adf816d597311f004ef98d209b59a2d4b901fa14c57b7297861ee58b89c9b2e931e4ce5818dd4006f3c40168bb4d3dbbd059c1f1cc24ecdc64d37df16b8e8d0529247c06f905ca88a5d283ca1b9e6856fbe8115a326061905b369791772a47900974339722d19b3aac16a0bedd93e1e4e4289bb8\nB = -de6dad276dcc0a9e271ad523620ec570fe6e3b350b934932ebbe36dd571edcde968b6590be14326e0f6394c0a2172052ff8dbc3ff15d94fb6e36a098286333768a84fd0404dfa354173d01f98484fb20897c439c48952b7f1791209fed94e9e72bfb3df5f368d420d587ae8bf036db6700f77b130459e9de2a541ed885c69c5641defa9436a4f7a69d2848d0e5d1074f77fa688b6dcc4d4c7de25a3b1b040546ef7f418112127cff173b\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd99", + "13b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2d3dfd14e7ec60f842d1db83e29a0f6b052990fe8900887dc44476ed3948870c57e72e91e1941c476baa6aa86f76dd8ab6e6ea41707242c46d39b54215bebdb1f28e59d719fde18bea9994610214ea68ad9f2da24e1ad8a06f8bc698f8e76379ff332a2745af472d52a4b8e57d60280e19f93d5be669e0832824321e9ad8e76b\nA = -5144d5ca834f7bbb35d3fb95818c1f89ebe08efdffd35993a7691c05aa1b67f6a28e219b27fdcb66e516097c9ef5f00e4257c561b1f94c52c577471cfcd7a55314d3b0fa308b59449a36adc884c48ef5f34753bea746bd6fab2f20b86814c9fe50e8abaab742916313a50e3c390c67fda8e3729ee3329dc5e4b7d3107083aa3a07daf7952ebbcfea15fae7338cd0b114e9ab2f81dc2e80f90abff7a7ac59e3aecf76fab87633ec\nB = 48b927a46dbc4e23d714b256084fdc7cb9d4c96a988a71c956e0bf98785ebc9bf22b9d5c6ba0c419e60afbef7b96cc0c4a13e397aa2d2dd7995875d2ccb127169423455d138131199a263151f28d232ff4ae24e316907ace1fedd02a02cb5ff9c831de33e6702010fee2232bbe3c1c193ce792eadcad0c81e7d7c17e49168377b68690bc61f22dfddb17d82a3b993804726037cfac8aabe8548befc52a3c6c6baaec89a392133cd9c45b1b5\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 3f66970f600a9d09d73fd1ff813e977f539d69fe1784b8a2f99506d868418e4b47338ee0cbceed555f88824f98ffed39befb69e8907a5822ef7cd2a9950a070aec8fe4db9d68e1c0620f9eab4ab529c7e69466e325fe1c6c011bf7ab62bfd1a136597d7d5c47e8eb161ea048477bedc88fa30e4f7ddab2cfeec3fd0bb3fb61a3\nA = -1343c391be3f2b72c4b79d8d6091389c9602e97774b18eabeaae81fc0539336cd8c899341cf75fa758421c7f32eba9df474c934642003408b32db66cfa92e6e414b42b1d49c7e655ffb4c80f5bbff8d2774ee4f7198839680175e1ffec0428939653c6697eb3681d0f92634cab1cabc63f423d5a71d65fc7150aaeea74f9e0153923a1c65dee4a165e6a01a88655fbecd2db7697f4d2b49fca2508e2b8f84129785d36d88bcf59f4e\nB = -225a0a4afdde6f6450f28736c3ef6e67d67ec6206a63b11763bc6e69b03f1494b275ac504868caa6d56d684a12dc1098ab0d030583e73a2f45a42b8607c0f19031b9c5f07fb71919868911806d210d43aaaced5894e844881e89bab85a203af9ec3adb105e50b4250343ca50c26df14c46d73a22c2e4804d26d44ff0bbcc13d0dc7e326c9e4eb441f493c9743ae0eea0de045e05d19ac32d2379196a165e63ba640ca42e4861caa24c29cbfabc\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 54e95e86e87bc220c8f53f8485402327885be34e34063a1b81e52a23fc3056758cea1c039ac4e513f70ed9d394f5806fb771dca8e342368184e674e6296b9a705c6380bdaf11550cffc73f9f55b9385c85fb648f105f11138a3e1f9dc0a39a0f9755f8328701484d45784e3e4b2ebddb32c9d9132867c6513201116428b791cf\nA = 5f1239e0b5dbfefaba906bfd9003336489ffdf634333cec2484c582dbc19b66782ba40942d047c3749597ec4d89ef61b7803d33a9842f0c903461be37c679ca213aea894d36c1e12bbcaa1c679599d2adda9bd23e712dd0d0bd3f91d146e7a04f3e7ddec8b0db7e12377ab32ba241ed1e01da070c1f3ec85efd8387a7b9421453969ecba8cbdeeeaae6ddb098084bcd250601af780960c32f0a1ad7d7e61fb19f40dff1060c5f332830\nB = 1113f145de014bb6dd6ca05de159b97e9736c45bd3bbd8477f739daf79615fe329ce948cab9787838d7daf797218af5ba7925685ea341b802690bc9588ba3e916145cd3ae9d0c4a149637b890cf50fdfa8f89a62e508eec68f9332787733aacdd57ec1f359ff7fde76138d5b33d32e64cf7d252f2bcff14be3adb1afd8da9dc930f5261e6d715ac75752b29f083bb1de7b0b89ddba633b8137f3fd299a7f77abf79781a10d897e7bf2c958a097227\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 6e0160eaac8e1c31cd3cb6c5fb91ba086d033b4b69e41dfffce7569e61770f6629f23e12f0074c47c46653bbba94701ca798e1a242f7c4e25708d3acb5af6ea307b95cfa220f8879cb4cfff96b843d6eeed2b15c8f1bb21bb2b511cefbad0618d49d9ba33cade6da6ab3b846a6a24e35fb36d41201d3b85be831522b9bf509e0\nA = 14f4e24627c773527ed2243c0d1947395aba5c9cf95ae62a48827ffc1477614ad9c7aaea4b4fdd97e3272d3e220601565aebf87928c301656e9edb08d6e680de845615bb3a81c61ed043adb9d708ec1447f057087211673fa6ad8977166a2b4a8079a4f29d48e7fdd6875ccad05d2c219922b814589996cd9642ea2b798197407acd274da30d3ca008fefb40a25b38cb6042a581393283d6448cc69df9a5dc2b0777052566a8608a1010d7\nB = -b4188ebc5bf3ba31cf7c5e100e79806e92ff6f863c3d68a66aeb3ae8385f596dabe6f627f3812d0f2baea319d93ae00de41ab65e42eae7d396cc8fd0a2dfd35f303117fde4db5e8438df0c2b3b680dca538b42a7c844a9bf0d3697fc89ad0a73594627578dabdc214e0f4aa06b40987aed473e7f42d318bebf7392d9c898b4b8d73a94726aef65807b2ff746d4a9aa76303ed7b4fefbab34f5c87c2df82d20457f68289f7b96dbeab581294974e322c\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 8dd91f390c1f85f153f332de17e5de82979755d835398cdf3dbda1ee73c68f8e7565a964ae33fd5b1f1060572bb3af67eec79c4c3e2eb4de118d471f74351b80a5dcafc682bc3cfde642e611ac1d5bc2c49b308c30985b1161c4d78cf7621b503e2dfaceed886befc004f3a729b4a9bcbb8f13791d973bf38fb8101d6b7a4d4d\nA = -70e99398673324ee83495aa0aadfffd7bb9c94ee5251fff365124fabc50175d794fa84509f034c2b86d83607789338b0eebdbbf709a129a0ed0afd21c130d94b279c56f1c7c1eacfc6cd13f724a9352b2b37412242a47b23ec61ef0040a8855371aaf238003c45ab9d18a66cc7dab9653b93c323815e5404762d3f964d4654a6995af507bb2db2149eea59acd72af4d034217eaec0be5ba1d23890081a6a234e125572e3bcf68a6ea52d9437\nB = 661d8832671a4974b493e5d71e547cd46b36730f4017e50c5d1a7520fbb75f0314cbc2ac948744dd494d566ba580a2108106b120a797cfeb1fbfdefdab6bd6b2e073f90c77e814cafd0b7f79afeecd59778b1dfee3446fb32139b2311011576674f96f151f896b477c631237995e11e61e715dd8dd38e802af93124c66eee735c472972000cb4788b26752a630ba63b45e8ebbd979f0a4da5b359abd2905f0b7f3a21b1d381cd02ac08e284218ce41c907\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2b591d2c57f6a5484b43cd7ca247c48a1b38319e843257331c8807d499c7763de4eefed529e70d4c144e5e843ac00ee8d106d0d82163cfb7afe528a7daad8e7ed105942d1128a67e38d59325cffc0c3dab9185247e0082e3ccca82a900d917c9bd0f892d4b518a752f8e9d38eab2acaf3b3b59f15b0fe4cb9a3dabe6e0191493\nA = -1896f67485a740720e23e1642ef02742ce5f10a92e51af19e112cc99c0fbddb60d7190086c942d293d076b474d056e74ec9f0c42055d745a57ba370c51ab2b761d889b766cec909811e2b2fd11d6916b753ae00622f038a4bc55b813a5d06e6ac136e81689407de721ee852cd21ea989ea7c8cbd00b64614caf0974a62097b2eb865f46fdb0c1a2e4f2d839066b797e51392e5ebd14dd92630c070acb546dc7438631fef01594878643a4cf77f6\nB = -3a8e2f3b8378a2605f5affa21c4fadcc655f2f8357a3427d2cec0118e55fc2bbc25931259e294d91bde8dcbacd39e6cbc125683da7d0dcbbc67d7c5866f08e7c4732cd4384d9366868370ea40a75beb23b81306303da4a3e26ad357c5c743d0a4ae775a472afddf8f21cb4a1a3350bb6aa71037607c334a0c79468668d3e727cf1d0610e49f27780901c68aecf1d145953e45f5b090855be714cb39aba2efb0f7db2786b331dd9bb8843de8c73c95ab13b6b1\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2f53bdd643b5b22445e2af3667a93de52f8bc7bc151e196c0ab0bf3b4e4dc0e5dae9e507508711a9e3de52e2aeece6aff7fc8a1db65588de3272839390a35a847e29204d3b9b70e10352c88a10c86cd33e067fb530d20a3a5ffe67938c5a7a9218f1164f36a73324adef64da64d5fa5540d29a76a87ce010fb7d73a59b109280\nA = 75e31ab221c08b3bd73bed03f878bf7742f9b36a89bbfa7e90f9b05ec11edeb0140dcff6e9ad1d62cd7af34bb4284b3a52bf1b48a40f744b561d9ece056a9405ab15f508700b14914e4f427ea1df3093497410a0108066e9b259c1a26ea72082b3cf0e3a99ad054804da7bfa0200d93d65354b75e605b47a4e1e17ef851a37c59a95e1b5172801e6ecabf70f1e6e382740998fcfd8a297aaaba7d04b668e3d6eed40358247767323a8393ec359628\nB = 107aca18938a9cb244ad646a37a212859b3dda7518a5827aa2146b47bfb3bd08d772eb7a866e1f", + "674aab7a1c74cfdc2bc6e9ad1a365686213655b2c7b1977855bcd42ccecb804bc01d92bd7d2667069d853f18a0f0661f028955e39f71ee82b9ce6a81dfb2951b33b123e71264e819bba4d0a8c53a1d99964ad9ffb58b7cb5cfcd3e30b1baf5aa5b3cbd20a0df7ec37563e2b32b4cba91bbf3bb6fd1cbfb2fe0f84d720efdf36e9645c7e9ec70442ea5174528bb\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 32d16f7ae2632b5cec2e90c34d191599acd9a1b5f97845595988c1d0d4ceb9acfafbc4aeee9924ce55e109ec88c57610fddc664316e0f9a5e3ed56ea447111c0383ecdf117ab42351b80e72720a4b1d98d4c73f5235507c5b4f7849d5e9b527d054858c0436ac3d2de2704c4bc25de4cc702f5880d5ae34094766938bee555c8\nA = 133a439cf006c753c132a8559ea13c64f598c5f8bd5043b89d04d7ecbf0ec58b225551c8df8dcb341198fb0b487774867e5b68f9058f58b3cc98168fbed0d0ffa86bf74b4fb0d4235976fa86d52b8dc7e82df176d70892954223cc484ae58b6a60459a9a0803ab856ff9699789172b163615e322e193bd758016f634c83cf50403e416ae241d9b1e44add17c2a663771ac88cf8b9dd94622d80d879ae41f0f4e7a1a32a1ab164f981900fc159aa85d82\nB = -fef33e21c07dc26a47d692c3094205bf4efae6af32f1c0f46ee579c1a22746a3663d66f2919f46f973fe558c61264157d531e66bb9ea10b4b49d9f6ad3ad8762a6ea8169a9cfe01d3dd65518c2e6e58e8c88d1b2f42d207399d7326752560cd45d0ff571309301683770793fe3765c1337d14021d39ea6980934c5fefadb93047ef07c807d0ea5625ae0cefd098988d6eb7af993c062ba313e23176e7abdebcc6e566304a5f9e03da05bc1cc58dfbbc898a67a5941\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 20877c7f53fca97f8e484ba31f23dcf51ac0f4fe4c5121eec576e043c6ec5492725f1b9f9ecfa64195f71909500a69fab2e591377cc2120bd5f60d3fb3812f9e80b2f6c787e0081c1439dbea76b819ab44bf6bffe87dffd771a870e4f5502609249c5260f91175fb217a9eece4166540be877d564049389306e0d6b313706297\nA = -534042b0811c9afca04d20d83898e7653f91a73de1e4b516f3228c6d6d9b963c7f8f4c36e05383da90f4edd072a7eda382c47b84b46b4dfa16f269c2d9ad0fc53ed2ce51cd31e4e32d0c1ee21604d3c7eed2deb35cf8df6fe1c0740a1515e4c702a2074ad6c0fcd403603b4a4e2195d19b265958ae854ccb0b41cf22480389a053f71544cf594f6833f3e4d91fd3d9091df0978d04d3922ed72a4fa3579c5fff50eee812dfb2a334148227a0f5739f8ac6\nB = 6935a3444434b0b03d27545721e253e4281884da027246e46ddefb01fa7cf7a9a030581dfe618431a68ef6d79b03b34f3ed598e7c8ac030e2b4cc887dd31664604fb8afe4e71fbc3135d6d3b4e596044d6b615de7184ebf8dae8fd58506286ae4d3b797aea911eb59ada39dac756d0e9eb6a6c767ab77b9348929a00f8e311f639d19ed88c86eb91f0d4cfddd34e98130eb520fcd2b77507c24b6804d3d65d1b21e6f6d55d1f6e92bba0544829687a096be79eaad7d88\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 24823628d4fe9540103ce5f611f8a6ccf18788120280179a40c2636f30a13e5076503e8a4b6b6ffca21da5b0f9f0d85feb2ce10b51292ed069f35289ebf5130972d720d20dfb8e6ee80c3ac598570d38e57ba33dbd75f1b03eab7847d865c3e8e471ccaf302461a6136dd13b8d31c9f163799a3c24c7284b8826608a9543816d\nA = -1d476cc98529efe5b926aba3160b261723b009e9b880bdea04e9b5b03f173040ffafd1627b38be8e00840e85d7acd3abbae2f7a60b305256b920c2b25a8a4373ebbf1a0c69f6e74792cb0d849872500519b6d1c190da30c572e26b44590b7ffdb464a900fc38db013feecf909b43bea549e05f1b7e70d6ad879c613293cf61f0cecdba1a6565eff1bfcdf740bf553ffd5bb7d74f7e9537897184c527b990dea20387bab0dec3e32727786bb14975b23ff09f8\nB = -2b6e12c87ad91a2fa878b9245875209cbfef400e637b557c868ccbd6e94dae65f1ef8caab61f292d739b139e384137a747210c09ee6f3b2ceb6dd212e14525852b8c54215191e116b7097f6729f6426a8bebdff86cdc16effa08d932ab512d7265cc0f57303aa5e6fd2afe0a45180557935c230558d02c3030b38ca88de5fc75c1240d25a22fe32c4e5096aad0078d50989812d7dd0cbb02c736fa563efd32d14109c44297cdb3d4fa3b93a2e15bbb6eb678e93e943979c2\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 2c4bc23d0b4b1f79141be9149ee20cc9f1b58ee0a76d5f4205e0862492c18daa20171285d6ff0b600c358be487e78cb5450d151efcff8d53004eece94c5a37f49a15fb2b5f62a79568382cf0a4232407b139e1ec5a9595bee8435b4f138dd72fdc2946b03817e49864812b7b61f179bdd8389791178a95bb6311df0a5c60db2\nA = 5b0a181f07068af6e1e4b715d92c1b8391949a1e3cf0fe0aa49f3333c826f5582615d39ec28b1367804c1ef54f15fb83b3c578ef3ae957fc89ef22a343175df3ef2fd425f724ec1c3363aa000ef624d64c6d678a4cbd90b41cf7d69a7e03dd60c5d3470dbb75228b34d35469847772ff3d74b1a89a2c492c082d3ddb45ba4df6e3f228de6c64913b79679cbbbc36a2924e722c2c640d0c5a0e90ae86b5364dfbfae80df3d75823aa58ac6c1da78e988a11831bf\nB = 19567bbcf615b777b35fa7030db7da18126cd695ca7dda67f5146c97beeb20df24ba0fda4a4f03523a0d9b9f85d9acbdb5793ecf9c1f4ceac81299a1aa34417779175a4bddc0e95ac68309da51e4f115dad6fec33a75d0c5520692a38df64e8d684c9304f9e2e6ac6a66d2e16a03c19a30efcac712aed2b9ee774ea28af4f37c45609464289de3f9be379c733d711875216bc223f2f468a0c9b4a8277bfe49c590ebce2e027102537bddbf2856c3b6e9389c4d1f5390cb0f346\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 36e1e0b44e5afc35d1e19e88e75f030569eb99d326721ced9bd7416ea7367a98305354eeafd204f1f8a652a8442eb0823d2e6644e6320933ac481a3709777381dce8a7c165b23aebf31b2ea2745ce5b352acdf0707234c824da9e1af98bbedf80e940fba00c229539f310838bd625f1fc103f267265ac1243855622c5df72c17\nA = 1dba8bd9d1e6cdc117a5a01b5046353084946fdddf2696f831a942d9db4637a5ee76b84d4ba63156b8cbc72e40559a2fe9b8e2682d8ba1db0cea042bb86f8ed71f6609df52526c42e7494f6114bb62263d36784dd55d396018b8fa47fa49ca6e5c76ebb0b00e6c764e36cb3ec75e3af6a2c14dee01fab78070239638521743d04f184dae79d49a2bf209ddeb4cc72e0c94a93a47c107f5369070ad95ffce034c554fe2a8391e67f817c6cab5b88ae9748072da5c9c\nB = -849602ea3b79b33af2bd3ef9d1250c507d332e759d428902dbee054fdbcdcdc0a357a51d00aaafdacd696a15a64cbbdb7e1fdb347be5ddb1f609a4390a6f29f79ccdb51bd1f0547d0d9a2780517f8753a906428fd236f8ee1b433e57f2810d0ad51846304a5729f53a871d8b0e14355d24d3f092e50de4f044e2b8aa14cd8a51fbb2ff36b0b37defa7be768c56fbd4f5169d9d4698fb9072cbb0a037c219552728587d7c35f27456c02020f5f9374b6c53bcf8eeaa14be51899d3\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 77eb3cb5277ced02b72368e41f04a35796c2c6cc1273f109336fdfa745aba7c755b6ff3833e9b124d9c78584f6bfda1c94273522f020371107870c288592b7c23964320729d2308bac8813586e72078119852e1d7706d8e15c195486b8d94358736869b15d59c037ba4dc8032ceaa31eac3a9e3dc51ee17706a6956cff8537b8\nA = -6a0753edddef8b74f762bf802d7fe9b38638923ee2d81bfdda354d40df4422e6ac43724de1715c4088da2e68b63c10c90b236d7dcab39b9a0ecbce57628f4c2950c79cc88a89daa20d7a8679232c8ce5fa30525c56011570107697222e0eaee6871adced52ba01a3aea0ccc9901cb3a09eb4db2f93aba0083180bb41f3f9eaae00fb458381213dad01997e9b88f21b0a79ada1ec3837ac2b63611455fab6839363b796b105c3be6106ff284544bda2a32352bbce6ef8\nB = 542c5fde65111ec8a38d76d8c5735cee17329dc41cfd0f13bf47e6d0e0093a129f3449db380ee9a70ec1e44640839ff18b950c8fd89346cb4701ef753e6ef49dfd9bd27d9987e572bf8e68df399cf945813582fa1d33e07be938a7729efd9a5e7d730bf61c537770a0727f6bb9ea6add5aac9267bf910eac1b7d92ab4184734ef8b1d184c292b2b4295ec1bfd17b8a2a2e4d315a8b37b8ff9bf6a1e94a4772267195c5a7ea6f0a0c267337fb97a023f1b50ad697ea31451192cebcbb\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = 660a1f378a23fc3b47f693a347d90640fef43add97", + "29d74546933f4b78a26968cc9a70ad6fe8d85bf28164881bf7a99e8b96683c6f4fb54162c144f99a27e3feb736f0d382d7e5b934cfa835c723191e5692b7672cf6918c4a7a93b24af00b1beaf1b80320b14cf2d1539e3376779872542406a5df961f765e59f3480e1cd40b\nA = -1cd74c052e62ee8156ba5d97f28aada75211979b1c5925ed015ea75f693a04c4dd0a705f6a723ae7b79958884c96fc07f81fca064ce2affc70768923bfbca6049952eea3ae048425b7c6ad1611ed4b8b77f7605629b9d198a77a27f25eff2f82867845cc868edee4ae31afc5d022b2ffbf43c14fa01bef8d7cd9d0e58362a0ff9abbf250e43ea5065512cd707791ea4868e95d8fd2357b3b3aec1a06888ae940751ceab01cf9e49015d42371fac30d48ef5853b6894ca83\nB = -2ac904d3632e25a4d536097d80a157791a6aca6eb10246ea21f4cae07aafe907c6e4c726694e14ce12e376c02d326f4bfc02ed539a5b4615a3cf5c838ffa52124f9b843598a3821cf9f1fe94e7206d6a525fad1ef77e7e77162e8c6d3d860d4f568e8f81153dc47f167860cd52c1ca59b15f1eaac6b9023c8b375bb63b6adf6972af8ca62b39f044378b11c4a969f3939d9fed5cbe18c06749956c7acbf963f640a1e1ceab73fc4c77463ee8d1575d018f49bf0f08161ce4f88aaab5a70\nM = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb\n\nModMul = cbbeda9c467ca801ec66fce801c6765a20148787dc6becb199a15c58fae8d20c1d391a1d9d57e1c74bb412e1b8f271dc2cc53c3355c83f3e2f00f15eaf0df735160a48e2273fd1bd75533cf94c5175ce67e79fa6c1422996fae36ba288a658a7a5422a59d39dd81ddea50979e933efc02\nA = 7ea551efeccda23622a1a5029e5525f46d5ccb83c28ec9adb7a3e97c2b7d936238c483a4a9bc92fe0e21208d5703611e2795b91fd5019272d255eeb\nB = 19bd92c534f56dc4235dfb7efff6d941112d66acf81b079382c86fb10dc5473bb8adebfa53ea3fe6e4df8412e7807aed029694ca786\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = b18a9cd6a0a89578ea773fbfbf642e05935a995a38bbd54480ea3ecea1751370ef95ff5ad0e3203613f0ef6833237d549676a95b720848c5e9897cda82642a2f373951d5746b559bae2d98ac00fae26e5957c61ac1de95318b1b1aa6d5c64a6ceb6575f1b807060f9e2a241e378e6ebd72ade7d2df18d5353db7737caf52f888\nA = 13c68e450e9e091ae45863f6c1faed25906dcd90a43620b1a40e7a506e7a954256bab0225f3678e7ce6c4ba6e3a83c8f04a3491d9bf097adbd98fa6e78\nB = -ddef76382342178fa6636e62887fce6e19590065c766b047073329ea15fbba96f2cf088fa5a989f6ee3f6a513fbf66f621c6ea6ef2fe8\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = b18a9cd6a0a89578ea772021f58ce74cbdd8c44a09b3937b198adbd8e95e8e35541eca26438351bfdcd8600b4f9b71616e1f16cee707c712d40da9a440681f8c8647bc90ba4c68b08ce4cbca458bebd5110222f06b2ca980a2e9419e71064324e8c36289eff9c67f6d5d011e6db8538a54aeff8c20800b0949fa42c38fbabfa1\nA = -6d7e88715e9854b435876fc9bb2d25218a1451efb73ad9cc5f52b2bee929530e6618a858000b3f24fa5f47b5f461c84eca971e38cda6e1f475f6612ec32f\nB = 49eb76e4614ac7b0ed3f534811a4ea6da5ea24be925ffeaa38bb228fa117ed56ae976b590d6c9d9a7a8546d8a6ebe4bba771d6587ac44f09\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 44f8596fc06afdb72a6e4f876b70b8d5d734589f41089c510b0da60ade642fd79cf8e705f09910912624fa1f646da596c137f124ec1a327beccba62a44f228f3c0977fda2af631e249b2a4de17d170df07bd812c233a96d17e1e93910267682d24c5c485f99aeeddceb658a7db258a2fdf73eb0266d26b92e\nA = -122231b14c249820f0dae625342415f0c6e7f93787b4206b79e9ecaeb09623636730810c7936e17a1eece68edc7c97218efb17c069bc59bdb9681a79c910c4a\nB = -3cdaed858523fd55553ef85d018c1097d7b88f6c30060d1e77b84821ca20b5625723c7d4331ccad1a70371eacc7f7aa11220f83f1bf3595650b\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 6de7efcfbc1e8d2cb14cbe4465c4ef71f0d1d7e80a1d80d9ac2d0b161d45fc9d915c54e33131591e8daeaa11ce02404c9b8494added1bd83e344ad4de7c04f626315caa56fcc5ca2ddd4e1ff064a2957afeb5d280477bf1f1195c7294d89049024fe821dceb53c7d270a8b4653e2fc0a4d8a3863a854bc3794753a\nA = 47423c4fec1eb6779fd23e3d4070d0a7bf9a946f5610eb469876797a39c58577242daef8c34926f6974089fc595508d9c573d0a275cbeaf37172f10b8c849a493\nB = 18ad789cf09e9ea182eaf43b28b4f2540e533f0fccad325430b73101c00e440bb64b70ce0f2680184aa8caea2f6f6517e9b80285fea8b61887a41e\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = b18a906994d3247bf8a00f20e4b349a500159d086aa863772e71a68f91af9d19e4c021843f8bb6eeed1df708d55047dc8faf219e00d559517632dbd1cbf4bda61651b9644481d052903be1970f04bb4ee8faab9adbbf858324e6cf5aa9384ceba655a1a107210a9497552ba8a56d5e0e70b0c757baa71d1613683707357827f0\nA = 122773509ee608cd9ab3ff6763629a18eae41be64bcfb05122e0b3e112db48c64d2a5a515d96a042850c1c848ae5fd5f0ccc57b273d25bd8d68568cb00bb17b1589c\nB = -af398208c01ec9700e332f3e694894c7cc412a73bde8a79e08764ded92f0d58db8056883972c79a0c9e0ce810786cdaa3629baeb9e5c370a5a59d3ba\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 64ef5e7063a1d95226569a27218e35e93d870a19a43fba9889a2ca98ca5c573fa56ebd77f1403b3bcad17c1351803a809c245a97bbe32b45e21768f28c5b11ad542f5e687a17f7811df6c8735e1778e94d9313c19fa32a6703af7ccbd88b489c96632d10eebb580cde3b905f6345a2a2b86a871b4fab36fa4b0dab9a6c1c5096\nA = -7dbdc37a51b601417efdda2516aba15827a40ffc304c523a47c544d5c0bba6c1367a20d8a6268a5c3f723b1b68de57eceabbb00d44185ec4ba7ecdce5d80456f8cfe7e\nB = 641cf85fcb5fbacd6214be4b7b06fda1b80f4683c21c1d08311f6e23a15434b42d30a51912898a1c46b46c00aef7ab7663ecba683897825a4b07d2b7dd7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 370f20360ac844bf4275f78b7fe71ba5db6f0bbabfbac3384c04b256eddaf04725d2d57b31afa48f047aade156c34441b4a41c0b2146790a2e15d13b584021ad55965588c6e55ed3b5cf5c36b780a27c5dfb72678d57528ab17ca2ac696aed3d9abb0ca448d9d5789fe37e632fa9709f3bb924c4ce34244d239a940dcddd9c77\nA = -1a0cc5b07271098a23f01b3c0d47cab8b294794b74a8b162ff3b313fcf85ea81fc99433cdf4450970311e1d5ff81e9ba27eb867073ed250aaa7795e44ba8d4000e879bf31\nB = -308f93984acb78c5dac2426d9bccc2e3ac361143807c7d34c24ef8f8db5e68a904ac8bfed1edf3cc90d21c87ae4d224b8c46fa42eea77797f94aa848160fef\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4c8f466d1d9829aaca1a22fb6ca5bdba885606b9264933ac2b4c18e3afc0c406aa71ee7ff490fcaa804f457096e44576ff8096fb1d2b3c68450a8bc36d1a2797ab8b621ddc91d75e7d6ba01d86e959171fa428a5bb1f26766f94a553c94f6dcc2e0af90d7776ed3d9fb67e842e88f7d7342afd86e2f5d159db7304ae4d204a3f\nA = 57e894e37159cf3c161be9c97a946454e43bf09a7ae8e1437570a86c6b06f84005c1463d27d726afd2e25aebb1657eb78957a9a12c8749049d12007a81d766dbe008aad6d83\nB = 16dba5cf077403ff4af47438f5840f65fa4e058c5cab3cb730154ae0fcc982ea097c6d0e75bbd635e97314f33ec7e31f0e41cf285ecfafaf36382b33d5e83cd55\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee6", + "5c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 29d13ec304f26247a45ab6869720720fe019d6cf370b9e2df9a65828214aeb4f8b17969b8dd54339d08eb99bbc66720ed78ef79033fdce6da33501fa8588af86ec18be4c4ecfe01781f9d1379865100dbbc020b892e77027d1f04f8171ca51fb73129dd9a96568904eb44e19f56f842b223724a9ffe28826803185e4208f0ff0\nA = 135ebb133a0beb909101da896e3aad7e26ea72b23e60802e54cc6c58a07b1205e2ba1fef6eb86c420f011b70e3f725aaf9fd1873b6e1c1cc7005c7c09e55550414875cfe846357\nB = -e8cbf3feb7be7fd12b01d5bd024e47538f434b496613320ad71f48a8972f687992f97e4b69b5842d2d6a4176a5701327c40325e98b27e4c0f8fee5a457d92181e40\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4309b728306535bafa6787dd79e58324b3f86eb5409d772018cce2159f75832b87909a672b8b4b14342b352e76ec5a6dd66737cb0a20b81c5ce222133bfddfea878b132b6f9fd557133973a0b44aa41a01d54ab565d6b9c62da67378a4058255047a95923daf5f0f7adff2a3f06074ab1facd986d7d26cb475ee818199a390b6\nA = -7a63e108bc9790ab687e0fb8a1cbe1e9ff876e7b5eccfbc136ba05fed93412dbc2ffb1ec49518e9fb867429cea1d7f82e2b159b75bd40eb8370e8a54bf0e0ac0ff24aa3662774bae\nB = 51ee025b2ee8abf9dc5ebf1a4600131c00ae4b6bff966dae5c49ab5b9017e6b1abd6434736df6daabb2bde254022783764c94e66743dc752c9040563df7016a1581fe7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = b9ddcb9ab858d2229cbfab87d87236e8206cf5e1a042eb5ddde201d56e2695a3d0b2a42bda6a284fbd2a5b2c2b80446ce88c024137780c277ec80bfa6e9d15397cc5bac98e58c9130756ed0fde58d475a033fd94b1fe0ecc6fd91a8b42177abf3f77e87c0847a4244b9fd4980f3b42c7c955836bc994f2babfdf9c5b43315ca\nA = -1f971ee9a7c966d1e82166503681afc280fab255665b850645321f67da8934baba1226e9efb59e0ac4483c8724f63556a213f2224b993e4e082eefff0056f7aa8a3cf5b655e0f72ddd6\nB = -39309313b04bda1103ca6f56514026538b4a29ae258a2a66424abe2c652b959f5c1dc4755ea37ebbfe404839505c2807ebe069c9abb9150205fe35bc286ca12b64ac46133\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 47555924c31f040619681d4a12064790e981db2c7853efa17e4d20f741f33c56d80862caf86bfe0730870b6c0afa9caf66e15047e60256fec29469d1760d5e9b77d79a84fcf7a1dcd0168a59f870f1635eb033e0ae0ac17bdb73da803206d48cfc1da48507cb812bea540daa2393321ccb0d88b57abdbf3a3bb765692a2c2ebe\nA = 754d78d5608fe8c7ed8e26a174fa27833a24c48d23f0e702454b7eb578cb107da537dda11027dd6b41daad329e036794de562d7623bed8d9b0e909cb3fa38d4d21a95c5f4246e0b030a32\nB = 1839baa8b8fb6575832136f1d4632f72f36cdbbdcbd00f197fff3cdb88b851cbd74910ef6d43cfae9d3248e9c85662d7fb596ae45a460feaf308823f06345bc5fae8823230af\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 9b2f026b11d0674e9ec060fdb24b45fceade3070db4405b363d53df1219a02a664882819fe602f430636fc0bda935b14c55c8a0bbcc9b6683417e3ffe7f5d58fae229122ac6e42e76899254295dc5a08ed43c79120a5e5e4124b8fa6048ee90836bd2de51bbd2c6b9b53212e913cde871f11bf32f91b3a78575a006da36627f0\nA = 11402b3b1a45d67cde9730062e38aafe1d04fb1f8bb1975f25cd9098813efa2727cb229adf9490267bd437220d9ffa05bb993e45d2f889f140faed3ac3c7b53216455a830d6edceb02e8db92\nB = -d8e011f18bde068badedce8106f6602429fbcac4766334a0101b57fe94603203a4a8975fa499d8a68198aefd9e68f28e68914f920eea1083e37c67d59476bca9819a8bd628b89c\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 3a74066e7eebd9b63a1dd28548be60573c95f29816f3b3ceef68a5f6bb797d7eb0b0f4ee612dca794ff82f5d7461d995b9dcc09649e2587639ea017865328bb5deef17b5283691724e8aa331d75c635d5e19ebfd268fe5471714aaca8b48aeb846f241c1675e18d35f029b132f81128f19028b0a471b3f75a530321135e35fbc\nA = -6c5dca3fb7b85573d1c8899868940794e428171e207b5f9f89fce4b7159236c0755e2959d870754e902e9c40dc1fddeeff6364f898ec0dd669283e6d26a612d9af3c3ab04468707bb8a7827756\nB = 5446269bbeb613e69286f1012ff62ea767965533624542f3b5c866cfb569d6193aa603061701992cb4873ea8b766606da1b57d7b37cf52f52bf85b58309387200b0ed36164f30d52e\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 2a4e727ac67451ca9dcba648050a085196460e4aa4836c5652de863c3e2a76213e0f590de3aee8639304c54a9dcd5f7d5d3592f647e3d07d322708e1e26329f4a31d66c7f2e9d482f22cd9823074dd57d14040a4f00ac2af9677a2c98d58ee1e094b1a8c40092e77eae454638bc3655e77441d4f218c637f95c147776f5bdac1\nA = -19fa688008a12cae228c6ac4982ecbc88da248d7ec785bf2289dc9103bfa3a91eb1e5fd6afe9e0cc035d3312e9ba64028fa6a229db6d0eaf8af43d8c410be7c689c3e557137ebd60d3fa04edb60cf\nB = -3e8c87fba4a41c3a84874c987acee9f560b9f027338b584a775c1fcabb766700f758c4d451077a9427257334a569037b0bd006375f71223add62eca19b1e26b86dde0cc251e48d3b60ef\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 52e4a3f6892b425b935c6f9d1396d2034eb0331cbc5241e1d745a9619fa0cf0fc521585cb9d6b1034c5fbbbbecdc81c757f768c7a82f6ca291cf5afc98500c579f82ccf0be233066730f738c205c3c188f94b878c11268871ba42a5d950dc8a399887997cef2b6b68badec1ca641b88d1455e6d97a2841da49df7eeb766b7be6\nA = 67df01e34a26e8239c8edc7ddfccc3850f39864ed237d4dd67588efbeaaed1f884105508f69e20ff6a5cfae1516f6179ae6fb515a66ef0a7d633ba4218c30875287ecd0cfeb5bafafc492619942f97a\nB = 19f5076405b3c81519c0863d0c963d545b2834343e42bb3c779788cbb46d89be3f775b62f4114268a0ca0e6af6c0dd659607d40071dfe7f1ad0df9a5c53b741c04612158de396e9c96f7523\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8ac1d96abd2cbcaa8f7e3267b716f675aebd23694d24c112d202653979636d4d47e27cc36f850355cfc5ca16b78cd1848944f8759fbf6b03fbb7eb347536a9328a5cbb778a6bcd983081374a3f543b1380add14a9468358009ec2baa7ecdf13e7260968eea74083459406e8889936b2fb98c8b9a3597e5f9ca10b76e1dd0337f\nA = 1c9ab23ea37f324544280d176cc02762db7a39935f1ede9695b53a3ee2db49d0485c6a3742a3b5cfb51f3c21711bf89ed05afd0886bbf61cbd57b23439a8a165484ee8e4c0e1c0ca2b6478776aa2897d87\nB = -e30d28dd01655b7a419d939e3e7530258a667420fc759bad585802c63fe5efbb309cb502babdad0afb208aff5ce5830071c5a974604c69ee47f76fd87e2460a5b03a57ef0185881502625886f\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5df0700adbd880a5730d8c0637a362a9d42c64503c3b9784046b946c2459a619b5bf804a41c92ed6370bba730c7d39fb2e01558f7ec38511b0449d6e9db8df2cece4ed348782ff1582396ca8b3196474e7e5817f8c197c44d771923b6e286e41e7e23c33fcd8765e06793169999544a310f2e080ffe13640b85f21a18fa11928\nA = -5c01fc52e86f3a344180bac284d2376d1bd693f20a46479c77fa57077df62f83b1e81c94e577d1d6733d276f9cf70555b20e3afcb97534e4e0108a6cce87e9292d78b2d7367ff15fb33d2c3289d2a2913b58\nB = 6bbc39283be06382ea91ad6b1630b38f32385ec90019d2ded7ca6fdaa39defbe22585be0df9c0cf613f6f146c71f901adf525336f6573f7f43e661c44b7097f110d4551e8c75449da8fd39201ca0\nM = b18a9cd6a0a89578ea773fbfc0767c8ab81", + "7cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 2a01005f1f387c4d8d24a365708e2506b044f86dfc011262d3577f7313a8f51ab943037361bed1858e021f8a46491a5c73284c666eb65cea1392a780219f13d7188721d7d4b975272293a5eef63480f30cc9618aa74bc51f4175246301a46fdbd34a6ec72d5974aa920be5f321a97b8f19c0ec56ba10eaf2e61f2b45f134b304\nA = -108bbd8824e8c16b81dfdd4dfee691e012e578cb9cc80cf050c0ec4cebf71a968732da36552979ffaccce6667e46c29144dab75132cb087681d5549dc5508f3719e129553fdc97f545d7ddb7d3a4fc575ea67c5\nB = -2ad4d4078c47a3c8f5f9b48e10d52d72349ecf0f54abc60bad63bbbf4d8efb185de90e5e1a686859e1c429e30977fca492aedbf084019e9ceb4490aa471776ed2e8a09151b37c5caed9ede66922b7ec\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a1b1b2d33cb610f1b398e03f274ef39a583d13af14b79e6766859b9ca748237b481a3cfd5d490a073e82e3c53d3ff5cb6219b2b2f71927f27ab6f567547a22dd35fb5919e1ed2b6dfae4d536d6d44fa6216d94d26b33f52db06c4ecb29702588b73ebce87569639f786df4fcf569bb07d5379bf8b83743327248c2d71b5dec6a\nA = 5bc53b3895cff2bf7bf10e24fbdc43d17d277a982d5d92f17b9b5a2b9ed8b6104229292ef3997591e2e6a116fca21ad5d061ce438f33b7f7110293770f8313077152c7546cd522ef4054147edbe1878072b1043e6\nB = 1599b541c9809779df3ef40971e7a83f21564bd5d6596d51a3d96defa4dff41e83ca6247969a3dd9a746ab72ce21137f2d7ea015ac6b2ffa8a32997e8b821064d35afde3435b23e47cccafa74d5192535b\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4fe8897417446c493725521c0ea5b2110f91a1b5ba236cbb6ff3f52b0036a49fc82274ca949ac2b592fa4bcc792114bf2f2a78a2cb44cb22c6fe7e4bee7981604de47f6da2ed1fc6a8eb32cd9b8aaca0f2feec76a2438126ae6f409645d897769a6d340308f82dbc6a98ac059fca6f903c5aecd668fa838b67300c654d4013e3\nA = 1717c6503d069103f10bb4b36427fbdd2371b30793e492e4161fe185b2e27469fef6a25566d6b46f6a7f97446315a22d1f1f662f912b17e71feb2c82411ed7eebb84d4f594deffee14934b75a845d83761f36141ecb7\nB = -8808f540521c20eefaa037fc5da782c891fdfc668b955eaa2e4edb592e027a964b4cfbc94c548d785d92992abe282d90dd137c4d76419926740ce138d567da7350d89f2e56772d8f5bcc9ca8d7076540fab3\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8b9311808bef497d8a5d14f7d851567a196a051610246964917a1f9d4f4449357d2411ba9fd93983f6edd76b8a8e1501146b08b6e1fcdd97b6a41cf637b6ff0cff7a2d6351aa1ded93f8fc1cedc81879eef751bebfbd1559d5d0320595c79e3eb1db0951d7c67c663bc57a672faed9e14c7da6be6b0c6bcab3d4d515e51a0b5d\nA = -511312fce1849c3d177d42088e55d534f9f7096282916e16b041f66ea90e2cccddab5cec0ba8ebf0b047ccce72da349f420cc28ab19bc156c1cccdcf5216f19ea922698127f090e97444751dd58fe7a2c90197a9ab3d35\nB = 6a5cab5e322d5f651f798aebf43a62af772fa2cc379905e72d253c49be8193a07ae6164f21cf08baff906ef800e361e1cdf1604f454483e10c8b2bfdcce77c12b0320dea63f9ac0afbb86115b656d0198aa883f\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 665e16ba6cba87c646637a233ae04805a302ef4a10d79c5b65b146cbab8c9ccd491faa32937d0ee955dff7dd0ea3f79fa43c133021c8680490b91d9c1d8a8102ab709ada7508bd59042940b2bd3a4f8c195f781313e45fa8d3abda1f8e13b35811b638b2ab101d1caaa92188d2b75b2b10d596ab159583135b0d4d15fcd3d882\nA = -1375af024e9974cf8170801f4a709b4e5862ab7d18464077727bfc2581e557cada991e9484a1acf80182458158c44871e67e783f7573f214ee4ea1f1821a65068f2bbbed7575f03a4bba36b0fa8cb6dc58c73b100a6c4a6ce\nB = -2d64b6bd987d496a3c121e89f4b0c88b6ebc6e30fa9d47981b52862551f3b7251a3fc376db0f2d6daab6e6fc5ea8fa10b040d0dce334ee91d8cfa6db9648df907b199bb11b2b5c41c67d72b760c404b0451f70fccf\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 49e9709810d9f3fef159e5cb45211453e7a94878dfdece19af839b89c0e43b226d7cfd46859963c7ccc753350e74c2501131474e3b8e0edcda18583b0392ee15f1dedcb7144000fc7fa7eabcbc83d12983d2ade477b4687d75b723c1a98a951d21b2e8ed95735aaec77e00de288d16422fd259c665a08a34331cb99299ac11e2\nA = 4e550ba2fc2a44452f068860ce2a59230738a7a15f5de0aeb4d15bda8c61ee3003568dc5971e48343d402112d7a86860a7f08f5cdc0de21fb1aa064ee5df26fa23839b5ff6adaf64a4a18c07efb3582c2fc9612d2208fe99f8a\nB = 16f31365545772f276d8ac952506bf4033a884edf1ce583a63d8d9f6809e29d9cce3b3d227f839e6c09b459951465ab4570d2d36127c0f677fc0a63975801896f2fd17887ca16ff7f265e2e7adab1516ce56ee1ee9de1\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 89ca20a3fa109a65b9449edcc729fe97ed45a9bd69eeb31d4a566ec1787b24cb7a2c25b3f89b36fef1cb3645b17c69ac8ae243cdba35e17f5738b35278478bcc391add0b5ec42db9ec1eeffa63a3ecd2ac0338db57cde9d2eb9ca4bb1df84f1a62245c4e585c4f20f26c98fa1957df34409a99a18bb442ac14f0bd309266a35a\nA = 1fd8a096be30e4435ce8cc604ded337a3d9d2fbc9666d1893c38546c4e155315b536d1bc323c1e7be162bb0fcd58440915b053ca0d0896e99265241f2afd46605a2a7486e1394a07b23f3382cd190e943e596c747b6529b04bdb13\nB = -a3960a51af5ecaaa70146ce55d639005e9b6b9b58592441d5876fa71470ade6d1e2cdde17bb80532551bee0dbbb71a0cb24dc8a129c1f6e28920055d87e9c66be27fc4b425737f36add7d72e39bc83aabee5534637e2e22\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 654d9c55d4a62976670a5ecac3a6165734a65f1edcc1ca81a8c444dbc98c3409ac8c4f6fbb92f122045fef8b7971a276c7dc4eaba21f7be7495394053d4f9bb14b63fc02c8a55ad8fa9bb9aa26aca5c47968ea1b7646ec606f53606d5529ded83639984683b8a020e8ded4b2d9f668ceadeaa8160245b36a819db14e58cf2bf1\nA = -67abdbc70db183b8c25b0664805ada269922556bf15aa80a47d31f215e216673b8d59edfa10a74f3f09d066055c3b9abd5434ce95eba91dd51576adcfbc7e2556df95fd6642a3b7e0486a635ed5699eb7fb285589c887c8659a2b7db\nB = 6ad3e854ea57aafb8980f1e99ab9cda24f183dbbc513e1fc92d4e239077816843f47927bac28e41d3f31c9ef134b72c09dcf14e2e9677a430d43002ae70c577d9958341243030fe58a800a068d6b01fd377e61844f0d434dfd\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 74bb23f7b0cde7924ee52e58bc0680f151e6898cc1bd4a2eaaa05faf218b419a19ebf85b0219f924a26002f9251b83506684af659e5b680e05138432ba227977f38a479ad9d1f3cf68a86ea214645fc4bd1a032f995307e9c9ee432e816fd852655ef20214e24522c17799ef41d1eebc6e097b9792757f7fc43124c609ef9696\nA = -19d3e6fd6de9092cbea55d65154208a0c93ae409c3ee35569cf774b8c8b7b1c9dfdd52e9f408e14ea3153073ed8d92746474e524a903a45a882fe46af92b033f2c41eacdd7e3c1ff661dcc5349ed6bd1aa845eb1762f27593708aa185c7\nB = -3d466d29e8c0008ee6f402551e3d62fe044787bc9f243db9252ea97da9bb75f5be416def97f13cbb008fee77f2eeda672bccce1f36fbcd26e1f1299619535da0a3fa3ffa0c6fee82a494efd7407cc770cf46ed1b8b143f42790a2\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d4", + "8\n\nModMul = 197eaeb8221b431d5fed3d701a175abc146a9fedf8060e8e611a54f8da2fb27d2fee4539ddce1f3481e6a64435f09a2d5012540d6069900a332461471b22192fb87b63221c7822d3f2fcc35cc38feb6b3e49b5b0fceb52b0ccbdb4e1fd7b0f3eef3d582a6ae194c249ebc52f215b568712b3e50bb8e01c64b114955ebac2da48\nA = 7bd216d0acd4ee392258a7341cd56bfb0968492fe75da0c9d935713a6ac883525a4a520b5b7940b05e3f5e0c40372cb11b7ca193e93f0d3883fe5840e66346aff0f38829322bbc1f0a0e63ce5e528ba5b13596ad7ca19d20b2a7c9bea4214\nB = 1ed4805e53630b886cd733e5281f6d2699b3c79da615f4056120165cc63858ed2ddfcfd0af0c5fc54662aad90f26c55dcf70a30d04ce05bdf61028730b900587716e690dc0c6e02419622ab8c115078b92315e7c7a5ffe38c4a404a2\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 40f69f2d1660eeb6e1840164817621dc95eb930875333bc3f62a644ca5910c1080505de0d54fc9fb6404a61bb2c03b3981e558abf9e86f2047c3928599b529ef3d91c7ccd13c1d69431fb9ea3f02b001427cf519d9fd8182219ad904f47b3785fa05ed24cb0ceafd537311633a2e26c27e61be92eefb28a49d7f583cb6e072c2\nA = 155fb75044fc54a6ba6c46972e2f97531861b8d6afbc358db456bac33a44bb0545deea2fc83023c08b7be473eb68accf5b65b3c5d6af88bc6d8ce722c80d5d1527e475905226b01ab9d7b5a6557250cf8be935339db330df2dff92f2e88e80da\nB = -8c6016966a2cdea4b2d8625aa367e1d079638870f1b61e6b3c3a1e6281ece41018d2ce93684d1f0088d021107fb595390664c11435c6c0a7b93c2c6895217a89c469a37d3250dfa457b928ba6119b5c9ca5f2d47b36e60e4325bcb4383\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 9b9e6e1727326fea099eeb008a36539f3d47e3882b77d6089032b99c6cd36ad79fa75b7c19d1509b3ff022ef781b6a8c16fa6881f9ee2c4e00a4dbc93a49829622f4ce6ba9c55639656102d81167ab8a5e1fcf14d71caa60be732f1fbc71250256520c7c5a4579c3fdafc39356a2bbf2c7ecc526dacc0293c7578424c939ab6e\nA = -54cc11ea9806ef27911ba721f19e2ccb111045711d301863792f0cfac798758f0a29111e3a0f84d294a79721067f50858767abf507cc10ec9ea3eb27a91f06e7f6b7b4be7001b548cb7fb734166bad6739935081bdf6d35d58ef56180d377e5fda\nB = 7263e8b9a6f5387f44c55af64b64160efe97ec8a8159e723ca8977bc17c861e22041ea227c9c9bb467faaacfe352b03cc620eceecabb6db2db108b49c69752bd0cc61a5e998ac2f404ad052a51286ccbcfaa214ea8ec14cd9a2a6db56c3d9\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a18a7498ac9194f600cea3d66615595c27a3efa7ea196ba12a80b5f608f85fa72afc366d23f5ca98452dd190b8f86031a9dc097f94a217b29fa676a6042a3aed2355cc8e767d464a8adb888491c8cb82dbec8f117f57c4a07b41e7e6f6cbd7dc25418603b1d1d865dd2140a649c9d52019ef39dbb6809d1b28b3c1ae64fc6813\nA = -1b663403c73e4a9003467ed12766f16354f79073ce89b66066857d19f3b42791eb360004d23e02874254bc6db54662717739eced153944c4776f334576746c5c4145b21a23caa2b2a137498554c7b749efcaf3393c5457b2bb87ee2ca3bef5f191107\nB = -21d12aad97a5c6e639a2ea0a82b1292aebd418567718014465a22b9ac5c8c927963a2a4530c41d5a7a6c14805e56a7092c8716e4767b54a393d8552c5d3c366b39fb3b8667c60e6075e9293bc938e407c53afdd1174843b76aed187f56bb4be5\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 1983576ed73d4d87d8b94cd3f70c149c0273e966176b85fbbbb7b3202e2c843bf1f8f4546ad7a4916ea4c731a22bd337b6177fcd2da8bd301f3af9bdcad800449b57986e7cbcbc7eb313d6512b2894c0cbb6cd753a870860a49d6a682c20b5e883b8c4839b3321aede51bfc42bca163a924191feaf05e196d8dcb7fdd9941a60\nA = 576759af0f02406e8dafa330babe9473d9d970bf371ceab30d2f98f4470f669e042e1708e2677d52cb9f99deb9b53f30727d16c389bb63e71e923475314b615762c7612269b5ad7bcb5108068bb5159cb8dbb8d08de2bd4fa4d9db6cf6e3f5997b9b416\nB = 1a4e34794747cf4aa626e964b839ac497b1357090ff63088f9fd4399312df894e41b395d17b8ca1806baec6115b1476912ca9c4309f00a46d5f7a52c8f640075422af06d6d6d796359132f4955072ce90e61b40c992a155b2bc31c262e753aa7d00\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 3448648ff9f7425937b6faa54551ce14dd15566e5d41b2bdb1a8db62037459235a5b9546d289cc2295b0ed584fab2e1a798bc25a0c114238f61ad3381a5b441cb67f92cbf66007c980db3351adb9cfd2cfc769b5b9b0bd1701425ce1ee8d4b9f438ce1207fa850aaa1d3d1f970aef874c2b2499a150d29c2ceb7bac375009b77\nA = 1fb54cec882c274b98913e76342a9b8e631bf1d381fd8a4f7e0eaef475642ab3f5da70ca2e38741bd0182a959e5e985f1e0e7d737beb8c725c9b5ea22f7ec25b6e564809601e8405a5b1362e7792791f55ab64a57c03a99a8518d7f65feb0e21be619a6a95\nB = -8180d172d3afe00e0423245f47591d5f750f20d2cedd8ba6ab6f9aa24f74498a96c9001a0124c4f98dbd402b63e71eaa3a7af8b0d2fa417fb1d45f64e10030232b9155169153496aa202745a432e547002954eedda7cc9c1ca76811bd902b192f1a1d\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = ae0fd585408a99643271eef575285a6261a4c4a92c1956b1ab436d3cacc8d4cffc07044e57b357ffa43bfa9aaea57824319579c5c3e2fe4dd48bc818178beb5fc1ed60afa08828657d00bb88894c975378b1dfb452a5b88fc3c1d81099644a998a47a497c8a2b12c444fd2a088f47576b7f4fa40f34a208fbc3348ce33e59150\nA = -7dc7dfb753c0bc3ab4d07d5aa78664a7f57d64be4d4780ea81e3efc967fbf1bd1390248bbe259da32108ad96bd8b39f2c9f118bfdc96bd06147f812af831288bb687e4e1742dcd1dbf2b7adc41afa28d07dfb8df8bb2da5359e66330f5c65964096a96b31dd8\nB = 756f3e407a3ae698f103fa37759e90554f38378a9b8eb38581e0970ec8f9c00f8392612c61aca5fd37d1063b78c19e3109f35c0684ce523c634190b3164ef06959cc42e2b77e1bb2fd50eb59c3dccdb6090beb809ecb0ca30457a5c5948328eb218e219d\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a2aa4550e855623a8ed488bb63db8fa4ac374c1ae953781aac590f78a364fc33380ca2806445fca5bb9ca2fc7ec4db5819dcd5769e3b746286c49a7c80149e7fe276d095929e2cac6ae57e8102f7d4c96261ca44cb6f1601f429528495b6c3169e15f9babc5be696074d45559d5abdac42393094c450d6a4a45bbf60ed7847da\nA = -16d0aea9c752b2e6e4e13f7ab1f0a2c1776874967b0dfeeef7e00f8d9edd1e11d2aa702be45fffc284c47811c51dcee184a134b8f6d1874026eb51e2ec80c94837af4602cac3efde556ebfff578fcc56c00de99a43638ab68387ec087ee269ca64233eb5b1762ae\nB = -3c6b60b0ce4b13a5d6d9ccd67c76ec6b71b94ea7205e408eea099c7ced2f3a462954741d353d0af850b10ffede8ce0bf80b6893288413674504829793d7ae0cba53b163e3f26cd99beb0a9ad540f6d2cd5097beac604b1694a9a2f4c48b28338f9d6a63e75b\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8a1a8fcb68c53846b3edae33ec070ef5cdcc1346ab3a98a116344e6d2810e2e3f60f0fe435fe7ff257c7ef4c122b3c34c776f4912a9621b6949308e2cfe2e0827536c7464371ce804bd7cac1d76c5bf8b4a6fd4ed56b65434c3fcf0ac7be543fe2d09ac01c564d7b9b463740dcdfa9068d4d8e33f29297ab452e6ec55c263de\nA = 7c4878334ccd9e20cb11a643b206626ea5d0b20973f18535cd8f0fc2f0325a67d3558e4cc9cceed0d88c6d2215c220b8d0ce230fd701502b02081e3f6548e58e02bc2e79e4991f8ef188a84b0a367758b4e534b72cd87de7f82a26de14fafd162a50b359574812cda\nB = 117d8b1d2a3e2049e6edbb9494c68a97145ac3e658aeaa05e8ecec4b090d5f467cde34e05fa7f5fbfa32f1d9dad70955f22130c358468eb371555fdf57a40e1df398c166a22a9df2e1f4e18590b00856b4f880f6629f1a4296056dc66a29b6f0f25490c6a8209b\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600", + "540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 2cd3de06953acb87b773b8bb28172b24adb283d6adada676f5f4548990827635c51506c85670767828dc5b4b91b45a7ab89a700d70bdba4e0355da32b52c173305767721d18dd2cb6c55f890611e7abc854277a453c7500efc4cd4fb8e6c9bb7a73fe5c77045e715fd35d415b3496f7463ec902cbdc18f9f6f67c33fd78c3210\nA = 1a20ad042f46330df937b879c72ef00dcf39fb85b59186b8e7a9d40723288677ff6ab2b9bce95f34f2de37887c8a9cdcaf231254bd00c7e25b6042695d7dfc05a11765120d1dbce29dc74f35aa1492ba0c5ee65114d9a246b57dcc2eb2ea4a310be98383fb934121db20\nB = -f8ec67323cff9d53499ceb3afd44b28f0538c39dae8c965ea27d645b430c2f8a4965eadc8ed864f2549eb636ec558419be71f986f4c5783d0dd5253738b876d9034735bd13b18fc670438387f84848308d9357ec2aa4f6a453bdd36ff08d54a6800bb41df416b17d\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 1aebe2bc35eb2e449bda63513b1bfb55988cc8e6ec8b3c8fed5ce4dcf53b95f1b438c41e3b2348412b35e1f734edba30273935b03d16efaede429960442a01849c352349e23b4af88de4d01e9ddb53ae900418d49a84b7fadd2669261a574557c4fbd782f8e8f400895f6a6c9679b72983ce01bcfdb641f5067c94694e9eb80\nA = -5f97994c39265b5389526e3847876a10aa3699e3c3762a127d1a9f892180cce68ca6139a6f71b235da26c287bd3e1aaa1436746d983c23c3105c33ed2e06baa1e880f1744d81a80b98ee1f16220940d721a92118a9b949d4da7d1477db8f5b357b3ceb7df34eb5f62078cf\nB = 4bb4f8f4f4c8e63238e8774ed61a7eeafb3fe9a6e19cffa648defe82f4846e3378c892d223957564fcce79596151658a726031a6921cdca0adf0f5325d858c048a6b94312ebfd19b803eefcb93bbfaaddef120ec3b8c366b6d978524d5c74218da77e4c3b5ebbc66cf8\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5d64678a32c163874d1c81824d628a1051bce3b55c37055acc47a8630d3fee648df5d319e50b4c56f465bbf696433409b89c07e442425d3018a059ec757d77b3a40d516ca3148010036b003721ec9c999665915a3c442d95ec3c01c232feb201be08c88fa3c6b0769e3da30f1d73b66f98e31f4306bf4e23de78e74743b224ab\nA = -178d81e419f0473c426e24428caf25d61b648bbf963f7fb753ae15e5ea3706b53b00bfc8fe917ac9fd6c7096518584566ff71e6d35197f9aa25107a235678cf9ff8ae1501c1d5a15d2a27d39d066e169745e1e8c808209bcede0d732423d0c9cfbea322ba3201ebefc5315c0d\nB = -27ed464895b65d9518923fde5caaac0c72aad0d1b38fcb7827d6ad4e0c8dc09e119b8b98183f0ef8d5d1133f3f108e951caee035bed0d48bbeee6d1ddbff5864bc192b84eb8a500cefd223972ed51c7f720d1736646825f95f2f10ce6ad47a267bdd8c80f65d644df158d7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 52dfb6bcbbc5cff46942d76ba45301cbff76e9b894703a6a7fd1af29d615336372d147c3932589affe5c6533f28d3e6a57ce2d3cd7448bbd81e09a13266ea31630cf044f654b87ec3fa3294eb65873964110fd42d86e78d128bead5f117cac98145051552cc3a86c193d738b973f866d068a8994a49df3fc7c7314fbd9805e80\nA = 797c67ebdc083f3c8b3ddf9847b7f3c2a39e35ce2119f746ec87fd5d86671d8fcf2b4f6d440c43e93f45019032e629879799eb58adea729d43d2e40ede6485143bd35979609a12faae7e4393879c40c0511c886c66a24454e4f9912bea944eaa417c9942f09ddfb227feb14e4b4\nB = 1a599d1cd0ab3614f50b71b93c999942bd3d4cbfe7900122d5083151c71d9e0c299bd927095c5c3291418424a7c12947389bd4e0a3c2fdf67b3f512094ec0ce5b52695e527de2b3804dca2edaeb1ea4b487911053272ea926cf2fb3386dc4b1dc268b808bbcf4eaedd21168ca\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 99bb9082e4537426c61f3b813f8c97675c44ba9ca418960ca6e2464cf61ad4eabb01ba00798463567ed3d829d3f14201c740f19fca623b1e9b57b534a65df0f070a2130489afae89b91003cee432fab11426c4d13b7721e6f9db1bbaf0adc0064b33e4b9f4b795511a0744b52f93e3db7bc9c0a991e4e122c463ff344fe14cba\nA = 187a8144a0045a92dcad94f0bae7285309ec8fac7dc864b08914e5a4dc3b1a6bb9212161a18c22682ace16a4bf3c03dbaef088b09844902a3255fd6adc0b7c6397dda86d6ab67204d8061c36ca20fd4bb348202037b249f6c110c31580148db46dc5b1bfffa38a683a27054c35326b\nB = -e93ff16817b725016279a32dac247961ae9bb00af890fb49c4fd8cf5e815cf98b58cfa1e3735095e6034c9a2f2b5d8030ab30e2271abb45b347d755cd9ab5ab5ce37950380cb306bbec42b6b8056793a0955bcaeb23e2d6a9548684030566eca2d34c458f224c8e337cb8e3c252\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 631f53d02c031f592b3dfaeed106160488c08e0672083ff195b22a2c0b006f11165a245acad6f35dfb15a871a9a2b45c544111f71f86c920b42fdb6551e56c55199e6173c00e27c9f47256349a80236bcfd3acd1730f823031ff9ef594725cb9429ea183a7fb2e03124ebdd98d435313e43819d995c4fe81fdd4ba718aeade94\nA = -72e20f1aa2b5f2c4218fb9e11ced3f45a218f4c83a2017d97d0cfbbf227c9082cd43f939c8909e52c8795cfaa75d80392d3649dd85ddc35bf1cc54ba389bed9e9dcf867da1c05eda080274beb6b868b54fc85e12ae127dcbfffeb043f9d59333d0ab3374c24971e1bc7269450b418c8b\nB = 61cb021a3a957703d14061c21d3b0fc19598e19a17df9d6f2418c76d4d37b3f62bd4037aeeb1eda37f83df44c440f5e49924cc72ec5b153856c6b621350ec89d98859d9d1ec7ac4f0c418c6599674322e7d618c5ca588d5a873d5af356d4771c6cd375f5dbbbc69f50b982b8c4d1ec\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4654a62d9491f28599a976288cd2068d8e3228da12f645413a92f482efc66d1737495cd4a4c733f147eb5414a2ef6266a116ce264491a3463c9df1b030d83b315f76f3bef8cbccb5c538478a65092547b91e991e6be91ce4549c3a6e34aa7b466e63eb3b88054f6714083695c616a078ed54e1ae46e00f3593af845fcd0ff51a\nA = -1a342c154aad619e567fd32e7053aef8d98335a4fa0e35bf06acd7998c43d821de1076dc1fb67dfa1156d7ff30203ec736384a9aa7f5f08cfb302eb3a2a7179b2664094c2cc0df73fa05bf2af24a62b8e394fc76014dd83b434df26f8a67a624884a0b9b4f08f33e9828ae64f5d0c8cdc2b\nB = -2c57e15889c3dc9c94361c17585d506933a72fa954ce44dda9f5e33408552ebf49cae87bd0be35197f887fc6c7deca1452a4345eb67d19bd2e7d3dcf651667a8900388e4d5ec71e9433e3b01d2b3d91bb94d0fc3c51c70793f978e4b5ef93a9c6356c0b2f7accb9e4eb457a2174b50dc6\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 6124d9ce4de2880ae3811836235d6d89a1a4b710f1d5a517153ed7729dfb5b56b0ac10a4bbc811db9b26465f03cda355701f9f28c5257fe288743cc0789cc54a8661f46e36eec357580b00a84f1d4c8e3d689bbc18242f1cac30a87cb7a47ea06f80d7c5633cde4c8cd8a1a7e27acdc3a2aacd608cce9e2efe7864d41a56ceb8\nA = 7b48a9663d914e0225d7275e965d866ee6649d7267474d5336d28d54027ffe8572f4aa26230dc7abe9957d211e6c2c8f3185cae962b878cfdfaaf6cfe32058c299247f372ae170a1f7cf71380787f6e90995da9ca5a4be8ab1ddfa8e6e5dc65b6f168b9b8e29e0257e0eec853a6e1911b1afa\nB = 1fc4dc77f4a18d4406a4ba536e500aff68d133c6e7725717ae6537b527c6f40f93202a2292522fe7d04e0ef804d1a7013b04cd3d88462fba31534770b56d2e5672e8a6ec7a723186024c40b4717defd1433b9967bd692ef81d5d4e39ba10a3223d250ab6e71d5d253dd0a732ed386ad57e54\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 6443de73e1c826c90aa36fd7ec5d0c3324c42058b1c35d3adeda1685470d363732d23cceb08c3f973034c24fe65506bd33dc45d7d617a53048dcc103d3d1b4fd0534586c2fb7489ff5ffb98303bb068", + "fc14b1bb6bb43f763dca2c891095e613bb7b6920163aa6cbce8cd93d9d39f4512b6e0b28d361ae11cf76037eab4cbc819\nA = 13f739846ed2c3aa0a1923168cbb46f4f0a2f3942ba57bfa5c426cb4d4b3d80d9530405a31bda329a1814c560d54defa3e03fc4f808606a598607783d539dbb1338d5bc0c2e272a7ff6ee6f93e1665d6f5a0ade30308fa047db086646c763106cb875e014e2c18ff8837e4d4d86861b85a5b7197\nB = -ba019333046f76325fa9f258006a7c10d27e89f6d482b95c79296c07a65b8e3bff4a9c9fa7e5d0038da129390ac851f8c0651dcf655a3d4164a731cd20a701895c12a906c732906038a8e459aaeb293fda21346964a6d53fa3e370ebf43c7ec8f66229405095c6a509d0fa15dcf45de8d0e901\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = d3a6fdf4a26993edd175de9a0f012e1eb15a5a1c4dd2741dfc6d0f9177cd5645508b8ab09c7fb34066ba893c38144c7f2ecadfc2b0d15728b407e5db4fcbbaf1871580426400433f14dceac43d28f03376e791b7ad01a112981f29ff4b66102305f0ecc4fd134c2cdc79a5e9d9f085bfcb7e6c187980e68b6c7639c12e8d200\nA = -464cb16fdd395e32fdc613c63ab4768f8cf72a5b74a0a5b0cc581ee4aad1972cd97db7966d3124e30c9a1c80d85c46da2d36eecd7c3bba5866f9eab4d0fa55b2d440a311654466432c681372a80a7896c9163c12314ac51f652aad68fd9012dc63fae6c7673c5da8faafcfa1b4ed5550f2baede5cc\nB = 40389ba4d2f5fc152308c9e8a8c36258c770fb2d03e6189b96c4f8dee97ccbe426cc14595c8482e9e22486b61fc570f0e7aeddad2f4e3a480d4b75d14294a3b912928da5692043bd98ab88ece87a9bbd973ec82f990c0ae6091245318c2810187d69c38fa80e835300ed06c0723fe475f3fb22de6\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8a0f9eff3a210912828fd7b5f2d72479cc9ccdcfd3e8d21739e301de02dd5c257c7ce4bee2def06c9d0c90d5a86bc45fa9f31e456d353775916b3d5684759e4500f99ca1f91f6767a5e2f4b735ae4b756d56c358a06447fa2c2ccf0ce667be4ed143e9e1dc627a561d92ae53a62477270a7944482cbf671138bd2a85fce92b08\nA = -1da555639228fc6ead68049d836d60a4927ee77472fa0ffd3c787d55b6067012560f5b1c2ef8bbf6119345dc6419444c675c1c9cd50602a93ba3718a5b3e1a30bc108d796998b24474cdad19bc2960b295fee97e03f2ca7589a3daf35bd28eb37a67b5d2cb35a30998d5f8622bd7e6b7d3fddd1ae9670\nB = -291fea1ae6dd1c66c62ae3a3d22904f4b4adb2a48cb795d50074095345d661a033f67b20c5d7231236dab871892deaa9458c235c342bc81457cca3f014a75f5124ff4da005dcc1108e75527528e5cc9c051a97fc6cd202bb9166f9e72e366bdd77c965a70592e5684fcaaf2e03421a2025ca190fe158\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 50f4d25875150bab63e4162265a632109d6b4743f9d6b55306858034732a4895ffb3720286acceff287c38320ee9945dcd0a1bbe5ae1456b7f36337cb7d22b679a6821a450765471257d52b6ab7d59a763e75e9e64581a93aa54761f6a760866d6baf186cdf4ad2b1a6af26a3e76cdc261d1f07b0a7122c8ffdef595812e7208\nA = 78a1609a7f08c93c9bf9090ca7c93459aef815719b5dde5f217567a9f68ceca05594f6ab17a4666ce1c0c4434e0f4f38ca1f33e501d6958a10da47211cc011da219d4373d2bec4b7c6477b1ab3b00b6c45279212db39bcc11d1e7ba49916c4271adca7eea531adad509ae119348f374ef1203c5af8bc019\nB = 152b46095d3f8db5e6e1a9e3f35c085da00e52764b261c3aa775ecfcd38572d2e86bab2f4bf29c2de4fd2fb6f35f66e8685714634e1be980773526bdbf9c43b1335c5d59f4dffe1a1fe2495ff9b7a3fae3e53e7c3208968e1ad1dd1dc8cf2e2415cc76dfe5df9e2e1eb63f7c7687d539706502d56247728\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5a3ad8d6f1b0763b77f5d40169ff0013de638b459e401f50f4cfb505565c8a4465e28ca1bf988071701dbf52ac456e01e170788ebd2b7cccb50dbfe1a65a89a8aee18b3c11986c9d6e6571f964f376f322e10a1ddd9310bbb40f14b0680385c40975aba43153970237c535c6b0e2cbf6bec918a8fa26cb2f69e98d77215c23a6\nA = 1d5c14b0b51cf31e9d97b7c49cd26097d40454978663f8a74095fcbf9c63e533708befb1a467f94cf599a41220ce13493a273fc30c49275412c5205db712d5e1832b39e65c150c3a4b251e2aab853e4ecb4f00ee5ce6982ef9215775a33565bde3ddbd932665aae506941d3ee31b3f9e4ffc0651f1fb4a5c6d\nB = -93cae5dd84584a2a3d88028d6d4cec4146cc5e350b4d92c52ba2393ab69fc1dba96e244f98e2f93f31230904169641aff30dfbdd3dc5fb1f3489d63aae1efd29335345a79ded546e42f2ee4a70ed932699fad17a771ba65fe6e689664bdd1135219aaa905c962d39531eba3e82c3425c24041e17858cbbcf2\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 61211c706730a1b98c628b3c8cb070a42e2ccf9fc6302bb1c2960fb165087f210e9d93416ad9fa21634a05dd0723cc23b8d2a846ab7c3bc402999138433725e737102094db5792249b4b5b1514a416b80c804ecfb04653c5ab18b0a34d8777f6c2955ac66fef62c9ec2819f0e3c075920f951f86b32e02bc43239d9218580067\nA = -46c8c68f492d8f7ac7834f89bc76098146432c59b3301d4eb70d9861a6e24c7c9073f910108c7b35538a79de10640291b54e5755359baf47482b97af56475211573576e9412ee017dcf961a090a6ffb5cd995992ab68e3fe60b6186f7595bd9b8acf8695c4f7359cb2ac709f032fb993d16a74822b4935536453\nB = 46953f424d988fd20700ea08880e7e09ac22d60cfc294bd4aefe637408a3cacfcd0ea6822a679b68b665d6bebed3506d25edc83cc7154b83e22953f9d91157cebd219cd5177fede28c63a15710d0f92bd9e542a7586855bbe57a94c520408fc920b3f8d65b194af2b2a580c90db1cdb27ec26ba929de4573c6eb\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 50a063fff02f2cdc68edccc23976f4b3db99641073c85709626292b9475b9a988fb8509a6223f0a517dbae0cf7cd39dcf1e8ae75196d9f5008c661d8b5153cbdb9520c71068e4719820bffda4c393032edabacf99339e0cbafddb6042ef887b8c498e87e16b62417934015172e63e7457242b864a47aa10e203f47320f03c0e5\nA = -1740e8be7b4775725516d37ba643fc64203f3a61e6b0164d112af56666ad97afb0059c2c4981fa81d72264f8669db4e50e11865907655b1f669c88f5935cacf1b12c1db63cc84507af12cf0210f990994055d04d93f148f213e3d4fdcfe9dc42117c059897697914e3e3fa8fdbf0eebbbb9c3b9fdaa7efa0c9d5c93\nB = -226308f8fbb35b5f9d129c0f6a2bd3e5c272a408bf32020905acc6d02d7e506191e76a3a2ac47cf7a63e6306b256f489ca5cdf76c7c3eede175ee4a7acedf922955e92599647b69d463cc14f2b178b88cd471b8a1c1512caa66b6d5fd8840b98b8d070e6593136e98cce9643e006b714388768920a79944be36624f\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 747cba0d1cde75dfcc0b2af9072c5027986b3e3917845870c73c452858ba21d6d1615eb71ae1b5a03ca44e22845d5432b368541b52a4bb02498668e8b99dfa2eb90ec1948d90564e6ebc388ee9816e329e1d8da0d3e2b12d901d47e22e8a1fabc37408be0f89e7a4ab0f30a03f7e2ed817006809e69c21104d0efe548165f64c\nA = 5fa76e37aaf0eb3d34d4f4c590e02b6c63fc62b1d4c9e172cb0dd82409df87ecb43a1680a2764f62d13a5e919db2db08feaf98d5cb92a859dd42bca1047ff57b8fe5974fb3ac11ba2c0d8e2203750f30650db4b2cbd31d07fe18c4df84a0dfdb30f9e528932c097e89d8f8be6ff029dd970a7d2c2551529455b9131e7\nB = 111199f91b3749f8cecfe90e9b9b6951472cb701beb39d63068c064cbb2a1e1d30736026f781836a52ad0d828be6c20303c6c0bd03ad664dbf6044a5bfb67fc20a049fd37c62ab0795d836487b883768ef7c8f427eb98e5ab6621fece77b4955822f8efd190c417ced398c221215b50e9532a869eceeb605fa1c936554\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 646cdb3ed472a7b4599f02329054846a8da173000eee7533240ade4dba82ee3d7a6a92baa3783c19dbd3f76fce6b5bdd83f1f229b1c71a6faa18602e368f1b0b9f8c62bd8c854844af85c2081924c9a153e27853b2a48147950fb614028e090e2198", + "e613631c95e565c2b9b64a43237fd4052089f9d1dd2c00525dd35fa946ca\nA = 1c8438247c0ca376f508ccef7933724df512f9e0877596f7f4ea73dcd824809bbc472749833b537eec01ab23656e9758da22ab8a4aaca1aab3fe8d2cffa6672ca0c44ac029c2ca6c3e71780c28c31b5f154c8dee782f6ba009a69d83b1a3a03a2d6275bb8bc3932a1170470fb7e405ae081f4770b535edf49f73a12ba589\nB = -e365c8edbca8dcc4cc11986a5a901e4ed0adbe89b0ab70a53aaf5821862432a1320cf1850b515177b630e12692cb025e3aa43e9acee0d8ad5e48bb15e9a3f34cbfd39d285127b52dde58751f572ae68ad98692899ab12d35e33652c4426ec60c5029e51f7e32ec3d2031032aa7b6b2b63f84fb0023c81d031773f3652cd6\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 7a3e22f4a3f7ae7512ed73a07abb5ce291bc90bad507a5ccc0c17185804b9d231b0ae2e72bf270dbd60170f34b240f716529a449abea0b3d98ea2890a4ce3d9e2214819aefd070e00201e9f271de925c4ba59651e55174c97a13a30197e46997c6c2b152548111aa98df120a617c54b71f8eb8b0c8b4dbd5251f5509fdb8a1a8\nA = -78a99d206b4f095847e9a21de273aa6c47034c9afd4c081a8e93c2d75f4ae5b090921ff5108c863785c413e2f7b4a361506fb66b7561b8b1c5cd537e90274bddaa4e91ce74ad81c6dfbfe1a34a631dbe455d74ed9d041a9183da3bc469bdb214d2ffe893f89c3ae30f8ab99c3aac4d2fe864b891fbf4f537745fddcc60504e\nB = 5c41274e9590c1ea44c113ce505931758f2cef80ba3b10440941ec9aa2ac984b29868bece2922eaa225555dde84a8334f1caede99091165151a39538e5b7390e81df757f521236314239c213e9b874e396a022f04629c09bfaf929a0e9fe0b0c7386b0541446f6a2570491067f64e662d8611c4fd6d1c78a9f3ae69f34d14fc\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 7fd27b6549494c9bc860146a3e8ceee785ca03faa94b0ce0a964844e7871e813414cf3f111da49fed1ede5e71e5539f34173d41f9a17ed129016bb9b04c86487f5def9fe350fd4dffc67b6e181e3cb26378ea15ff9b9ebdf1fc86c072c82ecd8bcdc241301daf1b774af5f90f37e45e6126c5da7dd3753a1e5b366038af6ae31\nA = -1930548d105661dc25a5ee303b61b559c4bc1f2e28b2c40cf3e25f98dfe01a7dcca0f3dead6463b55a5b2e0440a651cc9e08e125535e081c742bb3b2f8955ae897909cfca683a4822896d8a4a7073c29a80571445c6a0d53d2efe4a30a79d2fb5d08c0f95b735a1cab17ba40d71b054c9270ba6bc870e58591fb1bf9dc9b7ee8f\nB = -3e2a4c1509494f94406e3843c9446edaf0a6060144637234c6d9ce84d70fac54ed163d77d210bf557bbea0404922c8aebec67a0475a3c7b74bfa2f226403ce987c705c712bb8eb0934c2b390a173c3836378fe71a6939e48d187b27cc7236ac115309fbeabd9ffd0396fb7fcd6d46a1dc683606c757ddc3212f5d2ff3f2e450fc7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 2078bb5c82a394c30a287aedcfdc5271eb3246be05954181ae4f86ad2880ce674640ecd55c2ee3f4e89e2762139586516a28558481303e3071cc9ccb9a538f887553bf5726f3849fc41ab027fb1c680ce7dee3982587ec71b3760e5da6956d6894ad8c4526d8de953c0e681ecd44883a21f0abef1544fe601743efd3e5eadb8e\nA = 40b4ba1e977825b7accb941fe0c0a49936a8a47429dfff53502fc0680d705b9fa0efe003eea3ff0b649998fdbae8d0831bea7f34159aa4c7add6bc7cd56fea97d25fb9a6a10f4572c26d792b76c18ada19b0ba06b6142c420dbb40d66be669b7c51d8cd2a5022fe1a8aef7b60965c0176eee69c32ca5023782c5410adc1b15dbdc7\nB = 1bb2f18d7c8d306bf80ae1901115c8dc3d286baf537b812ce06d6872b61e5bd44f3c53d7f31ca8461b3628b255f85338cc325856fda5a6248b7c476532c1bcdf9713dff9932a50e52a9441aff96092d3fb0fd76046a8d88288d0cd55741083a1bdb20fc6e9c20e82490273354bd826bfe001322dde9a15763f2c0e6ffd2cf60019aea\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = ef21dcee9eadceaeab13287d6e3c9741811f6ea9d5bd111799ae05260b1de2ffbc192818fa45dd7befc3baf6840e3b9d24cecbcb2cb1c3d653c4aec6531b941d926fb6692f548cf81526acd0b6b0289d70dd11ba50ca8de6e174f502eddf47e57440142c7f74f594a9abcb48ce1873df057b132ccce8b364de3edf411089d28\nA = 19d0109e0c47ad45f57b8bb8519265a4390534d2ea07f969d84ad33556518b6234d40d1631be3c3cce6d59b7be14750aed114008458f50a6a84ff75b4ee7e4b826ddcb2d2293842ed29e4e484260a92199c5c66367c402bdff0f1a8057127c6ffe452498bb352802e0005e6cb084663bcfa82783a3d72f3a2a341b8075983892e86756\nB = -81fce71491eda139ed996f6a289dde8635a3a257ad6756e844c768e66746011fd797658184fb44b0e3f3c5600c56238ac7687b5be42529d5c9b97c3ce10f3219e1e451bb2dfbbb44cae0828ef894eff3b52b8dba4c115c3b471984441045f2c2db426cf5f86949d5bb7662cd40bb3b3172a19ca3fb6858315d688f13c17550e700cd5dc\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8a5f90344071790373044193cc4fd92116248aacf05ce639b6aac4461ec3ccb0805ff9876ef44fa71088c295db14fc820f7ae2c0aeeffca055f8f7238c6c90db706d02f2cc43b4960abe3ca4b6dec8bba55327b958e75c60c5d1f43fcf9136f12481c267481a725eecc403a16aa6221346df680560ff316a63ec8b51dc37aad6\nA = -7a54e7ca04b9a22e2b986e72e634317ffa20f6f4ee90353d559db3f3c1bc6b3b92ac6b364f6c5929090373962b49b59cb5d87554387761164982955470cb45dd00c4a8982dbaae3a1ffe700e8903a4a8e4a21eff9d00fa496d475e0e1a205be267499dacecd31551f8a9d437f37dacfdf5a2754f0876a3e02509b78674e7ea2169c43f29\nB = 652001f073d63ddd526abc957bbb48ca74154c8f9698b988178b3313dcde9acbb19ea11a935184fcbcc31e0117d8d2ec695ac56b5a71614a12cf90f21c8882187428755b6a5f11c314ac8b952ced0f65db0987f0f87e20b82a811599f4160e65c7418af7f33604e7b8952b70581e3e02dafa025cecda970d04383ee552abc620dfb9c5df9a\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 67f903e0e5623258826b681506f3e94cc0b086e262bafaa1395294aefc9f6b6323410a44427010d5e8d8288993973ad9939199b85cf02ae0a09dfb69801536a3fa6af5ac373add7efd25ba5fee6d8f040e97056f9f6fbb45795c0bac94c51ffeaf496710b00bc9ddd8e445261d976168771060c9bd9d83838a84ee9428f59d6f\nA = -19c695ee3a4ada840a7e3626e61047c5081867b15843ee9a6506ce45540d23ad25ff23b72f988bf26ab8b98363d9a2997773604f43fa732f59a4b16ddf3a45acdbc7976a1fce01b3dd55559c20acfbb7501730f794bc45fc09b1f035d60413bbcf32a83fd3c41599049a674f165ac5283c42aef213d777ae47eea960f7727f5758146efe5bf\nB = -210697d47beb73f45207340a183a729a1e78d84bdde1c7d8f80bc84559c4aa4572ab0e6927ea175acc7a268d05616201cb235e610d1012500c8ba9351a37bd68b4ec42227bea55cef5ba7d12ffb180873ab9d33d09e6e969df99fca728dc12dda6903169acbad38388fa9b001edb09056a2ee2aecfab0468822bca14a4bcdd3a4122290ec5ce1\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5fbaff0ffcfb2330283fe59611ef51cf045bc2690e31f2ad3265046fedaa990b5d5060b3c38f17bbe8b2696e527fd77ead8650d329c2e0c1f3b2f5bec4dd85641022f3e0ae6f66ce98cde1a785bb52eca796ae45c33142e8264621ab447cafe988de926544e1a7036710128c42fe8b574f7ad69d830894237d95a55d1bc7f5ec\nA = 482db04e35f9fc1d87b42bc5efe25a049ed924f816e1b0f9c8ebe34bc771e67e26d6057563fd5d5320681e1207c0b0f4b7df547cd6d5be6a2e0f2bfb088f990b0303d0ef263cf45681e0e9a1147c29f2ca5251faa633ca53f6e0b109ba69bbe20c58a76a22789243d1acf128dcc936602e832a20a2bfbfedf963bc1027650f483814d7f5e6905\nB = 105aaf563d4c1d436c6a4552770a527776f40bbb844b7701313c5ada95180160e7cd4b7175ddb943e5a22c910585dfc184b52935f06b12c84b6431395f28af2eb9ccfa66b2ee8f40fd44d753c6a83d67a6f3fe3658fecc7fb2f4a8f357c5d244422e48a33d0e2971059695a59d0d39b235d5194e919facbae7623ffc92d771532b6b0cf771912c24\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0", + "a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a9d204c1a497f350fa1300cbaf682c947eaeba8b3aa0450c1db9120852a2edd2a0249dedef3b3746298ee42834d869e9f765ce987a2aa4712a1f35ed10d0f7ba9cdef938b073c3a526e5bf45f3510c94ff1fb84bc77b08e2aa50f5cc75e2f4da37a8a711f8aed5e92f7e486877229cb4ff2a4d0755029972323c0b51a14fd1e5\nA = 13fd3d7cc9d6d6821d2f2b1c40c8e070bfa85b994ee8f3e0baab544dc71328a1a57b7ee57392ab6d24bd85f9ea0f2a312148fc4f4b22c589e9a265d97e73c7a5b420bee180409ec179c438a67abf37eba61ac76197f3c9ea5edf2d4b8aab91e9bb1a432ef1f214c043664a51ceed1f2854880dd458ca253f09d6f6acafafec310774a672d07147b1\nB = -8c90ecd56d6c7cb129d1c9c26e94cf919c5747450542cab52281d11d8fbfcf9ea797b29588340d146cc40e77dce007b68c0c24356d4b75513b75eccbef6e22a5b88417cb6c516578d17d871e7d0957c09795f9a0f19b811db75d61c27e1827fa2773846857fec020f98444e307d3e52af501114b962ea705cb0cdf815109054abd00810dcc270d7bd3\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 57aef35a3f5388c810f576dbc30d4e4e5a39248b319b7766311157179d8bc1d7ef019cdd8c2c0175a8424abe7b33565afc0128724fa38f0900140b6f96bda2e78d7c803124cec8c2f2d6649afde4030c76cd33394fb386342d1ce97a4ecd180872134fd4e22667a687915bb4fda21f7e0bc9100ed8cd3a6668ed3a235d7b15a8\nA = -673bb11795d9d20a1e4ce8ae71d041705990463964505befce5949f895fa31c92d53f91fbc110df4e789b3f3f01f184c55df92927b8b680cc92864466ce5590ed2e98901cfb78b32ea79bf68b57a14cddb53209e08a7f430fee23f4a1475fd2640a515f8b609e98c760b4301747ecb61f1e6209b07455f1c8a7bb4e20c269e17937f39c6a2fb7b2990\nB = 46beea6005cf96a2acb16f37e357bc8975f4dad502fc3aefb4666344dde456c0ee7ea43ec493b6aecbc7aecc7d4cd107aa09e874ff564f5d59d7e12047b048c1da1faea36a7e2d02d0567bc4db41b54a75110626d13597db698fffd577a5810286ea8bf50625296ee8070419345fa269a354ca2eb47fa3108387f6a4b2c0ea3e779908a14469106eefc14\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5cdb7c451b2950c9d87638857407276959142958b06241b2010a9f93625f9106f065798f79ce5c534b9e5a31fbcbfc63cd200fc1cf10217096aa0194acb9043ccf7ced30d9f0bf66e0dfe27ee2ecc40bcd8de66fe2ed6f8cb0d874ff7b5fe71951412731fe4e19c34bee64c9312577b9e7b2ac08ed15aea753a6cd3e286192ec\nA = -1eee9d5d3854db52f9b43698e05d6a0f1d1f8df5f32884a775b25110309c46ec5c7e112eb64b2d7f948868bb9670068779b0a78bfc7e17860ee02692ec6790222b4384b9bd7db5abf29c46261c10d95f503b821a4694c45553e0dbaaa977892b916cb8990ac9ec29ab5c3d63ed77138fa1e95f395b3b233d039ab5daecb0296203166e9386d1071c61cb1\nB = -34587c2bf3473a2c5d7f3399d5ba2bb09be8105a0b9f3d8737d67b03d8b91b1c869f4e223d6246abd36d99d84052ae5894e58288a614a0da8d69f1aa57428632c2b059ba99315ea2f68ee210e65a741e94125ee4a723a7828bcc410aa2dae06ea8ed6cd23f66ccca7e85d2e071055787f230ee405e50d1519377cfe0cab4e5f97b6cb893b01134813a7c2c6c\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 95d0b209654de56bd7d6f74afaabed2cbb3247f449d80511d2d3c689f84c9b79587d78abdf0eb37f1b89f1f8dc8a83f7f9fac2c8cda1fd3fd64e16f5597b7f0a1df6da6db9e828ce7be0e876012bd52f5a74ca73ff8ca4611dd9f342bf77b485305ac28a1f8ac7538169f2bf3e4ff4dc5fdb9dedb97fa743fd8ac8791b8e288a\nA = 7821d4b65d529c30b8747e184e450cefb11b5ac5dc77905e6fcd3df64336661c82ea68d588ba616d23df485ff0658fb3376d5276027a40b392f47219edc5ecbf510cf0c5b431b02c65e5f432092f941d32ac5f71ce3496e403c7637f63a23b91e3326d01d2d32e99e0ab265108dc5e7919d3983839b3c7541848dbcd420a594e850e587f1846951852ed76d\nB = 1adf5c428f2a95c27a943637758d5dcd7ca36592fcb9d52ac0b7d27adddad5804e3edef257aa51c716801ad0c731e13c5dd000f11b5ff1b69c198f236695c1b2f99c0afffb5d084f80fdc534de3b0df4597404b50c7e784c3c55dfc9753c414d145eb0ca4d07e2f65b63f3eef8d391250a5500ef64d9bf963d7250d6906694e7670f92e3d5a7930f0f85964a21a\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 46914b197b84fa99addeaf55dd803182083a7ae34d6d4d3a55d6272af40a600563cc8d9f6b48110d0521b8b99751235bd5a340b1743497ef1cc459dccf5d6da970c4c3103c978ad2d513298f1fb3e68b24a9c7b0795f47d8f7f6ca9caaab9a9d80f15982599d764f8738217f9158517806fded5f3552fef8b7dcd2e725ee04d5\nA = 1c9f5f2a0d72806dcca92dac1450a50cba05b5dd571c2b3b988d33528d90ecc83444e3ea8df80802c30fbd5a6ec2ad9969be73aba6dd27e0dd2c842b95371d7547768916c0cb036964d041284cd323c8073095b2a8cb8797add5cd80f03595de9d18af8df7dee0d250ea7048faa47ae0131ba3f350d82864dc95e5829b88eeaf2681433dd4d58b2c6f70426af3\nB = -aa1e1b3cfd5ca0facc75e46d872584d55144620f849ab05931210b4e1526f12679bbd9cf00efdbd8863970e2abe8fc9fa7bbd21afa9e364e3c9e32f51fe66844fea4bab7f3b1bd278fd803f6bdbd0d296321e67751a0b894da338ab431871adf1514269ba05e0cea5558cd5691920fbc18237914f3dbe4b253f774e5dc1dc57023c080a3b90a004b809d237658ca1\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = ada55d93c533716ebd8c16e23603071950aa714deb942ebbf77206753d2676a7aaf61673c03a4db69d67faf6273828594d85e3c8cbf38460fa2af603fe9c1b6ce104854e7281757b26589f079da80685aec153fc5fd1a223004cdf30247f8398b8e92899857dd199d5d5c32412bedbf9d55f20e52895fc1dbd04c84cabfe1264\nA = -7d22392a8da1966e6cc5ef50d7409c614f8c8f8e5791778f68a00b4a056d0002707933043d05e48347bbd4d0dc1b6ca32a1aa4bab9992e7e620263283eb68d97af13b90a29c1b7dce39ec0b8a63878e8d65aebfb3bff4e67129e3b3725f999f1ec9ae92007911f2cdf738499661c5b6c9bf27712d0f29e871b17318e95c3d14b2e472cf9e466bea91fb71a493b2d\nB = 40279eefe59f954aa8c51c9c214fa07707b1d095f697ca40edb820401a45c472d1d7bb413eeddb64c14ce6144b4863fe9337ae4ae8698db92facacd6a56f3b33129c5b608eafa29e9d92dea620113051b926b80b75f320d7ca3d2ab597168c68774e68c47670458f5ef2ffd4604f20bffcc7817eb09c9057fd9989a6786a7e067ebe6724a89e7d1580f94ee4ed502cd4\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4dcae9def5467526b0ff071003e56f5537852cc0bde9d86eaed2c15e36e6429c68c061e12d321bad12e29626b5013c28f118ee59624ae2f35d2c53bfd89e6afdb6db79f0321ad5c55cab03e6a1a97ff7bd58c760d0e9fd7507de987ed2f94f9c79569fe7f03652cd53c67ebc6bd3c9e6c5672891a9d2ee11b300ed3b19753c0f\nA = -127f5ca6924851faa2340c4c8f425b1dcf41b313c5c2910e5eff8ef2faaeaa43305de2b3a65a75fe54c00fb30c0ce3e8007db1ea222521190ff1de6d0cf2e777ed61ce8211dc167bf115a77890d0bd1ca786e967a04f077c89939ce484bbb1c560f669aacf7756a4338d97cbd7f09a376d2dfd4d632bb451f52c03c05762f050ebbf112f8dc5acdd9b631292fd7073b\nB = -3bc5e9c352c46449a9155b7ce5478c771293599cd2dda58a962010f1f21d094aa6bee03f9311545e8dc6213f6aa73c08b55bcdf4d1d84fecb9eda35c83eae5fedee75b2d15a003f8a82b2b788ea19f7460fdd8f447d973c950b3b250a3022c19ff312ccdc86b6ab50c4ba627b15968c8a66d306bbdae8e88fe28c1853fdfb3fde92353f46b5bc448ae42306a4c91202f03d\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 62a812e35f46e04b3afa7d26c8fd4eb168b6b64cdc839ebd0a46bf2a3a712af8e97380cdf0bfa8a274f7b73e887bb4cc73c6104a176d425aaf5352f14ee51ba549a6926bd8d059b8e3826b174385d4635b0c36df75a4e7da44c34e51eb82322b34ae00e8c712eb75b3882822bce5a2f2f5fd74355319ebe1973284c690bed2af\nA = 71c57b08127a956f0c17fd3c639bd1923ba19bfdb83c0cb9dd78e62b8fe4b7e0019cd0a6b73a334c622118f96fd6d91c1e06d4dcef8a3d0d6bf8f5beb", + "6389226c50d14d3947ce9f24f7e0e6a7befad2e4e92dc9ed8fbb9811d908c03ac074b2a5c67b67831a350c4d548ac70810bb5617d261a045e53cdc48117b9fe86d35950d0a181b73c8cfd35edd31af031178523b\nB = 1cda2a51a707f8c4d2cbff6337c3f63519705614c26a489b545b1faf366b705af1d953701b568a684856fd3186c035f878788f7e5dbea16b5e7b6e767cf611452a4272abf2a9c5e72b7251a1ebea5098c60cc5bf649cb70980b97d48580967ffe2913309b6b78cc12d91025ae403928851902dcdaaa60f5b323a1302a5ce114cbe174e3eb3c2fb5eafc44076396c23d53b028d\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a9213cd809d41b6bbfc2123bb84860788ce22d5b91f8e24fb616efc286a218ae9652b42912a58bf8ce596a1b48e4c72f27e52c36be1940f7d2138eb895ee36bbb917a59f73e0b6c3266bf4759ffe2ffaee3f6179492658e0778bb43c4df4bfa1a46300c9da496033142ae2c1e33333fd7e82c5a14686b255e224c51aecc2a590\nA = 1cf4e2d5924510a5fd06ff4eeb94a740e430613277149993004b8de1a2b96ada54b05365f305e896df5fdffd3d7bcb54f9a9dba9689e5ad498012f7a684d083c31d7017aaaee720bbd42382e526a35d2add21d9369f7faa41dbcfe3dae426948a402635771a977e19d5c353ec7c1abd279975f2effc0b7bc19990154b723f2f8c29e606581ab9d3966702f68d8bb8065e9d8\nB = -cdab60f9b8e1add4c54427b638ec5f76b30654d3649b500f833b2943bf6cd5d8647549657a8ff999eaffe413ed87e06267b97bfc1b77637b57f29039235548a7569fe6d4bb16ae9c6cfd38c0b8c73aa60797d0d69b03d5a98314f7f7ee25df8b896ecdfc782cf8057f038b6c3e79c99df52f839fd4eff302ddd1256e51eb31cee24585782a0439da3db2eee79a58f889d8847fe2\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4dde3d63aeeee47441a7e733bcccbd4f2e495ca3c746468e9855177f7672d5d82e51da8e268ac24e8971d802e25d842a16a6b8d76b8e46a7724108c02d38a4830453408ca5ced7093676a1db4bf4c94b9b7a9531ab7c26f8de520bafe4431a55a5f5d8c7576427a0f5bf2081b998b82da2e8e959f2ec4d5141b55e40bf6ddeef\nA = -5770ea0a75ff451fc2c86d428f2569884b2c88cb6d9d407cc22b191849d389f57a5765b83adcea21c350b37bc6d750d4859f547da22ea8a3698a5cb6154b946331ae2ca18e7eaace951dcd49405bf8d8a716f7762eb242b8bf5e4c53a662c906c3be89e53ddf7a706ee2406c7d0ac17b54ff259c1bd5a092325938832763ac4caf0232e80a016cd1994441808d8db7e546de3f\nB = 7e4246ad4af268695a51912053ab6628969af4fcaf7f1e97dd977984a1604e8c9fe6b920f39a764c27d89f75986a4bbc122f92ccd1860f24677cf346474fd9441f572f769daf834e6a00cbc027e15d6aa7ec2030becad41e1068740cde82abed768de7e2cfd325848f6063e2186faa76982b9ca73ef22434a28bd2e3a5ac477af50f258140bff938d3fa02fb904a8ee0ef3c1f6fed7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 3d8bde8d0625fc46dec46fc657c49c8ab12a988cec4ec1c24e6f4d8ff94514c8d8fee4a08399c6bd23fb6464a38bb5f249591456c283325e343cc289c85df0ff2c1707a6e407ff7a24383b66ab603b75e2dc3835ffe9274eafea148f20764b8ca30cbe483c1cefd51f82dfb93d7793b3ec19a57f2ba03d884f345bcc3188fe28\nA = -1680dd51d8be6069c86ae157922d55df3b58ee6f53738677bcf7332d6e7ef304ecc7ff7c5a5e1f525459d77202f3e815c68f17f9a6bf358654a92f9f9acb252ed8e9e6a849da7491f26d0e33900541ab67ce966d042607258b4382b8108729a703b429babc34496528f198a7e0f814db80fad4900fbccdfb64908febf5e09805d3a3049c0f164f0bcdaaa9bbb06df8f05309be83c\nB = -2c6c6b3c89f6e1d1cdd9abd1a9706e4f642a25738aebbc97cbd60e1f4ad79b419dd54bd14f2bd147b1d8e9bfcf92faccee61a43dbd1a2c084bf06a2ca476b3d169fa2c99794fc827b7f4dd010c0534e7cdd03d00456033ae0203b78a7ed229afcec2d1cb96892eb18898bf53584dde56b4316b3bc5186d97e3a9edcd059d7fe14561eefe4881beb8519c1cb7c3ba22cd2e13d874aab77e\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5b4fbf0445807c8feec7efa3c2bf8dd86b1070638f3c87f1e173ee980412a28847b263a266506e70381aae919ae05d306d3a67a6c1e72c8ccf1c27d6296526e87f0f436c98fd1391f83440b58fadd4fb1905a484bfe8f516661e7176a268660387fe6a7266ef02e5fad91ffa69247bb11cfc1b5c3a88c76b7923a26f8a31ece4\nA = 65fe4d55bfcbba2bbfbdae831aef3dc8c8746e1d04cea174c1d336974d81d026f562225b4a297b1c3b044ccc5dc9c830a805a399bf26c0369b52ab0dd2c0ad19e723fcf9f5de2990ebe5a1266653195a2aefd9a392fd3da8c22c523a362f195babbbf5329018e3b454221b3e77cd0dee79f612f86332b1d104aeae7d8d84ad06b107715bb76bce20220d1340ecfc666b2bfce812814\nB = 12f775dbabf1c112523feab443f6e95d773e8220d66fd87bb7fc702588136a048e17ab6845a9c784dca275cfa445d007e8d8383740b156df7048650f89c5ef1a84148488fc405898f9e326cb8052f626c8881abeb70f3a0f52dd83e3ae0cb82d178cbfe8c393449caa2a87e7c8e2901a87e276b49b6d012f3cbb65641add3694fed3e3177777e78fe375f3a3b378091bb8d2998286562faef\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 4f0af7cb0c4e82d0e6589b24b55528818bf2164d41f58505a2b302a8f677df146f8077945dad3790c323e19b37e3379eb95de8abdadfbe4417f8bf8da643768a622ad4898513fdbc72d3b1d2791ec9ff40634678faf0e17d6e0851f08c39405907db85b74937ac403a9a3a1004013c7bd95a585728010689fcaf63b2031bc8c0\nA = 156dcadeca94985ea8bc0d1378daf1e85ecc4c7f8b6d6c7a5cb9f9ac368a97c07e381004023bc575691c082b5e9e13a02fe813a55e76196e4ad4b0f9b1e089bb71a0d5c94254b66e3e645fea25d69bbc5af266e730482a60105306d664f0ddecbd76d54e7235979aa2d806b809b3468078b5d90aa22cbd2c441198d4a52f6259972cf3d02003dc39dafdf3581638e56d08c5181d36e9e4\nB = -9a54586072d093939ad86df11fcd3337ad7e9e478dcbefb2b89d7555883fe8565abcd5b0a9c88ab135ce5327b2a326db645bc7c0e3ce24f902544675ff9d946abf30302f123aeed0f4e28edc72758ffa760277caaf4817a3ae8615784c81896d2404e2cf47c06b09085cd0ad1ec46cfc1f04d0272eac29e774b30f19939d08c036b185983c93ba15d1d27aebe4a357b9f6a298acca3940d2730\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 7c3ac09486a6fb518b98a9bc8a8b382bf2293e2c1154470ff7961212430fe2dd28697e49256b1ad8add082ee27b6ecc016b120e971665be801b720069d30c0a8c6ea4795613017e8883e5c0d0e68f982c328379d7a0afb7825c553e087b33e9d78f90e0b95a6597076b8ec2c1d375e2143bb778c318ca0680a64072cf9a4fc08\nA = -71d8e7ef13d63b4f417c01ec1241020a8ff4c9b2db531500984fd3e45d22b2bd581894c8a248ed7cc345e70a5698407df8f0e4ac71ed2c0d42122a4f92279346f463aed899253206786928a0eb7c37f2e51e1cde7f97cf9288d85c3ed7f49e62af0bf9abf062d2c6544d83b9d3438b3881e0d07b1fa0f2a4446fd43ab3b4f81fa2cdaff199c87965e298943c68cc15f2f3f3225efad68b73\nB = 64d52de221f102af62ab1e9526935b005c81658f8fefa019bc58e641023fa785798ed0dff8f7f999dbcc2ecfa47d5314ac6676c82170d6f2b18122c17c1e1ec1b9b54e333a184a46ad35b2150c8165f0de19a24b98327715e5a641c1b6d3ff9d247c89c8749e775e6fcf5f967c6eb5e73523d4f1ec12db7321b14398f26201a364e1371f0ac922781ee252c6d2b3c657ef259ab73cb7992a370598\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = cd08b388ffd41d0aa29a3dbde74106c57b18d325be8f446a2d9ae95fa4144037dbd41eccd50fa34096984cb11bce555c117c5568d76a8f79d308ce11043fe2413d37d6aa60c366af6c1da93d525e4b2d79fc82c0a53ed62fbf72c919db8a3ae11f5ff8057d7501f5f6dfc9ae461c308d21919d0de9e31b759d1d8e3526fee58\nA = -12e58708c30c93383cfe6e99ee3c5caf1900a7e610605706e77d8f428fd59db2884f5021d7a382cb18b75ed22528961cf43be1c700c581ceac3877e83eabd860583e6e94f3f2989c179ee5047c82b53d37054c9cb7ae08be60a91b10d49510e9f0b90ddf89f93790c3e18cccad5a9d223c605a6c567550e2b4950e184fd97dd68bf30681d3f9c585365de2cadf36a43f5a5305dae555396dd50\nB = -26ea5079ba7ed137a14d00d413d6f818e911cc", + "183c88764de4d91d7a9b4cc7af3fad703142dc7905992eb8bf489f6d8231bdb25603ddf3c31fda8bd9bc4d78835f9ddc1e6445037f05125cb1ccd92eea2e927297e5eb915d5d965a25e5d58feb8d79a890e6036c80ee91e7469d9eb672d7a8db68905d06f5981fc40bf486575a067d35cf14ceee3ccb79b72871bf8f52b92e4910ab17e5e59ab3ae6f9\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 34714506322dccb91308c403c267f1ec75f80faf3cc4272dff4a84c13eb1e6133af6681387006c61e7e087046b64e7ae74eea8a3c0564a7c1f381e1c940d92b2c766fffdaa7318d07dbeb877943a73b50517b49e5117778b8a60212284fb92f29a9f5304f8f537e88acf8afaf01fdf64773f988cfa9551d6884baa70587ab76a\nA = 638b7c549ed14256956bad532945ef9e11a50313172965386635a2fc7db79deb0cb5c157e9854117c17f1509d505d01a0e138d2e510dfcca45b4f7ec968b5214a6699b61b8ac68adf64d5394f50d577a154c013612090e2045462160d1f552592197d7da78e03491ae284dc9faf643805f2674af8652bae93ff230fc3eaa833dc62781e5f74d0f0b90290d51d481b0a94ae6e972197c6e84ad7ae\nB = 141f62297ee88ad527fd1e0e09d9ab5dd80e17b32f34a674a27b00d719839701664ccca1b00da2613396cf633b0bdc4482ad3a0c3e209eaea7c22f33706ae44155f527c9ca4e341e651760d1c39f65d5e99e649d013730d2502b6b65adb8a73e6bc734b7d879b430798dcd53fa6c0badd57896cb566d9f1e0a7b3a9161e9808e762ca819330ce9319dbe7f49bd663a9f57ac53d65c6851dc7bc4ee66e08f\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 7adf54c77eaea2a1743bc5011ace45b7651846e77f90402297f117d8b1c0377f93f49e92a2457f3d3debec3022a96c74c166d01b2279553ef518ec0e612bd7b382529184640c55b89255b2679da9cf370913351592de39f804f1724de36db90c045fa644e8ff20627f67d6afd4546f00d7af093f668629f9a06c07fab5654ac8\nA = 19c491d5b55aa25f2e18cfb7fda18ed4b020e3f63244eb9f6c4dfa86eb8a70875cc898e305a7acdd3eee081300edb3e4c837940bbc1927f5ed9f651e46581639e133515457464e9c451390828e5e7e00a688daaea74620363706cb69e02717489ba9ad05774c424c18e295278caf4df4ced80b4cbd20cd631df43f2e16ec0334564d9dc03dfbc7111e4252504fb449d5a25cb13630b7c0c565a82ea9\nB = -c3f765349639beb80f888d9c8b7b335ab46b55064ce2a88180c80ad280c6b7314df52b7e73095dfd82896e24604854a48121353aa1de663eff07882771803010005905896357cd5a56a59f0db0045f1aa2c0b5626e132c169abc64b9893f95932f54c1d8cc25f215a9ef6e4cfdd6dba85f6faefeca81793b2258ae1d1427e81e458482aab87f6563abf435be69a05b195d1eda90146a8cc92748ca6f798b10\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 32ba5fc81a7747c3d812cf036bc0edc49f08824d53b91a65a6d41edfb1651d99c11ccb4c074d7f04e652276ae3fdc8d6eedb72c6e46cbb1f7f4070dc9d179ce3e21a3826f7dd2c27943a8d26b192d7f5c4aee9ba0647e406133e3e89c262d37cf468aa3ab8c5dd1b8900dd06cd600abc6d372d9408497d9e20c86a9a6a4ad9d1\nA = -73958019a5a52357b9c1d954c9b14f51ddaced32a4d7b7c95730697cf90029564118ea168d23a54381f7bbd6718a6b662e4c87410e48ac53b7767148582b0bd6a3d35f488e7fcf2b128e0a58b5d468dedabde4d624f4a82e808dd7b175af0d3658c6df1ac0da6495bc9a8dc012f8de55c2003da9b2d478e1a089fab776d99026684026968fc309dae46a6ef2412039a8207c3084f96b4e38e4fa01d131\nB = 4330fdf00bc6d13ffc267073b68aea7419ebef257d63f8f244accb9ee46edd04fe5481292de69d377ba6b6304804ba7ec0a063b42339e6e37867261b9945ec705d3a0029c6f499420e02a773476546993b3c5e1efc2417f51afcec7145a9c2625496865c11636e285d4c8b053ffe66887333c51a712fe9c8ea57606103fd689dc88f1fe37dbc33ae4e92067c5bf51b53e2f8205164c800e5abd677c73949b00ef\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 69b850a99b471003a56931f7856da357a2254ac50ed81dfae019c9b722b95af16047a0d5422cf7ab66ccd898e85caf0e03e74cc8a5a413661e5da483b3f0363e63a7031bb30626c8f73d6e99e290071094b7fe5bbaf4d303192e59acb5e53fc7cdee78576b51595d9f7a25ccf3c7f8889de68b9deec167778ca27ac9d4c71c3e\nA = -1976b3bbbf92acbfddbc05b5d9e7b62a7666b239c1e6270db7ec6dc2929bad1024e745b897840853d14cd815aabb01aed580e1cc66ce37f9d1cc4c9bef8ddd35d28285faa29f2003d2a4623ead7d73302ea9f380f16b3fc06b7c2b8bb4ce4c8b03bfb6056a61c620e4decc6048cdda5e2d3ed8a13b779b8829e2bbab91e9f6b0304b1c08bf8fd85e0f3cd7ee72255e5342e077ababdbb545d7f809bdf8145\nB = -2cab554f7a5d21c499a1025f61e6c81ab0fc68a874bf60470cfac57425a451365be62c380ddd31f6e202f29769e2b6106868da7c81522e03fa6f0704522a5f8bfadbd007bac65595e149f6c585d7fc022db016bab32819049e7547bf85d4232a7fe19084907c528e7eb0434f2e5a375ad9b7d463821bef2f6a721a635252576c176ba42519bfa5d97d0e47facb4426aea0d755507dac81ccf1537b1003ddbb0727f6\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 2ce33adf34f2249f8a2d2e073976cb4c78b71414e027657fcefd56fceb022a06c1969dfafd519eb9e2542662c7647102f5c528734dd005fca666be57b46234123bc3db286cfce07bcbb399eb6764daf2b9aafbc2898a5ff43ddfae849c7549289640edc4ab7c4b9fcf5e159623e5497f509ad6f0270a41fd864c9437302ce380\nA = 509f5d5b160e923b4fdd72f4d522a713d780daa4bfd10ddbd62b26497a2e7925c495afc2abf0ecfcb7980e588f96c4078bde51c7b2c19d86d15bbdad5de72fec2e0a284dd693ce0902b40e54af87ac5a5df38ae6d1d882ea6299fbe6910121ebfebd06b454ec5f855bf3e7cd544a4b0d9a764428662e824e2a6185723534f5e6ad829734347d240c48c2c0f8bd6be6ae8a495a9e383fbc7402a4096b8c2c214\nB = 1a3b7f55307031609afc974857a6cc75821e73a1a9535bd6b8e141437c3fd4a6871c904e22c5d9289df7525ac69a0341d3620bcfc5f04b38ae540e26beadbce0002a8a8bfd0f6a270007e4c52aec2fab11fb2a831b9886997256e4b7e7ad3b0ec64c0f31fb0d637869143712291f5073a5756466d7c82c31e08e09683478229bccdedc2cabb7e426af9025185d8dd5124e08afa4e981236180e0a390004adb7918de6ba\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a81fcf9a18ce476a839c896cc5d9b639fb1d74610e2f618c25310147b57cd77806c2aab90be7be4ed10f0122baf9b862b141ee8e4be5e0c23ea776267f14c31e50b119bdd33f2b41f6a4c43d35bf6f095864593e0d8c0f1fd4656d8371af844d197308bbff14e5a28b7181eb6e6a2b31ead7361e287f3b4550ab0484bf7baaac\nA = 19f1ce60ca50bfdf8e02313f1c9a45496720a2ce467f1e8bdedbb32525d762878b61476989c7f6ae8dd29c983ea596e521bd4cbf74dba4d505dd9ea5df423474fa9725d5b65f1575d26ead95725e2a59a6c8a5397ebd6b54123e42bca44781b84c014b8e5d2c1a86cf34d764b242baaad5be285cec72ba8ace808058a0226c04f95eb2b53a828d0ac41e6b40e5a4c4092788d9f7e988752f175f075d545f421205\nB = -b115a1101d97664759538d22154de4b000c008e551e2ab10ad05f12274b10a4cbfee762d232df5188fa1161f37ba61d146e8b95fa715d98e016da8beb0600de65216cecf8b8816f6e7e73e2a2bfa7d0bac74b517b906bbc43357fca69de9cb5507bd95205515b97b3a4d6842f3d7b09606cce1c7436c462f49dd05e915d04ab6fe2748ccaf025bd5d19749cc468d228ba43452ccc479c146ac6d781717bb9966bf3835dec\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 1473f092540ae30de595666beb33e430cbec42d7a28d4f7982e62f58025cdb617cfc33f1e5ab93d2ebefd7345561b81271bdc50bfbb0db6381dc0ea023ff7c72605da26dc7da2b5664d2ad7967426ca97b3745f82528964bb68e70087e14dcf2d71d30fa0d1f7b3f10b19b357e7053fdf22bccc5188c6919eff1e5c402b750a4\nA = -68f280cecc512d51ae534f30aa198cf7b170c346c1159fa9cf158d0127d43e50a8d4704ec54b8b4295dd7f51c6771cb5767fe0c975414cbe6d2bb58ae66a095e8832d5f443498b1ade1f5bf249da58595ebd878677b34e3b4c99ba6124e2b71d86a8d99727a16746469de51b0a61d9d981459a6cebe206cd36a09f00ffce7f532e2c31999847ba000b9e01a4b84f454544b6362a5c093b9abe9d583716f4534f2d", + "e4\nB = 5b79684387f18d7de6eec3a63d737490dc2a46c0616ec16388dca2be60adcda11ae13063ede3fec177171a51dbef430f8c4b3f6d297b9d6c020fc44e3ffab891d0d751d033fda813861bc067c181118dc613335ce89c5960f952e5fd28bc72c41b7b6e374ec29b837f1e00271cab646c794579d315260921dbc3b984b86d98b8f8816aca4f16de50657e4102f34d9e29ec3a03e0da06e70f69952339bf2ec4a7e74daca82239\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5e4b3f4aea7115d592bde9bf7c6594fee77372ffb19f7745b4de878a4024f81e8290c77d2915424df20004a7abb64c214104a3123e7c8f230c159ccb99bd937521b433dcfb065b186a685fc40f9166bad9380a02e297ffd6a307ce8d2c8f2f1330447a9c06c327b74f3cfc2e98f3351a8b385bae855941228969d1c29e9da3e4\nA = -11c1d396693139df5bd91825c119d1241c3f57b7ce95b46472dd82081738cdeb0868d18eb7c8ee7808016b3311f982adebd5a2e5f4e201ec4a34f3037d260fe580e771222de5a1a67947a4552cc03c5c59f9e60e25063a702ad3c3aa43f061a22567f938a91f1dd697c3e3978fa11ab1d65030bf327f8049bda745658bdd4ba8f3e34b060c6a2c6c5a8be54c7cb5f6b106f54a37d2be9f674f7747744d4350b3acdf373\nB = -25a65b6acda692ba3330d70dbc3ea4dfe208c0df358c50b7872245a909c5ac19ec568b1a1340e1a094f5b8e7d1e3b7e04bb4df002558aefd4540135d62d75bd5ce959128c1300b9d98429d7369610866d98b22c345e531f2beb80b042b6ad48da077043401a82e223e9e529e7407bfa466dd2680973006d047d837c26a60cabc36a7ef538f603ba19f8e923f168ebfc3834df8f77a559c9e0342e33df245f551bb242e5a66e5904\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 47872b544fa0425981ae17bb450ea346135e6ed7a9de0572ae14a6e85e8319f27cfab778cdd8cb5f93b417d9c66ae0fb7bcc6652620f7f3f74acc2bc9f2c090129fa8315aeec9ca7adc5356484474ee803883ba4695d7bc47c87eec508d16a15150cf3f757c4713de71366e958d6af045b2d282b6ce96976692c80b1e0b6f846\nA = 7e8f55c040862f12d8cc6e506608eeca65ce38e9e8ab18ef7007e3cf0f1c9a0696795bd10f8e1e1f55bb4f4f3a35c2e0ad18289e250571ccc26a961f730346efb1e29fb143ed97cf72deaab19834fa2e98e9c12ae4cd23b9c5ecef4a04c439f7d42e110b30caedc4334372ca24cfe4171ef1430528f7b57bbc823fd606fbd30915c5817e6c57c967c4c404a0847b1455da17effeebbec3f9357358e00001239aae209228f\nB = 1cc00b95f6bd3abfa697400c98110725a7e109aa9b8cbbe9ae16327c4fc8e5bc93afc7a94da32e98e85e4fd5eb545192c73007d97a4e84ba64fe187ef61d17f0941e165c9fe64c7b8054e24dad30f92b50d1f526b4bb031e6b1b9058be24884b170a145212273c51692b71bc57ee53176d8702b975bb6ba96284b462da2ce38e12d86b342c7f4d3cd489fbce88a309c7df1121d7bbbaab6814cd1e54953e5cc46813ead98f02360372\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5d193b085e57c3f1e825cf3b36c8bdc936c603136bb782a244b04a79fa713dc7b08436b85ca3b483d2e100a012d6430679b30c8e4101c8f08ca0f9010dc0f27fb37be842054dfdd99362e03a7f55ae58db7b47f694bd35d91a58975ae1f255c41617e773f91c2640f768bc702a213f073682dc761e056b34c57edd85585fe04\nA = 1bb1c759ea94b61a1721ef5680f42af30fa31444b27591a03b7c9bf5b90845ab965339f463a78bddedcd62fa21197c32d6850c61bae195f86e1c7a23e7a20dc618c59ce3a1c6ea6306c0b01b11a36d0fadf8214c36a133d689438021ce7c78b20c85256ec607360cce14f139513d9f3ea6eab067b1ffd0935d7c43419b93ecfadf2c5a902b7c39a69bdc023173bdad574adc77706c1a666d66f69578a5bffdc7cd6eee28ad8a\nB = -e8072c49cea603d48f20276df188fd2fb28f8721d578220cef7db1e56379c04a6b372e56a047cbe59ea84ad026adc5d0aa930011db63bf4959f15781e060e0240dfac0e2a2c26be12a21e5650d12140bb49a2a8e0f6a86e4b1eb79d9b8aab3202bfd339096529170cfe3e0c18263128686bd9305e92a3c43e1523f97d8a6a2707773e3d441da162a79089c9ea1e094cd5a23474121188013c8c287965a5e77599f6a7d64174b06cc165e\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = aa79c899c2b9518857c9e4f96523a44607c3f6a97d1f40d6474ec79deb2feadd955fe92d789df4d362c828084559fab56b5e33a971abc5449208d31671c7e220c5945886e33ed1d804c059a8e439a92524a785076f9730732bc5a152aeffb5b9ecf3a7e4b55983016355c4c29827496fd4d7e6532c270cb9ef263573e4c63074\nA = -41b326c2b86e7ac14a2050bff67bb5bf9697f02594789c4a2b3e8455df4522546278d0620f28a680f6a88ab545de5829305485422f4e70a5ebf0ad15508dfe3f16ac556436d8fe8a8cde83ead549d88e0bb24dee52ebbb49159ae71589d918d3fac8011cfc3afad613ea09173856b7b79b55a2e43e0f7cd21eb9122d5f6a1fc5408414f5aafcff863b870c67b740256d317a0c58af9a81d8025a086a1f3d79f7408d4bfa06b9dc\nB = 4730f03c389f9bdd92fd864177e06140c9dcc02d01fe7d37b51d44de140696f116d11bb67adf7db797edeb7c304386a7f5e37bfac46a5462a6d4c49b1bc034c2e0dfa56f14bbd2a4bfaf86bbad4f6d0dfa13c782fe680847d4b43373d7137f5c2ebe4ad58c695a7d4c407bfd888ce04abaaec60a3fd33db10eaba6b6acf0e16cb61d1beb9212c2b07921bfb5595ef1eb389200b356eafe8b5288d8f0e2cf252b38301de65190d56bfadf57f\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 23f9850dccd2af799f18268c3a2918a69019513c55268faf2477c50677fce277d8ce58a0cc06dfe389170faf5f0ae13ffc4954c746eebae66efc14eaef2c2ac9001f3c7ef7e32fdc31dd725b6a8093e33daa6d19808908e0c2d3e7c1c58e0fe9ed92f4d7cf3cc222393ca4f95feab5d34fe29116410a1882dff7cd92acb87590\nA = -10a75953e5fb9903411869a2949f8f04144d6e2d61f95704ff55a02f40c4f283add405353a68bf7d6acc1b8cce738f0c6f9271a538b4c688dbeface58eef0a0a1d491a9e66958750db97bd01466edfd245cef03bb6a3acb81acc63c38538e7f15deefd15afc422a8641c357c31a069258dc0ebb63f06094ed8fe7d4d420246b40302361967c81f0a9ca542fd1de01967514ff2565de7ae3b4a200d63feaa22fb99a251cad66624df4\nB = -351242b6e6d0122f7120deb8357c3bcf25d221a15f83579883bfb4dc2e6099e6b7b95fd08f6e573d93354b0676f7bc9fad563d6eb0f3567ef43efe3d874b9c7733e4fe1ef491043e1f80aab6094cc9b9c236570972233ea74e8779a6eecda23a65d08d878850cab6005159265893dc0f66920a12c26dfb421ec326a1ac09e9ab8085825c31aba488af02cd51f96b205c50e692dbf2d844ff0a989c3ba9f1c2bc7f2e7dd9458a72d310eb28d490\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 69c7fa326630d7de69249807cd8bc55c9315acac26fed3caa3c8a9c6b51ee96a7dd0b3bacd5cc13c15f199e268c5eb91d1ec36c085f83b437b9906caa6e39ed7bf09778610b621426cc8d36d96f541d0bfcc7693525d33e0c2ecd77ccfe80289a11155b37c7ea7791b5c2be3f9b954e230c19d746575afe9a1a3a9677d23c5bb\nA = 7cb78ca8e5d903096630744c85975719c16333e2e44931956d8c45b001d35ed4e184dec88c9e2167d2f338fe6f25540a144cc419590a4ac7caedea3bbbc565365d3357baa62fdccef2c5ea616614e0bff60e81916eb4abde0c9725b1bf6869e8b1e11f6d0d08fd712bc68003e55ed462ad4946f7f982e663f65d45c07c659d9620d5139d2b3332a68d33aec36e21716a3b75f44272a19f860e6ab3864f06def9a5ddeed340ac0733353\nB = 16d5b074e008fdd30e73ea95cb5fb87de806319388b3a44f33c94d38be0e6f1a92103dbdfb3d23b6e1d19bdb29ac14833003e9482cb7524d0d7b4c377f4911e3372f2cea6f84c938d84e3994e80f0d68e7e385ca29e02f70294c921dce7cd3829c5854ce51d1f4fcf7dba910b51b48a3f53cb1f187182435f21f6981cf8440f9c8287a9749c92c0304cc2bc91eef32d8e6526be802de8aa16684e8854cb0b67d9f7ea00f6f0145d14e3c251f70881\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 72192604b2f3f68b9ed3e261120ea52b06a05869f6abd21828ce8abadb3a71c360a14947bc738e5d1d530b9636d796f785bb44508477eefa80c4b77d4e8e35463e15ea2a48c682d3288c5abeb66181e4bed7d5b4e0db20fdf5ed68513aa5ae7e0978ec1c4646368f206636ec90e808817bd1d03acf9adb9ba57dc153873fec11\nA = 1112d291463b28ef45e879412e6607a3e20d50", + "dba5044e71883bb3cdfe9bc694a577fd7d896dfb836a171f3a4d8fd025d3a979b43e41baafaf7b535d9050e47f4880828640e952435648960bbb74a3c25dd90bccb3fedd254dfc0f031d0e8a468e93bb69f771ed35f1653cffea1a763491fdf6efa21aefc287cb611f5ea0085f64cc3705c784f87ce00846901833d01a3c45ce047d822ba390b538f0a24720155409f60ca0d90e13991aa1\nB = -d553fa2dff0265cd9d083ad097af87a99af3d8d93a9f4c07440a28a427082004ae5c81d22bda1dd2429f540de8df175c1b4d0d50f0227489ba570b28baa35055df951d05b584ae6b051a135d7eb2a501b2441f82c135a8ec0eb81d379b96ef8f2fd526ee62293bcb934c76ef8083727a4b28bbfc9f515ebcc2bb7ed9594a106e137ce94e9105b2e2f4776aa9c6abdf426a181181fece3251c3ef4f8eecb634e6bd47c5878663fd51c74a66b92713fb7\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 459e19faf105ab17ff794927aff86196b3cc3461e69cada53ab8c8c81e2b1820408421ea1af6ae10257e8cd9dc16386906410761fed62cf9ddcf0da2a92800d99563fbb9cb1ab0ba46a17cb9dee3f2b68992c2b832a5932e4533fbd5c4487d870f3fb5d7a1c358f4aef02993360915a9e9cfde234df5f51c761d84568400b618\nA = -7a964c62e38e4124cd2bad727138dd12a086a2bf01c095b078ce2f81288d3c8435ccce0c8e00229184091130989434bcd107a3a0787a2f5f4b0e8c23b1cee9a8f39ea279fb6081efb6c3df1704fae9e87d63ac6eac4c6687b3551ab7ddac5ca0541e12047d04c2fc760fda0916cd2b585a90d25880fcc1bde8f0a1a413969938d42e8b3b5f73118798e85b901c2e15860e29e2ee8b1c95336b97dc10a21f5300e0352adb60b40a8a99333380\nB = 743ff4d91ea3e0f9c4f72e5daecb4fb00b15b86e30bacebbe4384324523d14e22abe29b00573733f594d652a88d98c987f8db08b27b4dc68577784fde02dd410ebdbfaad9e9afc6a22a8cbb13a780222bd212fc61e38faf409e940fba35ed909e6938e83b0fdf5b5e3ce138604823e788efc3aa0df924554fb70fd2faf8249e17a827c5d85942005b328bed97e5ea1f1810219d77f2fe121ce66518e37c84d64aebda3c397684212384deebd520a776b95\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 183950095d9424b0ed09985aafbbd2e5d64bf541a56b68b42ea8cf9b2c051615ee7bb6c0687ca6fb0036888fbc927cb7aeb303750871442ff2c0087a95f4efad568f48b03bd2b9a9ac26af8c259a3fa97cd2af7e3d8f36148c26785489cda6c00a21e7eca219d1f41b2e82ba8e2c1cd752eb08a2fd50c6f9077f3096e2eba05e\nA = -1d2fc778cf44c6992d1f3a056860eeb12f969358cadb087dcaebf5f96bec42bc0aa98672260adf1732da057e9e0d22081e33f5fa71f248cf89dd361036ad58692637cdfff584a191279f178242ec0ad397efc52e99462f496caa0f3133c4238aaa877fa7094662f080eb284c4cbeb992a368c2d157ac5c8c9160c167716406190fa39ce0abcdac52c8020969b87a4f84bc09a51f7b2ca288c93b1aac64e19623a7d9e69976a31074f637e4c82aa\nB = -2f188f1245b75cd21d052ec76edeb5881944a143fee31c67370fab0420a748f3f1957bb8332ffefdeabd0ca806169629f130c86c99bab490a9668fd8200f4a9b1704c589e75b5c8c855f133d50b2ce06191875e2872b36c78438d6032d53004c047f49e4cb81e19fa84da16d053e6cbc7c8eec0b9129a8831eba690e0542ca3fefd204258624e92844c8b7bcdccab986475a47c8b22e89079ea6580ef8f496099cc24dc2911dcb1921d1451e2163b55bbb7db\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a02c38d5df9ff7055ff84122342ccdf6ed7f7d54fe8227af091371f5ae62844645586adaae99c11f4ccd828103a81471bac72dc20625962e41d603e760591bb3569a21f45bf062b86b5fd1c617a4769a4d767a0ee14d104084c12ae875316a8f2be7adec0104381dc02c20b5851efdf7d4bef0d68076975e0ada3e58e101e8b4\nA = 5daf37d616da184acb278a75fda4e4fa49e544eadcf373c054b203a309ba198233f2285a1b55dc92e05d0213b26c82e261d8383a845813077b2e1b5f4553400f09410987c8dd21d4383e0f05747d0482d1a89f160a5220b22c78393873564fc5b1e4d5627ef3d4a05612709f301381df35606e99560fba07a917d7ea7413110fb5a8290e114d5200cfecb00b6c53b2ee29911bcb2fb2930eadba0ab9dfaf46443370307d9c3b61a329f0b8b8cbe7d\nB = 1d9539fdb1afabeb9be6e774dc7c7cc4bb4fd63af7abb557a5fc80a3fd23a4600de3c7fae89b91f3d441b61d3e24b2fd3d7803cd71620e7313917b4afb89ef5171a3d8a68c3c74aa3dfc8058d555eac429dfb6db40a9e0c25aacd2050418d6f32bf21cbb76981269dcd5883178d4b69a931a0338b93022a2ed0f78f3d8877989cc406f19d6d082ea344309318c56be7946412ea0867c78418ec32b9fa3a61017c10939c9345021133116933a3d1eb86a3ef16424\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 5fca287abf1f487e0ec18c230860eed4a2e550228b1500b1e33bcd6675646b5afe505b55073129f22352dc2b113c584ea1b98808214b6916933e90e036b129b61657cdea9026e1fa087ee300e055ae8f94ffca933a2d70453ed220468a5a3cf1a65d81eca11cf570d7d038722397f487af60531f24a5f069671354882c8bd2c1\nA = 1d9fe15171dce97475f4ad329fc8fb5469fb2b8086e4b01eddb6ceffe5324cfbd28d791705848569739b6758ca7e7d7d49adf0c11d891b0a5879ca870d1ca5ff475513322ff218cd26024f97623bb8a53084594e1fd64154e1db702522883fcf4c0d677a7fe90096fc76dc3800816996308d8f0be2dbf3b879f8a000c0ac534511437e2ce2d7ebcf42fd1698a829eb846b3afa581c24d5bf97abc6e247f110f4e872a2474e3acca6c8c0d518104c3375\nB = -dc0da8f7adb8e9f7b0e3f293cf623528dc8e9668317910417e52301c50c62e7d30e77ec7e38d6817d1f5a93e851f8560f642f23a0b9f836812d27b1b41c0867088a3108332b8711047560052ea30c8840f03a25c65b227a175d8f340095823788adb5bdf2b7ebb801e20f6b6435e154f78d17b8fc4373aecee56ec7b8f5686a7d22c8571797fde85cec884d45ddc4b1f2cc47ebf56a879bf286f349a0edfb531168b733d43de3b86b49eacb10b06a432c96c63440b\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 6222c1a14c6390d73944cead58eae5e7a6c19d19e4563c36cf624f5b61d99991bed7dbf6a0723abc56469eedfb1f7982987c2c7af6191178cf0933ed5f191b8117c9d726cdfa8b82a2fb25ca5436023f5860aff5fd482c611f134569ae87395dd99e5e9d400b5ab1e3064210ded096411654518110ea45899f4be2516e35a229\nA = -7f6766be6c6ca9bd1fd7ea1f80bfe68693f7ee4b5ba2946846839060d6028eabbb9079a165c1a07eb6a01239f3f14095225b8617753a1cc3d9c1e69b516d8705cfda396f4f0d05b0944a0f08b478d261e968c06918914ba87c8e7b7adef5cc2a875917d00585571542af219bd726e502b7f3f0bdf0cb1dfc6796be2e22e8ffb5b8bfac7e15e991022974e75d3a5eba214ab8a1aab2fcfcdbc6ded2abf834d1899d2e3ff94bad9c696aece045212531773f\nB = 49c6f869745983cae44d33cb7ba141234905441ca53172abd1a2dd8bfeeac4b236605cd2dc5b04ff9aa13de84872145b935b85479136065d2d57fd15fbd97480c25c6354636c17ffbca33c9319d65e82523e39fab49321380a130fc160857a451a69b1d0509d5718a9cff8b49c2d677c1f66bf77333d2511f58d3eb2fb47b3c162cc9be8b012d8df70278f0e21123a69724a1f126369a236d54da026ebe222c513f24b577707b5ab4b90ab0e22b4e38ceb4181d4ca101\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 9e9cc8c5342dc6d6daf55fc9aa9f79ec18592e8b9724a66881c379245c91f06a7df50a6ba0964603a6dac97e77a55d06efff17c93d5faf107fe65788d0f56483915f6ea0f1ccbda7656eb58fc032b5771600beafdc12c2076110a9b9670bd0754ff6a72c5d6e1a9e4e42c688e1cc96d7aecd815bdf5dcb16fcd1be1275ce7282\nA = -11635fe16dafce21efb1c599305e9a16eb5651187cbf054cd9d911c13e8eafbb738013e212f9c2b3662ea15ac9bd82b5751d43a38e4475d2310945a812262309094ae9cf59e0e9f3d02c92d8ab01f5733a20f051054a240bcbe3a7b6bb3f7c434229f631c4af239d33bd3ce30a372a480fdb49b2716091d26071aef372b8bd8ee8eb7f2965a372a836000b3737d2a833a39230e721e4844e16031ad69cd45ced60a64510c1248fd776611934d8d2a913d965e\nB = -3bb2cde9d3fda96fd7e6b24645f8e00b43affb223f2b5c3f4b7cfee905ddd6703a9d6c01f1f099ad1174da215a645ca4707d8156e762e2a253d7cfddd05ca19823ada9d33924013f677cfe4d86bde025391e0aaf91c6b776a9cf8a09dcad7cea59ee7aea1cf5f5bfe67c9d4456332d1f98e5310db9a0230381e1867a8f75b8757283f911f1a5e0d4afe5d544afa8d86637f9c9d87428fdcf8b4eb8f477e617960948253b24565b2f23081c47e211cd3c788a92732a49077f\nM = b18a9cd6a0a89578ea773f", + "bfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 30dc89bad4b449d1df9ea9b8f9d40b323c71d7e1133bc44d33bdb87c38cddedf83bb849e83436e4c92a06546fcf3e24ce6cc89d2e97a48aff2c7e3703da1b167a112f662a89742355e11e131e41052f1b379753cfa32cb0efa3a07465a258c585cd68c86bc9a473f5262c86c50992aeccbb9725b69ea8b3a7ebd2b6a24db52dc\nA = 60463fae1e9354559160d55a453c12d75775a53d1606d1fd16bef7e4ad1c78f9568954112f9280c46781180951534c5372dd5aaff3f33ac9c2e0ce4934d7009aad2ab5d6a5e5a141a36846e8925c7a28d116c68fb78aa9a687ec9bef173c1b69e0d7261f96eacacf237e1fe5874e5d553985b0fe7692ce8f2a5feab9ad9a2ad9c4bbf050b73b8030ebc36b94af8c6ecb67f8c94607d80cf600efd4ce4aa006f9b1832da8a1fdf8a564be0b4369149e8639e1714\nB = 15bfc50290b771ad147695a4c6701c47f2e8aec0657a4ef999eb45685200981b0ab5f8abc143d64878b85e9548651a1afd0913e3b14d11d3a26ab9793596801662a67b0062fdc8888feb029266f71d170518b6a4a040f59996bd4f257f221e830d0faaa9688aaa6afbc1f9b40d25097eab9d71d80aabc085f3a07e48bcfb37119aa00de60be55fd07d5b1281adf7b98bb589cdf2026252edf2f075ee176e23afa6b1f924c9fcf3c34c76752e833278a2e6b62017b88b77eece5\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 8b506c9bfb75ab7ab420ae6c9b371ef035fab512188d9df76f0b31831573b44cb08266186a04d20cc761d61b6df3e33ecb86c269205c2c79ae6aa4d3ebacac8ec71d9bce1d7ab146530b131c9038041c6ce8152a6f1c09b9bec8eea4462dda0f08d75edf296eacbcefd62a0c197ed30f799343268bf6edfee4995958db7e0420\nA = 11c16713fbf8bc9696782cb5a88174cddbe68a04e8fe93dd074aab33dcd85f92baa178b2f3b8817be0cecb802cfd3ebb06734c9d399a1f090e3a8a2110aebbba0e920427bcda74bf11700b945985bd532286d44a1a615cf7c501412e454edd647f8371cb8149474557a0d47cbb782f460de7a3cc28991491ea0fc510286711b882987b09341c079565414f2c930e7c3c3a3e3e0f1d786260a7f45c70e0fa20dfc63849906af61707cfdf5a9b7a4291a1c1586d16b8\nB = -cf5638af39c6da3757a09a92e0bd54f852742682dc91c71dcdc6e72f7825a0979a1ead2e158479ce5565d22472dc3853e6bf7ba43296a5e0e0a355f0703cecc02ec79da83e3e9de10a6eccb858dedf7d4c400c27486a5b8cb34d787cde6a5fd271e83a6cf66057838fe30db1f30663cdfc22ef5d002b0b5a05831228ea200f95382a58d0d8aba36523d9b5cb7506f193131916f3ab66ac9552c26cd0c2ab1c449eaeb8fde752f4f3c3f9b060cc1f8a1e37c4fe5ec306674b66158\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 347706abeb168205cef9b0b8c6b9d6449ac501af7dfbdfbd41a20a6a47872cbd7d4cd32f7b0805ecf1573d534418b7cce98181e079d5061b02639fdf0161cea5314dbbb2ef39ec841f695281f3c7de45f33664e0dd1658f645adc1dd225f781a3fb1634517c556403587b2aecd56dceca9ec19b930cead2b1d303aa056d28bc7\nA = -5e1c869e5dbcc684c245d5c69093bfeaadf388cbf928d33a8ae2148a2b5145937e4f654c5f6a36de1124bad1de8bcc9067fe1f9a44fc6ffe55ce7ed5cd0dbb6337b0e1e96bac1eb2a3606dd97b0bdb975ea59448be50191cc7ea36481ca9fc85c1c3e1c97378dbcd6b355622046888df2ab3d18d805f4d31d464f62a8e630e955beeeb5e00c70242b8f8df708705abbeb95dea3561756298b5f3f7fe16e965294eeeea4546f5e8bacf9d6b4f2136d2e206a87dad1f47\nB = 70225f0cadd328be36ece2172c836405db3fe80ef99ec74fca25406b73a537adf5073f2b550abfc4c0fcc2c2850dace0da9a266768cb4d5ff7fc6c1c248ad74f47592101b61ef96c1302924381abbd96cf49f50c44bf7e0551721a8ae85abdf9925548d13b8c5d1a27be8a40d0f43eec3136bc3035057b75aea779b4262cc66e6bc68da93c218f1920979291105d4b02117d66deb92c3e511aa588b27130202acc9f69521957f79c7e731bbd5461552b9b6b24240dd71ac449be9777\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = a2cb238f326d47f95869e2dcb295eba819a443dcc7c2785461389b58327742702f4c86e47af129f1fd4611cda93631f9333c358a29121d58286333083d13e66f30a9533b77ba3e26089e7eff7baf19bef8054af4e24735525908864ea9c4756b42a69c897003cab7b63cfd9a5927ed562e29845308eb2a55e7f8f03c87a5b7ce\nA = -1aa7ae6f56c38b654b281525b9da953ef366c2b9cffd3042105ed428dc7e5f2f2d53ef90b468bb471753606cc7a3775d86bcd2f4d5119cdde3c487cd39bf31752c5ba297e529c1b8121487e0e1de702156d0166ccaf51888a24fe7b48624eefaec855e2200929c21858676ec9bf4ceed0a832b69efd5065af544e49a3d209b85a77b0953652cbf0aa897527c52c9a98de9ae4c827f762e251478c88d410123625ea52b3478b52f6b9987d42009ae427763357ab53195772\nB = -226630b6fcdb5e274a25066ae2ca2c803549dbb935a97c0d7f6ab2c971d74cf6acd265c9d6815a6b2dd23dcb3c23b390fe8b1bed92b8c64c76c0ce62d5e7ddd7ce445bab0ca905dcfd0f128e5f4ffe966f3903d7ff1c61fe174e373cfe35a6d83249ec40b4a354d46fa1c90682efe468e895ea3da710838c262e8a47752dc6e7a79fe20051f51180173b58e0aa37b22eb8efee5b6dc264459ce4d135f430cb15afbf8c53f0de894bd2aca1f7ea32b4209a22a075f7b3b18e86f778a9e47\nM = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48\n\nModMul = 9ea62ef634\nA = 55cc58c9d8\nB = 6b49179821\nM = f753311ac9\n\nModMul = e9ab3a2aa60edd30108\nA = 5134a36c2bad180dd5bf\nB = 2ba6485656d041690666\nM = 9b9cc4409e86c8b0fbbf\n\nModMul = 621f9b797e866028b7bd1ff828bf29\nA = a202338dffe171c99434d84f3\nB = fb71eee7045b3e3ab5dd809dd\nM = b3e6e8d53b7249df670e3c59c55d33\n\nModMul = 808d463d06b7b7f98e3cb2783e2196c349d62672\nA = c669426a92d3cb5b316e2b5b9\nB = ccaea3874008dcc92450d8b2f\nM = b04dd2bb325baed1940cd000e8cb2d786009ccd5\n\nModMul = 872164b92b9426b237858c4cdafe1694f96b0e0e4c19e894a0\nA = c3255cb24a813e27c3dc410f0\nB = b144f39e7c2d33605ba7bee16\nM = f3639f4dfb782f3107eb402fabb5fc878903acb5e02e129077\n\nModMul = 6124d7d171\nA = 235b938139\nB = 3a56a22a28\nM = 83eb4af4e5\n\nModMul = 9c006f56095d442ba98c\nA = 207e14237c42e3764e5e\nB = 8a495a26872432fa8e33\nM = d0cf2b8ae5c67d6736b9\n\nModMul = 97387cfaef652932a230c82de59cac\nA = 82ae0fc5e943af5bb8c4adebb\nB = db1279be12d59ba3a9c036a61\nM = aa36dc1d13390169cd54d711eb511b\n\nModMul = 32ee73c98da657464c6fed4274df20b099689e00\nA = 9baf08248ee24bcb17714e420\nB = a7f0428147bfe098666180749\nM = ce0bc198331c9ed1d21f0d498326e8185d3d602d\n\nModMul = a8b3fc0b53df3b92753edecd6fbcc5f4840dad3a44da704e34\nA = b36249e259b303e453757721c\nB = f0c1db50670d92abd93bdc84b\nM = b05cf978bf2dc7e093d7d164e46d547219c480382df32b33d9\n\nModMul = 2663b741ff\nA = 58c8e7f7f6\nB = c84681fc87\nM = e0a50dcb45\n\nModMul = 21af3c0b42328f41b81e\nA = 1f79f5b5bf78c9700d\nB = 5bd1734ba0f0e59c2a25\nM = 9ff3fdfb5c089244f327\n\nModMul = cbc280b5106c2c36cb31ad7e7c986c\nA = cadf6482b769e83ce7f7277dd\nB = f9862a06da1a9c89547b76c61\nM = cc36144c88139ce921d2fd1740bc4b\n\nModMul = 3813f2fabe016e19fd8e70687ff473651a5fbb4b\nA = 9c51a5bacb5d9f055a9ac2962\nB = bfed5625b21b4e82d1f105a0b\nM = a47977acad7c5deeb683ccd265cb30cb193f22a9\n\nModMul = 76ff291a02715fc87ebfb3e99153c04e53358dbd7beae43478\nA = 997c4a7b537d9500d73a205a4\nB = c679ce666af284a459ae5a26e\nM = d0d0fd4922953941acad8beb65c00603b19eb44fb8ca51e3c9\n\nModMul = 1a90c92fdb\nA = 94fa7bb475\nB = 564b0a3339\nM = a1501bdc75\n\nModMul = 5e7ae5470686bad7996a\nA = c725797912c6c5f30d94\nB = 3a7f4c99ee3f5fa9582c\nM = cc50c8b7408f09a74973\n\nModMul = 72a15b13bcd1b63747342a6be8f0f2\nA = c33357af48a2df569e3c11ce6\nB = a4b4c5c14d7796adab54b6cae\nM = e22a0fdca62a37f4c8a61c96a429b9\n\nModMul = 31e179bfbf65b0695dde36a4fb72d131830dcdd6\nA = ce8d3adab8cbf15c332c0b289\nB = 9333f94eeb7d7a86b82becc51\nM = a532a76bd5cff409b580d54d12ef75ad8179b381\n\nModMul = 8f4b8a585415adff3a7bc35fa88891ba31e4a82672c664fb14\nA = 9a2b56a54bd0727ab4be57ff2\nB = edf1781b4296567990773005a\nM = c5a7c3b97ba00d6f174a019c6d37eda52036c528f351bef0f1\n\nModMul = 917bcdb402\nA = 55c7dbd314\nB = 997b29ef79\nM = af5b4cbd0f\n\nModMul = 660c4bb2b771f523a4fd\nA = 43fe52461d5139620a11\nB = 1f8ec4b67de1db54ddda\nM = d0458e215b7e6903d96f\n\nModMul = 7aeff02c143e4426fcbcf32bd1277b\nA = a2671586369a990dde7829f36\nB = c7ff67937c900daccc0ab1d8c\nM = 8ad9c1d4d3cce681", + "d1ae27c27982df\n\nModMul = 4b153d57433f0f7276674d3484e9bd0d25227d07\nA = aea36cf51dd2ce06c66b7a407\nB = 80c9fe5bb0afd2bf8b3644f96\nM = 8cc22a67ed7e5a7a2322aaa09ec2be94998494f9\n\nModMul = 7f8447dd983b113f04c6288f9539e53a2e9cddbca8b2fefcc0\nA = f67636b03821c8f13f21217a5\nB = 8473a29f4ae33f36a0d2c6dc0\nM = b829af37b557c3ddbb5257c8b19144b90708a45a274d6655f5\n\nModMul = 17fe4644a2\nA = 912611576f\nB = 7a10d36b80\nM = c5fa605133\n\nModMul = 8159b23d4fd697b4fd35\nA = be2d646e76494439e60\nB = 60fa770d05ebc69772b2\nM = a6e7c940cd749925a85b\n\nModMul = 7c412dad5c9fff91357bf181caf2bf\nA = 80f476ed5acae75b34ed54c52\nB = fb818e2bdab3b5f4bd84db3d0\nM = d0339f7ee41337d8462d1a9c207d1d\n\nModMul = 70432c749da4ade2c38237545ebfe6c4c6a92f6b\nA = ee9c92de52210e61adaa6eb4a\nB = 8ab55a85b1abab62d33e75fe3\nM = cd3faa6de4cb62fece4c3f94492d457834a6a041\n\nModMul = 9fef1c18778a8691c5e71c0b5208e82778e9bfb632da0b7e28\nA = bd162c90bed25e84dd5b6b77c\nB = d887ee03020c5df356f091db6\nM = a2c2d45fe9decd93a0ca3edab8fee46d27ba23fad9b5294d5f\n\nModMul = 958951bd0f\nA = 12bd0d3375\nB = 668bb65b4e\nM = 9c617dfaad\n\nModMul = 8a109ebc9cbf86613e43\nA = a3e7019f1bbc35689a77\nB = 3189ecd3fd4ffd0229ef\nM = ddadc50600dff2abc1af\n\nModMul = 2b4d9f85a398c852b3a0cc82524619\nA = c244fd157267f707319ba6c6d\nB = 8a07018a748992429bbdbf326\nM = bf3813fb54f749ea5627f59ce30e07\n\nModMul = 28cab7d574e6dc56a6a622f8a7523cbb8dcc5e0f\nA = c9909dcfd3a59a3cfa538b267\nB = 8bbf89cd5a4e24adc2d8c646b\nM = c8f02682b9d480ea98faaca53b747ced33ed0419\n\nModMul = 69b2dfb3f1d8dbb13e9e479f38edcc427d5968acb7751a226a\nA = 8019266c548982a520ab48eff\nB = d33c3e3b13576dcdb3ffaa796\nM = e6255103732475604df7c6f7ef7e6b49a8ef9e2b0c717925a1\n\nModMul = 3eaa4c99fd\nA = 6fc42faa85\nB = dd0b4e318e\nM = fd7f22301b\n\nModMul = 56b6b811ced3433755cb\nA = 145573d17cb0c996c69\nB = 9d3297d5ccc184896822\nM = dcfb3b383506239e83e1\n\nModMul = 34315b6bc6d3690c28060485ae331f\nA = b963a26973894cfb42fcb2d22\nB = e8523304bbcdff1a0ed4141bb\nM = d7a379aeac7d8cf94f19e7924d35d1\n\nModMul = 2ec9466e8b3357496f07e37ba24d36a237883846\nA = a75f3904e564997695b6707eb\nB = f9f47bd779834dc1f5fba0654\nM = b3ae5abed45d09c4dc5abcadc3ac9abebe1949ed\n\nModMul = 88b4d86b2c1e1bd780e8d2499c2221e05fab4f9b7047c2a044\nA = a38eceb9c551f0e69a544072c\nB = d5f8e7c2d534b2b8985bfd213\nM = ff81809b84fb8eed3508ad891d3d8208249d8a902a12d6acf7\n\nModMul = 172f2e2e22\nA = 1584ff1055\nB = 2e0aee014d\nM = b904cb0bc9\n\nModMul = 122c10d3200270b9eaa1\nA = 86fd189e62a6dc1e4ba0\nB = 5235635f7b0336f5f235\nM = c93da97d0e95fb63dc4d\n\nModMul = 3e461e10ac4eb749512097fbf76616\nA = cf4ce10cbca07164f3812f89c\nB = b7e4639c233fbb0f923fb5104\nM = 949647857e1406871593fad5c30101\n\nModMul = 88117b59d9fed79dd6aaf083ee938215a995a221\nA = 94c888795567d434123d441a7\nB = c60ca79e61a352e34e0f78bee\nM = d2553a7c5dccd639a3927697a2e1af03845f2f25\n\nModMul = bc5f0076a8c2f6cc8f4e61540d2d6f6d6b13b775b363dcd71c\nA = c170eaddca5295d6ec6272dc2\nB = f94a5685ced7661df2efbd34e\nM = fa6bc46aa05033af72aa42793e9174af2e3ba38992f33572fd\n\nModMul = 1110cdbe5b\nA = 5db02b38f3\nB = 3369537903\nM = a8863f7979\n\nModMul = 90fcc5f3a346d3d4ea4c\nA = b93373680ea0feeb31d8\nB = 37f9dfaf0e180be64bd5\nM = d595cc29237d1c19e2db\n\nModMul = 8623a9997e514cf3c1d06c33c14053\nA = b396f5ede6212f1fdfc7e7b77\nB = 81a1ddc18306f2d2e84030148\nM = a6be32a91b34857842255ef8b1aafd\n\nModMul = 63f8f0254df06356f5cab8941b77619ad58025ed\nA = 806b2627b08d987438f920bae\nB = 83297039f4aa8efc1a185fea3\nM = bb8a7e7c19be02c25cf5682a0eee655fcd5b69a5\n\nModMul = 697238dbe3d395e81f20c9fcc8db30c234a1f75f3b2bc27438\nA = 930b04224bc097ac1d8bae8be\nB = b79496a80e45212c4663e5b64\nM = 8ff7e19d967d317c255380411898d73e3786269f09079f19f1\n\nModMul = cd93b5b8b1\nA = 47a51b2d5a\nB = 86d6ba5155\nM = efb0ad3643\n\nModMul = 2037821ea789118bde0a\nA = a92215dcae19be637ff\nB = 93b9a3664a406737958f\nM = 9df360b69ed26f610253\n\nModMul = 3bf11785d28ceb668dc55b870faf7b\nA = bc8758854dc48e057cb6210de\nB = f03ca689620a77ecd8a6f0de3\nM = f3ff0747d6e5f34a0ba4200f579259\n\nModMul = 7b30b44f75ed12f54136858ce4fe77d00e0952cf\nA = 993cd09f3e46423a8ba2053df\nB = feabee384158032dd013dc08d\nM = cd0b21388cb2033b1e792ec4078334df70b6c8f9\n\nModMul = 8ce1e17972f1a9d2e9437d0c5219354728a5f31337808d7650\nA = 90e5d18b017118177ffb080da\nB = f8e7e09032574f6c66e623ec8\nM = da795e6ef63ff7dc4baef5c327022ccf65d44e3c4e24823f11\n\nModMul = 8fcd412054\nA = 2e7f9b1a\nB = 6283de2c9a\nM = 9bff560ae7\n\nModMul = 57d0d3b79f1e2f3632fc\nA = 2f8cc403de5af54cfa39\nB = 3b798c3ead52878dfb2f\nM = 805e6cbde400d4b4bc9b\n\nModMul = 23331614e88633af879201f568c359\nA = f21f19da4b20980979a645dac\nB = ea752050b79883dcd69222536\nM = aed3faf4c88f7c4afe257c5ed90599\n\nModMul = 56dcf9ae1c787e773774df3c8762babb4675a212\nA = 9accf901fa599da05fa6ab5ff\nB = f7f6b9b1d7bae06237532e39f\nM = b5bcd776bb2eb0805ade3c8b47e883962d3cbdf5\n\nModMul = 61d0ee0786963906a028a1df01f836841ab6d39d88ca2717c0\nA = 8e57680f213d088ff1a1e7db3\nB = afebecc9943b0093f87022940\nM = b6201f68a45265d7e9183c3255feb4c110c05dadbcb13881bb\n\nModMul = 143ae78a29\nA = 334abb952a\nB = 74203e7a50\nM = c9535a9505\n\nModMul = 897a2b57e69f5a1469ea\nA = 1ec8ca0ea4fed52bdbbf\nB = 3a6273cab05e478a57b8\nM = dcb33163a8ea42c1ae6d\n\nModMul = 4a2c10e90e2d37111db79a44d3e31b\nA = a90e7bbd63fc4af6de83029ee\nB = cf09c3dd50b41afc7045e057b\nM = 8ab85d47e4270116a64f97dc4f0f15\n\nModMul = 70f94276c9d85fd3f71edfaad6051456f754da85\nA = fa3e9ff6e1aa1fb78e51711cb\nB = b115ed197c50b7ec4040ca255\nM = ad63f69ef1346e7549ba71c13b24b279f53bc9bd\n\nModMul = 861e7ef401866f815b983ba18a612913ecc20a67016d79cfac\nA = fc41a9ce06e882942f751be7a\nB = 881c05a51d1ba8134d126a48e\nM = b12200b39526c33b70e8aa23ebc400dea0d4d8fe42be103d5f\n\nModMul = 4e0051898a\nA = 2a06523f70\nB = 651b5044f0\nM = 9da4eb09b5\n\nModMul = cc8274c88d6affc3742f\nA = 9ccf0133f9628532f4f6\nB = c1d80907057be7a67b01\nM = d6e76e362da831f32685\n\nModMul = 568f15bed5c4405be9dd04673a9c46\nA = dd6029c3196feb6da7f0f4a48\nB = a5f6745f2cb64913d1d3236d8\nM = f62f02c9b9ca8993e3be9a02b444bf\n\nModMul = a629452d5ed19df040eca26eaca37d82c0fb1d8f\nA = 963c51a9415b03e85ccb09f25\nB = b1cffe333afe44311cb968ffe\nM = ab2128698d498e8d75455033cfbbf4487535773f\n\nModMul = 814030123025d287aaa8b826792999d72f2d589e0c7f7f3dbf\nA = c3b33f391e78bee97ceddf313\nB = a9136f3af450fdeb245eff425\nM = b6aa9c517eaecb70781e597b907583bbb569e970d229235a35\n\nModMul = 8735bd486d\nA = 563e15c52a\nB = 31293264e1\nM = 92f4b193df\n\nModMul = a541f69ca163b288dd0e\nA = a608b48c1dcaa18424b2\nB = 891b0b296e911068b00c\nM = d4140921f4b2c84f1eb1\n\nModMul = adc1b7cf65967b013d046866b4ed9d\nA = e97941448f65060cf63ecd486\nB = ca68936f76cb87a8fbdd37311\nM = ebbca2482fb82eeca2866057cf1179\n\nModMul = 44aa9f0dd58d4510a7364e130698b34eda23a632\nA = c11f83f01bb964ffac93a2e30\nB = e05ee40eea39f4538d735193d\nM = b5e8b511738979dc740a6a1f7291cf4561787be7\n\nModMul = 8b16b82f064f471983c7154abc9f9ba355111bacb90400372a\nA = acff8da571e1c96810bf95707\nB = cdd23e5504cc26d0c34a62b06\nM = f38902a99190ae0b5ef26849a6e943d651925666fea271fee7\n\nModMul = 193f453197\nA = 8cb3078675\nB = a8fb003a87\nM = b60ff22f4b\n\nModMul = 849c26c8cf5cae426a80\nA = 5d1e3d2b4d038a0a34be\nB = 34f70325565bf0523314\nM = cbc189f9a732cad8f425\n\nModMul = 9a4e64ff530c53a4c6c5b6b5021920\nA = f53b81723cf74f520a61e614e\nB = 9d8ac2e6b839143fdd079a2ff\nM = a115375435151798f3644bede9d863\n\nModMul = aac303a4623e80158af1cb3331965cc8e3184edd\nA = cce0a88606ff962fdc37e72c9\nB = 9840a500a2051625c517104db\nM = b99dafdbd91ec3c05791031df5e193c03d6a441d\n\nModMul = a31401dfa761bbe82b66b5f094151865b18a4ba75bb9b3dedf\nA = e6f48c027284856aaf3b96425\nB = b4c326f72a6a22fd4b93ba5b3\nM = e57d9608ac6e5b129b2c014958bfc59137f63838b1ba88a4ab\n\nModMul = 8b0929adbf\nA = 61fdf77ac0\nB = 8892f05400\nM = f12b3766eb\n\nModMul = 91b57f353307b173679d\nA = 33f8e73752072b4b5cfa\nB = b4c730f79f4f2c07945d\nM = d41be1d8d2e5753e3ae9\n\nModMul = af04c564adfeb120bc4770bc8c650c\nA = af151333b3d4cd1d29fd801db\nB = 9ccaac44ff91be11b30bdcdd0\nM = e0bd6e70d5f5ce08fbbfd48d43101f\n\nModMul = 1b8d623796a5065d9e993a53a9587a0fdbea1bbd\nA = a2fd08df2d4eab0cd6d29e213\nB = 92c9d26ae7c215b52199ee28b\nM = cd529f4cfa46f3bd3e7fadf167fdc02f6f881da3\n\nModMul = 4a8573dd8dc50a4fa39f3579d3869745eb8c1153ca508deefd\nA = 855f941d085305725da617f5d\nB = 8f09b7d2c36e0340523da5421\nM = fd8caa05edeaa81beefa01957eed97a981ab34bdeb6d8c704b\n\nModMul = 2d278e089\nA = 59d20a1716\nB = 8e2a58bc75\nM = b3d61ef699\n\nModMul = 2f937ce359d0f6cedd1\nA = 1019d11d26040ffd5b1d\nB = 7cdb6252087423d43e08\nM = e8f537323004447e669f\n", + "\nModMul = 6567332e25af83089f7458786ab0ca\nA = bf9565e9f8a098894447b58fb\nB = fc867626f268c24cc0ab7bf8b\nM = 930f39183353363dcd822933a438ef\n\nModMul = 3692e73ad1d91ddc19cad3808eba2c5fc88e2bf9\nA = d0a42ce512629f0ffd233a9aa\nB = 97f6d3c4c655c7353a62d6ac4\nM = eac2ea84851f880214b8f40f881a2e56a6ba6f2d\n\nModMul = 81df390c9e51b30bd639db15adb464c7cb1d011cb5e260be58\nA = c237eb242c40960861c938c08\nB = ab2f481f0d768eebd90d2574b\nM = 8697d7a28a5f42c9a7b31949b8b568f861142f44fe66c6cd3f\n\nModMul = c952f9aef\nA = 81973bbcb3\nB = 28ddee3bf7\nM = c4a40993c9\n\nModMul = 241dd53d93f7bdbbb2ee\nA = 2136eda4495c45c9f96c\nB = e74c4baa8ca3f6b7cd5b\nM = fff4594e7a5f0a1d3e15\n\nModMul = 5f861ed8b0aa835761613e6c869cfd\nA = bfc5c1572086079f5f5d18d1b\nB = 95902e14923c8010b7e905178\nM = a819c6c109d623f9b845aa23712c9b\n\nModMul = 5b8ab089c4e4c6804e48a2bc1d218718b3a32598\nA = fbe65d3852224a812c432672a\nB = d57a3f38da966d2471d70a048\nM = b9e6a626d3ad026d14248fc90c882bedd64a1f13\n\nModMul = 761438baf5b02dc095b7040e082da7b167c2b9ace956284ed\nA = fd91701ed2151f8e994bf4ee1\nB = 88b66e735b76972bccd9db182\nM = 8008b2d1274456aa68dc627b1ec3e1762c6ed2d660c64a1a55\n\nModMul = cb743c97a1\nA = 9c69ca9b60\nB = 7488f48f5\nM = d67040ed0d\n\nModMul = 931b2bee1bc30725a31\nA = 650f567b544ce02303d4\nB = 5858da30dd1fae88a675\nM = 91ce30234bb29fb9e833\n\nModMul = 5b4f262cec958a20390b5e568ccdaf\nA = f7e240e8a077e8e87506db2f1\nB = f8653fe64e3bd414782f51634\nM = fdb8225eefc1620648737d31dfe1f7\n\nModMul = 4c011d1ddfa30c901793cc6ce74db47584cebbd1\nA = eda8e9a9ea3cdae17bd50b1b4\nB = 992e8ef4a45593e4ceff67876\nM = 95e2f120cfcefbada1058af6c8853cbebedd5763\n\nModMul = 6e99aa5b8107399848cf24fbd88ed6350efb68d737e505b466\nA = ca6c51ba2f410d09bf71d60fe\nB = 8bdfa8fe5ef3b2ad02bc63c4d\nM = 84daecf412b8c50ad6dfdb546c3eb783dcc6f32003eda914bb\n\nModMul = 536175913582e73c1002083cb0cfce5471d4193a5b717881e60abfe927c829d\nA = 9b474b6f7d7f11dfbeb7a0724694f2daf9ccbaf2ec13269b5ae3329e8df95f7833baa68324509dcddfb5afa1d14f2dafc55e2c225475f16fb396beecc7a66dee\nB = d74a5081f00af2361c3537642c06cd47aae7e366741c9b4785e185af8b328acf3e2ed71e3b9a4b6fd49d956eef76740b3c6ec5850a90e7e444dfeaa7214c5eca\nM = 5efaeebe212752b28b5441a5d0b2600190504467c6359e9ab26320ee72cffcb\n\nModMul = 6161cceee2b74e7965a926fdf5344ddf8cc41994d72154a8b6014c18cf71634\nA = e7d6b74a1af0834aaf93e09a6488340b661449ba2bbc73d775e7d828163813ddbcd82719351879a6d67ab6b518011e1db43a3d620d1f24403917691d15ed6f90\nB = 3ecc8fd3103fe52a7e73ec4be4e60b69584bd886a030f017b482bde9d4b0b964ba8471cb32b3e9bd49864d9028a22d6b6b46be0451bb4222c3987b74a509f8fc\nM = 7c3e3b8b1a6110da82674aaf88c288cef4cfddf22e7c9b75640fd67fa5fad59\n\nModMul = 2acd55bdcccd55882eff0bb262bb62f78bff8e932aefc9d32f54d5d4e9b8bd76\nA = c221d1f0d1b7efe7e078dd01bed773f8876fa324b3fe91985d47d343e7f3878b457dae2f9ae68971245278a1d23cb541c56b94dd9ac43a9fbe28a46efc627651\nB = 49f94c19ff7ce990637c3d2019ed66f7e6dbb1442b04a4593cc480521b991cb1b878f8c31903240f89e34336d9e6785433617e729b71adcbef622a683357e035\nM = 43760c71742e9cf22cae6fc262c008b7f1b97a78c8063957b74aa4cd370c1eeb\n\nModMul = 504c11e38284a30e3647c1ddfaed94503d833bcecdff05e749422ad1d9442540\nA = 3fbabe2d65f443e7db0a6f332330ecc4d1d40e14fcb510499552020405cafcf10a50a5ee47cf60fd8c22a22b3f753b4167c213851f32109babe4b5c298d6c4cf\nB = 62e5b0f887dcb1f1794bae7dad46a066f810cf5f82a1eea99207b5f0fb0ae9084c5e62cc97b2672b1cf4cc1400a19bdcb093c97404876b584a6482931e7ba9b7\nM = d79fab3eb31189268b2a0689cafdaa0826f07d432591e8aa8bd3c7cdce1470a7\n\nModMul = 13a6431c57ddf0ed3979412ba8454a0dd9a2694a0dd76453aae63366c46e41db\nA = 7e1fd0bd9ab0aa75b264475604aea09f24239f94847ce2549d43b71890c0549938d167adebc7890d3c492b5874da7bf18d895ccaf1803b9776820598928b407c\nB = 5e54e5185bc86f16177f1354a57d36ac2980def141b389e4bfda134fae7c158009ccc61ef66281905128b6297f876662104ead2315024f129c56eaa387f80b4d\nM = 182572149b860615dd853f37f7d51a35e85f5e4a4249a60fde58dc68e0dd7401\n\nModMul = 145a44566bd75103083b7556a822ea6008ed3a6a1bf135b68fcf87a294c09b4\nA = a195e4315caa8cc0707063c7359c28139d4dfffb57eb726156336e13227ad9766ea1fc99152893ebb194fecfc153d47cb927a633217328f05e4d8782aeb89d04\nB = a97ae97dc7e9a224cab94ecedc08d0cbf7a012dc5209b1e1e8b5b843fcf61e65db3457d6085545a633be47b742e8237cc716357ff5bce9b00e23671ec1d049a8\nM = 29b060ee2aef7e43e02163d279ce49259127198adf462d13aa195c7dccf573a1\n\nModMul = b00740cef7791692d45f5a7110f3eeb260638f19f87c9245436fc0422de90658\nA = e6b97c11ad44fd451d168d65d1691d2220db8c3b6c8436d59f4c1366aac52558d0d6b61f5d6966460a4a31085fac711e5a09af5563d938963555d4730982eb0\nB = 6805eab5a4da534f07def6d2c320a6cbdfe4831fc2163dfcef740607b3181d8647bfae8f8c16237c1c1c5d14b9e3417132f81b3a7db4b7fc11927aab30dca590\nM = f975a94fa62b4c0e68df5c3ac5917d18927c0a6d9cf39c26f6ed97a81cedf227\n\nModMul = dc04b6ba2eb1e34ea8942a50d1d0c5479dd22109895796ffdc9cd32b53d4764\nA = 7fd3310af09a67e0684dcd8e3b4b651c7c13c2f6a0a47b59a7f5cd8bd80854d1d4fe02eaa61843d6bb2b87f99d8ec4842864681eaf056538ffff610c231e1d\nB = 15f1661c59ee9f93400073e18a91503a93d47537d2da5cf5e4bc69ccc87b07bed171a95f1c5eaa9c7d7ab207ab3f1f7634c5d16e706969e869364207f61d84bf\nM = 22e2856f4c2b6c01448d4aef74aaaee3a14e9660b5b277200f2e67464ecadfab\n\nModMul = 19299c9e960ce15087e9fbd66f95cafe82546431b92d70db1de87c3425c1bef2\nA = 8e3abb1f24e1f91496db99be9409f57f67cfb6e0e33d603a2a31e1309f1d0bbdc413c3e4fbb5e3d923f683afa9942b9b9fad6a6e558b2297889fff47ccef7d23\nB = dbdf5940dcd68127d476badbd5a2f3018aa4d8db79f81337ddfcb108637110b934e946d3284ec09d5255605ad72424f1894238ee4f7964dffc27fad838532321\nM = ab6b4e3d3909512f5d1d62a30c1ab8dd5e584cadbce9dffd12fe203f8936ee93\n\nModMul = 4f88ad4e30e6e8e38cba0452d98d4a3547c680f16308692e33e5577772658764\nA = 5137697bf48982edd869e4a42f3cb858bf65ad5b25d1c0e8b75d054460d0944ecb5a6924721c5728964d84231c7ae808f556837aefb23fe3ad36aec9f5f60f20\nB = c79554304620f8116b9a8bb56f6a23620e9fd504f7163f732e1e6367d25c6ff98cb01d16faf3e018dec6a067d1204a6aa95470598ce757bcfbc3ab4f5d8ec88\nM = 9ba20dd78923d8ef82897ac46a509cf22c9b7986a4facf42e5416bfe3576a735\n\nModMul = 985a4d2a7431e09fcad03e6a3f926582dbc0aedc588f17aa5db40c2d3566233\nA = 908bff40440aaeee6c90b6312dc017c3bdae884a9074e02b26f01be1f018390e01f0d111f99a06c16e20538df8000d4066cd4bb3628da88a3a5cc240cfac719f\nB = 6ebfe9fe53909876784f9d6e5dcca4cfa9463fbd8426c5bb8890ae84c2fad119615fe1e1f2ee5fa544a5ac713ed1da8c1e04f282f1f1b9fba4b4c4bd9db20538\nM = c66842e0a11ed6ad1e8f192ea97f5f244536cfc5234c7fdae1ff905123c72793\n\nModMul = 133d7b31537b627da2c042217cd28625437c28c3e06258427d9a4384046a1f4\nA = afb695e3e40347f60a500e01fba4df1c1f2fd4ed79e3f65913d82369f79d80db6b3978e6351c70c148f572b9c0c2b1efeefa605251b3156d9b66d240467e550f\nB = 8855046dcf50f80f278227d5260b9be53ca2e4a1cfe1afce4d35b11d0fa17a36a8bee8126e13bbb318d476becad5a935e9d160fa481e1437b292bdc169dc7d45\nM = 3eae4f0d6c7e1fb9de1a4c160404a8767783c7f839fe27a543f5c389c679d47\n\nModMul = 7f4576a315bad5c7fbb1616e8b26c5b34ca6f701b9b1adf0485fec181c41dee9\nA = bc2baf0153a4598f6b5f488c43b2546cadfaca2c1931b919f98ba71835a8fe78886da1fea25b194e60ed6f9e0ad23c988b64af9278155c1722dcf4983a1566c2\nB = d8374d91fd3c523ecdd6bdd265c9a8958dd222f9f0e25454fd683bd86d7900a273b56f1f47e033c46527e32c721094ce6bc927d25fac05d7fa6db4d7a6773c94\nM = 9975d8e7f2a4d9d1ff8d442b93ff269a83fee43a18bbfa8c2ccd7ca5fac3a8d3\n\nModMul = 57ebfb39605d4fa6ef5fd03bd8e4fd685664297c29b7ad75a40b133e15fc5ae9\nA = efed8e442154b1eb6c75775cc23e01fa65c9c361e222da123d07daad3039f305e7102edff23b65c333f0caae4f7929857c3169f4ae47c9f0fd920c38eb42bf2f\nB = db05415ea90269a74b0919ff772c148c0eeb2ff9dea76a6e73e82eb86bc76fb42308b55ef83a769a91d23b7840d5d2f5129f15279dfab7cd8d63778acf202f26\nM = 7704390c4b1da86d51ff817003e5451d601a5352296e339e5da219ec5a330479\n\nModMul = 40b6b0d44cf8a5ca7f4fd03dd6e1e2a11f74f3911dcd8727e57db8d65cd490d\nA = 6500f3cf686eec4e1f243616ac0ea8e8d11ddbade490b86baf231e7b2fd55968ee14b6bb7badf8c898874099831976af46bcbfbfaea10d49aa803c6e51238e2\nB = 1fac744fa1e26e789639e049679d0e2eb57336279f09555e10210e7143199a3df5fbf5294edc386ac762fa3a3b0b4bc28945adf21a8af747a29018bf76d3710a\nM = 5c0781a87b84ecb4362b09c623d511de53c085671dd4f08e9a551685b55ddfd1\n\nModMul = 6b778ae9822221e6a8376379e0032d7edb14d7b5e32a7310897b54d1d5626113\nA = c4a5737a9496129a136753f8c2e52bbd2660f2d3fafe4ed702900b01c14e506d13e3bbeab19b357e5ba9fce8a4fc3dcc469406a16248d6fb53862781fd9d55e4\nB = 444e5a673eeb37fd3b4f6b6f5133b0f46c2ea532e1953da4a0e144407a8e2534c5ff40cc9af7756e5aff9df57d938fcedaffb", + "868dcf4e458b36f506ed7fe0ce5\nM = 7f5978c0c066132a9bdcb00727bb802b72777b9e8e4265f76b80cfdc3a788817\n\nModMul = 5c717e5dd25abe60f761d6f9326ed056416add4c1384682d87b7ff12e112f855\nA = 4351965a421c75c5b4c251861e53316a300ed7983e27e17f9308420f0d2cb11e9c476294fcd9042a525bc1a044bb442d1d9f853c9e07245170e0e2711010cd1c\nB = 4e1046647c362c8f9c414be54075b4e9d151c6fa0c3da40d90e6042625947ca2c9f20cfbcfdab8666dac5a15f6cda9d47b09f654131fc5addc07e382c9639323\nM = a6c789884c66c7f028099e0367b3ed86871277bf070c541ee12fc02fcb6181d7\n\nModMul = 4452688244f542125168853f1d444f96ab0f82903bb12a97e59f0db633edfd6\nA = 9fd1cc81981bff977244c044146918057ad06d3cc26edfb8fb4118ee02b959d45555f9507ffeb23c3688e29ccdfe5f583fa3761f6727573542bee8ab5f5b600d\nB = 856e6a03b5c93fc19deea51b3bfe42c810c5bcf9ffbd08e2625eb209baf6a4e24943a3c090d89c1f70aea9f0128e511fe92e03715d917168c1e1ca77a3a8731f\nM = 2c245d407a78903ef2b279ddbe32106e6333b6f44cabf87b8641b047c79ea06b\n\nModMul = 375f8474ee47df6b9a038512002e56cddd374d69c69719d8d369232c64a839e2\nA = add40f1dd6d4a2414b17f0c628eed9a8f082f3ad1f34ec41935fa86b34d4505b22ea80c062386a9ed63f95c67e55c686f837bddf8f4da791f98b08c02f32d4b2\nB = dab1caaa11d5a208b7a6b7a1d6482a4859daaba5e3a77b1b1020e8ae62a664953dfddd0b47d40526e7a3c6a5363c6d41dd9f529fd8b58d5d31bb67e745cb71b3\nM = 4f506313a4f49873a405f2e5a6e9cfae9cd5e9f67b5ef900153366570e28a955\n\nModMul = 36fb0733a26902f0f8f11625305a3c94fcdfffe294eb6ccba110aa628a314df\nA = 52ee1498bd6a1677db801ae2eab4951345a1fcf8fe7d38e3f28dbc27fae508d87c9958e02a375ff4891b88ee916b96331e7cc082615faa028f6d541b5ce37876\nB = 9343cfa074f50c20e8472f8f7c4a7d330aa30ee417ed8027a4c956e84cc5cb31d5411c14796d9325fceef79a51b5d8a4c89182ca273ab633e6a7b22a27352300\nM = 9d7c334aa33634f9f313b71b42476a3b627a6c5bb8ac1d07a8d732d5c087bd9\n\nModMul = 4a377267508eb045e00cea66a417112dac07545304bbeac6315625275b7cbfad\nA = 19616a82b75b08499d4b1f869df2db8f71398672f3f97ffc6177a4a5aa913605ce8a6ab5f778cac508f0b3f2aa680b01ccdc57c0fdd6cd678a2ff2dcd7f01f3c\nB = a5643a9a9fe3be4134082daae4ee7dfd85d9452beee856fd939d3be9788b6bebcf3571c67ec481ff9b20f70d23e82e2171b1d0ddf0a9435b40115d32aedb6811\nM = ea0477e7f1a02cb6c21171066f3dab69d4e24429043b0f049de660fc80e51937\n\nModMul = 7952dfdb91252658430e365adeefd9093740de92cfc9dd3d92294f2dab6ca0b6\nA = 8e6cd7639b7c134b53e6ae6ac5f51268da83ed09e8e96d65e4bb130dcdbbab9e48226ddba6efe93faa510bde8ee92f2a641774c4272b5a2f88024b77a2cfa110\nB = fe4e8109a49b16b96871e384564cc096277dad4e1bbca8e5feb33f140a4fb800c8f3096b1bc7042bccf249aede88e6055c0db609f94e214b1251eda494be724b\nM = aa46853682af960824140c35d145a6dcff6283b2c59994b30ecf9b8def41a025\n\nModMul = 1aacec7f7e66b0cf4eb2dfda9d8d3fbf4eb8e928cbbc967d13e3e38612f0346d\nA = b0fd7a936b0908ba6fa797e4b855d673ff85d665ef3a345e560e2c0049becf5c25b6c0068dd617ab47a8fd151939ea0631f86806ddd40e557933c0e880fcdd0b\nB = 105c87fe2b1bf0be5405ca0d530beda1780f0045e892d7810f8a8abbe890f0a19de66497cba55bf38e190c52992467c22a320c38a4bd167f774ed812f1271d5a\nM = ac4f0a2b22df691331ded955a5d0e7d1910d7920a59d4a87636b2635397b7335\n\nModMul = 2c25d180156fa7d2fc20c9bd6d9ff0b111c9ad76ada0784e2f8fa0bd06413f66\nA = 2aa4a0a73df11f4e60956619d0b35eaef45730d619f9b920298e6d369b9861f6411de28a34af038f288d7a3d6a35b10c8082b8ad0fb275a8f67c6832ac46ba9\nB = fae1d50b72feb25da2581829409391bf289cd9f730c99d265b5b2d63889381cde4adbf85c3998c2478f2866526b8f64605d75765edd09b78ea45337207d173\nM = 65c9d79a09a820adbc9beb152bef387c1439147ed50cef872d36a69f1c7d5fe1\n\nModMul = 56ec8624fc199e7b4e68358f88f1a99f1d4d02577b8c6f7e28e4ccfdd981f995\nA = b0a0f9d05d144d2ef257c1e63a7127a3b8e0d8b64ff8f6447618560593574b5c5da6258b274efc28da0defd988bef1efca0f481f809665a78954b36741d668bd\nB = 10901b9dbf0016cbcc671da75a75b7a6ec6a66dd17b53a97344864b08f037098537380bfb0137b6becfc36a75206686d16bc4eb8fd54299494374e3f383d9b10\nM = 73882376ca850c125ce9f20c291e550ee48f0eb0d571109ab08c22d6719496e9\n\nModMul = acceebe131aa34ff21b3235f045bccc8a8f762dca20c1dd1ef6eb461ea971c6c\nA = a7714b249eb0f0cbe3e6fa0b04e895fcf14c404876197defafc6b57026ae7e5e993fc47c1819581adc03860ce07f2b7877a3f6d0912c0cbc659f5f6170a1cb2b\nB = b7278ecd154ef5243ad973ead291ea186acb63e09977e644a6a9fde195d1a33993fc47c1819581adc03860ce07f2b7877a3f6d0912c0cbc659f5f6170a1cb2b\nM = c52ae49e1a4b21ec392b76844ad559653b7b9f67a58b3bba6c2ce250017eab09\n\nModMul = 62b5b04dc84bb4ee04934c03ef361bc6e59b42144dc117b9f7771525c67c3688\nA = 2b65f491caf0b5cd9c66c859fbcadaec7213e6b848884638791b1620d6e4bc9dde087af0e7329d3b15a45df2d43ebde61b053ad7f63917aa922d58b4f3222620\nB = c1bfcdb34b0766be980540dc3256b9ee4158310fad2c43cf24bfafca08ee185647043f5842a9d9eda224449259341b7c50998086434528d47661bf5762a7ab5f\nM = f73398c32191b436d14a0b76c6069b1d61395568753c832dd0c707780a232dc9\n\nModMul = 5613c8fb0721bd3f605089def48fb2c38a4862bb387886c1edc1bc37d10f0e15\nA = a3d8b12a2c8f4021ca045a4e4903687dea63ee7e88893b1911aea77efbff00f8f5c7884cbafc71f59fa2636195c2ebee61edbf642923f34d87ba5eb49b06a7ee\nB = 3231829c81b26dcac432b502ce22e126ab564922b1e9818cd3da46edc5ce7df026d0e515809c97bcfdb9666581efbfd364437ba9959dfad099f90472f97c69ec\nM = df8344fa848d1066afe4f8d985cff65441751677dcf3a4e99b40365fc3c978e9\n\nModMul = 30325f7ccbc2c69e11d739ad7132a947c53377aa902ec70b152f3a75e050c244\nA = e4ba620125f58a63fe12fbd3eccdea477d56b120c76d5d1421bebd74e8686b4093f8169070453ccc04b63b173568385313a1d9c841a4aa82a61cb84d4286a941\nB = e87aaa990307855f8e5f2e5509d2ce31dd4b13bb7199cf5fa0593e350326e222efc33a26c69245565d6ebb5a484cfef7d2558f22dea8054d07831d536803d0dd\nM = 43d57108eb0ab9bebaa8ce137628ea825951c6accb9acb7f1e991c93b8563897\n\nModMul = 1975db7b72434ad32c9aee412645f6670b7f4af1f8a424a5031c559d3e18dce6\nA = bd64b1db27fa7da4c92a4ee092f58a2a53ed0f12d009fe13b36d5fd585defe778fafea4a60e8fe567d03e9ba3b72b189e22504ae8ca6aad7c2ac0f44abca2f6\nB = b487d8116198560d6c5b08c7ce63b0acc0c98e6f2a8d709cf4e3a409edd55f64d72fc27a70dc341e280ff5a1b09fe131773d466cb31991d2db23a2a86d225c80\nM = 39d57af763eabe569dac1a103e169e6e3b4375168e41e5c3b961b6e743915923\n\nModMul = 3bbb5bde9e3e240694326571360090e1fc0a4ea7b2311c1e0bd3961f6c159385\nA = 4181ee3bf9a98bcd49eaea243a179cddbf160981efc720685c7be1dfeb5aa552685a2cd46f340e1e1da893b3b460692fa2eaf6c100f24a14f239e45123242d53\nB = 77cd04d86dd5da322af78be54246dd6b7af490d903db1db03cbccde535570b81c6053a84110c07f097540ffe7510320024b7bafb77e9e239761def76092e1d59\nM = f3b9833a303eb540cf8b6cbc3cf16394b1634ef517be57684e42d364d8bec3e5\n\nModMul = 2d8174211f0367233b3a8df7c5bf0066d6aa792be7cdc5e850a477454d5c829f\nA = 1c08cec52d96136fbd9078b7b8db36ab63b86e19dd3dba7b2e3190ff566180e89dfee9423fa4e99be2187eda6aedfa86b9a45eb1e4655257315ae6a280f0a6ee\nB = a8b4bc9647d8df9b7c76cc6d0f2248cdbc41f5da9c061f9864aa8415c9557582cada456cf23cc32d47d1fc1caf19d36b398019aac4734e10f55ce3cad419e5e7\nM = 7eacffe21f88413af94155a2a8e37f70a431a59653738afda04a1bec72d0d9ed\n\n# Regression tests for CVE-2016-7055.\n\nModMul = ccd6f75b5f24b7c5ce2ce755fa89c2450c6a7d96ce8c8791e659eab84577a7695e3b2caa7c980fb23f60634233e9798499c28b0338c1f1a326d0ca89fd41f2fd88b759f317889832966b551a950043ec7a4b6152d3e2cbfb40e88458e70ab783b96f12d271f828d5b39e198ccaf8665411d85026282dbead5d24cd01b6c8a8e9\nA = 7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878\nB = 095d72c08c097ba488c5e439c655a192eafb6380073d8c2664668eddb4060744e16e57fb4edb9ae10a0cefcdc28a894f689a128379db279d48a2e20849d685939b7803bcf46cebf5c533fb0dd35b080593de5472e3fe5db951b8bff9b4cb8f039cc638a5ee8cdd703719f8000e6a9f63beed5f2fcd52ff293ea05a251bb4ab81\nM = d78af684e71db0c39cff4e64fb9db567132cb9c50cc98009feb820b26f2ded9b91b9b5e2b83ae0ae4eb4e0523ca726bfbe969b89fd754f674ce99118c3f2d1c5d81fdc7c54e02b60262b241d53c040e99e45826eca37a804668e690e1afc1ca42c9a15d84d4954425f0b7642fc0bd9d7b24e2618d2dcc9b729d944badacfddaf\n\nModMul = ccd6f75b5f24b7c5ce2ce755fa89c2450c6a7d96ce8c8791e659eab84577a7695e3b2caa7c980fb23f60634233e9798499c28b0338c1f1a326d0ca89fd41f2fd88b759f317889832966b551a950043ec7a4b6152d3e2cbfb40e88458e70ab783b96f12d271f828d5b39e198ccaf8665411d85026282dbead5d24cd01b6c8a8e9\nA = 095d72c08c097ba488c5e439c655a192eafb6380073d8c2664668eddb4060744e16e57fb4edb9ae10a0cefcdc28a894f689a128379db279d48a2e20849d685939b7803bcf46cebf5c533fb0dd35b080593de5472e3fe5db951b8bff", + "9b4cb8f039cc638a5ee8cdd703719f8000e6a9f63beed5f2fcd52ff293ea05a251bb4ab81\nB = 7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878\nM = d78af684e71db0c39cff4e64fb9db567132cb9c50cc98009feb820b26f2ded9b91b9b5e2b83ae0ae4eb4e0523ca726bfbe969b89fd754f674ce99118c3f2d1c5d81fdc7c54e02b60262b241d53c040e99e45826eca37a804668e690e1afc1ca42c9a15d84d4954425f0b7642fc0bd9d7b24e2618d2dcc9b729d944badacfddaf\n\n\n# ModSquare tests.\n#\n# These test vectors satisfy A * A = ModSquare (mod M) and 0 <= ModSquare < M.\n\n# Regression test for CVE-2017-3732.\nModSquare = fffffffdfffffd01000009000002f6fffdf403000312000402f3fff5f602fe080a0005fdfafffa00010001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000002000002fefffff7fffffd07000109fdfffef3fffdfd06000405ff00fdfbfffe00010001\nA = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff00000000\nM = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff\n\n# Regression test for CVE-2017-3736.\nModSquare = fe06fe0b06160c09\nA = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f8f800000000000010000000006c000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffff8f8f8f800000000000010000000006c000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff00fcfdfc\n# A in Montgomery form is fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8ffeadbcfc4dae7fff908e92820306b9544d954000000006c000000000000000000000000000000000000000000000000000000000000000000ff030202fffff8ffebdbcfc4dae7fff908e92820306b9544d954000000006c000000ff0302030000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01fc00ff02ffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00fcfdfcffffffffff000000000000000000ff0302030000000000ffffffffffffffffff00fcfdfdff030202ff00000000ffffffffffffffffff00fcfdfcffffffffff\nM = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f8f800000000000010000000006c000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffff8f8f8f800000000000010000000006c000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffff\n\n\n# ModExp tests.\n#\n# These test vectors satisfy A ^ E = ModExp (mod M) and 0 <= ModExp < M.\n\nModExp = 00\nA = -01\nE = 01\nM = 01\n\nModExp = 01\nA = -02\nE = 01\nM = 03\n\nModExp = 01\nA = -01\nE = 02\nM = 03\n\nModExp = 01\nA = -02\nE = 02\nM = 03\n\nModExp = 00\nA = -03\nE = 02\nM = 03\n\nModExp = 02\nA = -04\nE = 01\nM = 03\n\nModExp = 01\nA = -04\nE = 02\nM = 03\n\n# Regression test for carry propagation bug in sqr8x_reduction.\nModExp = 19324b647d967d644b3219\nA = 050505050505\nE = 02\nM = 414141414141414141414127414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\n\nModExp = 208f8aa0\nA = 86b49\nE = 2\nM = 30d26ecb\n\nModExp = 27308229\nA = 17591bb\nE = 6\nM = 30d26ecb\n\nModExp = 2bdf498f\nA = 21292626\nE = d\nM = 30d26ecb\n\nModExp = 11317167\nA = 4a655df24\nE = 10\nM = 30d26ecb\n\nModExp = 2e1b88e\nA = da6b761a86\nE = 35\nM = 30d26ecb\n\nModExp = 20a12ec3\nA = ea811\nE = 2\nM = 23bc042f\n\nModExp = c42ced\nA = 1011a6a\nE = 4\nM = 23bc042f\n\nModExp = 4637d79\nA = 28d9a601\nE = 8\nM = 23bc042f\n\nModExp = 20e5669b\nA = 72fe6bc20\nE = 11\nM = 23bc042f\n\nModExp = 142ab9e3\nA = 9a07b9363c\nE = 29\nM = 23bc042f\n\nModExp = 14c64646\nA = 822df\nE = 3\nM = 30915765\n\nModExp = 160e35a2\nA = 15ea542\nE = 5\nM = 30915765\n\nModExp = 2f23a488\nA = 34d2e02e\nE = e\nM = 30915765\n\nModExp = 28e67f93\nA = 636a32703\nE = 14\nM = 30915765\n\nModExp = 29bfeaa5\nA = c8646998e6\nE = 2c\nM = 30915765\n\nModExp = 30959e22\nA = 81dad\nE = 3\nM = 326dd68d\n\nModExp = 1a1da4fa\nA = 116adb9\nE = 5\nM = 326dd68d\n\nModExp = 272bf0d8\nA = 2d21ef08\nE = 8\nM = 326dd68d\n\nModExp = 29f5054b\nA = 76989850a\nE = 16\nM = 326dd68d\n\nModExp = e6c7b77\nA = b88ee70d2a\nE = 3e\nM = 326dd68d\n\nModExp = 369605e1\nA = cf26f\nE = 2\nM = 3ce082eb\n\nModExp = 168a3c5d\nA = 1f82caf\nE = 5\nM = 3ce082eb\n\nModExp = 125c4bb8\nA = 2e9c4c07\nE = 9\nM = 3ce082eb\n\nModExp = 1c5fe761\nA = 523ab37f1\nE = 14\nM = 3ce082eb\n\nModExp = 21703009\nA = dc832165e8\nE = 20\nM = 3ce082eb\n\nModExp = 1228d1e\nA = a5555\nE = 3\nM = 24665b27\n\nModExp = 5226af4\nA = 1077bd6\nE = 4\nM = 24665b27\n\nModExp = 1b14eac1\nA = 2db3a834\nE = f\nM = 24665b27\n\nModExp = 161727bc\nA = 6bd962cb6\nE = 19\nM = 24665b27\n\nModExp = 10d61d0d\nA = c10caed407\nE = 28\nM = 24665b27\n\nModExp = 233da406\nA = b125f\nE = 3\nM", + " = 33509981\n\nModExp = 24032799\nA = 1656b7c\nE = 6\nM = 33509981\n\nModExp = 129ecebe\nA = 2e671504\nE = a\nM = 33509981\n\nModExp = 20c20bac\nA = 4d7a2de44\nE = 1f\nM = 33509981\n\nModExp = 2e3ce9d3\nA = c53b3def4d\nE = 31\nM = 33509981\n\nModExp = 12fadfd6\nA = b4cf8\nE = 2\nM = 36e9d4ae\n\nModExp = 457ac85\nA = 1b1c7e9\nE = 7\nM = 36e9d4ae\n\nModExp = 31debef4\nA = 3a973028\nE = d\nM = 36e9d4ae\n\nModExp = 2333ad93\nA = 552b97c45\nE = 11\nM = 36e9d4ae\n\nModExp = 99ba1fb\nA = 8bfb949cbb\nE = 28\nM = 36e9d4ae\n\nModExp = 27b691de\nA = 93492\nE = 3\nM = 298fdb16\n\nModExp = 3c2b70f\nA = 14e7b0d\nE = 4\nM = 298fdb16\n\nModExp = 1486cda7\nA = 29acff81\nE = c\nM = 298fdb16\n\nModExp = 11725275\nA = 507489205\nE = 13\nM = 298fdb16\n\nModExp = 24d14627\nA = e71c55606d\nE = 35\nM = 298fdb16\n\nModExp = 222b8d14\nA = 9b1a0\nE = 3\nM = 3db59d12\n\nModExp = 3b8bd47d\nA = 13f4e8d\nE = 7\nM = 3db59d12\n\nModExp = 17e72356\nA = 334774ce\nE = a\nM = 3db59d12\n\nModExp = 306447ca\nA = 47079ddd2\nE = 12\nM = 3db59d12\n\nModExp = 90bef3b\nA = a75d62616d\nE = 37\nM = 3db59d12\n\nModExp = 1\nA = cddd44f47e84b3276cc36a5c0d742cc703e61c4756168601fbb1b6eb598c161019562344dd56ab6f603d920a12c360b285e6496a3605a2f8d691c3598233ee9366b5f2692554893bdeb67b7bdaf35ab7273ac593145e26bed82c70ba5793bf4bc5cac4c80b01785d1496beede493806e4f4aa89fd8d41de80dd6d0a3e2742678\nE = 0\nM = c95943186c7567fe8cd1bb4f07e7c659475fd9f38217571af20dfe7e4666d86286bc5b2bb013197f9b1c452c69a95bb7e450cf6e45d46e452282d5d2826978e06c52c7ca204869e8d1b1fac4911e3aef92c7b2d7551ebd8c6fe0365fad49e275cc2949a124385cadc4ace24671c4fe86a849de07c6fafacb312f55e9f3c79dcb\n\nModExp = 0\nA = 0\nE = 8de689aef79eba6b20d7debb8d146541348df2f259dff6c3bfabf5517c8caf0473866a03ddbd03fc354bb00beda35e67f342d684896bf8dbb79238a6929692b1a87f58a2dcba596fe1a0514e3019baffe1b580fc810bd9774c00ab0f37af78619b30f273e3bfb95daac34e74566f84bb8809be7650dec75a20be61b4f904ed4e\nM = c95943186c7567fe8cd1bb4f07e7c659475fd9f38217571af20dfe7e4666d86286bc5b2bb013197f9b1c452c69a95bb7e450cf6e45d46e452282d5d2826978e06c52c7ca204869e8d1b1fac4911e3aef92c7b2d7551ebd8c6fe0365fad49e275cc2949a124385cadc4ace24671c4fe86a849de07c6fafacb312f55e9f3c79dcb\n\nModExp = 5150fb769d5c5d341aaf56639a7bcc77c415fe46439938a2190283409692f29cd080bfe3433005d98d24718a03a3553c8560c5e9c8ed0f53b8945eb18290e1c1a83d919302510f66dd89b58acc2de79ad54b8a30d3e1019d4d222556beefca0821b094ecf104b5e4cfce69d2d520d2abf54f3e393d25ed3d27e8c2e3ca2e5ff9\nA = ead8c5a451541c50cab74de530c89376d9a55c723e0cac3c84b25f0093c08a2961e49ab48966361c42c9f99111587252d98395b76788400d75c66ef208ea2767a28d6f8dc3a859f39c95765d57f139e7fc14f47c908c62df051e7216d379f52028843b4d82ef49133cce8fe671ae179423ac8da5be43b01caaf425cd969300cd\nE = 8de689aef79eba6b20d7debb8d146541348df2f259dff6c3bfabf5517c8caf0473866a03ddbd03fc354bb00beda35e67f342d684896bf8dbb79238a6929692b1a87f58a2dcba596fe1a0514e3019baffe1b580fc810bd9774c00ab0f37af78619b30f273e3bfb95daac34e74566f84bb8809be7650dec75a20be61b4f904ed4e\nM = c95943186c7567fe8cd1bb4f07e7c659475fd9f38217571af20dfe7e4666d86286bc5b2bb013197f9b1c452c69a95bb7e450cf6e45d46e452282d5d2826978e06c52c7ca204869e8d1b1fac4911e3aef92c7b2d7551ebd8c6fe0365fad49e275cc2949a124385cadc4ace24671c4fe86a849de07c6fafacb312f55e9f3c79dcb\n\nModExp = 1\nA = 935561297d1d90255aef891e2e30aa09935409de3d4a5abc340ac9a9b7dce33e9f5ce407f3a67ec30e0dc30481070823f8542463e46828d9cafb672a506d6753688cbad3d2761079f770c726c0b957071a30876c4d448e884b647833befbcd6b582787bf769d63cf55e68c7b869a0b86374f8920516cf5d528f348b6057450a1\nE = 0\nM = dcc24236a1bb94c71d9ec162a6aa4697b932717e82b667cad08b6bd1bbcbddf7cd167b7458de2b0b780486b39574e749d6405f9ede774a021d6b547271523e9e84a6fdd3a98315607ccf93356f54daa9c75e1e311e1672d0dc163be13f9ed6762f7dd301f5b0a1bb2398b608f40ac357ae34fc8a87d4fef3b961cbdb806d9061\n\nModExp = 0\nA = 0\nE = bb552be12c02ae8b9e90c8beb5689ffefe3378d2c30f12a6d14496250ecce30317c642857535a741642c3df689a8d71a276d247ed482b07b50135357da6143ac2f5c74f6c739c5ff6ada21e1ab35439f6445a1019d6b607950bffb0357c6009a2bfc88cd7f4f883dc591d4eb45b1d787e85aba5c10ee4fe05ea47bf556aec94d\nM = dcc24236a1bb94c71d9ec162a6aa4697b932717e82b667cad08b6bd1bbcbddf7cd167b7458de2b0b780486b39574e749d6405f9ede774a021d6b547271523e9e84a6fdd3a98315607ccf93356f54daa9c75e1e311e1672d0dc163be13f9ed6762f7dd301f5b0a1bb2398b608f40ac357ae34fc8a87d4fef3b961cbdb806d9061\n\nModExp = bbad67352704a6321809f742826bf3d1c31c0ad057bf81432abeb30dc9913c896c03e69eb1cde6b78ffcb320c4625bd38ef23a08d6c64dc86aec951b72d74b097e209ce63092959894614e3865a6153ec0ff6fda639e44071a33763f6b18edc1c22094c3f844f04a86d414c4cb618e9812991c61289360c7ba60f190f75038d0\nA = 855144760f2be2f2038d8ff628f03a902ae2e07736f2695ec980f84a1781665ab65e2b4e53d31856f431a32fd58d8a7727acee54cc54a62161b035c0293714ca294e2161ea4a48660bf084b885f504ad23ea338030460310bd19186be9030ab5136f09fe6a9223962bce385aaaf9c39fe6ed6d005fa96163fe15cdfa08fc914d\nE = bb552be12c02ae8b9e90c8beb5689ffefe3378d2c30f12a6d14496250ecce30317c642857535a741642c3df689a8d71a276d247ed482b07b50135357da6143ac2f5c74f6c739c5ff6ada21e1ab35439f6445a1019d6b607950bffb0357c6009a2bfc88cd7f4f883dc591d4eb45b1d787e85aba5c10ee4fe05ea47bf556aec94d\nM = dcc24236a1bb94c71d9ec162a6aa4697b932717e82b667cad08b6bd1bbcbddf7cd167b7458de2b0b780486b39574e749d6405f9ede774a021d6b547271523e9e84a6fdd3a98315607ccf93356f54daa9c75e1e311e1672d0dc163be13f9ed6762f7dd301f5b0a1bb2398b608f40ac357ae34fc8a87d4fef3b961cbdb806d9061\n\nModExp = 1\nA = 9d92629c1ab181c50c31619e8acd0d235a1f5fc7a0bef4d4fd54b4f1968d45921f8522efe88e69c6c14c576c564592b9feb00d1554b88b038934eaf4a8ce81a2582732387490181ef158360c8b2d9ccb326ffe043f776a50cb8202837f08ca743b562eefa007150ab7012c341b16248478d4775c02ad71ea13d5e82b71e2d600\nE = 0\nM = cd607549668469b792f495c141e500871880b0611c8004293a561ec7f9ab6561f8a9b90872742386adafb5cd1890e8204ae12aec529cca0a9e382c96439137f09de9973b12c8492c62847e107deabb7dd946ffbb9d0ac73b462c481092bd65326a17f21d8d6527c47a5dba50aaa20c7048b8788a49eb3ea5f29bd5cfce24eb3b\n\nModExp = 0\nA = 0\nE = 9f43dcb641f3ecf4dbc97450f2bdf3b7ec6a2f3e8e96bb1df2bf34b8d2d78e1a9018d04d960ffd0e932cfc60d3b9b923e3f9f29b3f3d61cae3a9f7245078143475c7fcb896ff200f7d94c4f2708bb42750e37c185a31c876814e4f06a00771707654e1da2fb69c16b6500b16385e3b933e2276ad3569977473f699b1c7926c3b\nM = cd607549668469b792f495c141e500871880b0611c8004293a561ec7f9ab6561f8a9b90872742386adafb5cd1890e8204ae12aec529cca0a9e382c96439137f09de9973b12c8492c62847e107deabb7dd946ffbb9d0ac73b462c481092bd65326a17f21d8d6527c47a5dba50aaa20c7048b8788a49eb3ea5f29bd5cfce24eb3b\n\nModExp = 24eaead5b57883c2f454928f8edd470a344bfe07a953194f7d635d705ef13ddfc64140c8ad6f363d4c828e7c7891a6b6d4df37335de4552c319dafd1c06d1f743240082a3535df4da1475d3eea3fead20e40815fd5a0876c881c162ab65a1eda494280c258901ca953d1d039a998bf0e9aa09273bbef4865f3054663b72d75ff\nA = a31618b4532f53729ba22efb2221432fab1dbb70853d6a1159b42fd19fc949965c709b209de106a652aa422d88922ce51dae47f7f6deaf0055202e13db79ee84fc3d3c6f4c003ef96597c49d6895fa53c22ac9e4819f7048146b5272f6279424fdb389819a0b251c823c76f4bebf4f1246de455aafe82a0d34454f5039e90839\nE = 9f43dcb641f3ecf4dbc97450f2bdf3b7ec6a2f3e8e96bb1df2bf34b8d2d78e1a9018d04d960ffd0e932cfc60d3b9b923e3f9f29b3f3d61cae3a9f7245078143475c7fcb896ff200f7d94c4f2708bb42750e37c185a31c876814e4f06a00771707654e1da2fb69c16b6500b16385e3b933e2276ad3569977473f699b1c7926c3b\nM = cd607549668469b792f495c141e500871880b0611c8004293a561ec7f9ab6561f8a9b90872742386adafb5cd1890e8204ae12aec529cca0a9e382c96439137f09de9973b12c8492c62847e107deabb7dd946ffbb9d0ac73b462c481092bd65326a17f21d8d6527c47a5dba50aaa20c7048b8788a49eb3ea5f29bd5cfce24eb3b\n\nModExp = 1\nA = a8558e7f455b27c0c46d7d0862eb409cdefbeca945e0284b5bf425b7ac0f3d316bc365594cc1639decffc621214d61479bc75135120d4ac09ea8b742ad7ec1822091b62b1c6f564fe5e2f4f5b7def92cbaaa9a898549207ab01b91c2324fbd306a87f7d6379b6fb6493c5fca76729767f136120da9c90bdc7d364f7d242d5acc\nE = 0\nM = 88f3c87ac5e3272a21b8a858da640d6939fb8113a95412c38663a0f352686d69a5d7927e60b484b9fcb8ef12978fe25ff2ebc9b61c5450e04222ef20ba3cbbdc5ec45581ce0f58e10be7bb9de7fa08752303a7a1db23b2ac9c6692ec63bf09ecd6639e06c5491ba568ea886620d71da32d329615f0e1443a75d09ae35b8a2d7f\n\nModExp = 0\nA = 0\nE = a5524b41dfc6b570df1d8f6633ac7777c1131abe3a99c6166b0d29d3b8883c41b00a0c53cdd6f42820bf05c810b6ec53e77a8c1b9344ea0c91d4f410a2f204c369f3db33bf8c88217fc2cf802a9d9bce8119242d8e781875b85431be170076498c0963574ee423551aec9557e2fc672ab1ab5d0cbb1c400535df9481e7934d8f", + "\nM = 88f3c87ac5e3272a21b8a858da640d6939fb8113a95412c38663a0f352686d69a5d7927e60b484b9fcb8ef12978fe25ff2ebc9b61c5450e04222ef20ba3cbbdc5ec45581ce0f58e10be7bb9de7fa08752303a7a1db23b2ac9c6692ec63bf09ecd6639e06c5491ba568ea886620d71da32d329615f0e1443a75d09ae35b8a2d7f\n\nModExp = 292f0b39ca0f1c850b1a00cffd2d54924fcd5fc7e7504c9d593e6c0ff74760b1f4bdd81679fe06c50248336f3108c593fa111072ee87d0fcc89a63243a1dc89044503663eee9bc18f51c3e0193d9108303e12ac90ff78f6ec752a4386af09c42db524a7cbe9a3d4fcccd56c34d283bcc9debc17158b5fe8df0c1888a9841bf8f\nA = b4fde2908745ff92cc5826a27dcfdda09e8fffee681844fa4c7f1354d946d5d84e0e0c7a4a4cb20943d9c73dd707ca47d796945d6f6b55933b615e2c522f5dfc33e0652917b4809bab86f4fa56b32b746c177764895492d0a6a699812b2827fe701d40ef7effd78ea8efe1cac15ff74a295a09614bf04cae1a5017872ba22efe\nE = a5524b41dfc6b570df1d8f6633ac7777c1131abe3a99c6166b0d29d3b8883c41b00a0c53cdd6f42820bf05c810b6ec53e77a8c1b9344ea0c91d4f410a2f204c369f3db33bf8c88217fc2cf802a9d9bce8119242d8e781875b85431be170076498c0963574ee423551aec9557e2fc672ab1ab5d0cbb1c400535df9481e7934d8f\nM = 88f3c87ac5e3272a21b8a858da640d6939fb8113a95412c38663a0f352686d69a5d7927e60b484b9fcb8ef12978fe25ff2ebc9b61c5450e04222ef20ba3cbbdc5ec45581ce0f58e10be7bb9de7fa08752303a7a1db23b2ac9c6692ec63bf09ecd6639e06c5491ba568ea886620d71da32d329615f0e1443a75d09ae35b8a2d7f\n\nModExp = 1\nA = e2845c572b46496ac158a731f612fd40ef626fa7134755c25b1b7614f4d7b29164e6142ddb7985e4c7ebc575855ff901e95927fe98a5aea2ad3a4720c75782323bea1518b2c57790f44efd9411be4e95b3896bad1e73c59658290b309e5a7eb5ef8be08125063e57336b80f17eacee88966d12bbaaa15a25929c82e027cf696f\nE = 0\nM = cf0dee80177869a532f0c6c3a0bda3aad79bdb6b70b6c227b32d75c26e394a90c1f2a6c2bb841ba9f6556b15654a79d8b1dd0c90709a093497bf40be0807cdbb378a74de5893c25067224d3ea8d37387ed6c4a981138853cb89caa9ce6cd0f6a1e95de24d558e90960f93844db4d01e372650350d45a9d34a36042b4d4b9e78d\n\nModExp = 0\nA = 0\nE = a55703a72ca3f6074b939ed3d748196a684a3c8e411c2b39a9beb98993b6eb7ea3fa16f41bc5b5c3710b91c0fc74a8072793052f872f61695db3a2df872eaa427a110f1a8d568c85d58bd350d0df8eced7a10be80f7567360c1a8047b9c44aa2967cd0d9dd2caea2c1492358c2db4f0214da343fdf2e34272865dc5c63be2ae4\nM = cf0dee80177869a532f0c6c3a0bda3aad79bdb6b70b6c227b32d75c26e394a90c1f2a6c2bb841ba9f6556b15654a79d8b1dd0c90709a093497bf40be0807cdbb378a74de5893c25067224d3ea8d37387ed6c4a981138853cb89caa9ce6cd0f6a1e95de24d558e90960f93844db4d01e372650350d45a9d34a36042b4d4b9e78d\n\nModExp = c90e4c69df92e26549b016950b59080947f5403430698e128477782480dd70be96bed2b9042dd8c708eb432e02710555b97af11ce6fa9b53395022851c32d1f53f04237fb0763563b440ca6e81a50d909d907d9c26b7d3c420dbf88f7dadd488666848135f8cdc608dcfb0691989289fb54379c2e84c262f9765f68c012ca1b9\nA = 882ea1b9b6c79a3b1bdfd284658cb6227ad825e0178cab713c7413c2ec34f03cfaec470c4f5c521f5e9899a2123878ff0f5b36a4196c08ad1b04d03746c4bfb5d126f5eefbfe172627d6732710a8ac8890cedbd4fdef69a19f2b3253a5aa0e5dd5484f72d59b17bdd1dad3db209a3ab839368ed3975069685911d7b35e41a9e6\nE = a55703a72ca3f6074b939ed3d748196a684a3c8e411c2b39a9beb98993b6eb7ea3fa16f41bc5b5c3710b91c0fc74a8072793052f872f61695db3a2df872eaa427a110f1a8d568c85d58bd350d0df8eced7a10be80f7567360c1a8047b9c44aa2967cd0d9dd2caea2c1492358c2db4f0214da343fdf2e34272865dc5c63be2ae4\nM = cf0dee80177869a532f0c6c3a0bda3aad79bdb6b70b6c227b32d75c26e394a90c1f2a6c2bb841ba9f6556b15654a79d8b1dd0c90709a093497bf40be0807cdbb378a74de5893c25067224d3ea8d37387ed6c4a981138853cb89caa9ce6cd0f6a1e95de24d558e90960f93844db4d01e372650350d45a9d34a36042b4d4b9e78d\n\nModExp = 1\nA = d7a99e65b8af86b1c51d851f0447e43cd4f343cb0ada7236283e69aa7ebd383826acc9809e5dbc4002d0f2430022cb026458189db3805ce2de1142a31ba71a6c064ab51f0059eb4b931b8bcbaef023c38d57aa5f3e14f5df77e547fc028702071b58bd57338be1e1e4f98d3553484e4de359cefa29c5f58d3fa5d823f389dbef\nE = 0\nM = 8315dacf124bd473c578946347e83d1b20c750a7d9533d6215591be40bc78bcca77821f8c8f95375bbd6372515ada63d22bed2fa49bd6fabb0040c538d08db25b09d2fda02a93ab086cd1c27df93c37ee9c6a0527d089179b8f92b5dc3acf5ef1c75906fb80b03f5c2442a7a4088640f66376575ecfa4c697c1a571397ee5a0d\n\nModExp = 0\nA = 0\nE = 95793fe33696f53e37498b2b65aaf27079e27acf1da97dda2c3e0803e8a02139f574e04ee03f7d1ddd029f528e3f3644515ad6f10f0beac2767f23d9cd8a8b9b6c6e376e36b64a0ae2711d7d31a5a75011641935b503110edbefe9f0ff2da27b5c5f6bb8cc151fdc86f67191bb99160c6cacc86ca368d5bdfafd3f3ff5161b1e\nM = 8315dacf124bd473c578946347e83d1b20c750a7d9533d6215591be40bc78bcca77821f8c8f95375bbd6372515ada63d22bed2fa49bd6fabb0040c538d08db25b09d2fda02a93ab086cd1c27df93c37ee9c6a0527d089179b8f92b5dc3acf5ef1c75906fb80b03f5c2442a7a4088640f66376575ecfa4c697c1a571397ee5a0d\n\nModExp = 186c50ae259aa0fd31859cbcfea534e626a254de33956d5d719334bb32e7cf37cf199a21f079a5b90497228994d05efe19ccd8c769cd81f896286e8ae557cacd1630a928c629ecdfece29ab3697794aa707734e007318fa7029b050bb09ebbe6986187c6ca843f55266d275620b3f0fec0ad5f847ce8b314d929d128b33a249e\nA = 9d5e345793faddca9867f23eeddf6816c1e837f7a2cf96fa077212514acb6be87ac01a237d8f2f1d07d27a8ddd1b0ae0d97e1bda4f205a89435017284cdedea3e407b1b940d6f52112b6359b3e86e4c83074b17c210ae2c8856b42b169b4a7a6dfa65b368a7959496cf9bb1ee93d019dbd79101830e3f5ed08604ab90890b914\nE = 95793fe33696f53e37498b2b65aaf27079e27acf1da97dda2c3e0803e8a02139f574e04ee03f7d1ddd029f528e3f3644515ad6f10f0beac2767f23d9cd8a8b9b6c6e376e36b64a0ae2711d7d31a5a75011641935b503110edbefe9f0ff2da27b5c5f6bb8cc151fdc86f67191bb99160c6cacc86ca368d5bdfafd3f3ff5161b1e\nM = 8315dacf124bd473c578946347e83d1b20c750a7d9533d6215591be40bc78bcca77821f8c8f95375bbd6372515ada63d22bed2fa49bd6fabb0040c538d08db25b09d2fda02a93ab086cd1c27df93c37ee9c6a0527d089179b8f92b5dc3acf5ef1c75906fb80b03f5c2442a7a4088640f66376575ecfa4c697c1a571397ee5a0d\n\nModExp = 1\nA = e6a079bdf7b0638d50b183475e9ddfd5cbdebfb29f5fae8e9be402a0bd36085737b556492ea7fb4b1000ae9ce59db66098129b757cfb29224275fdaa46b8b7eb18a93ca7d3e446dc38c734b683d7ba7927b008d993aab01f44239d3c76be76d1503908e9b5e73b36c43ae0771368b01f39c042693bd92c4fc50810f059e1b332\nE = 0\nM = 81dd561d5d5327fc5ed7c9236b5fb21ef713c6d5e36264ba65ccc801b8eb107b714aad65bb503bb1f4721c0a6f97e5ab89300f049f42a4616ae43d29c089c286687484d18629c1be1b5befbdd0b3cfc86b1d28add89df4cc5e68dac3f56f2490a9068ca9c634ec258c030ec5023baa9133fd2af32fd1112895f9da549d410247\n\nModExp = 0\nA = 0\nE = f0460c5ca9b3a5c2d1b93c201d020dc43e1c81d1daba432e2cd310902da23eb81a5172b0b357484eb8fa2c04c270893b8198c8ad35453405dadaf05195b3aeb5ec0ccacecb4b6227ca43b27b97e240a4148a472670ed60f304302f757495fd4a91af0fe09800db0c3043a6ae213bee6703ad80523ca433d99ca0eab1e0b7c929\nM = 81dd561d5d5327fc5ed7c9236b5fb21ef713c6d5e36264ba65ccc801b8eb107b714aad65bb503bb1f4721c0a6f97e5ab89300f049f42a4616ae43d29c089c286687484d18629c1be1b5befbdd0b3cfc86b1d28add89df4cc5e68dac3f56f2490a9068ca9c634ec258c030ec5023baa9133fd2af32fd1112895f9da549d410247\n\nModExp = 60719701a2dc0bcde281a93ce0b8421d1a718adee43c1b5d9fe9e697a48ab3db4f9f33c73cff305ab6b6c300c149b05c6b289dce4580860dc56bc59de81ac074ecebdc65aa3ca040b44e5b3c80ddba1658d78b9abbc4c77e5f171f5582e70ab4438a8e1e2f062d618c4ad09c70c73b5b5fbc9f8f0bbdf1d530a933b705f85af8\nA = e1b400cd3b1f2f1c6b437adfdb970d2c8108f1b39bdbb13582179552011c6c97cba6bff2c463212b7f62776aa3e3aff9f175990e79395e819c144350b0a23d61638d500ecc97726b098e1af334aece23a851c718612442c04eb7b3805a24cc8f5b90042145eb5e5d6a408092832b6bbeb8a621419a9282fb5c075f41c7f1fdc1\nE = f0460c5ca9b3a5c2d1b93c201d020dc43e1c81d1daba432e2cd310902da23eb81a5172b0b357484eb8fa2c04c270893b8198c8ad35453405dadaf05195b3aeb5ec0ccacecb4b6227ca43b27b97e240a4148a472670ed60f304302f757495fd4a91af0fe09800db0c3043a6ae213bee6703ad80523ca433d99ca0eab1e0b7c929\nM = 81dd561d5d5327fc5ed7c9236b5fb21ef713c6d5e36264ba65ccc801b8eb107b714aad65bb503bb1f4721c0a6f97e5ab89300f049f42a4616ae43d29c089c286687484d18629c1be1b5befbdd0b3cfc86b1d28add89df4cc5e68dac3f56f2490a9068ca9c634ec258c030ec5023baa9133fd2af32fd1112895f9da549d410247\n\nModExp = 1\nA = 9dd1e6f2d3ff24096b54e0ebf0f10e283e484a1cbafc0431adda1296ed97692f3ba99440fd4f67c96dd8bab850e1123361c99362df9ea205ff8e90d1b329459f54730992d5a360e46fcc5f5a909e691abb9a06613d6991bd7c2aa609f0d7b441d7ded0c07b8c394327672d38a905efb2d76aa3be5bb14d0c002aa37e287aee79\nE = 0\nM = fda6f9d8588e3614f5a68ce867a5619f6ddbb8d64450ff402e1c4f1a08b518f79dca21e5983c207c5b7324c16895a1e9f1282fc6cf60b0645f6b02b652ed5b129e67c939e854ab492dec30ea878c3edde10a4b7d1d14c57100c6cbcc5fc085a0d7308715ed132fb", + "917251919c727487fedb66500d5610b0014a43419acfbb92f\n\nModExp = 0\nA = 0\nE = 8622c37631e428402343dccf8ed09d47b3f4201e95058910289a62707c3ce0b7113c390056cc4796cc9893e471b12cb3f63f900f3356ffd25c8b2fed6f6a7fba2c684eb241ca706c76cecbf72473d8a58c02338e40714b5610465cc319f0a529a7aa3898d9e638b247abd1380c6e8f7fa210c9f1a1a2164db6db83a6bba79436\nM = fda6f9d8588e3614f5a68ce867a5619f6ddbb8d64450ff402e1c4f1a08b518f79dca21e5983c207c5b7324c16895a1e9f1282fc6cf60b0645f6b02b652ed5b129e67c939e854ab492dec30ea878c3edde10a4b7d1d14c57100c6cbcc5fc085a0d7308715ed132fb917251919c727487fedb66500d5610b0014a43419acfbb92f\n\nModExp = 86fb0b8dc161c41de2adb0f3ddcc8ad49c1efd729a52793a3ac987d4011c9c1dadb18657dca718df75c8ddcc49d60f152c46ab85ae9076ee7bfd405679a7da3a5195a1bbfd7d2b998c7b135ea91f8c445cbafe1276fa502c2a85477716829a2e0d24ba02623405a3654bed8f355bc7ccdb67c3f9a01e249e358b60d7699498a9\nA = 816610e6018ca47074d55750dd16a281019dbf95dc752605794cbb8ea8d75775317ce685737859728320b529fb3b4414b40bf3a93d08d8994a21ae54682cc1c357eb529837a7b0129a0843eebd9341c9bee3a8ae30475bdbff517e885a0c9f2b6a680643bd981efb53bf9dd49f3dc3cb757e117895fb34b1b4336d9bf8384558\nE = 8622c37631e428402343dccf8ed09d47b3f4201e95058910289a62707c3ce0b7113c390056cc4796cc9893e471b12cb3f63f900f3356ffd25c8b2fed6f6a7fba2c684eb241ca706c76cecbf72473d8a58c02338e40714b5610465cc319f0a529a7aa3898d9e638b247abd1380c6e8f7fa210c9f1a1a2164db6db83a6bba79436\nM = fda6f9d8588e3614f5a68ce867a5619f6ddbb8d64450ff402e1c4f1a08b518f79dca21e5983c207c5b7324c16895a1e9f1282fc6cf60b0645f6b02b652ed5b129e67c939e854ab492dec30ea878c3edde10a4b7d1d14c57100c6cbcc5fc085a0d7308715ed132fb917251919c727487fedb66500d5610b0014a43419acfbb92f\n\nModExp = 1\nA = 9edfce4691f46eadaa2043c7b1092b831ed50f3429f0bca02f985c0b77c686d951be84d772ae4b55f08935bed6e3206c8441574f215736b5c1c1b7595b3b789b55cf56db83741b10144d6767ba2b97b23a5e83504c60e06ab22834b0145655aa0463108317a379cbfc8a93de8a66925a999b8b02bf88dd85fb9898cefe9c95c8\nE = 0\nM = dcb68f6aa530ae9b31d078e2e82670adcc98228e7cf1aa59f81e66426ef14b1591b833d889463564c75b5fd5551ea295a0da581dd80f62c7008ff0f26a1c9f4f756431d48198af157149be8698336b306b0a8b8635d3fc2c4c2194ecc4d2af31ca1892917cc2e621d702eaaeed0d9a0c3dca575451eb8bc5487e313988cae745\n\nModExp = 0\nA = 0\nE = a3be10ef04535fca6784e5dbf3733d677dedd50fabbc3a860496628950b4747a328c2ce0d903cbe1e700f0af30f59fb917202257815097a2b516df5d0a82642faeffdfc3b7883766c78fc4be5901ebef891a9ca27f3bcf00960729e659bb3fddd54a19ce628e95ab86e4c7a168588bc9f67b05dd21a583acd8dc36e615945648\nM = dcb68f6aa530ae9b31d078e2e82670adcc98228e7cf1aa59f81e66426ef14b1591b833d889463564c75b5fd5551ea295a0da581dd80f62c7008ff0f26a1c9f4f756431d48198af157149be8698336b306b0a8b8635d3fc2c4c2194ecc4d2af31ca1892917cc2e621d702eaaeed0d9a0c3dca575451eb8bc5487e313988cae745\n\nModExp = 442866609915aa6f1bae9dfb59e721e1b63f42c0f75fbf0a88344120fbbd7aacf15208fb7c9d8bb8477d553cbd826d7e685ad764a8423e81c2131c040ee83a03cab8d5ce50866a941b48c78e9f1330794d908562d4141cfbf26e8c80c69551339eec41e37e2b37b54330f7bd75748f8d26d56ab9eb3b0c127540484c6445a7fa\nA = 8ff65e2cbcbcd8697cc3ce9a26855d6422ac7eb4e66500648c08be697e005cc3c854a54cfab91d43489cd60be8b516a9b3c9688e5e009a1689c6b164a133859a5464ef422c86344fef42cc477c9df27768377c126a066d1b62f593b7f6d6e906feaee16addb7cfbfc043d741b7dc81a87c17f167b7b8ef1b1fb3dfd1eb14102d\nE = a3be10ef04535fca6784e5dbf3733d677dedd50fabbc3a860496628950b4747a328c2ce0d903cbe1e700f0af30f59fb917202257815097a2b516df5d0a82642faeffdfc3b7883766c78fc4be5901ebef891a9ca27f3bcf00960729e659bb3fddd54a19ce628e95ab86e4c7a168588bc9f67b05dd21a583acd8dc36e615945648\nM = dcb68f6aa530ae9b31d078e2e82670adcc98228e7cf1aa59f81e66426ef14b1591b833d889463564c75b5fd5551ea295a0da581dd80f62c7008ff0f26a1c9f4f756431d48198af157149be8698336b306b0a8b8635d3fc2c4c2194ecc4d2af31ca1892917cc2e621d702eaaeed0d9a0c3dca575451eb8bc5487e313988cae745\n\nModExp = 1\nA = fe9f77f7d0475e00ec964c0effb9b8e079c32e376ce77a9c40ce4018c3df44a77b4f294d9565502b2b79accb30cb58dda6d15e1543b6d4a53296543ed11c7f51baab60283ef03fae37dfeacb431392487ec2839551a933895c4dbf18844f7b375d3e6f558d3c39993cea1bbf7fb743a6a07bd3753c03eb7298811476d7f3ff1d\nE = 0\nM = e7a96cf6fa930f73c8bdc2726bbba246001a9d27f39cc2b978c99dc6f15af0e8aaf26b565302f1112e607e2df4066948baba931b89cd9bbdea2072e05b9a4968fdf282c43d997987c3a3a0434e925a679ac81f316b7a7b724b79be3d6888b66f4512759bf66cfaaa88b9513dd27a44aaea75437268a014c4eb50ba2e50093511\n\nModExp = 0\nA = 0\nE = a0bc148ed50a9b54036bb8fa1f214979052ebd47db8b347af3bb03b806bb457b468ba34781f8a25f289a7a90af4903dc14809a166df2f4c3527de2ea6911cb1afb9071a4afbb522a7d50634d66fd584c73f32d05217dc9f7f16394c68a692a953492ca85f89cc11da95fd8cac6231647923ced48a1b3b0ee68c010286d452836\nM = e7a96cf6fa930f73c8bdc2726bbba246001a9d27f39cc2b978c99dc6f15af0e8aaf26b565302f1112e607e2df4066948baba931b89cd9bbdea2072e05b9a4968fdf282c43d997987c3a3a0434e925a679ac81f316b7a7b724b79be3d6888b66f4512759bf66cfaaa88b9513dd27a44aaea75437268a014c4eb50ba2e50093511\n\nModExp = 91fd879d02f95a9f40fcd1037726f73892caf84e9b43b4aa4126d9062a0d22c464e7af2fbd91aa849612d99d9519b724a7fb1cb018fffdcff321d883ab2519953c9f174f09dd8f13ac87339887385966eb4a94842276637b2c36c0a5036b1d3bbea438bc6efd4b4851c7ec06879d60694df894717569bcd31c4b13d80df6cbca\nA = cdec5edc1cb3ea974342b85aabc0f9385cf877ca328747d40dd4d297623ad69ab6582653faeed5aef225208305135cfbee32e066cb43e18afacea3a32acc8aabbc49617ac33e741651924ae56dd6aa044a12a1ea50fef573b5befb2f4b21b9cf83ab2aaa6fd153580a0761666ade8fb94f202a3c3dc4f33297eabb4564374168\nE = a0bc148ed50a9b54036bb8fa1f214979052ebd47db8b347af3bb03b806bb457b468ba34781f8a25f289a7a90af4903dc14809a166df2f4c3527de2ea6911cb1afb9071a4afbb522a7d50634d66fd584c73f32d05217dc9f7f16394c68a692a953492ca85f89cc11da95fd8cac6231647923ced48a1b3b0ee68c010286d452836\nM = e7a96cf6fa930f73c8bdc2726bbba246001a9d27f39cc2b978c99dc6f15af0e8aaf26b565302f1112e607e2df4066948baba931b89cd9bbdea2072e05b9a4968fdf282c43d997987c3a3a0434e925a679ac81f316b7a7b724b79be3d6888b66f4512759bf66cfaaa88b9513dd27a44aaea75437268a014c4eb50ba2e50093511\n\n# Craft inputs whose Montgomery representation is 1, i.e., shorter than M, in\n# order to test the const time precomputation scattering/gathering.\n\nModExp = 9442d2eca2905ad796383947b14ddfcc341f5be8fec079135c36f6f0d9b8b2212f43e08bf29c46167ff0fe16b247cd365df4417d96cc31c94db1cf44b73b0ee3ebcc4920d9b0d003b68e49c1df91e61bc7758a8a1d2d6192ff4e1590b1a792f8be3a1b83db3ad9667d14398d873faf5d885ec3a2bef955026fae6dbf64daea2b\nA = 3a4b4c57e62c5e9d1a9065191f8268fed9d5f6f424d071acef66f0662b8210f4c029ed991512e40c9c912043c816d2c4c5b53fa0e5c253e16808aad4225130dafbbb89fd4f30cdfc1c2f2179b636a7ddc4be579795820b4b9377637bd8a21a0ef5a90d0e0f865321eee23d9be2a3b7320b4012d02941b892df2c40bdc85c1898\nE = a2c56ea1362511cac0301918e15a9afe7d37edd438a5c3538d258ea01f0a6df758de07111e868b3ad8fc89b629b4955d78a1b3af902be1806410ddde25ccc6a196ba5949395c1ad5d8725b18815dc1cd5ac1c7dd17773f571e3f2e628255af14476e0494be23a4a4dfd18e23142f33d7a59c236fec61660e360d9676a747c69f\nM = ede35a3a7afac817d413373a2032abbc067b1493f709ae6e1282ee5469743391d891b904938857168802b7872d3cd7ac18ab249a9e540a86f970b1d0f310a4cc29df1cc9d4063d98c554f1a32f4ca5eba3523cdfb142e0fc609907c7a92bb0187009d97ec471db3545f42dd5fd29c07b7816085d09477ba31fcf90084660116d\n\nModExp = a7f5844fa9e7202d4b70ee252c9846e63d3d091b0387768ded872cec53458e19df0d9b4960226e269b8ca5dd4c4eda423a67b6dbb48235c08c12c6c7c78db47287756d3ed9cecb9232f7d18d5d80b9676cb68ba4a290c97e220beb1a069976b5e6022a4c1e5ddbeec86b62dda24ffea1deda37695c9f61a8817218e6370c0679\nA = 7d6d0cc947ceb949cdc4e9e1044f5deca5bb05a491041e0d85bc4b92a0944a57c72845fad91e59010c61ad1712bd2f612d53a846a044632262a9f2e3373b062fde2484e0c165ff947f2469f743ab6e2e5e13c640fc4029b1c9213eb8473c674e7f9e95a4a5c5636d4656c1e696962340d77b322daba47d6fc894f2a2cd9e0afc\nE = b78012afe806e2344d004c739c97324256850980ac97d88c4ed9a838517639ca112e235978d21a176c33f5a68703aba0f2a05501bbe3fc8d49a000fbf530cdb431581dfaf8683cb15a2aee5e239cbc542827100da3b47babf4a16ca7c588aff9912e674abb449e0b767a15e415f4e7f2bbd6380d7131da3df8d49b13bfd35ce3\nM = b72d5c55bd2998472f1965e75a51be6155c1ba04656da8f66bcb34db36a7b1db66a89d1d05b1bde10206acf85be7b474ab689220faf1bb52ab39d8dc00512dd4e26df1179c11b973e1274db85a88c7cc2a17113abdffe58cb930ddc5f3ccc4d68b4e65c913730509f7ce5656e8bbaba9b1be177ab9f766678f018fea05da9cdf\n\nModExp = 465ff295786a88496828fdc763e9292d557", + "957544e9322b7996807b87fdbfa7a11614bffeec557ca831c4824c8e4ca3b1a1c7f3f4f95ec3fd6a86b73bb13d78b73af2b3c7e76954d0cc03bcb0cd606867ebb3765a8b3d0108cbe4f343a14016be9c33f6d200f0dc547e7d6b02bfab1e79dcdf9c9835a814cc6c855a12ebeb66d\nA = 89ad02bea3e9ab839a6e23f20122409daba52c68e1e893034b30d321c0305434a6af940015e3fa5ca9c35230da34beeb1ed4fbce6c1da3a8bfe3f3ae172276c1d1723b47ee61e6f8fcfdafad102d6f7ee2a79f510c7edb93096205a40a6c9e665b88b18f39a979e2e61286d939952a6f02fe8148b7515bb25f4252337cb6e60d\nE = cbd6ac628cc7afa3c61bee9c22a06a395087ec1811fe9681b55216700c435996c815e7cec8aaa90016dd2382d0306a5414630124e14f3d396a4ba02ee17851bf720f1607ff813e4bbddf01338983db12f59bd6371a738eee3eeb716f21051d6174d2d6c77602942b9edaac18d4b3a723096c0d00dd23a8a605c585022f311560\nM = fa7a3e40364c8a8d0f14f0213a3f3e035222ca0ea19d46d10ba41580e5dd2805c8a133f3856d7d5d97f922ea540e5eb0d10ad04dfdbb74f518f58da0099a6fc2b3f3def92985176e07fc78aff2faebccca10a429794e5f15ff92f75fe90f527c60ddea8093a9078c703c372ca09f7aeb27ade02f3595308c61dd9c44e62fd101\n\nModExp = cf08bf00261402102e9fe03f3074471dcf0e9b3c96d4d1503f099f24ec85e1901b023e9e048c1ad042244f5f70b38b25a99f4c0a7b57d5844bb0d0137367f45f4ce2cc7746105b77414768cb97648dc5721149aed2d4c682408cc0d50d26dd0bd77e848911f8625c727cac5f32e63bcb548f41a57d718d772f23983a42f603bd\nA = a419646a6631c2c69b18f7aa65011825eb31692eecaee9d74f92d92203811b68e9764bda31a1585bdf69b6273fc6f9f508c395ac081336506525dad88473512f08a205621ac8b16e9864c7a7c5a4f17435de00d0b32badec6ce4897e3e1076c562b6d9523f63d0b2079eaa416cb090471657763f24931d955d1fa2720c80a9c9\nE = d5a6f4a1842aaee39805356dc8d0d678ee03b2c81277345beccb2742f899132feb43271f95968a01ae68aa8277201851992dc0aa7a71c90aae71b124d873ee264ea400fb131be0fc6c4ce8c04c45f6bdaca89ac743635caf6158983d257e21cef6800d7f990e912ba21bbfb8fb779afa4abd19e07e7e07eee9908493d1ca502c\nM = e739689b6cc6def1d45fb1a2ab551643beeb303f4aaa4da47ee5e4948510f8445b4c40e99ae8354dede60b2ba6694e93bc4d573b7e8adf871b7a9a9636eb7d70f2e49328e2d7978143b177cee8374ef01bd1ee2d95862765883f5e7971668b53ef0ff41b6539faf63c397522b0bdce916388e72e26c8d3d2e58dadeb9eb5d479\n\nModExp = 827e6312ec3b14600203bb83f5b277ded197b2967363630ef673240df05edd3ba8ab2b11c86251a612206569c6c33952b31e264f129909bfe723bd0ee1624b36cfcfaa893a6ec8b5a1f7de79f83e79b459a3350f89f412ad1cfd6bc4c2a7a29272c783d6ecceeb1398fa17041835643f4debef9b5e87b098d104bb8912dddf7c\nA = b8e49c637829021d32db3a39a0c1e58cdd4c6e4eda7e8e9293be379e9c2e2d184f929d278598a81ae231cfedcf69cce4a6e31cda3c8ac14d753a7311f2436e29795f0dfb60259a0f61a997918ff984aa2284b43a9d64c974059e9682adfffd018305835f74eda8c75fe4877d811c1620f654ec9f7f32d1af5ce59115e2f41785\nE = 80e0febf369d234bf1aaad4f82df2e2ff02882c3184781f6ccdf4f7cd93b6887af86830077c84dfb02109ada05b40970b1c65228b0c19030bd6361c3537fee22a8155c03b4e7007ca006c6daa3659518d05bb81ea0079456d0ef6116df248dffdb0c935f321f5a1034deefd5a9414a0652aa6548de33325b474b9e5a8507a082\nM = d5eb1d14af842a9973274f7463d90cf0ccff19c47d710edbae184478d4f29b02693ed7958bd487054327b9e6d8879e24c9af7730b92f323eeac05558da6c1b952e5dbf13de236050a77628bb5325fe0d14cc5773bf73338759d5ab43c212b414581280f1cee250007e53791b800b61c90de0328acd7bc43fbdda48158939392d\n\nModExp = 4a1efd29c7e78549f5cd4deed1454b37462c7810ee6a8a2493b764dfa479be13b314cf9ff98259517d61865567ef499a511630c0038c97914625df181c6fe07892f329f98b344a78d751e9471483eebaa7977371bf97bb25187ae7e93a9227d6c124ccb4644423c961a11ae59c4354f89d5a95164c23d9aa256e289e9cc0858e\nA = bd86c9211fa6a47a06e5016c46cb8a99e34a043a29e22f8c3196fa7197c26b38927b8d9bc0ddc11a5fa4bcc44deb69dbf37cbe7ebc9a2fad6c74e09ab5a9dd929fa04ab4319b6caad1035739be78ba631fb0748d9e53944836d37ccda6e6a62823c696d8f31139ccd7f2f86b22fa026ecf433cfb1271a3539ac4f1c83aaac059\nE = c40b9972006d28a84c2769a86e526a2b274f73afc7c5c6a2742166757f61b5f5fdbb228afa157af62af989ffe966f232bba9e6beef5403d1690ade31a6410f7f349a35bc4267a129afd647993df7d45cc0e1a1ba4678d7f1b6e8a344d8ff7037679e1f4db25a454e4246f6b55c416567fcfa188e8a3865115851d9edf0aa8902\nM = cf424d7af75ce7eef90cad75ae55ca8810cc7b4703fdb5bce701e7bac07e0c371cae06df2aa8facb55a0faa6793e4d2bd9d7969703743b9be170be82792aeea55e2bc0f7ab7617b276486bf474dee2f4556aab595ff3ef115139cfe5e21ccd4ee05c0e1cf901bd85df86cc17195a783b0be836d00bee82ce064077f9191188f9\n\nModExp = 3137a3049fd4ad2e26d870f5c998cf11bfe82101884a82e85e43facd0928cd7434a2e346ca124619769fa141bbe92ad6f36b99231032ddaec3b349a410f82b5ca36f45e56e5fb85dc63d32053dc90805d3f1854ab385281a71a57726bf97158494e7476057214ca7379ab8b70f5bdc15f70bdad3adf33c3a1f9cd1b6bbbad556\nA = 39a1dc6a4c3f14d9c350ee968d5ce139ef725952c967a2d1bedf48ace22091283525be03807e2e263d2640be77f0525247bcd07149bba50568cec5a082c87d72962cf9e43bcb5cdb1e7e9a650fb53e0ec2fad37f09a9f036c0d7dfa528fef846769f80a9a60854910ca1b4ee05dba82ed2ee018348d6b3e52a764b8ffae61e0\nE = deaee3a3f80c9f684ed7110c0653847ccc7be5ff6d982fd4b49f59b5dd35f7210b1077babbcedbc127df35cd469dc6e569a0f84e58149b5605c94b09fd7f0b098d02b4a04631328b3fae39e6c2fce25334225cab71829abdb9507cb903701559660f2c08c3b743336119d1260a0db27054cad3f28bc1b04b2289baa58fb33965\nM = 938388927d06ed3bb1286c0f06d3054cb0ee16dc7a0bbbf13a45293c09a5f40f1d611b2e1a1b0ec2ef109b508e27af4274954905cae52034f8740a744153b4d22059f0dd262ea51785522098ecacced6da07709ee6b5acc8c4e99331379a7c3de7f4e2d1431e43b19570140955b7bcba118dfbaa552cbfa2be531e8f781166ed\n\nModExp = c15ae334455d9f4d1030cd33e734726a27c63624c2afc576238cce5e0498298a4a0c93090a0d19568b41290303c4b558f3d9dd74f9cde8798710f68569ea0d6fd971ce67ec5b54495031de3d8842b8b49288725bee5c9f72b99054d64986ccd4e18d70d5f33943f08cd694eff538f84438ea993ebaba0910c95b3a694f213510\nA = def633b955a917569df3ba8517455eef0655e7a35985edda27097a063e0d82c7c3a76dc36c5d8a71ba9d540790ddd0ea514aaed98925f9a1808eb288d387aaf9605a9ef8a333ebee7ad7057bca012efd619d5867f02266f65976ef4b16da17468426ac4f99b3e8921707e01b4de20f6f9a068e6a19d872079a27f3a44449db83\nE = a465c47b0d15d48e01bb8b1d8e3b3253e11515f6874dbed6c25818adf1a8fd927124d5593beb367f685c11e46f18415be73ccdf16fa2e93a600b728163d21d232849e5278c3749d903edad3f1c4535a2f55a2ab65e7ebc64888bd2a0527e876ecf38cec3ab1980d08138709fad8eb88ae65d960adc3f0f8e92f784fe96fcb693\nM = e43cb9ac1446154356cdc31ec771c79b0e461e22d95185bbe1a279c0945e3af07903a0cb54d553380716fcdcafb4b7cf5dc6da481dc74a8c583d75ff6c1f8e429182d200246ebc473bb56e173787987c1b7fb2dd23f5b2e438a97bc4a1df628bc044fdd1e80c0cf37030adb7b04784dab827d0dcd64f0dbf37c980612570ce11\n\nModExp = 75c3f79ab7c991b98e65505342a8a563cfb08b5d3ccf8664c7db1de50256b1d17ebf7096dc98c7bb5d7f027a894ae5cbb14dee04d5d445e775ad7e239acc82673b0ac2d819a69c83864f34e73d9a636f05de8279619a067b4c90ad038db5910447e03841d2034635018f08cbcd21efa00994247763a249082594128112f95232\nA = 34def7d76f6f158a359fd12759fb889cdf6af0a24830dc3e84283a1ab4e9b2647a6a36b86482f829b2cdf3e3d6028f9a884b1f64f7262315446bea8b0231828e2f3d990fb103c17f820b39e4b8427c85643ceeca8f5dc8f191d1255768300e859bd7d88c770319ef38269660d221cb3bc061389b6fc0783485ef042b1c7d6fef\nE = c6c46453dd5aac6b37277a446b1d0c69cbe476eeff55b3ac35edb89ba97116b0e7783660f2c7b31b2a2d6c4709d0ab45d01a838100694b0777c9c9c14c959b07c437c73a5eabb7402f1001e802d797a2e7707285834fb6440a1c2f727f7bb84ddb2a49312d32fa0ce620c43872655cb5c394749c9e75d7fa25be00efe50d47d6\nM = fbbab6698a9142095c46b38a732592e4366c1838b84bf40f8c8fc7b630f73380a0d09765562365798f8c8030ed1b6728329d8bb06e882c35a1d59bfe84146a9db2afe42a414014e247390281c782fce806d62adb54778d2bcb49555459429d6ed446af5359657667f6aa19e8e3e0e24ab2bc312b2d90b5cb1ce6f2f15af15d9d\n\nModExp = ba16d7f3f6e162ce248490d164a13c00e7720d8a667e2d3ebeb13f1663e15ef5408d5b56cbc7bc793a8ca787cc50f8e15e0e9d4ee764531d04a9114eea556bb3e206ed7d85267151a056b6e68fbf35e03f2cf829708ffe1de13e95ecfe365aff1eea36340ffcd3892dee659fb1ecbe50f5080e54737c10f9c1ba638b14ef537e\nA = 9025e6183706105e948b1b0edf922f9011b9e11887d70adb00b26f272b9e76a38f3099084d9cccf12d04b1a99c0f654f8b9ed90c6dff9478c60bf05d58d734ab60eaefa14a22230ec60c90dc1f0704b61eef0bef345785ae0e6a9af7db069cf6bd2b4e0fe58a0ade83c7e46a04b9fe1d24cb9b65c6f80de713e61d70eae5b286\nE = d7e6df5d755284929b986cd9b61c9c2c8843f24c711fbdbae1a468edcae159400943725570726cdc92b3ea94f9f206729516fdda83e31d815b0c7720e7598a91d992273e3bd8ac413b441d8f1dfe5aa7c3bf3ef573adc38292676217467731e6cf440a59611b8110af88d3e62f60209b513b01fbb69a097458ad02096b5e38f0\nM = e4e784aa1fa88625a43ba0185a153a929663920be7fe674a4d33c943d3b898cff051482e7050a070cede53be5e89f31", + "515772c7aea637576f99f82708f89d9e244f6ad3a24a02cbe5c0ff7bcf2dad5491f53db7c3f2698a7c41b44f086652f17bb05fe4c5c0a92433c34086b49d7e1825b28bab6c5a9bd0bc95b53d659afa0d7\n\n\n# RSAZ 512-bit.\n#\n# These are regression tests for code which historically reached the RSAZ-512\n# code. That has since been removed, but the test vectors remain. Note that the\n# lengths of the inputs, especially the *bit* length of |M|, matter a lot.\n\n# Control: No relationship between A and M except that A < M and they're the same number of limbs.\nModExp = 7f34c1cd63377bc3abf2bb5b2d1bf5f06454e1e8040fe19a72245ce9731cbee1bf9e84532300776c8021ed4f3a8de508d85b4cf320bd82065a013754857b50c4\nA = 8e4e67da6ff890643d0599387955996ef6f0c2045eb9944576ddb965ca64cdb6247727ce128ef178d4a84e5a56d2e67eb0fe389ecbf691f9244ae80f4c11b364\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n# Same as above except A is negative.\nModExp = 71fa6a4c8ae75368eda8cc6282c26afa69e2af12a97fb9444f16b7dd6c99e0a5d6034cab4248cae4357346b211039f4a2bc4c5a20a297372094162417af703cd\nA = -8e4e67da6ff890643d0599387955996ef6f0c2045eb9944576ddb965ca64cdb6247727ce128ef178d4a84e5a56d2e67eb0fe389ecbf691f9244ae80f4c11b364\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n# A == M - 1 == -1 (mod M) and the exponent is odd so A ^ E (mod M) == A.\nModExp = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490\nA = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n# Same inputs as above except A is negative. Note that A mod M with a \"correct top\" isn't the right length for RSAZ.\nModExp = 1\nA = -f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n# A == M, so A == 0 (mod M) so A ^ E (mod M) == 0. Note that A mod M with a \"correct top\" isn't the right length for RSAZ.\nModExp = 0\nA = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n# A is negative, and A (mod M) is the right length for RSAZ.\nModExp = 8d76eb0f8c7bc3160cc8bb0e0c3590fbed26c5932f5f525b48045c0bd46dda287ba5483f97c851fb7c12c2e858ee7a4a4d1af745cbfb3eb311fa54bea12cde25\nA = -80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\nE = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1\nM = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491\n\n\n# RSAZ 1024-bit.\n# Note that the lengths of the inputs, especially the *bit* length of |M|, matter a lot.\n\n# Control: No relationship between A and M except that A < M and they're the same number of limbs.\nModExp = 8984f8c16044f9c0ad7bd72347af90f58e6e003acda92b76e3c7c4a56ea8e918409d8e9b34884d4c89d0b17cb40fe898f2627c084a0f1698e46beccbf6f48eecc281e11ea9e5135adba460ddae157f2c655b5f589ce29b254d43a960a71cede8a08dbb86be4dac22458da232fb1ec2470856827302ed772c9ddafa408c931aa7\nA = 21158da5fe20356825e72b3f5384ec57720d22f727b27ce2f945c8ee311db781add73bf8fae96b775c909bd22fca75c44c2b0584284a5bb1c07f8eefcd6b0a44047a02b185df34f897f11d4fb9a86c9eb841b4cb8d0383441fdc5af3ef385b5e8380f605d73ed41bb42eb2c2a5704d6034b3ad058dafffce83dbbfb6295daaf8\nE = ecdebd112b3b5788669449dcddbd479a203ee9ab72a9bb9c406b97623513bf0ab9a22f1f23634d269e16bfd6d3b64202b71fc355057411967b6ac70f8d9cef0a4e06819a9a18cc06bbe438243fa9759303d98be8a65dc1cb13595ee9b99f138554425d50f6fbc025d8ffa3eaea828d6f3b82a3584146bafde34da257995f0575\nM = ff3a3e023db3bba929ca4ededbace13d0d1264387b5ef62734e177eaf47a78af56b58aacc8ac5d46f5b066bafb95d93d4442bb948653613eec76837b4ffb7991cb080b6c8b403fb09bc817d026e283ee47ab2fc9af274b12f626eda2fe02004a8e27b9ed7d3b614e8955c7e7c2c0700edd079455237c4475fbd41857e206e4b7\n\n# Same as above except A is negative.\nModExp = 75b54540dd6ec1e87c4e77bb93fd50477ea463fdadb5cab05119b34585d18f971617fc1194240ffa6bdfb53e4785f0a451e03f8c3c444aa6080a96af5906eaa508862a4de15b2c55c023b6f278cd04c1e24fd0711244afeda8e3444256e51261ed99fe66beedb52c43c825b4c7a1adc7d4b111e2208ecd495df91e175573ca10\nA = -21158da5fe20356825e72b3f5384ec57720d22f727b27ce2f945c8ee311db781add73bf8fae96b775c909bd22fca75c44c2b0584284a5bb1c07f8eefcd6b0a44047a02b185df34f897f11d4fb9a86c9eb841b4cb8d0383441fdc5af3ef385b5e8380f605d73ed41bb42eb2c2a5704d6034b3ad058dafffce83dbbfb6295daaf8\nE = ecdebd112b3b5788669449dcddbd479a203ee9ab72a9bb9c406b97623513bf0ab9a22f1f23634d269e16bfd6d3b64202b71fc355057411967b6ac70f8d9cef0a4e06819a9a18cc06bbe438243fa9759303d98be8a65dc1cb13595ee9b99f138554425d50f6fbc025d8ffa3eaea828d6f3b82a3584146bafde34da257995f0575\nM = ff3a3e023db3bba929ca4ededbace13d0d1264387b5ef62734e177eaf47a78af56b58aacc8ac5d46f5b066bafb95d93d4442bb948653613eec76837b4ffb7991cb080b6c8b403fb09bc817d026e283ee47ab2fc9af274b12f626eda2fe02004a8e27b9ed7d3b614e8955c7e7c2c0700edd079455237c4475fbd41857e206e4b7\n\n# A == M - 1 == -1 (mod M) and the exponent is odd so A ^ E (mod M) == A.\nModExp = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964\nA = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964\nE = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103\nM = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965\n\n# Same inputs as above except A is negative. Note that A mod M with a \"correct top\" isn't the right length for RSAZ.\nModExp = 1\nA = -b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964\nE = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103\nM = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c1", + "6f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965\n\n# A == M, so A == 0 (mod M) so A ^ E (mod M) == 0. Note that A mod M with a \"correct top\" isn't the right length for RSAZ.\nModExp = 0\nA = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965\nE = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103\nM = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965\n\n# A is negative, and A (mod M) is the right length for RSAZ.\nModExp = 9cf810b9e89d5cbc4b79ae64e123ea06d92965e2bab077df97a1b906dc2e1ddcf96a9c4ed14e2cd96309b829ea9cc2a74a7d4b43c5f34d792a7c583201427754b8f78b783608070a84b61f18913e3ced7f7f530972de7764667c54e29d756eea38a93cd1703c676a4587231b0ebfeadddf908e2877a7a84b5bfc370ecf0d158d\nA = -8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\nE = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103\nM = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965\n\n\n# Exp tests.\n#\n# These test vectors satisfy A ^ E = Exp.\n\nExp = aa6d7ac431\nA = d0e07\nE = 2\n\nExp = 12d416b110dbb4e467ff0c89a22122f4da8240\nA = 1a18cf6\nE = 6\n\nExp = 49a3b33e23d84f1ce0d5d83f5dcb651d50cf3920f0143da2310d0512a90a06cd8f38977df8a756c30883de38df092000\nA = 2a3acbd2\nE = d\n\nExp = 5b4a0d5a956f885f275712b194459980f24708bfb6393d71bd37dce852ce455724f5ee5030775fb86b4295edc98afaafc097e4d82a97c0078ec0eac763db16549c5145c4cf2d3124f88cf9a5c71da0625afb99b26801786fe49a778415dc025954021753d08691947a208b613f0be5c1\nA = 54b3ae461\nE = 1a\n\nExp = a0ea5f6a4de49beb8fb7f0dab280d6a32c5a3814c9a5153a7944cec0a9028497846a8a89044348721a0bb5f0c3ded3e980574ea321b0cdb0ead4f4e93841ea7478a7f15d9729b646a8165813a0750e8124f5465dda9b105e1bbeff18fd09c09a2e26610d9176d253b877c3a8908a6be521cbe1e472a7a1b7820e4e890f8f28aacd34609c686e76e15b01bd9324a71290812724ea564d11c874a6765b262c3e57d479da0287a76026a1e8fe53da0b02405da1d379eaa30fc65f\nA = fccec0f6df\nE = 25\n\n\n# ModSqrt tests.\n#\n# These test vectors satisfy ModSqrt * ModSqrt = A (mod P) with P a prime.\n# ModSqrt is in [0, (P-1)/2].\n\nModSqrt = 1\nA = 1\nP = 2\n\nModSqrt = 1\nA = 1\nP = 2\n\nModSqrt = 1\nA = 1\nP = 2\n\nModSqrt = 1\nA = -1\nP = 2\n\nModSqrt = 1\nA = -1\nP = 2\n\nModSqrt = 0\nA = 0\nP = 3\n\nModSqrt = 0\nA = -3\nP = 3\n\nModSqrt = 0\nA = -3\nP = 3\n\nModSqrt = 0\nA = 0\nP = 3\n\nModSqrt = 0\nA = 0\nP = 3\n\nModSqrt = 0\nA = 0\nP = 5\n\nModSqrt = 1\nA = -4\nP = 5\n\nModSqrt = 0\nA = -5\nP = 5\n\nModSqrt = 2\nA = 4\nP = 5\n\nModSqrt = 0\nA = -5\nP = 5\n\nModSqrt = 3\nA = -5\nP = 7\n\nModSqrt = 0\nA = 0\nP = 7\n\nModSqrt = 0\nA = 0\nP = 7\n\nModSqrt = 2\nA = 4\nP = 7\n\nModSqrt = 3\nA = -5\nP = 7\n\nModSqrt = 4\nA = 10\nP = b\n\nModSqrt = 0\nA = 0\nP = b\n\nModSqrt = 3\nA = -2\nP = b\n\nModSqrt = 3\nA = -2\nP = b\n\nModSqrt = 2\nA = 4\nP = b\n\nModSqrt = 2\nA = 1e\nP = d\n\nModSqrt = 2\nA = 1e\nP = d\n\nModSqrt = 0\nA = -d\nP = d\n\nModSqrt = 0\nA = -d\nP = d\n\nModSqrt = 3\nA = 9\nP = d\n\nModSqrt = 8\nA = d\nP = 11\n\nModSqrt = 6\nA = df\nP = 11\n\nModSqrt = 4\nA = 10\nP = 11\n\nModSqrt = 5\nA = 90\nP = 11\n\nModSqrt = 3\nA = 80\nP = 11\n\nModSqrt = 9\nA = -e\nP = 13\n\nModSqrt = 7\nA = 7d\nP = 13\n\nModSqrt = 6\nA = 37\nP = 13\n\nModSqrt = 1\nA = 1\nP = 13\n\nModSqrt = 8\nA = 1a\nP = 13\n\nModSqrt = 54d4cf0fafe265056a29016778cea6b712bc66a132fb5e6b6865e9b49e4c97ec\nA = 599c10484b22d0b5a115268c7538ca99b3253a311a4ab1ca11c3665b0bec393a1167d1ad94fb84cb2c7ad7e2c933e8f613bdd08fe1f1aa4a9b0b9de0c8a7c9d4\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 38a7365a15365e911286c1be2a7afe76ef390234d76269e04dee17313f6ea54d\nA = 1c4aabb4d8369710131c664ecf2849e963c1bc31d66e0b939bacf99a870c71f24ed71bdddcf566f3908271fee43fc1ebb51eac7e3153efae641b49d2e796a12a\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 35ab18a560dece04725667f640ca61d1d59f14d191f94c79f58531acd097d444\nA = 685168ae855d60eba220d803f5296459b30a289580668db9ed51bca51cc2d453a937e13819ae34f7a9a143ac96d17420c53919167e46279b562b550be1cd9abc\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 288370029e87024175e5bec0eab0929179f42e16995e7f6194eefc61061e54f4\nA = 2a14ab77c045bdc48220ba9c463e1a4b4049cb01edb53be0937767eb2ec19b7d719855052281250a36a0b76d9a5d967d0756e1ded7a052f7056191ad66bcfc9\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 32255cf01dc943577ec2bcb221b98491d7a1130d046d6c68e95fedff643ce3a4\nA = e26f6dd46a513a1dd3fb14b71be1d4c9e9d79eda1cde10ea4d1eb8abfd4d5857572205e247184dd0cbefa37b5c0bf680ba2bd28c5741f725cfe2aae37419baf\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 5172345e801ada63fbc4782e32583cc3b4fea88b9e6dfd542f3542f8538ade66\nA = 40dafa8342b302bb04b1f3ddb3b9015a8fc1b597857c115b40631c7be9e22de89358fca23b331596ee5ff304dad7811e6d8e8822f7aa533c9e7c882634ea550\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 4dcf63c423bf0e39aca2293d57f6792d023db649d6719fe936446904b9f7e60d\nA = 5bcdb514bbe84261e169203e8017909b60c9bb330400c766ee01b0189378e70e61867a164a12643ddc9e94b61e09e5b158cbe85be228a3cc48f95a552958b8f2\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = cf77c5c2d12a500b75cbfb1f3e66ee75d886b9365cf4f8b4d1bd18a6be0f387\nA = 4652ddc2ea7b460d8ec3c9059b8f9b5dae6cac55b51f2ad86fcb336b25235737965cc515e2ff0b54835015b7ebeeda6fadd986471d8cb424d309fc353d1e269\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 1e0549e4c5a26023e9d24fd8c67419960746f82b1ecd113bdac66f570a475d87\nA = 5f4a6d450ab1390d96ab1deaa0ba18f897cb63daf0c9e1ef6c08e804c26b5e842f6c08f13db5d4a6e88f07af2a3cb04fa06fc3e59c410b9356f025ed81acc74\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 144481a781d831c1ca046ca9e322d79ad4d2c6dd9f780bea9d1ced9cd20b7b23\nA = 4c254fabca441017132b9eacd4ca40a336db3e5c09715773fa07af095989a91cc968ff07a9ff56ed06b0ce0c5269f7b2ab68564ecab9f4467a7e96b6cc6b21b7\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 216fecc7667f488a3d2d102a38b46b4860ab858300b8638af4f34e1103fd73ba\nA = 17878f8048227573a9d70f53c0e76ff13fe9f56e9c984c92514d3d13dec23c816661f0618d21371b80dfd885cb59551bdf80046f65f22ea9b89c78645a6e455a\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 458e5e789ccd2417174f7e30bb31914b9656bd8cf2b9f5a9752a8737a67707bc\nA = 5c7d39a4bb04e69201aa519f80ee7e62ea14ca55e13656d1da3f45367e2fb2d061aa2940708d02ac67d35cd2ccf54a1bf95bcbc759779e692cfdcbb3aa1a05b\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 543125a16c2bb8b8f8a2c39c497e5224ec77533602d7dbe24002e32dcbd2ef1a\nA = 3413afae333b2ad9ff45c7f3c7e5934b3127e8b1a55225958ee6ccf42423e81559bf070ad3f3353b78c0ffd41475af49f59d268ef78bdae879f5155e8d1cc07\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 10e16859c67bdb2eaab52a7c847dbf37162eda258a9f6262ebacfe4cbbbc1080\nA = 21ce7905894faf220bdf4a82a2d855994ca2dc9feaecaa53c7f146e1f49934215695e9bb46ba370b7005a90c399674caa8969eb442e7914d90f749774d7fd194\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 32a00586adc6f6cc2b1a04e1be0ab569fde235e1436c38b6af92bc5ebd60bc1c\n", + "A = 350da4fd8cf03c12f7dd6ac6d3ab801a3413964083e374662aaf878d6838b97d4feb9e52cd307a25b113e101661a865463ee2480c626aa4e2ec437d72e7bae4c\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 971f75bc7afa8b4b50f1d4b05e52deac7d4836a08d30546f29649bf1ca6a247\nA = 655ed4c5d8d0afb4f9360372ee1ef1303898d2423e585108a3303faedb55064d2ef25666ed4c4d71fe6063fea1f3142b435714b0e30b339dd791d347c884654\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 48fa882b7cb6a29de9e3769f72eb67f1efd4d2af56f0c7e410c610efcbce2065\nA = 14f3503f33b243800eac1defaab33e04c01e80163fb3efd03860970cc016832431ca4fc6d1b760f4f40166b0b8b3c40dbebc81460cc10890172243770338f090\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 236fd7e397ea7f8bc2a288eb7236ca41936fa702b7dccca56c8852e147511f7d\nA = 1bbd0980feac854782813bcde4da85e8a054549a1b515e065da4236528035e756882e29e762cf60453e375cca9dc6ff637f9558bf86646e3b928f68f82af7efe\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 693f0cbe8c81b0afde0cd2f83e53795dcae6b0cc4ba930ab5c752400d787f14\nA = 7b20f9664b23907e152ab8c9a907f72e8670c1c38ab4cd1411ea7c2159c09aa131afe068929b8e6ad1409b74c04975180d1cd0a9fa74e923c3fd451e8da2c34\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 4a086c50b0bad576501ddb6280743b2c9d247841eb7f14d90561432ff7dca6f0\nA = 4367431ec0cd0d7626538b93a090c30fe0c97c18ca03b97ddae304b619112b5b4d02bf0f041fa3fd673f9ef2ceb07eb2079d11c56dd903b1a87e8252a97b8079\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 18f8433fa468d8065157708f1f1e53b8e31d39c6011fbc2bad93de1b5548e19c\nA = 739c032bb4139c199c40f548d37234298772e4ccb9d3ba28412b60ad23b4c465b0787e2382f1c5a4a87af2d20eb978b7dcbe73f2112249477d15c8a85e54a79\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 49e3c8eef5e067cabd51a7c01384ce05ab8f4342f655559d8a689eb7b20e0106\nA = 18400c2cc3e06b99b4e39c77b9af5ff0e9c683f1708321afa4cd5b6988d13b36b1d9eb4379b7902d9ceb40c03f814b2b6a01b90509bbb4532f13ab1571c4d04a\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 35548c530745f440329325cc8a5fbd90c16a7f0788879a4869bc4d4f73acda0e\nA = 181a3c5ab02566e7166c4d6d2f2bd4a8ecc25991a98d270bde80cf4332766a7068b14240bf5f5dcd45e90ef252596da3eb05b11d68b2063f7b3a825742593ca9\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 1ab7046e6af061ade5f9719008fa4d989007e2a579a134a5b9f19ec410984096\nA = 1008a03e211fab0d45856377079bc96b0776c2d4c0175661f3493246cea2ab0a02a706c85314fb707ad9906bedb2cfd577d62092ae08ff21d7b949373ea954c7\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 2be9e3e7515960d90f115b89f60dedc173a73ce163b4036e85b7b6a76fd90852\nA = 392053a9f0100540a8e1a0c353e922068a84dad3a4a8e8962fbc0bee2b6a06e20d08ade16eb1409a16acfcac3db5c43c421505e07035ca308b15c4a6db0864c0\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 5b301bb93bdcf050183107e36258b53b4805918114ea1c2227b0911d5b4dc077\nA = 55e55e5f94dc3d7aabc921f6469d85fa2e1e92a87347c57afad5872306ae69f9fb99297d1e3e793dd9e8632244208154de5da7114fd876383bf1422f7ece024\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = 2df9609e2f5a5156c3260461b2ee52eacdef00bd8b091479813143a6c5283f71\nA = 2099325b7f12fe77353ddf3f2b2c5ef77b49671b150af954cf84e9675e3ecde3e057084641a633d19533b4712ab49924c8b5c31d591abcc88291f51253fa2a7\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = dfab751710e9008e25e422d1199d6fbec4dc7fba35b4da9d225a746eb4126a0\nA = c006af53d4737fb293584df6ffe2e4cb3fd8dc77fb7c1f13b97bb9c249e3ee5fb9feff7488265b3093906c08a4946f142ac7b491937d24bfba6413366ce371d\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = 26bc030008d6c60a09fb0e16093a649fcb40c6c21a8e2da2353ba4b07c4f85d5\nA = 1eaabcfad2ed349ac9356e6f4da0b301266ddde811cb0f817aba8f5c10fb8b8ba9d0ef2dd386b668f16eac296118fdb8cb7afe1b865648c81c2fa3cf21f2711b\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = 35051b1482ec2578f3dc0000a422cb5111e43c37f1ac20b1844d3de2128c4556\nA = 315ff9de178681116f2a5fa78eebf4818e1d680435eacdfaf9d0e5c4fc01fc034b352c82fd52c81ca30d68864952dacc99d08269c9dd7ca99ccf22da98c3840\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = a5474252885cacf004c460a7793ff0b0a2187bb1a9ed700ae3470199faef71f\nA = 19856fc1351c4b02abf573bb2fc6ff92355fa369d62bb8f2260fa772fb1693f509a56cad661930abcac049dd70f4b16bed4a4c172e73e772504c9990ce7f92f\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 12daf4722387ecf47de1b0b6b110a062dc5ea2685bc9dbde66b8d15622985029\nA = fb8479787069116abc42abfd7dc0c24d2ad04fe0c04b42a6dff714af715d17e0fd77855f950f264542b06d48e8818de813ddb7975798b7debefcdaa5ff86beb\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 397996ed5c0ac6ad32e43c337e9de421b87774cc162bf7ac7bbedf4a9029255e\nA = 5aa04353321bd2de92481be740357f979da464b53aa39111fdbb734cf7af6b3857d1baa08d3a126a3dd34a2fbae2bf2b84e900686c1d31505b390185acef5fe5\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 2cf4b844a54ba359dc592ef1b49f43fcfeae84d1087edfefdd0b9174b43c0a3c\nA = 365a8650510bcfd8fa87432f167cf487234c215857403b9270b5eebeafa48cd6da47fd60dc311b94d1d72baad0447c31f0b212d755f46c256e16e5e015e6546e\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 9277c73043ff767c3fa606f0cd66b9d854a600c8c18287f191ce277758c3f31\nA = 62cec3901626d03e8df66299a87c54b1f7a55cafc99f0b6bba1b5d51a3d2b7d2171c9135a9d8a5346d436e0136b12e515e703e3cd84ecfe154eb94c6772a6d72\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 4189e5a90c1b1abdc1c7c05b3587e6f362e06f927b6cf5f0d271aab3d6f90765\nA = 336b8d0f9dac842c696bc020f49c6aa023842c16f2052eb02f17959006554ca0012042c80c72590f21c6bf5a3714c9cb552aa69730e33db93a56a909b273f39\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = 36ccd38cb5a6bd8a73bca55936a2227c503664422c2296faf7e2b1c6a375a43a\nA = fecfd60a376befbe48d2c4f6d070d716d2f403cd5daefbce62b720df44deb605162c8f20f49fd7ec30d4f8e70d803d45b3a44b5d912baa3410d991165d7c507\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = 198fc8569be172dc9b71023ed3d42d2ba94bae4099643f6517ab03f540527fdb\nA = 65bebdb00a96fc814ec44b81f98b59fba3c30203928fa5214c51e0a97091645280c947b005847f239758482b9bfc45b066fde340d1fe32fc9c1bf02e1b2d0ec\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = 21b7f74c30ded681d6138cf8e6fd798f32a049e94138e982f1845df3dc9e686f\nA = 9a30b791c1ba4f394b4e3dcd5837e474237f4fe8987b255c098a47b2c14c598ec69d2beae444dd4fe9c4ede8173d2b187677cc706a3c28f3b81627d8a5fb6fd\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = a1d52989f12f204d3d2167d9b1e6c8a6174c0c786a979a5952383b7b8bd186\nA = 2eee37cf06228a387788188e650bc6d8a2ff402931443f69156a29155eca07dcb45f3aac238d92943c0c25c896098716baa433f25bd696a142f5a69d5d937e81\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\n\n# NotModSquare tests.\n#\n# These test vectors are such that NotModSquare is not a square modulo P.\n\nNotModSquare = 03\nP = 07\n\nNotModSquare = 05\nP = 07\n\nNotModSquare = 06\nP = 07\n\nNotModSquare = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951e\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\n\n# ModInv tests.\n#\n# These test vectors satisfy ModInv * A = 1 (mod M) and 0 <= ModInv < M.\n\nModInv = 00\nA = 00\nM = 01\n\nModInv = 00\nA = 01\nM = 01\n\nModInv = 00\nA = 02\nM = 01\n\nModInv = 00\nA = 03\nM = 01\n", }; -static const size_t kLen35 = 834773; +static const size_t kLen35 = 835053; static const char *kData36[] = { "# Negation tests.\n#\n# The following tests satisfy A = -B (mod P).\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000000000000\nB = 0000000000000000000000000000000000000000000000000000000000000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000000000001\nB = ffffffff00000001000000000000000000000000fffffffffffffffffffffffe\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000000000003\nB = ffffffff00000001000000000000000000000000fffffffffffffffffffffffc\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000000000007\nB = ffffffff00000001000000000000000000000000fffffffffffffffffffffff8\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000000000000f\nB = ffffffff00000001000000000000000000000000fffffffffffffffffffffff0\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000000000001f\nB = ffffffff00000001000000000000000000000000ffffffffffffffffffffffe0\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000000000003f\nB = ffffffff00000001000000000000000000000000ffffffffffffffffffffffc0\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000000000007f\nB = ffffffff00000001000000000000000000000000ffffffffffffffffffffff80\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000000000000ff\nB = ffffffff00000001000000000000000000000000ffffffffffffffffffffff00\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000000000001ff\nB = ffffffff00000001000000000000000000000000fffffffffffffffffffffe00\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000000000003ff\nB = ffffffff00000001000000000000000000000000fffffffffffffffffffffc00\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000000000007ff\nB = ffffffff00000001000000000000000000000000fffffffffffffffffffff800\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000000000fff\nB = ffffffff00000001000000000000000000000000fffffffffffffffffffff000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000000001fff\nB = ffffffff00000001000000000000000000000000ffffffffffffffffffffe000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000000003fff\nB = ffffffff00000001000000000000000000000000ffffffffffffffffffffc000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000000007fff\nB = ffffffff00000001000000000000000000000000ffffffffffffffffffff8000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000000000ffff\nB = ffffffff00000001000000000000000000000000ffffffffffffffffffff0000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000000001ffff\nB = ffffffff00000001000000000000000000000000fffffffffffffffffffe0000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000000003ffff\nB = ffffffff00000001000000000000000000000000fffffffffffffffffffc0000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000000007ffff\nB = ffffffff00000001000000000000000000000000fffffffffffffffffff80000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000000000fffff\nB = ffffffff00000001000000000000000000000000fffffffffffffffffff00000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000000001fffff\nB = ffffffff00000001000000000000000000000000ffffffffffffffffffe00000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000000003fffff\nB = ffffffff00000001000000000000000000000000ffffffffffffffffffc00000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000000007fffff\nB = ffffffff00000001000000000000000000000000ffffffffffffffffff800000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000000ffffff\nB = ffffffff00000001000000000000000000000000ffffffffffffffffff000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000001ffffff\nB = ffffffff00000001000000000000000000000000fffffffffffffffffe000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000003ffffff\nB = ffffffff00000001000000000000000000000000fffffffffffffffffc000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000007ffffff\nB = ffffffff00000001000000000000000000000000fffffffffffffffff8000000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000000fffffff\nB = ffffffff00000001000000000000000000000000fffffffffffffffff0000000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000001fffffff\nB = ffffffff00000001000000000000000000000000ffffffffffffffffe0000000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000003fffffff\nB = ffffffff00000001000000000000000000000000ffffffffffffffffc0000000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000007fffffff\nB = ffffffff00000001000000000000000000000000ffffffffffffffff80000000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000000ffffffff\nB = ffffffff00000001000000000000000000000000ffffffffffffffff00000000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000001ffffffff\nB = ffffffff00000001000000000000000000000000fffffffffffffffe00000000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000003ffffffff\nB = ffffffff00000001000000000000000000000000fffffffffffffffc00000000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000007ffffffff\nB = ffffffff00000001000000000000000000000000fffffffffffffff800000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000000fffffffff\nB = ffffffff00000001000000000000000000000000fffffffffffffff000000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000001fffffffff\nB = ffffffff00000001000000000000000000000000ffffffffffffffe000000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000003fffffffff\nB = ffffffff00000001000000000000000000000000ffffffffffffffc000000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000007fffffffff\nB = ffffffff00000001000000000000000000000000ffffffffffffff8000000000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000000ffffffffff\nB = ffffffff00000001000000000000000000000000ffffffffffffff0000000000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000001ffffffffff\nB = ffffffff00000001000000000000000000000000fffffffffffffe0000000000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000003ffffffffff\nB = ffffffff00000001000000000000000000000000fffffffffffffc0000000000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000007ffffffffff\nB = ffffffff00000001000000000000000000000000fffffffffffff80000000000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000000fffffffffff\nB = ffffffff00000001000000000000000000000000fffffffffffff00000000000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000001fffffffffff\nB = ffffffff00000001000000000000000000000000ffffffffffffe00000000000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000003fffffffffff\nB = ffffffff00000001000000000000000000000000ffffffffffffc00000000000\n\nTest = Negate\nA = 00000000000000000000000000000000000000000000000000007fffffffffff\nB = ffffffff00000001000000000000000000000000ffffffffffff800000000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000000ffffffffffff\nB = ffffffff00000001000000000000000000000000ffffffffffff000000000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000001ffffffffffff\nB = ffffffff00000001000000000000000000000000fffffffffffe000000000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000003ffffffffffff\nB = ffffffff00000001000000000000000000000000fffffffffffc000000000000\n\nTest = Negate\nA = 0000000000000000000000000000000000000000000000000007ffffffffffff\nB = ffffffff00000001000000000000000000000000fffffffffff8000000000000\n\nTest = Negate\nA = 000000000000000000000000000000000000000000000000000fffffffffffff\nB = ffffffff00000001000000000000000000000000fffffffffff0000000000000\n\nTest = Negate\nA ",
diff --git a/third_party/boringssl/err_data.c b/third_party/boringssl/err_data.c index d8dc7aa..8a62c95 100644 --- a/third_party/boringssl/err_data.c +++ b/third_party/boringssl/err_data.c
@@ -184,43 +184,43 @@ 0x28340c5e, 0x283480ac, 0x283500ea, - 0x2c322c30, + 0x2c322c4a, 0x2c329283, - 0x2c332c3e, - 0x2c33ac50, - 0x2c342c64, - 0x2c34ac76, - 0x2c352c91, - 0x2c35aca3, - 0x2c362cb6, + 0x2c332c58, + 0x2c33ac6a, + 0x2c342c7e, + 0x2c34ac90, + 0x2c352cab, + 0x2c35acbd, + 0x2c362cd0, 0x2c36832d, - 0x2c372cc3, - 0x2c37acd5, - 0x2c382cfa, - 0x2c38ad11, - 0x2c392d1f, - 0x2c39ad2f, - 0x2c3a2d41, - 0x2c3aad55, - 0x2c3b2d66, - 0x2c3bad85, + 0x2c372cdd, + 0x2c37acef, + 0x2c382d14, + 0x2c38ad2b, + 0x2c392d39, + 0x2c39ad49, + 0x2c3a2d5b, + 0x2c3aad6f, + 0x2c3b2d80, + 0x2c3bad9f, 0x2c3c1295, 0x2c3c92ab, - 0x2c3d2d99, + 0x2c3d2db3, 0x2c3d92c4, - 0x2c3e2db6, - 0x2c3eadc4, - 0x2c3f2ddc, - 0x2c3fadf4, - 0x2c402e01, + 0x2c3e2dd0, + 0x2c3eadde, + 0x2c3f2df6, + 0x2c3fae0e, + 0x2c402e1b, 0x2c409196, - 0x2c412e12, - 0x2c41ae25, + 0x2c412e2c, + 0x2c41ae3f, 0x2c42116f, - 0x2c42ae36, + 0x2c42ae50, 0x2c430720, - 0x2c43ad77, - 0x2c442ce8, + 0x2c43ad91, + 0x2c442d02, 0x30320000, 0x30328015, 0x3033001f, @@ -398,175 +398,176 @@ 0x40471c5d, 0x40479c84, 0x40481cc1, - 0x40489cda, - 0x40491cf1, - 0x40499d0b, - 0x404a1d22, - 0x404a9d40, - 0x404b1d58, - 0x404b9d6f, - 0x404c1d85, - 0x404c9d97, - 0x404d1db8, - 0x404d9dda, - 0x404e1dee, - 0x404e9dfb, - 0x404f1e28, - 0x404f9e51, - 0x40501e8c, - 0x40509ea0, - 0x40511ebb, - 0x40521ecb, - 0x40529eef, - 0x40531f07, - 0x40539f1a, - 0x40541f2f, - 0x40549f52, - 0x40551f60, - 0x40559f7d, - 0x40561f8a, - 0x40569fa3, - 0x40571fbb, - 0x40579fce, - 0x40581fe3, - 0x4058a00a, - 0x40592039, - 0x4059a066, - 0x405a207a, - 0x405aa08a, - 0x405b20a2, - 0x405ba0b3, - 0x405c20c6, - 0x405ca105, - 0x405d2112, - 0x405da129, - 0x405e2167, + 0x40489cf4, + 0x40491d0b, + 0x40499d25, + 0x404a1d3c, + 0x404a9d5a, + 0x404b1d72, + 0x404b9d89, + 0x404c1d9f, + 0x404c9db1, + 0x404d1dd2, + 0x404d9df4, + 0x404e1e08, + 0x404e9e15, + 0x404f1e42, + 0x404f9e6b, + 0x40501ea6, + 0x40509eba, + 0x40511ed5, + 0x40521ee5, + 0x40529f09, + 0x40531f21, + 0x40539f34, + 0x40541f49, + 0x40549f6c, + 0x40551f7a, + 0x40559f97, + 0x40561fa4, + 0x40569fbd, + 0x40571fd5, + 0x40579fe8, + 0x40581ffd, + 0x4058a024, + 0x40592053, + 0x4059a080, + 0x405a2094, + 0x405aa0a4, + 0x405b20bc, + 0x405ba0cd, + 0x405c20e0, + 0x405ca11f, + 0x405d212c, + 0x405da143, + 0x405e2181, 0x405e8ab1, - 0x405f2188, - 0x405fa195, - 0x406021a3, - 0x4060a1c5, - 0x40612209, - 0x4061a241, - 0x40622258, - 0x4062a269, - 0x4063227a, - 0x4063a28f, - 0x406422a6, - 0x4064a2d2, - 0x406522ed, - 0x4065a304, - 0x4066231c, - 0x4066a346, - 0x40672371, - 0x4067a392, - 0x406823b9, - 0x4068a3da, - 0x4069240c, - 0x4069a43a, - 0x406a245b, - 0x406aa47b, - 0x406b2603, - 0x406ba626, - 0x406c263c, - 0x406ca8b7, - 0x406d28e6, - 0x406da90e, - 0x406e293c, - 0x406ea989, - 0x406f29a8, - 0x406fa9e0, - 0x407029f3, - 0x4070aa10, + 0x405f21a2, + 0x405fa1af, + 0x406021bd, + 0x4060a1df, + 0x40612223, + 0x4061a25b, + 0x40622272, + 0x4062a283, + 0x40632294, + 0x4063a2a9, + 0x406422c0, + 0x4064a2ec, + 0x40652307, + 0x4065a31e, + 0x40662336, + 0x4066a360, + 0x4067238b, + 0x4067a3ac, + 0x406823d3, + 0x4068a3f4, + 0x40692426, + 0x4069a454, + 0x406a2475, + 0x406aa495, + 0x406b261d, + 0x406ba640, + 0x406c2656, + 0x406ca8d1, + 0x406d2900, + 0x406da928, + 0x406e2956, + 0x406ea9a3, + 0x406f29c2, + 0x406fa9fa, + 0x40702a0d, + 0x4070aa2a, 0x40710800, - 0x4071aa22, - 0x40722a35, - 0x4072aa4e, - 0x40732a66, + 0x4071aa3c, + 0x40722a4f, + 0x4072aa68, + 0x40732a80, 0x40739482, - 0x40742a7a, - 0x4074aa94, - 0x40752aa5, - 0x4075aab9, - 0x40762ac7, + 0x40742a94, + 0x4074aaae, + 0x40752abf, + 0x4075aad3, + 0x40762ae1, 0x40769259, - 0x40772aec, - 0x4077ab0e, - 0x40782b29, - 0x4078ab62, - 0x40792b79, - 0x4079ab8f, - 0x407a2b9b, - 0x407aabae, - 0x407b2bc3, - 0x407babd5, - 0x407c2c06, - 0x407cac0f, - 0x407d23f5, - 0x407d9e61, - 0x407e2b3e, - 0x407ea01a, + 0x40772b06, + 0x4077ab28, + 0x40782b43, + 0x4078ab7c, + 0x40792b93, + 0x4079aba9, + 0x407a2bb5, + 0x407aabc8, + 0x407b2bdd, + 0x407babef, + 0x407c2c20, + 0x407cac29, + 0x407d240f, + 0x407d9e7b, + 0x407e2b58, + 0x407ea034, 0x407f1c71, 0x407f9a31, - 0x40801e38, + 0x40801e52, 0x40809c99, - 0x40811edd, - 0x40819e12, - 0x40822927, + 0x40811ef7, + 0x40819e2c, + 0x40822941, 0x40829a17, - 0x40831ff5, - 0x4083a2b7, + 0x4083200f, + 0x4083a2d1, 0x40841cad, - 0x4084a052, - 0x408520d7, - 0x4085a1ed, - 0x40862149, - 0x40869e7b, - 0x4087296d, - 0x4087a21e, + 0x4084a06c, + 0x408520f1, + 0x4085a207, + 0x40862163, + 0x40869e95, + 0x40872987, + 0x4087a238, 0x40881a78, - 0x4088a3a5, + 0x4088a3bf, 0x40891ac7, 0x40899a54, - 0x408a265c, + 0x408a2676, 0x408a9862, - 0x408b2bea, - 0x408ba9bd, - 0x408c20e7, + 0x408b2c04, + 0x408ba9d7, + 0x408c2101, 0x408c987e, - 0x41f4252e, - 0x41f925c0, - 0x41fe24b3, - 0x41fea6a8, - 0x41ff2799, - 0x42032547, - 0x42082569, - 0x4208a5a5, - 0x42092497, - 0x4209a5df, - 0x420a24ee, - 0x420aa4ce, - 0x420b250e, - 0x420ba587, - 0x420c27b5, - 0x420ca675, - 0x420d268f, - 0x420da6c6, - 0x421226e0, - 0x4217277c, - 0x4217a722, - 0x421c2744, - 0x421f26ff, - 0x422127cc, - 0x4226275f, - 0x422b289b, - 0x422ba849, - 0x422c2883, - 0x422ca808, - 0x422d27e7, - 0x422da868, - 0x422e282e, - 0x422ea954, + 0x408d1cda, + 0x41f42548, + 0x41f925da, + 0x41fe24cd, + 0x41fea6c2, + 0x41ff27b3, + 0x42032561, + 0x42082583, + 0x4208a5bf, + 0x420924b1, + 0x4209a5f9, + 0x420a2508, + 0x420aa4e8, + 0x420b2528, + 0x420ba5a1, + 0x420c27cf, + 0x420ca68f, + 0x420d26a9, + 0x420da6e0, + 0x421226fa, + 0x42172796, + 0x4217a73c, + 0x421c275e, + 0x421f2719, + 0x422127e6, + 0x42262779, + 0x422b28b5, + 0x422ba863, + 0x422c289d, + 0x422ca822, + 0x422d2801, + 0x422da882, + 0x422e2848, + 0x422ea96e, 0x4432072b, 0x4432873a, 0x44330746, @@ -619,69 +620,69 @@ 0x4c4014a7, 0x4c4092d5, 0x4c4114cb, - 0x50322e48, - 0x5032ae57, - 0x50332e62, - 0x5033ae72, - 0x50342e8b, - 0x5034aea5, - 0x50352eb3, - 0x5035aec9, - 0x50362edb, - 0x5036aef1, - 0x50372f0a, - 0x5037af1d, - 0x50382f35, - 0x5038af46, - 0x50392f5b, - 0x5039af6f, - 0x503a2f8f, - 0x503aafa5, - 0x503b2fbd, - 0x503bafcf, - 0x503c2feb, - 0x503cb002, - 0x503d301b, - 0x503db031, - 0x503e303e, - 0x503eb054, - 0x503f3066, + 0x50322e62, + 0x5032ae71, + 0x50332e7c, + 0x5033ae8c, + 0x50342ea5, + 0x5034aebf, + 0x50352ecd, + 0x5035aee3, + 0x50362ef5, + 0x5036af0b, + 0x50372f24, + 0x5037af37, + 0x50382f4f, + 0x5038af60, + 0x50392f75, + 0x5039af89, + 0x503a2fa9, + 0x503aafbf, + 0x503b2fd7, + 0x503bafe9, + 0x503c3005, + 0x503cb01c, + 0x503d3035, + 0x503db04b, + 0x503e3058, + 0x503eb06e, + 0x503f3080, 0x503f8382, - 0x50403079, - 0x5040b089, - 0x504130a3, - 0x5041b0b2, - 0x504230cc, - 0x5042b0e9, - 0x504330f9, - 0x5043b109, - 0x50443118, + 0x50403093, + 0x5040b0a3, + 0x504130bd, + 0x5041b0cc, + 0x504230e6, + 0x5042b103, + 0x50433113, + 0x5043b123, + 0x50443132, 0x5044843f, - 0x5045312c, - 0x5045b14a, - 0x5046315d, - 0x5046b173, - 0x50473185, - 0x5047b19a, - 0x504831c0, - 0x5048b1ce, - 0x504931e1, - 0x5049b1f6, - 0x504a320c, - 0x504ab21c, - 0x504b323c, - 0x504bb24f, - 0x504c3272, - 0x504cb2a0, - 0x504d32b2, - 0x504db2cf, - 0x504e32ea, - 0x504eb306, - 0x504f3318, - 0x504fb32f, - 0x5050333e, + 0x50453146, + 0x5045b164, + 0x50463177, + 0x5046b18d, + 0x5047319f, + 0x5047b1b4, + 0x504831da, + 0x5048b1e8, + 0x504931fb, + 0x5049b210, + 0x504a3226, + 0x504ab236, + 0x504b3256, + 0x504bb269, + 0x504c328c, + 0x504cb2ba, + 0x504d32cc, + 0x504db2e9, + 0x504e3304, + 0x504eb320, + 0x504f3332, + 0x504fb349, + 0x50503358, 0x505086ef, - 0x50513351, + 0x5051336b, 0x58320f2b, 0x68320eed, 0x68328c6a, @@ -1094,6 +1095,7 @@ "DUPLICATE_EXTENSION\0" "DUPLICATE_KEY_SHARE\0" "ECC_CERT_NOT_FOR_SIGNING\0" + "EMPTY_HELLO_RETRY_REQUEST\0" "EMS_STATE_INCONSISTENT\0" "ENCRYPTED_LENGTH_TOO_LONG\0" "ERROR_ADDING_EXTENSION\0"
diff --git a/third_party/boringssl/ios-arm/crypto/fipsmodule/aes-armv4.S b/third_party/boringssl/ios-arm/crypto/fipsmodule/aes-armv4.S index 2e6c7efa..516c89b0 100644 --- a/third_party/boringssl/ios-arm/crypto/fipsmodule/aes-armv4.S +++ b/third_party/boringssl/ios-arm/crypto/fipsmodule/aes-armv4.S
@@ -171,7 +171,7 @@ #ifndef __thumb2__ sub r3,pc,#8 @ _asm_AES_encrypt #else - adr r3,_asm_AES_encrypt + adr r3,. #endif stmdb sp!,{r1,r4-r12,lr} #ifdef __APPLE__ @@ -426,7 +426,7 @@ #ifndef __thumb2__ sub r3,pc,#8 @ _asm_AES_set_encrypt_key #else - adr r3,_asm_AES_set_encrypt_key + adr r3,. #endif teq r0,#0 #ifdef __thumb2__ @@ -956,7 +956,7 @@ #ifndef __thumb2__ sub r3,pc,#8 @ _asm_AES_decrypt #else - adr r3,_asm_AES_decrypt + adr r3,. #endif stmdb sp!,{r1,r4-r12,lr} #ifdef __APPLE__
diff --git a/third_party/boringssl/ios-arm/crypto/fipsmodule/bsaes-armv7.S b/third_party/boringssl/ios-arm/crypto/fipsmodule/bsaes-armv7.S index 1cf914c..5e2ebf0 100644 --- a/third_party/boringssl/ios-arm/crypto/fipsmodule/bsaes-armv7.S +++ b/third_party/boringssl/ios-arm/crypto/fipsmodule/bsaes-armv7.S
@@ -91,7 +91,7 @@ #endif .align 4 _bsaes_decrypt8: - adr r6,_bsaes_decrypt8 + adr r6,. vldmia r4!, {q9} @ round 0 key #ifdef __APPLE__ adr r6,LM0ISR @@ -584,7 +584,7 @@ #endif .align 4 _bsaes_encrypt8: - adr r6,_bsaes_encrypt8 + adr r6,. vldmia r4!, {q9} @ round 0 key #ifdef __APPLE__ adr r6,LM0SR @@ -1021,7 +1021,7 @@ #endif .align 4 _bsaes_key_convert: - adr r6,_bsaes_key_convert + adr r6,. vld1.8 {q7}, [r4]! @ load round 0 key #ifdef __APPLE__ adr r6,LM0
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/aes-armv4.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/aes-armv4.S index f11bc7e..d401fc7 100644 --- a/third_party/boringssl/linux-arm/crypto/fipsmodule/aes-armv4.S +++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/aes-armv4.S
@@ -170,7 +170,7 @@ #ifndef __thumb2__ sub r3,pc,#8 @ asm_AES_encrypt #else - adr r3,asm_AES_encrypt + adr r3,. #endif stmdb sp!,{r1,r4-r12,lr} #ifdef __APPLE__ @@ -421,7 +421,7 @@ #ifndef __thumb2__ sub r3,pc,#8 @ asm_AES_set_encrypt_key #else - adr r3,asm_AES_set_encrypt_key + adr r3,. #endif teq r0,#0 #ifdef __thumb2__ @@ -945,7 +945,7 @@ #ifndef __thumb2__ sub r3,pc,#8 @ asm_AES_decrypt #else - adr r3,asm_AES_decrypt + adr r3,. #endif stmdb sp!,{r1,r4-r12,lr} #ifdef __APPLE__
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/bsaes-armv7.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/bsaes-armv7.S index 0b1a9f7..f9c6de7 100644 --- a/third_party/boringssl/linux-arm/crypto/fipsmodule/bsaes-armv7.S +++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/bsaes-armv7.S
@@ -90,7 +90,7 @@ .type _bsaes_decrypt8,%function .align 4 _bsaes_decrypt8: - adr r6,_bsaes_decrypt8 + adr r6,. vldmia r4!, {q9} @ round 0 key #ifdef __APPLE__ adr r6,.LM0ISR @@ -581,7 +581,7 @@ .type _bsaes_encrypt8,%function .align 4 _bsaes_encrypt8: - adr r6,_bsaes_encrypt8 + adr r6,. vldmia r4!, {q9} @ round 0 key #ifdef __APPLE__ adr r6,.LM0SR @@ -1016,7 +1016,7 @@ .type _bsaes_key_convert,%function .align 4 _bsaes_key_convert: - adr r6,_bsaes_key_convert + adr r6,. vld1.8 {q7}, [r4]! @ load round 0 key #ifdef __APPLE__ adr r6,.LM0
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S index 62c6cd6..e7b4c48b 100644 --- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S +++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S
@@ -4,6 +4,7 @@ .type _aesni_ctr32_ghash_6x,@function .align 32 _aesni_ctr32_ghash_6x: +.cfi_startproc vmovdqu 32(%r11),%xmm2 subq $6,%rdx vpxor %xmm4,%xmm4,%xmm4 @@ -328,12 +329,14 @@ vpxor %xmm4,%xmm8,%xmm8 .byte 0xf3,0xc3 +.cfi_endproc .size _aesni_ctr32_ghash_6x,.-_aesni_ctr32_ghash_6x .globl aesni_gcm_decrypt .hidden aesni_gcm_decrypt .type aesni_gcm_decrypt,@function .align 32 aesni_gcm_decrypt: +.cfi_startproc xorq %r10,%r10 @@ -342,12 +345,19 @@ jb .Lgcm_dec_abort leaq (%rsp),%rax +.cfi_def_cfa_register %rax pushq %rbx +.cfi_offset %rbx,-16 pushq %rbp +.cfi_offset %rbp,-24 pushq %r12 +.cfi_offset %r12,-32 pushq %r13 +.cfi_offset %r13,-40 pushq %r14 +.cfi_offset %r14,-48 pushq %r15 +.cfi_offset %r15,-56 vzeroupper vmovdqu (%r8),%xmm1 @@ -417,19 +427,28 @@ vzeroupper movq -48(%rax),%r15 +.cfi_restore %r15 movq -40(%rax),%r14 +.cfi_restore %r14 movq -32(%rax),%r13 +.cfi_restore %r13 movq -24(%rax),%r12 +.cfi_restore %r12 movq -16(%rax),%rbp +.cfi_restore %rbp movq -8(%rax),%rbx +.cfi_restore %rbx leaq (%rax),%rsp +.cfi_def_cfa_register %rsp .Lgcm_dec_abort: movq %r10,%rax .byte 0xf3,0xc3 +.cfi_endproc .size aesni_gcm_decrypt,.-aesni_gcm_decrypt .type _aesni_ctr32_6x,@function .align 32 _aesni_ctr32_6x: +.cfi_startproc vmovdqu 0-128(%rcx),%xmm4 vmovdqu 32(%r11),%xmm2 leaq -1(%rbp),%r13 @@ -516,6 +535,7 @@ vpshufb %xmm0,%xmm1,%xmm1 vpxor %xmm4,%xmm14,%xmm14 jmp .Loop_ctr32 +.cfi_endproc .size _aesni_ctr32_6x,.-_aesni_ctr32_6x .globl aesni_gcm_encrypt @@ -523,6 +543,7 @@ .type aesni_gcm_encrypt,@function .align 32 aesni_gcm_encrypt: +.cfi_startproc xorq %r10,%r10 @@ -532,12 +553,19 @@ jb .Lgcm_enc_abort leaq (%rsp),%rax +.cfi_def_cfa_register %rax pushq %rbx +.cfi_offset %rbx,-16 pushq %rbp +.cfi_offset %rbp,-24 pushq %r12 +.cfi_offset %r12,-32 pushq %r13 +.cfi_offset %r13,-40 pushq %r14 +.cfi_offset %r14,-48 pushq %r15 +.cfi_offset %r15,-56 vzeroupper vmovdqu (%r8),%xmm1 @@ -772,15 +800,23 @@ vzeroupper movq -48(%rax),%r15 +.cfi_restore %r15 movq -40(%rax),%r14 +.cfi_restore %r14 movq -32(%rax),%r13 +.cfi_restore %r13 movq -24(%rax),%r12 +.cfi_restore %r12 movq -16(%rax),%rbp +.cfi_restore %rbp movq -8(%rax),%rbx +.cfi_restore %rbx leaq (%rax),%rsp +.cfi_def_cfa_register %rsp .Lgcm_enc_abort: movq %r10,%rax .byte 0xf3,0xc3 +.cfi_endproc .size aesni_gcm_encrypt,.-aesni_gcm_encrypt .align 64 .Lbswap_mask:
diff --git a/third_party/boringssl/mac-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S b/third_party/boringssl/mac-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S index f185d0c..2513904c 100644 --- a/third_party/boringssl/mac-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S +++ b/third_party/boringssl/mac-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S
@@ -4,6 +4,7 @@ .p2align 5 _aesni_ctr32_ghash_6x: + vmovdqu 32(%r11),%xmm2 subq $6,%rdx vpxor %xmm4,%xmm4,%xmm4 @@ -329,11 +330,13 @@ .byte 0xf3,0xc3 + .globl _aesni_gcm_decrypt .private_extern _aesni_gcm_decrypt .p2align 5 _aesni_gcm_decrypt: + xorq %r10,%r10 @@ -342,12 +345,19 @@ jb L$gcm_dec_abort leaq (%rsp),%rax + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + vzeroupper vmovdqu (%r8),%xmm1 @@ -417,19 +427,28 @@ vzeroupper movq -48(%rax),%r15 + movq -40(%rax),%r14 + movq -32(%rax),%r13 + movq -24(%rax),%r12 + movq -16(%rax),%rbp + movq -8(%rax),%rbx + leaq (%rax),%rsp + L$gcm_dec_abort: movq %r10,%rax .byte 0xf3,0xc3 + .p2align 5 _aesni_ctr32_6x: + vmovdqu 0-128(%rcx),%xmm4 vmovdqu 32(%r11),%xmm2 leaq -1(%rbp),%r13 @@ -518,11 +537,13 @@ jmp L$oop_ctr32 + .globl _aesni_gcm_encrypt .private_extern _aesni_gcm_encrypt .p2align 5 _aesni_gcm_encrypt: + xorq %r10,%r10 @@ -532,12 +553,19 @@ jb L$gcm_enc_abort leaq (%rsp),%rax + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + vzeroupper vmovdqu (%r8),%xmm1 @@ -772,16 +800,24 @@ vzeroupper movq -48(%rax),%r15 + movq -40(%rax),%r14 + movq -32(%rax),%r13 + movq -24(%rax),%r12 + movq -16(%rax),%rbp + movq -8(%rax),%rbx + leaq (%rax),%rsp + L$gcm_enc_abort: movq %r10,%rax .byte 0xf3,0xc3 + .p2align 6 L$bswap_mask: .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
diff --git a/third_party/boringssl/win-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.asm b/third_party/boringssl/win-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.asm index 741a9e4..63bcd48 100644 --- a/third_party/boringssl/win-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.asm +++ b/third_party/boringssl/win-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.asm
@@ -8,6 +8,7 @@ ALIGN 32 _aesni_ctr32_ghash_6x: + vmovdqu xmm2,XMMWORD[32+r11] sub rdx,6 vpxor xmm4,xmm4,xmm4 @@ -333,6 +334,7 @@ DB 0F3h,0C3h ;repret + global aesni_gcm_decrypt ALIGN 32 @@ -349,6 +351,7 @@ mov r9,QWORD[48+rsp] + xor r10,r10 @@ -357,12 +360,19 @@ jb NEAR $L$gcm_dec_abort lea rax,[rsp] + push rbx + push rbp + push r12 + push r13 + push r14 + push r15 + lea rsp,[((-168))+rsp] movaps XMMWORD[(-216)+rax],xmm6 movaps XMMWORD[(-200)+rax],xmm7 @@ -454,21 +464,30 @@ movaps xmm14,XMMWORD[((-88))+rax] movaps xmm15,XMMWORD[((-72))+rax] mov r15,QWORD[((-48))+rax] + mov r14,QWORD[((-40))+rax] + mov r13,QWORD[((-32))+rax] + mov r12,QWORD[((-24))+rax] + mov rbp,QWORD[((-16))+rax] + mov rbx,QWORD[((-8))+rax] + lea rsp,[rax] + $L$gcm_dec_abort: mov rax,r10 mov rdi,QWORD[8+rsp] ;WIN64 epilogue mov rsi,QWORD[16+rsp] DB 0F3h,0C3h ;repret + $L$SEH_end_aesni_gcm_decrypt: ALIGN 32 _aesni_ctr32_6x: + vmovdqu xmm4,XMMWORD[((0-128))+rcx] vmovdqu xmm2,XMMWORD[32+r11] lea r13,[((-1))+rbp] @@ -557,6 +576,7 @@ jmp NEAR $L$oop_ctr32 + global aesni_gcm_encrypt ALIGN 32 @@ -573,6 +593,7 @@ mov r9,QWORD[48+rsp] + xor r10,r10 @@ -582,12 +603,19 @@ jb NEAR $L$gcm_enc_abort lea rax,[rsp] + push rbx + push rbp + push r12 + push r13 + push r14 + push r15 + lea rsp,[((-168))+rsp] movaps XMMWORD[(-216)+rax],xmm6 movaps XMMWORD[(-200)+rax],xmm7 @@ -844,17 +872,25 @@ movaps xmm14,XMMWORD[((-88))+rax] movaps xmm15,XMMWORD[((-72))+rax] mov r15,QWORD[((-48))+rax] + mov r14,QWORD[((-40))+rax] + mov r13,QWORD[((-32))+rax] + mov r12,QWORD[((-24))+rax] + mov rbp,QWORD[((-16))+rax] + mov rbx,QWORD[((-8))+rax] + lea rsp,[rax] + $L$gcm_enc_abort: mov rax,r10 mov rdi,QWORD[8+rsp] ;WIN64 epilogue mov rsi,QWORD[16+rsp] DB 0F3h,0C3h ;repret + $L$SEH_end_aesni_gcm_encrypt: ALIGN 64 $L$bswap_mask:
diff --git a/third_party/brotli/BUILD.gn b/third_party/brotli/BUILD.gn index 500fb98..a5b7420 100644 --- a/third_party/brotli/BUILD.gn +++ b/third_party/brotli/BUILD.gn
@@ -160,6 +160,13 @@ ] public_configs = [ ":includes" ] + if (is_win) { + # Work around incremental linking randomly creating corrupt binaries, + # crbug.com/644525. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } + deps = [ ":common", ":dec",
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index a73e27d..3086a4d 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: a7453394d6ed712a56c000dafa465857f9eee970 +Revision: d5ead4d70f0ba11eb2aa2fbeb76133b3136ddc22 License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/BUILD.gn b/third_party/crashpad/crashpad/BUILD.gn new file mode 100644 index 0000000..5c3918ef --- /dev/null +++ b/third_party/crashpad/crashpad/BUILD.gn
@@ -0,0 +1,31 @@ +# 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. + +import("//testing/test.gni") + +config("crashpad_config") { + include_dirs = [ "//third_party/crashpad/crashpad" ] +} + +test("crashpad_tests") { + deps = [ + "client:client_test", + "handler:handler_test", + "minidump:minidump_test", + "snapshot:snapshot_test", + "test:gmock_main", + "test:test_test", + "util:util_test", + ] +}
diff --git a/build/secondary/third_party/crashpad/crashpad/client/BUILD.gn b/third_party/crashpad/crashpad/client/BUILD.gn similarity index 77% rename from build/secondary/third_party/crashpad/crashpad/client/BUILD.gn rename to third_party/crashpad/crashpad/client/BUILD.gn index d78d954e..3e24d6d 100644 --- a/build/secondary/third_party/crashpad/crashpad/client/BUILD.gn +++ b/third_party/crashpad/crashpad/client/BUILD.gn
@@ -1,6 +1,16 @@ -# 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. +# Copyright 2015 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. import("//testing/test.gni")
diff --git a/build/secondary/third_party/crashpad/crashpad/compat/BUILD.gn b/third_party/crashpad/crashpad/compat/BUILD.gn similarity index 68% rename from build/secondary/third_party/crashpad/crashpad/compat/BUILD.gn rename to third_party/crashpad/crashpad/compat/BUILD.gn index 89ed9aa..ddeb53d 100644 --- a/build/secondary/third_party/crashpad/crashpad/compat/BUILD.gn +++ b/third_party/crashpad/crashpad/compat/BUILD.gn
@@ -1,6 +1,16 @@ -# 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. +# Copyright 2015 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. config("compat_config") { include_dirs = []
diff --git a/build/secondary/third_party/crashpad/crashpad/handler/BUILD.gn b/third_party/crashpad/crashpad/handler/BUILD.gn similarity index 85% rename from build/secondary/third_party/crashpad/crashpad/handler/BUILD.gn rename to third_party/crashpad/crashpad/handler/BUILD.gn index f1e576de..2c17f3d9 100644 --- a/build/secondary/third_party/crashpad/crashpad/handler/BUILD.gn +++ b/third_party/crashpad/crashpad/handler/BUILD.gn
@@ -1,6 +1,16 @@ -# 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. +# Copyright 2015 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. import("//testing/test.gni")
diff --git a/build/secondary/third_party/crashpad/crashpad/minidump/BUILD.gn b/third_party/crashpad/crashpad/minidump/BUILD.gn similarity index 88% rename from build/secondary/third_party/crashpad/crashpad/minidump/BUILD.gn rename to third_party/crashpad/crashpad/minidump/BUILD.gn index 34b6b52..42f8c3e1 100644 --- a/build/secondary/third_party/crashpad/crashpad/minidump/BUILD.gn +++ b/third_party/crashpad/crashpad/minidump/BUILD.gn
@@ -1,6 +1,16 @@ -# 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. +# Copyright 2015 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. import("//testing/test.gni")
diff --git a/build/secondary/third_party/crashpad/crashpad/snapshot/BUILD.gn b/third_party/crashpad/crashpad/snapshot/BUILD.gn similarity index 94% rename from build/secondary/third_party/crashpad/crashpad/snapshot/BUILD.gn rename to third_party/crashpad/crashpad/snapshot/BUILD.gn index 10e3d30..49402fe 100644 --- a/build/secondary/third_party/crashpad/crashpad/snapshot/BUILD.gn +++ b/third_party/crashpad/crashpad/snapshot/BUILD.gn
@@ -1,6 +1,16 @@ -# 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. +# Copyright 2015 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. import("//build/config/compiler/compiler.gni") import("//testing/test.gni")
diff --git a/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn b/third_party/crashpad/crashpad/snapshot/test/BUILD.gn similarity index 82% rename from build/secondary/third_party/crashpad/crashpad/test/BUILD.gn rename to third_party/crashpad/crashpad/snapshot/test/BUILD.gn index 5552c70..5b9b745 100644 --- a/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn +++ b/third_party/crashpad/crashpad/snapshot/test/BUILD.gn
@@ -1,6 +1,16 @@ -# Copyright 2017 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. +# 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. import("//testing/test.gni")
diff --git a/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn b/third_party/crashpad/crashpad/test/BUILD.gn similarity index 82% copy from build/secondary/third_party/crashpad/crashpad/test/BUILD.gn copy to third_party/crashpad/crashpad/test/BUILD.gn index 5552c70..5b9b745 100644 --- a/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn +++ b/third_party/crashpad/crashpad/test/BUILD.gn
@@ -1,6 +1,16 @@ -# Copyright 2017 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. +# 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. import("//testing/test.gni")
diff --git a/third_party/crashpad/crashpad/third_party/apple_cctools/BUILD.gn b/third_party/crashpad/crashpad/third_party/apple_cctools/BUILD.gn new file mode 100644 index 0000000..c627728 --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/apple_cctools/BUILD.gn
@@ -0,0 +1,25 @@ +# Copyright 2015 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. + +config("apple_cctools_config") { + include_dirs = [ "../.." ] +} + +source_set("apple_cctools") { + sources = [ + "cctools/include/mach-o/getsect.h", + "cctools/libmacho/getsecbyname.c", + ] + public_configs = [ ":apple_cctools_config" ] +}
diff --git a/third_party/crashpad/crashpad/third_party/getopt/BUILD.gn b/third_party/crashpad/crashpad/third_party/getopt/BUILD.gn new file mode 100644 index 0000000..573d844 --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/getopt/BUILD.gn
@@ -0,0 +1,20 @@ +# Copyright 2014 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. + +source_set("getopt") { + sources = [ + "getopt.cc", + "getopt.h", + ] +}
diff --git a/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn b/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn new file mode 100644 index 0000000..db158c7 --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn
@@ -0,0 +1,24 @@ +# 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. + +config("zlib_config") { + defines = [ "CRASHPAD_ZLIB_SOURCE_CHROMIUM" ] +} + +group("zlib") { + public_configs = [ ":zlib_config" ] + public_deps = [ + "//third_party/zlib:zlib", + ] +}
diff --git a/build/secondary/third_party/crashpad/crashpad/tools/BUILD.gn b/third_party/crashpad/crashpad/tools/BUILD.gn similarity index 83% rename from build/secondary/third_party/crashpad/crashpad/tools/BUILD.gn rename to third_party/crashpad/crashpad/tools/BUILD.gn index d13de63..e2a82d39f 100644 --- a/build/secondary/third_party/crashpad/crashpad/tools/BUILD.gn +++ b/third_party/crashpad/crashpad/tools/BUILD.gn
@@ -1,6 +1,16 @@ -# 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. +# Copyright 2015 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. source_set("tool_support") { sources = [
diff --git a/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn similarity index 95% rename from build/secondary/third_party/crashpad/crashpad/util/BUILD.gn rename to third_party/crashpad/crashpad/util/BUILD.gn index 6338eff..b61a76e 100644 --- a/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn +++ b/third_party/crashpad/crashpad/util/BUILD.gn
@@ -1,6 +1,16 @@ -# 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. +# Copyright 2015 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. import("//build/config/sanitizers/sanitizers.gni") import("//build/toolchain/toolchain.gni")
diff --git a/third_party/gvr-android-sdk/BUILD.gn b/third_party/gvr-android-sdk/BUILD.gn index 28052ee..34d4ba5 100644 --- a/third_party/gvr-android-sdk/BUILD.gn +++ b/third_party/gvr-android-sdk/BUILD.gn
@@ -43,6 +43,200 @@ "*google/common/logging/nano/Vr\$VREvent\$Cyclops*.class", "*google/common/logging/nano/Vr\$VREvent\$AudioStats.class", "*ThrowableExtension*.class", + + # The following list contains all the java classes in + # com.google.vr.cardboard.* and com.google.vr.ndk.base.*. Gvr allows + # loading GvrLayout and GvrUiLayout from VrCore. So a lot of classes in the + # two namespaces are no longer needed. + # For classes that are still needed, we comment them out from the list + # instead of removing them. + # If any class is needed in the future, please also comment it out from the + # list instead of removing. + # TODO(bshe): Instead of excluding classes, we should consider use something + # like jar_included_patterns. So that we only need to include the classes + # that we need. And we don't need to worry about forget to exclude new + # classes after a GVR roll. See crbug.com/764446 + #"*google/vr/cardboard/AndroidNCompat\$1.class", + #"*google/vr/cardboard/AndroidNCompat\$2.class", + #"*google/vr/cardboard/AndroidNCompat\$3.class", + #"*google/vr/cardboard/AndroidNCompat.class", + "google/vr/cardboard/CardboardGLSurfaceView.class", + "*google/vr/cardboard/CardboardGLSurfaceView\$DetachListener.class", + #"*google/vr/cardboard/ConfigUtils.class", + #"*google/vr/cardboard/ContentProviderVrParamsProvider.class", + #"*google/vr/cardboard/ContextUtils.class", + #"*google/vr/cardboard/DisplaySynchronizer.class", + #"*google/vr/cardboard/DisplayUtils.class", + "*google/vr/cardboard/EglFactory.class", + "*google/vr/cardboard/EglReadyListener.class", + "*google/vr/cardboard/EglReadyListener\$EventListener.class", + "*google/vr/cardboard/ExternalSurfaceManager\$1.class", + "*google/vr/cardboard/ExternalSurfaceManager.class", + "*google/vr/cardboard/ExternalSurfaceManager\$ExternalSurface\$1.class", + "*google/vr/cardboard/ExternalSurfaceManager\$ExternalSurfaceCallback.class", + "*google/vr/cardboard/ExternalSurfaceManager\$ExternalSurface.class", + "*google/vr/cardboard/ExternalSurfaceManager\$ExternalSurfaceData.class", + "*google/vr/cardboard/ExternalSurfaceManager\$UpdateSurfaceCallback.class", + #"*google/vr/cardboard/FrameMonitor.class", + "*google/vr/cardboard/FullscreenMode\$1\$1.class", + "*google/vr/cardboard/FullscreenMode\$1.class", + "*google/vr/cardboard/FullscreenMode.class", + "*google/vr/cardboard/LegacyVrParamsProvider.class", + "*google/vr/cardboard/MutableEglConfigChooser.class", + "*google/vr/cardboard/NFCUtils\$1.class", + "*google/vr/cardboard/NFCUtils.class", + #"*google/vr/cardboard/PackageUtils.class", + "*google/vr/cardboard/PhoneParams.class", + "*google/vr/cardboard/PhoneParams\$PpiOverride.class", + "*google/vr/cardboard/ScanlineRacingRenderer\$1.class", + "*google/vr/cardboard/ScanlineRacingRenderer.class", + "*google/vr/cardboard/ScreenOrientationDetector.class", + "*google/vr/cardboard/ScreenOrientationDetector\$Listener.class", + "*google/vr/cardboard/ScreenOrientationDetector\$Orientation.class", + "*google/vr/cardboard/StoragePermissionUtils.class", + "*google/vr/cardboard/ThreadUtils.class", + "*google/vr/cardboard/TransitionView\$1.class", + "*google/vr/cardboard/TransitionView\$2.class", + "*google/vr/cardboard/TransitionView\$3.class", + "*google/vr/cardboard/TransitionView\$4.class", + "*google/vr/cardboard/TransitionView\$5.class", + "*google/vr/cardboard/TransitionView.class", + "*google/vr/cardboard/UiLayer\$10.class", + "*google/vr/cardboard/UiLayer\$11.class", + "*google/vr/cardboard/UiLayer\$1.class", + "*google/vr/cardboard/UiLayer\$2.class", + "*google/vr/cardboard/UiLayer\$3.class", + "*google/vr/cardboard/UiLayer\$4.class", + "*google/vr/cardboard/UiLayer\$5.class", + "*google/vr/cardboard/UiLayer\$6.class", + "*google/vr/cardboard/UiLayer\$7.class", + "*google/vr/cardboard/UiLayer\$8.class", + "*google/vr/cardboard/UiLayer\$9.class", + "*google/vr/cardboard/UiLayer\$RootOuterLayout.class", + "*google/vr/cardboard/UiLayer.class", + "*google/vr/cardboard/UiUtils\$1.class", + "*google/vr/cardboard/UiUtils\$2.class", + "*google/vr/cardboard/UiUtils\$3.class", + "*google/vr/cardboard/UiUtils\$4.class", + "*google/vr/cardboard/UiUtils.class", + "*google/vr/cardboard/UsedByNative.class", + #"*google/vr/cardboard/VrContextWrapper.class", + #"*google/vr/cardboard/VrCoreLibraryLoader.class", + #"*google/vr/cardboard/VrParamsProvider.class", + #"*google/vr/cardboard/VrParamsProviderFactory.class", + #"*google/vr/cardboard/VrParamsProviderFactory\$ContentProviderClientHandle.class", + "*google/vr/cardboard/VrParamsProviderJni.class", + #"*google/vr/cardboard/VrSettingsProviderContract.class", + "*google/vr/cardboard/annotations/UsedByNative.class", + "*google/vr/cardboard/annotations/UsedByReflection.class", + "*google/vr/ndk/base/AbstractDaydreamTouchListener.class", + #"*google/vr/ndk/base/AndroidCompat.class", + "*google/vr/ndk/base/BufferSpec.class", + "*google/vr/ndk/base/BufferSpec\$ColorFormat.class", + "*google/vr/ndk/base/BufferSpec\$DepthStencilFormat.class", + "*google/vr/ndk/base/BufferViewport.class", + "*google/vr/ndk/base/BufferViewport\$EyeType.class", + "*google/vr/ndk/base/BufferViewportList.class", + "*google/vr/ndk/base/BufferViewport\$Reprojection.class", + #"*google/vr/ndk/base/BuildConstants.class", + "*google/vr/ndk/base/BuildFlags.class", + "*google/vr/ndk/base/CardboardEmulator.class", + "*google/vr/ndk/base/CardboardEmulator\$ControllerCallbacks.class", + "*google/vr/ndk/base/Constants.class", + #"*google/vr/ndk/base/DaydreamApi\$10.class", + #"*google/vr/ndk/base/DaydreamApi\$11.class", + #"*google/vr/ndk/base/DaydreamApi\$12.class", + #"*google/vr/ndk/base/DaydreamApi\$1.class", + #"*google/vr/ndk/base/DaydreamApi\$2.class", + #"*google/vr/ndk/base/DaydreamApi\$3.class", + #"*google/vr/ndk/base/DaydreamApi\$4.class", + #"*google/vr/ndk/base/DaydreamApi\$5.class", + #"*google/vr/ndk/base/DaydreamApi\$6\$1.class", + #"*google/vr/ndk/base/DaydreamApi\$6.class", + #"*google/vr/ndk/base/DaydreamApi\$7.class", + #"*google/vr/ndk/base/DaydreamApi\$8.class", + #"*google/vr/ndk/base/DaydreamApi\$9.class", + #"*google/vr/ndk/base/DaydreamApi.class", + #"*google/vr/ndk/base/DaydreamUtils.class", + "*google/vr/ndk/base/DaydreamUtilsWrapper.class", + "*google/vr/ndk/base/ExtensionManager.class", + "*google/vr/ndk/base/ExternalSurface\$1.class", + "*google/vr/ndk/base/ExternalSurface\$2.class", + "*google/vr/ndk/base/ExternalSurface.class", + "*google/vr/ndk/base/FadeOverlayView\$1.class", + "*google/vr/ndk/base/FadeOverlayView\$2.class", + "*google/vr/ndk/base/FadeOverlayView.class", + "*google/vr/ndk/base/Frame.class", + #"*google/vr/ndk/base/GvrApi.class", + "*google/vr/ndk/base/GvrApi\$Error.class", + "*google/vr/ndk/base/GvrApi\$Feature.class", + "*google/vr/ndk/base/GvrApi\$IdleListener.class", + "*google/vr/ndk/base/GvrApi\$PoseTracker.class", + "*google/vr/ndk/base/GvrApi\$ViewerType.class", + #"*google/vr/ndk/base/GvrLayout.class", + "*google/vr/ndk/base/GvrLayout\$ExternalSurfaceListener.class", + #"*google/vr/ndk/base/GvrLayoutFactory.class", + "*google/vr/ndk/base/GvrLayoutImpl\$1.class", + "*google/vr/ndk/base/GvrLayoutImpl\$2.class", + "*google/vr/ndk/base/GvrLayoutImpl\$3.class", + "*google/vr/ndk/base/GvrLayoutImpl\$4.class", + "*google/vr/ndk/base/GvrLayoutImpl\$AsyncReprojectionSurfaceView\$1.class", + "*google/vr/ndk/base/GvrLayoutImpl\$AsyncReprojectionSurfaceView.class", + "*google/vr/ndk/base/GvrLayoutImpl\$\$Lambda\$0.class", + "*google/vr/ndk/base/GvrLayoutImpl.class", + "*google/vr/ndk/base/GvrLayoutImpl\$FrameFlushWorkaround.class", + "*google/vr/ndk/base/GvrLayoutImpl\$NullExtensionManager.class", + "*google/vr/ndk/base/GvrLayoutImpl\$PresentationFactory.class", + "*google/vr/ndk/base/GvrLayoutImpl\$PresentationHelper.class", + "*google/vr/ndk/base/GvrLayoutImpl\$PresentationListener.class", + "*google/vr/ndk/base/GvrLayoutImpl\$ScreenOnManager\$1.class", + "*google/vr/ndk/base/GvrLayoutImpl\$ScreenOnManager\$2.class", + "*google/vr/ndk/base/GvrLayoutImpl\$ScreenOnManager.class", + "*google/vr/ndk/base/GvrLayoutImplWrapper.class", + "*google/vr/ndk/base/GvrSurfaceView\$1.class", + "*google/vr/ndk/base/GvrSurfaceView\$BaseConfigChooser.class", + "*google/vr/ndk/base/GvrSurfaceView.class", + "*google/vr/ndk/base/GvrSurfaceView\$ComponentSizeChooser.class", + "*google/vr/ndk/base/GvrSurfaceView\$DefaultContextFactory.class", + "*google/vr/ndk/base/GvrSurfaceView\$DefaultWindowSurfaceFactory.class", + "*google/vr/ndk/base/GvrSurfaceView\$EglHelper.class", + "*google/vr/ndk/base/GvrSurfaceView\$GLThread.class", + "*google/vr/ndk/base/GvrSurfaceView\$GLThread\$GLThreadManager.class", + "*google/vr/ndk/base/GvrSurfaceView\$GLWrapper.class", + "*google/vr/ndk/base/GvrSurfaceView\$LogWriter.class", + "*google/vr/ndk/base/GvrSurfaceView\$SimpleEGLConfigChooser.class", + #"*google/vr/ndk/base/GvrUiLayout.class", + "*google/vr/ndk/base/GvrUiLayoutImpl\$1.class", + "*google/vr/ndk/base/GvrUiLayoutImpl\$2.class", + "*google/vr/ndk/base/GvrUiLayoutImpl\$3.class", + "*google/vr/ndk/base/GvrUiLayoutImpl\$\$Lambda\$0.class", + "*google/vr/ndk/base/GvrUiLayoutImpl\$\$Lambda\$1.class", + "*google/vr/ndk/base/GvrUiLayoutImpl\$\$Lambda\$2.class", + "*google/vr/ndk/base/GvrUiLayoutImpl.class", + "*google/vr/ndk/base/GvrUiLayoutImpl\$CloseButtonListenerWrapper.class", + #"*google/vr/ndk/base/SdkConfigurationReader.class", + "*google/vr/ndk/base/SdkDaydreamTouchListener\$1.class", + "*google/vr/ndk/base/SdkDaydreamTouchListener.class", + "*google/vr/ndk/base/SdkDaydreamTouchListener\$FinishInitilizationTask.class", + "*google/vr/ndk/base/SdkDaydreamTouchListener\$RefreshViewerProfileTask.class", + "*google/vr/ndk/base/SerializationConstants.class", + "*google/vr/ndk/base/SwapChain.class", + "*google/vr/ndk/base/ThrottlingMonitor\$1.class", + "*google/vr/ndk/base/ThrottlingMonitor\$2.class", + "*google/vr/ndk/base/ThrottlingMonitor.class", + "*google/vr/ndk/base/ThrottlingMonitor\$SetupCallback.class", + "*google/vr/ndk/base/ThrottlingMonitor\$TemperatureTrigger.class", + "*google/vr/ndk/base/ThrottlingMonitor\$ThrottlingTriggerCallback\$1.class", + "*google/vr/ndk/base/ThrottlingMonitor\$ThrottlingTriggerCallback.class", + #"*google/vr/ndk/base/TraceCompat.class", + "*google/vr/ndk/base/UserPrefs.class", + "*google/vr/ndk/base/UserPrefs\$ControllerHandedness.class", + #"*google/vr/ndk/base/Version.class", + "*google/vr/ndk/base/VrCoreSdkClient\$1.class", + "*google/vr/ndk/base/VrCoreSdkClient.class", + "*google/vr/ndk/base/VrCoreSdkClient\$DaydreamListenerImpl\$1.class", + "*google/vr/ndk/base/VrCoreSdkClient\$DaydreamListenerImpl\$2.class", + "*google/vr/ndk/base/VrCoreSdkClient\$DaydreamListenerImpl.class", ] deps = [
diff --git a/third_party/gvr-android-sdk/proguard-gvr-chromium.txt b/third_party/gvr-android-sdk/proguard-gvr-chromium.txt index 92fe117..495d836 100644 --- a/third_party/gvr-android-sdk/proguard-gvr-chromium.txt +++ b/third_party/gvr-android-sdk/proguard-gvr-chromium.txt
@@ -1 +1,2 @@ -dontwarn com.google.common.logging.nano.Vr$** +-dontwarn com.google.vr.**
diff --git a/third_party/openvr/README.chromium b/third_party/openvr/README.chromium index 6806c1a..94f2014 100644 --- a/third_party/openvr/README.chromium +++ b/third_party/openvr/README.chromium
@@ -4,7 +4,7 @@ Version: 1.0.4 Date: 2 Feb 2017 Revision: 7fa6470f2972970859f2395f1390f6d87d4b0fc3 -License: MIT +License: BSD 3-Clause License File: src/LICENSE Security Critical: yes
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn index 072f6f1..5058fcf 100644 --- a/third_party/protobuf/BUILD.gn +++ b/third_party/protobuf/BUILD.gn
@@ -619,6 +619,13 @@ configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] + if (is_win) { + # Work around incremental linking randomly creating corrupt binaries, + # crbug.com/644525. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } + cflags = protobuf_lite_cflags deps = [ @@ -639,6 +646,13 @@ configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] + + if (is_win) { + # Work around incremental linking randomly creating corrupt binaries, + # crbug.com/644525. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } } }
diff --git a/third_party/yasm/BUILD.gn b/third_party/yasm/BUILD.gn index 94dbf913..21dffd3 100644 --- a/third_party/yasm/BUILD.gn +++ b/third_party/yasm/BUILD.gn
@@ -85,6 +85,14 @@ ":yasm_config", "//build/config/compiler:no_chromium_code", ] + + if (is_win) { + # Work around incremental linking randomly creating corrupt binaries, + # crbug.com/644525. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } + deps = [ "//build/config:exe_and_shlib_deps", @@ -102,6 +110,14 @@ ":yasm_config", "//build/config/compiler:no_chromium_code", ] + + if (is_win) { + # Work around incremental linking randomly creating corrupt binaries, + # crbug.com/644525. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } + deps = [ "//build/config:exe_and_shlib_deps", @@ -122,6 +138,13 @@ "//build/config/compiler:no_chromium_code", ] + if (is_win) { + # Work around incremental linking randomly creating corrupt binaries, + # crbug.com/644525. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } + # Must be compatible with yasm_utils/yasm configs -= configs_to_delete configs += configs_to_add @@ -163,6 +186,14 @@ ":yasm_config", "//build/config/compiler:no_chromium_code", ] + + if (is_win) { + # Work around incremental linking randomly creating corrupt binaries, + # crbug.com/644525. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } + deps = [ "//build/config:exe_and_shlib_deps", @@ -180,6 +211,14 @@ ":yasm_config", "//build/config/compiler:no_chromium_code", ] + + if (is_win) { + # Work around incremental linking randomly creating corrupt binaries, + # crbug.com/644525. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } + deps = [ "//build/config:exe_and_shlib_deps", @@ -224,6 +263,14 @@ # correctly. ":re2c_warnings", ] + + if (is_win) { + # Work around incremental linking randomly creating corrupt binaries, + # crbug.com/644525. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } + deps = [ "//build/config:exe_and_shlib_deps", @@ -343,6 +390,13 @@ ":yasm_warnings", ] + if (is_win) { + # Work around incremental linking randomly creating corrupt binaries, + # crbug.com/644525. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } + # Disable WPO for yasm: crbug.com/604808 if (is_official_build && full_wpo_on_official) { configs -= [ "//build/config/compiler:default_optimization" ]
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py index 811b767..6a24edd2 100755 --- a/tools/clang/scripts/package.py +++ b/tools/clang/scripts/package.py
@@ -358,6 +358,18 @@ filter=PrintTarProgress) MaybeUpload(args, objdumpdir, platform) + # Zip up llvm-cfi-verify for CFI coverage. + cfiverifydir = 'llvmcfiverify-' + stamp + shutil.rmtree(cfiverifydir, ignore_errors=True) + os.makedirs(os.path.join(cfiverifydir, 'bin')) + shutil.copy(os.path.join(LLVM_RELEASE_DIR, 'bin', 'llvm-cfi-verify' + + exe_ext), + os.path.join(cfiverifydir, 'bin')) + with tarfile.open(cfiverifydir + '.tgz', 'w:gz') as tar: + tar.add(os.path.join(cfiverifydir, 'bin'), arcname='bin', + filter=PrintTarProgress) + MaybeUpload(args, cfiverifydir, platform) + # On Mac, lld isn't part of the main zip. Upload it in a separate zip. if sys.platform == 'darwin': llddir = 'lld-' + stamp
diff --git a/tools/gn/analyzer.cc b/tools/gn/analyzer.cc index cc403c2..b69b4d8f 100644 --- a/tools/gn/analyzer.cc +++ b/tools/gn/analyzer.cc
@@ -6,12 +6,12 @@ #include <algorithm> #include <iterator> +#include <memory> #include <set> #include <vector> #include "base/json/json_reader.h" #include "base/json/json_writer.h" -#include "base/memory/ptr_util.h" #include "base/strings/string_util.h" #include "base/values.h" #include "tools/gn/builder.h" @@ -111,7 +111,7 @@ const std::string& key, const LabelSet& labels) { std::vector<std::string> strings; - auto value = base::MakeUnique<base::ListValue>(); + auto value = std::make_unique<base::ListValue>(); for (const auto l : labels) strings.push_back(l.GetUserVisibleName(default_toolchain)); std::sort(strings.begin(), strings.end()); @@ -197,7 +197,7 @@ std::string OutputsToJSON(const Outputs& outputs, const Label& default_toolchain, Err *err) { std::string output; - auto value = base::MakeUnique<base::DictionaryValue>(); + auto value = std::make_unique<base::DictionaryValue>(); if (outputs.error.size()) { WriteString(*value, "error", outputs.error); @@ -206,7 +206,7 @@ } else { WriteString(*value, "status", outputs.status); if (outputs.compile_includes_all) { - auto compile_targets = base::MakeUnique<base::ListValue>(); + auto compile_targets = std::make_unique<base::ListValue>(); compile_targets->AppendString("all"); value->SetWithoutPathExpansion("compile_targets", std::move(compile_targets));
diff --git a/tools/gn/bootstrap/bootstrap.py b/tools/gn/bootstrap/bootstrap.py index 7098995..c4dd5d2 100755 --- a/tools/gn/bootstrap/bootstrap.py +++ b/tools/gn/bootstrap/bootstrap.py
@@ -63,7 +63,9 @@ def run_build(tempdir, options): - if options.debug: + if options.build_path: + build_rel = options.build_path + elif options.debug: build_rel = os.path.join('out', 'Debug') else: build_rel = os.path.join('out', 'Release') @@ -109,6 +111,8 @@ help='Re-used build directory instead of using new ' 'temporary location each time') parser.add_option('--gn-gen-args', help='Args to pass to gn gen --args') + parser.add_option('--build-path', help='The directory in which to build gn, ' + 'relative to the src directory. (eg. out/Release)') parser.add_option('-v', '--verbose', action='store_true', help='Log more details') options, args = parser.parse_args(argv)
diff --git a/tools/gn/command_desc.cc b/tools/gn/command_desc.cc index 8dbe6de..6203d01 100644 --- a/tools/gn/command_desc.cc +++ b/tools/gn/command_desc.cc
@@ -5,12 +5,12 @@ #include <stddef.h> #include <algorithm> +#include <memory> #include <set> #include <sstream> #include "base/command_line.h" #include "base/json/json_writer.h" -#include "base/memory/ptr_util.h" #include "base/strings/string_util.h" #include "tools/gn/commands.h" #include "tools/gn/config.h" @@ -457,7 +457,7 @@ if (json) { // Convert all targets/configs to JSON, serialize and print them - auto res = base::MakeUnique<base::DictionaryValue>(); + auto res = std::make_unique<base::DictionaryValue>(); if (!target_matches.empty()) { for (const auto* target : target_matches) { res->SetWithoutPathExpansion(
diff --git a/tools/gn/desc_builder.cc b/tools/gn/desc_builder.cc index 38b78e8..ba5291e6 100644 --- a/tools/gn/desc_builder.cc +++ b/tools/gn/desc_builder.cc
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> #include <set> -#include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "tools/gn/commands.h" #include "tools/gn/config.h" @@ -114,7 +114,7 @@ template <typename T> ValuePtr RenderValue(const std::vector<T>& vector) { - auto res = base::MakeUnique<base::ListValue>(); + auto res = std::make_unique<base::ListValue>(); for (const auto& v : vector) res->Append(RenderValue(v)); @@ -122,17 +122,17 @@ } ValuePtr RenderValue(const std::string& s, bool optional = false) { - return (s.empty() && optional) ? base::MakeUnique<base::Value>() + return (s.empty() && optional) ? std::make_unique<base::Value>() : ValuePtr(new base::Value(s)); } ValuePtr RenderValue(const SourceDir& d) { - return d.is_null() ? base::MakeUnique<base::Value>() + return d.is_null() ? std::make_unique<base::Value>() : ValuePtr(new base::Value(FormatSourceDir(d))); } ValuePtr RenderValue(const SourceFile& f) { - return f.is_null() ? base::MakeUnique<base::Value>() + return f.is_null() ? std::make_unique<base::Value>() : ValuePtr(new base::Value(f.value())); } @@ -182,7 +182,7 @@ : BaseDescBuilder(what, false, false, false), config_(config) {} std::unique_ptr<base::DictionaryValue> BuildDescription() { - auto res = base::MakeUnique<base::DictionaryValue>(); + auto res = std::make_unique<base::DictionaryValue>(); const ConfigValues& values = config_->resolved_values(); if (what_.empty()) @@ -192,7 +192,7 @@ config_->label().GetToolchainLabel().GetUserVisibleName(false))); if (what(variables::kConfigs) && !config_->configs().empty()) { - auto configs = base::MakeUnique<base::ListValue>(); + auto configs = std::make_unique<base::ListValue>(); FillInConfigVector(configs.get(), config_->configs().vector()); res->SetWithoutPathExpansion(variables::kConfigs, std::move(configs)); } @@ -235,7 +235,7 @@ ValuePtr render_config_value_array( const ConfigValues& values, const std::vector<T>& (ConfigValues::*getter)() const) { - auto res = base::MakeUnique<base::ListValue>(); + auto res = std::make_unique<base::ListValue>(); for (const T& cur : (values.*getter)()) res->Append(RenderValue(cur)); @@ -256,7 +256,7 @@ : BaseDescBuilder(what, all, tree, blame), target_(target) {} std::unique_ptr<base::DictionaryValue> BuildDescription() { - auto res = base::MakeUnique<base::DictionaryValue>(); + auto res = std::make_unique<base::DictionaryValue>(); bool is_binary_output = target_->IsBinary(); if (what_.empty()) { @@ -283,7 +283,7 @@ base::Value(target_->check_includes())); if (what(variables::kAllowCircularIncludesFrom)) { - auto labels = base::MakeUnique<base::ListValue>(); + auto labels = std::make_unique<base::ListValue>(); for (const auto& cur : target_->allow_circular_includes_from()) labels->AppendString(cur.GetUserVisibleName(GetToolchainLabel())); @@ -321,13 +321,13 @@ if (is_binary_output && what(variables::kConfigs) && !target_->configs().empty()) { - auto configs = base::MakeUnique<base::ListValue>(); + auto configs = std::make_unique<base::ListValue>(); FillInConfigVector(configs.get(), target_->configs().vector()); res->SetWithoutPathExpansion(variables::kConfigs, std::move(configs)); } if (what(variables::kPublicConfigs) && !target_->public_configs().empty()) { - auto configs = base::MakeUnique<base::ListValue>(); + auto configs = std::make_unique<base::ListValue>(); FillInConfigVector(configs.get(), target_->public_configs()); res->SetWithoutPathExpansion(variables::kPublicConfigs, std::move(configs)); @@ -335,7 +335,7 @@ if (what(variables::kAllDependentConfigs) && !target_->all_dependent_configs().empty()) { - auto configs = base::MakeUnique<base::ListValue>(); + auto configs = std::make_unique<base::ListValue>(); FillInConfigVector(configs.get(), target_->all_dependent_configs()); res->SetWithoutPathExpansion(variables::kAllDependentConfigs, std::move(configs)); @@ -349,7 +349,7 @@ base::Value(target_->action_values().script().value())); if (what(variables::kArgs)) { - auto args = base::MakeUnique<base::ListValue>(); + auto args = std::make_unique<base::ListValue>(); for (const auto& elem : target_->action_values().args().list()) args->AppendString(elem.AsString()); @@ -419,7 +419,7 @@ if (what(variables::kLibs)) { const OrderedSet<LibFile>& all_libs = target_->all_libs(); if (!all_libs.empty()) { - auto libs = base::MakeUnique<base::ListValue>(); + auto libs = std::make_unique<base::ListValue>(); for (size_t i = 0; i < all_libs.size(); i++) libs->AppendString(all_libs[i].value()); res->SetWithoutPathExpansion(variables::kLibs, std::move(libs)); @@ -429,7 +429,7 @@ if (what(variables::kLibDirs)) { const OrderedSet<SourceDir>& all_lib_dirs = target_->all_lib_dirs(); if (!all_lib_dirs.empty()) { - auto lib_dirs = base::MakeUnique<base::ListValue>(); + auto lib_dirs = std::make_unique<base::ListValue>(); for (size_t i = 0; i < all_lib_dirs.size(); i++) lib_dirs->AppendString(FormatSourceDir(all_lib_dirs[i])); res->SetWithoutPathExpansion(variables::kLibDirs, std::move(lib_dirs)); @@ -486,7 +486,7 @@ } ValuePtr RenderDeps() { - auto res = base::MakeUnique<base::ListValue>(); + auto res = std::make_unique<base::ListValue>(); // Tree mode is separate. if (tree_) { @@ -520,7 +520,7 @@ } ValuePtr RenderRuntimeDeps() { - auto res = base::MakeUnique<base::ListValue>(); + auto res = std::make_unique<base::ListValue>(); const Target* previous_from = NULL; for (const auto& pair : ComputeRuntimeDeps(target_)) { @@ -546,12 +546,12 @@ } void FillInSourceOutputs(base::DictionaryValue* res) { - auto dict = base::MakeUnique<base::DictionaryValue>(); + auto dict = std::make_unique<base::DictionaryValue>(); for (const auto& source : target_->sources()) { std::vector<OutputFile> outputs; Toolchain::ToolType tool_type = Toolchain::TYPE_NONE; if (target_->GetOutputFilesForSource(source, &tool_type, &outputs)) { - auto list = base::MakeUnique<base::ListValue>(); + auto list = std::make_unique<base::ListValue>(); for (const auto& output : outputs) list->AppendString(output.value()); @@ -562,7 +562,7 @@ } void FillInBundle(base::DictionaryValue* res) { - auto data = base::MakeUnique<base::DictionaryValue>(); + auto data = std::make_unique<base::DictionaryValue>(); const BundleData& bundle_data = target_->bundle_data(); const Settings* settings = target_->settings(); BundleData::SourceFiles sources; @@ -583,7 +583,7 @@ data->SetWithoutPathExpansion( "partial_info_plist", RenderValue(bundle_data.partial_info_plist())); - auto deps = base::MakeUnique<base::ListValue>(); + auto deps = std::make_unique<base::ListValue>(); for (const auto* dep : bundle_data.bundle_deps()) deps->AppendString(dep->label().GetUserVisibleName(GetToolchainLabel())); @@ -593,7 +593,7 @@ void FillInOutputs(base::DictionaryValue* res) { if (target_->output_type() == Target::ACTION) { - auto list = base::MakeUnique<base::ListValue>(); + auto list = std::make_unique<base::ListValue>(); for (const auto& elem : target_->action_values().outputs().list()) list->AppendString(elem.AsString()); @@ -608,7 +608,7 @@ target_->output_type() == Target::COPY_FILES) { const SubstitutionList& outputs = target_->action_values().outputs(); if (!outputs.required_types().empty()) { - auto patterns = base::MakeUnique<base::ListValue>(); + auto patterns = std::make_unique<base::ListValue>(); for (const auto& elem : outputs.list()) patterns->AppendString(elem.AsString()); @@ -644,7 +644,7 @@ template <class T> ValuePtr RenderConfigValues(const std::vector<T>& (ConfigValues::*getter)() const) { - auto res = base::MakeUnique<base::ListValue>(); + auto res = std::make_unique<base::ListValue>(); for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) { const std::vector<T>& vec = (iter.cur().*getter)(); @@ -678,7 +678,7 @@ // Indent string values in blame mode if (blame_ && rendered->GetAsString(&str)) { str = " " + str; - rendered = base::MakeUnique<base::Value>(str); + rendered = std::make_unique<base::Value>(str); } res->Append(std::move(rendered)); }
diff --git a/tools/gn/function_get_target_outputs_unittest.cc b/tools/gn/function_get_target_outputs_unittest.cc index abe07d4..d7354eb 100644 --- a/tools/gn/function_get_target_outputs_unittest.cc +++ b/tools/gn/function_get_target_outputs_unittest.cc
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> #include <utility> -#include "base/memory/ptr_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "tools/gn/functions.h" #include "tools/gn/target.h" @@ -61,7 +61,7 @@ TEST_F(GetTargetOutputsTest, Copy) { auto action = - base::MakeUnique<Target>(setup_.settings(), GetLabel("//foo/", "bar")); + std::make_unique<Target>(setup_.settings(), GetLabel("//foo/", "bar")); action->set_output_type(Target::COPY_FILES); action->sources().push_back(SourceFile("//file.txt")); action->action_values().outputs() = @@ -77,7 +77,7 @@ TEST_F(GetTargetOutputsTest, Action) { auto action = - base::MakeUnique<Target>(setup_.settings(), GetLabel("//foo/", "bar")); + std::make_unique<Target>(setup_.settings(), GetLabel("//foo/", "bar")); action->set_output_type(Target::ACTION); action->action_values().outputs() = SubstitutionList::MakeForTest( "//output1.txt", @@ -93,7 +93,7 @@ TEST_F(GetTargetOutputsTest, ActionForeach) { auto action = - base::MakeUnique<Target>(setup_.settings(), GetLabel("//foo/", "bar")); + std::make_unique<Target>(setup_.settings(), GetLabel("//foo/", "bar")); action->set_output_type(Target::ACTION_FOREACH); action->sources().push_back(SourceFile("//file.txt")); action->action_values().outputs() = SubstitutionList::MakeForTest(
diff --git a/tools/gn/function_toolchain.cc b/tools/gn/function_toolchain.cc index 2d80273..aeeb4e1 100644 --- a/tools/gn/function_toolchain.cc +++ b/tools/gn/function_toolchain.cc
@@ -4,6 +4,7 @@ #include <algorithm> #include <limits> +#include <memory> #include <utility> #include "tools/gn/err.h" @@ -453,7 +454,8 @@ // This object will actually be copied into the one owned by the toolchain // manager, but that has to be done in the lock. - std::unique_ptr<Toolchain> toolchain(new Toolchain(scope->settings(), label)); + std::unique_ptr<Toolchain> toolchain = + std::make_unique<Toolchain>(scope->settings(), label); toolchain->set_defined_from(function); toolchain->visibility().SetPublic(); @@ -1022,7 +1024,7 @@ subst_output_validator = &IsValidToolSubstitution; } - std::unique_ptr<Tool> tool(new Tool); + std::unique_ptr<Tool> tool = std::make_unique<Tool>(); tool->set_defined_from(function); if (!ReadPattern(&block_scope, "command", subst_validator, tool.get(),
diff --git a/tools/gn/functions.cc b/tools/gn/functions.cc index 4e469ac..60a6eb7 100644 --- a/tools/gn/functions.cc +++ b/tools/gn/functions.cc
@@ -6,6 +6,7 @@ #include <stddef.h> #include <iostream> +#include <memory> #include <utility> #include "base/environment.h" @@ -337,7 +338,8 @@ g_scheduler->Log("Defining config", label.GetUserVisibleName(true)); // Create the new config. - std::unique_ptr<Config> config(new Config(scope->settings(), label)); + std::unique_ptr<Config> config = + std::make_unique<Config>(scope->settings(), label); config->set_defined_from(function); if (!Visibility::FillItemVisibility(config.get(), scope, err)) return Value(); @@ -825,7 +827,7 @@ if (args.size() != 1) { *err = Err(function, "set_sources_assignment_filter takes one argument."); } else { - std::unique_ptr<PatternList> f(new PatternList); + std::unique_ptr<PatternList> f = std::make_unique<PatternList>(); f->SetFromValue(args[0], err); if (!err->has_error()) scope->set_sources_assignment_filter(std::move(f)); @@ -908,7 +910,7 @@ } // Create the new pool. - std::unique_ptr<Pool> pool(new Pool(scope->settings(), label)); + std::unique_ptr<Pool> pool = std::make_unique<Pool>(scope->settings(), label); pool->set_depth(depth->int_value()); // Save the generated item.
diff --git a/tools/gn/functions_unittest.cc b/tools/gn/functions_unittest.cc index 949b844..1ed509ae 100644 --- a/tools/gn/functions_unittest.cc +++ b/tools/gn/functions_unittest.cc
@@ -4,9 +4,9 @@ #include "tools/gn/functions.h" +#include <memory> #include <utility> -#include "base/memory/ptr_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "tools/gn/parse_tree.h" #include "tools/gn/test_with_scope.h" @@ -22,7 +22,7 @@ Token undefined_token(Location(), Token::IDENTIFIER, "undef"); ListNode args_list_identifier_undefined; args_list_identifier_undefined.append_item( - std::unique_ptr<ParseNode>(new IdentifierNode(undefined_token))); + std::make_unique<IdentifierNode>(undefined_token)); Value result = functions::RunDefined(setup.scope(), &function_call, &args_list_identifier_undefined, &err); ASSERT_EQ(Value::BOOLEAN, result.type()); @@ -31,14 +31,13 @@ // Define a value that's itself a scope value. const char kDef[] = "def"; // Defined variable name. setup.scope()->SetValue( - kDef, Value(nullptr, std::unique_ptr<Scope>(new Scope(setup.scope()))), - nullptr); + kDef, Value(nullptr, std::make_unique<Scope>(setup.scope())), nullptr); // Test the defined identifier. Token defined_token(Location(), Token::IDENTIFIER, kDef); ListNode args_list_identifier_defined; args_list_identifier_defined.append_item( - std::unique_ptr<ParseNode>(new IdentifierNode(defined_token))); + std::make_unique<IdentifierNode>(defined_token)); result = functions::RunDefined(setup.scope(), &function_call, &args_list_identifier_defined, &err); ASSERT_EQ(Value::BOOLEAN, result.type()); @@ -46,9 +45,10 @@ // Should also work by passing an accessor node so you can do // "defined(def.foo)" to see if foo is defined on the def scope. - std::unique_ptr<AccessorNode> undef_accessor(new AccessorNode); + std::unique_ptr<AccessorNode> undef_accessor = + std::make_unique<AccessorNode>(); undef_accessor->set_base(defined_token); - undef_accessor->set_member(base::MakeUnique<IdentifierNode>(undefined_token)); + undef_accessor->set_member(std::make_unique<IdentifierNode>(undefined_token)); ListNode args_list_accessor_defined; args_list_accessor_defined.append_item(std::move(undef_accessor)); result = functions::RunDefined(setup.scope(), &function_call,
diff --git a/tools/gn/import_manager.cc b/tools/gn/import_manager.cc index c9a44d4..b94ea70 100644 --- a/tools/gn/import_manager.cc +++ b/tools/gn/import_manager.cc
@@ -4,6 +4,8 @@ #include "tools/gn/import_manager.h" +#include <memory> + #include "tools/gn/err.h" #include "tools/gn/parse_tree.h" #include "tools/gn/scheduler.h" @@ -24,7 +26,8 @@ if (!node) return nullptr; - std::unique_ptr<Scope> scope(new Scope(settings->base_config())); + std::unique_ptr<Scope> scope = + std::make_unique<Scope>(settings->base_config()); scope->set_source_dir(file.GetDir()); // Don't allow ScopePerFileProvider to provide target-related variables. @@ -80,7 +83,7 @@ base::AutoLock lock(imports_lock_); std::unique_ptr<ImportInfo>& info_ptr = imports_[file]; if (!info_ptr) - info_ptr.reset(new ImportInfo); + info_ptr = std::make_unique<ImportInfo>(); // Promote the ImportInfo to outside of the imports lock. import_info = info_ptr.get();
diff --git a/tools/gn/input_conversion.cc b/tools/gn/input_conversion.cc index 2e905c6..7cce107f 100644 --- a/tools/gn/input_conversion.cc +++ b/tools/gn/input_conversion.cc
@@ -4,6 +4,7 @@ #include "tools/gn/input_conversion.h" +#include <memory> #include <utility> #include "base/macros.h" @@ -74,7 +75,7 @@ if (!parse_root) return Value(); - std::unique_ptr<Scope> scope(new Scope(settings)); + std::unique_ptr<Scope> scope = std::make_unique<Scope>(settings); Value result = parse_root->Execute(scope.get(), err); if (err->has_error()) return Value();
diff --git a/tools/gn/input_file_manager.cc b/tools/gn/input_file_manager.cc index 9fd3def..9f92130 100644 --- a/tools/gn/input_file_manager.cc +++ b/tools/gn/input_file_manager.cc
@@ -4,6 +4,7 @@ #include "tools/gn/input_file_manager.h" +#include <memory> #include <utility> #include "base/bind.h" @@ -111,7 +112,8 @@ InputFileMap::const_iterator found = input_files_.find(file_name); if (found == input_files_.end()) { // New file, schedule load. - std::unique_ptr<InputFileData> data(new InputFileData(file_name)); + std::unique_ptr<InputFileData> data = + std::make_unique<InputFileData>(file_name); data->scheduled_callbacks.push_back(callback); schedule_this = base::Bind(&InputFileManager::BackgroundLoadFile, this, @@ -162,7 +164,8 @@ InputFileMap::iterator found = input_files_.find(file_name); if (found == input_files_.end()) { // Haven't seen this file yet, start loading right now. - std::unique_ptr<InputFileData> new_data(new InputFileData(file_name)); + std::unique_ptr<InputFileData> new_data = + std::make_unique<InputFileData>(file_name); data = new_data.get(); data->sync_invocation = true; input_files_[file_name] = std::move(new_data); @@ -202,9 +205,9 @@ if (!data->loaded) { // Wait for the already-pending sync load to complete. if (!data->completion_event) { - data->completion_event.reset(new base::WaitableEvent( + data->completion_event = std::make_unique<base::WaitableEvent>( base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED)); + base::WaitableEvent::InitialState::NOT_SIGNALED); } { base::AutoUnlock unlock(lock_); @@ -230,7 +233,7 @@ InputFile** file, std::vector<Token>** tokens, std::unique_ptr<ParseNode>** parse_root) { - std::unique_ptr<InputFileData> data(new InputFileData(name)); + std::unique_ptr<InputFileData> data = std::make_unique<InputFileData>(name); *file = &data->file; *tokens = &data->tokens; *parse_root = &data->parsed_root;
diff --git a/tools/gn/json_project_writer.cc b/tools/gn/json_project_writer.cc index dfb3cdb..4f4b0e7 100644 --- a/tools/gn/json_project_writer.cc +++ b/tools/gn/json_project_writer.cc
@@ -5,10 +5,10 @@ #include "tools/gn/json_project_writer.h" #include <iostream> +#include <memory> #include "base/command_line.h" #include "base/json/json_writer.h" -#include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "tools/gn/builder.h" #include "tools/gn/commands.h" @@ -86,7 +86,7 @@ std::vector<const Target*>& all_targets) { Label default_toolchain_label; - auto targets = base::MakeUnique<base::DictionaryValue>(); + auto targets = std::make_unique<base::DictionaryValue>(); for (const auto* target : all_targets) { if (default_toolchain_label.is_null()) default_toolchain_label = target->settings()->default_toolchain_label(); @@ -105,7 +105,7 @@ std::move(description)); } - auto settings = base::MakeUnique<base::DictionaryValue>(); + auto settings = std::make_unique<base::DictionaryValue>(); settings->SetKey("root_path", base::Value(build_settings->root_path_utf8())); settings->SetKey("build_dir", base::Value(build_settings->build_dir().value())); @@ -113,7 +113,7 @@ "default_toolchain", base::Value(default_toolchain_label.GetUserVisibleName(false))); - auto output = base::MakeUnique<base::DictionaryValue>(); + auto output = std::make_unique<base::DictionaryValue>(); output->SetWithoutPathExpansion("targets", std::move(targets)); output->SetWithoutPathExpansion("build_settings", std::move(settings));
diff --git a/tools/gn/loader.cc b/tools/gn/loader.cc index ba214c2..57680e0 100644 --- a/tools/gn/loader.cc +++ b/tools/gn/loader.cc
@@ -4,8 +4,9 @@ #include "tools/gn/loader.h" +#include <memory> + #include "base/bind.h" -#include "base/memory/ptr_util.h" #include "base/threading/thread_task_runner_handle.h" #include "tools/gn/build_settings.h" #include "tools/gn/err.h" @@ -123,8 +124,8 @@ // should not specify a toolchain. DCHECK(toolchain_name.is_null()); - std::unique_ptr<ToolchainRecord> new_record( - new ToolchainRecord(build_settings_, Label(), Label())); + std::unique_ptr<ToolchainRecord> new_record = + std::make_unique<ToolchainRecord>(build_settings_, Label(), Label()); ToolchainRecord* record = new_record.get(); toolchain_records_[Label()] = std::move(new_record); @@ -149,8 +150,9 @@ DCHECK(!default_toolchain_label_.is_null()); // No reference to this toolchain found yet, make one. - std::unique_ptr<ToolchainRecord> new_record(new ToolchainRecord( - build_settings_, toolchain_name, default_toolchain_label_)); + std::unique_ptr<ToolchainRecord> new_record = + std::make_unique<ToolchainRecord>(build_settings_, toolchain_name, + default_toolchain_label_); record = new_record.get(); toolchain_records_[toolchain_name] = std::move(new_record); @@ -168,8 +170,9 @@ ToolchainRecord* record = toolchain_records_[toolchain->label()].get(); if (!record) { DCHECK(!default_toolchain_label_.is_null()); - std::unique_ptr<ToolchainRecord> new_record(new ToolchainRecord( - build_settings_, toolchain->label(), default_toolchain_label_)); + std::unique_ptr<ToolchainRecord> new_record = + std::make_unique<ToolchainRecord>(build_settings_, toolchain->label(), + default_toolchain_label_); record = new_record.get(); toolchain_records_[toolchain->label()] = std::move(new_record); }
diff --git a/tools/gn/loader_unittest.cc b/tools/gn/loader_unittest.cc index 20b8609..fb33e5e2 100644 --- a/tools/gn/loader_unittest.cc +++ b/tools/gn/loader_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include <map> +#include <memory> #include <utility> #include <vector> @@ -68,8 +69,8 @@ // Sets a given response for a given source file. void MockInputFileManager::AddCannedResponse(const SourceFile& source_file, const std::string& source) { - std::unique_ptr<CannedResult> canned(new CannedResult); - canned->input_file.reset(new InputFile(source_file)); + std::unique_ptr<CannedResult> canned = std::make_unique<CannedResult>(); + canned->input_file = std::make_unique<InputFile>(source_file); canned->input_file->SetContents(source); // Tokenize.
diff --git a/tools/gn/ninja_binary_target_writer_unittest.cc b/tools/gn/ninja_binary_target_writer_unittest.cc index fc0b3280..71804ef 100644 --- a/tools/gn/ninja_binary_target_writer_unittest.cc +++ b/tools/gn/ninja_binary_target_writer_unittest.cc
@@ -4,6 +4,7 @@ #include "tools/gn/ninja_binary_target_writer.h" +#include <memory> #include <sstream> #include <utility> @@ -582,7 +583,7 @@ pch_settings.set_default_toolchain_label(setup.toolchain()->label()); // Declare a C++ compiler that supports PCH. - std::unique_ptr<Tool> cxx_tool(new Tool); + std::unique_ptr<Tool> cxx_tool = std::make_unique<Tool>(); TestWithScope::SetCommandForTool( "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} " "-o {{output}}", @@ -593,7 +594,7 @@ pch_toolchain.SetTool(Toolchain::TYPE_CXX, std::move(cxx_tool)); // Add a C compiler as well. - std::unique_ptr<Tool> cc_tool(new Tool); + std::unique_ptr<Tool> cc_tool = std::make_unique<Tool>(); TestWithScope::SetCommandForTool( "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} " "-o {{output}}", @@ -709,7 +710,7 @@ pch_settings.set_default_toolchain_label(setup.toolchain()->label()); // Declare a C++ compiler that supports PCH. - std::unique_ptr<Tool> cxx_tool(new Tool); + std::unique_ptr<Tool> cxx_tool = std::make_unique<Tool>(); TestWithScope::SetCommandForTool( "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} " "-o {{output}}", @@ -721,7 +722,7 @@ pch_toolchain.ToolchainSetupComplete(); // Add a C compiler as well. - std::unique_ptr<Tool> cc_tool(new Tool); + std::unique_ptr<Tool> cc_tool = std::make_unique<Tool>(); TestWithScope::SetCommandForTool( "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} " "-o {{output}}",
diff --git a/tools/gn/operators_unittest.cc b/tools/gn/operators_unittest.cc index d72e08b..4b8ab37 100644 --- a/tools/gn/operators_unittest.cc +++ b/tools/gn/operators_unittest.cc
@@ -5,6 +5,8 @@ #include "tools/gn/operators.h" #include <stdint.h> + +#include <memory> #include <utility> #include "testing/gtest/include/gtest/gtest.h" @@ -62,7 +64,7 @@ } void SetLeftToValue(const Value& value) { - set_left(std::unique_ptr<ParseNode>(new TestParseNode(value))); + set_left(std::make_unique<TestParseNode>(value)); } // Sets the left-hand side of the operator to an identifier node, this is @@ -70,23 +72,23 @@ void SetLeftToIdentifier(const char* identifier) { left_identifier_token_ownership_ = Token(Location(), Token::IDENTIFIER, identifier); - set_left(std::unique_ptr<ParseNode>( - new IdentifierNode(left_identifier_token_ownership_))); + set_left( + std::make_unique<IdentifierNode>(left_identifier_token_ownership_)); } void SetRightToValue(const Value& value) { - set_right(std::unique_ptr<ParseNode>(new TestParseNode(value))); + set_right(std::make_unique<TestParseNode>(value)); } void SetRightToListOfValue(const Value& value) { Value list(nullptr, Value::LIST); list.list_value().push_back(value); - set_right(std::unique_ptr<ParseNode>(new TestParseNode(list))); + set_right(std::make_unique<TestParseNode>(list)); } void SetRightToListOfValue(const Value& value1, const Value& value2) { Value list(nullptr, Value::LIST); list.list_value().push_back(value1); list.list_value().push_back(value2); - set_right(std::unique_ptr<ParseNode>(new TestParseNode(list))); + set_right(std::make_unique<TestParseNode>(list)); } private: @@ -113,7 +115,7 @@ node.SetLeftToIdentifier(sources); // Set up the filter on the scope to remove everything ending with "rm" - std::unique_ptr<PatternList> pattern_list(new PatternList); + std::unique_ptr<PatternList> pattern_list = std::make_unique<PatternList>(); pattern_list->Append(Pattern("*rm")); setup.scope()->set_sources_assignment_filter(std::move(pattern_list)); @@ -189,7 +191,7 @@ // This should fail. const char str_str[] = "\"hi\""; Token str(Location(), Token::STRING, str_str); - node.set_right(std::unique_ptr<ParseNode>(new LiteralNode(str))); + node.set_right(std::make_unique<LiteralNode>(str)); ExecuteBinaryOperator(setup.scope(), &node, node.left(), node.right(), &err); EXPECT_TRUE(err.has_error()); err = Err(); @@ -276,8 +278,7 @@ // Set right as foo, but don't define a value for it. const char foo[] = "foo"; Token identifier_token(Location(), Token::IDENTIFIER, foo); - node.set_right( - std::unique_ptr<ParseNode>(new IdentifierNode(identifier_token))); + node.set_right(std::make_unique<IdentifierNode>(identifier_token)); Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(), node.right(), &err); @@ -295,8 +296,7 @@ // Set right as foo, but don't define a value for it. const char foo[] = "foo"; Token identifier_token(Location(), Token::IDENTIFIER, foo); - node.set_right( - std::unique_ptr<ParseNode>(new IdentifierNode(identifier_token))); + node.set_right(std::make_unique<IdentifierNode>(identifier_token)); Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(), node.right(), &err); @@ -336,8 +336,7 @@ // Set up "foo" with a nonempty scope. const char bar[] = "bar"; - old_value = - Value(nullptr, std::unique_ptr<Scope>(new Scope(setup.settings()))); + old_value = Value(nullptr, std::make_unique<Scope>(setup.settings())); old_value.scope_value()->SetValue(bar, Value(nullptr, "bar"), nullptr); setup.scope()->SetValue(foo, old_value, nullptr); @@ -350,7 +349,7 @@ // Assigning an empty list should succeed. node.SetRightToValue( - Value(nullptr, std::unique_ptr<Scope>(new Scope(setup.settings())))); + Value(nullptr, std::make_unique<Scope>(setup.settings()))); node.Execute(setup.scope(), &err); ASSERT_FALSE(err.has_error()); new_value = setup.scope()->GetValue(foo);
diff --git a/tools/gn/parse_tree.cc b/tools/gn/parse_tree.cc index d1de9cbf..3dae3e6 100644 --- a/tools/gn/parse_tree.cc +++ b/tools/gn/parse_tree.cc
@@ -6,6 +6,7 @@ #include <stdint.h> +#include <memory> #include <string> #include <tuple> @@ -110,7 +111,7 @@ Comments* ParseNode::comments_mutable() { if (!comments_) - comments_.reset(new Comments); + comments_ = std::make_unique<Comments>(); return comments_.get(); } @@ -315,7 +316,7 @@ Scope* execution_scope; // Either the enclosing_scope or nested_scope. if (result_mode_ == RETURNS_SCOPE) { // Create a nested scope to save the values for returning. - nested_scope.reset(new Scope(enclosing_scope)); + nested_scope = std::make_unique<Scope>(enclosing_scope); execution_scope = nested_scope.get(); } else { // Use the enclosing scope. Modifications will go into this also (for
diff --git a/tools/gn/parse_tree_unittest.cc b/tools/gn/parse_tree_unittest.cc index 06092157..a786925b4 100644 --- a/tools/gn/parse_tree_unittest.cc +++ b/tools/gn/parse_tree_unittest.cc
@@ -5,6 +5,8 @@ #include "tools/gn/parse_tree.h" #include <stdint.h> + +#include <memory> #include <utility> #include "testing/gtest/include/gtest/gtest.h" @@ -24,8 +26,8 @@ AccessorNode accessor; accessor.set_base(base_token); - std::unique_ptr<IdentifierNode> member_identifier( - new IdentifierNode(member_token)); + std::unique_ptr<IdentifierNode> member_identifier = + std::make_unique<IdentifierNode>(member_token); accessor.set_member(std::move(member_identifier)); // The access should fail because a is not defined. @@ -37,8 +39,7 @@ // Define a as a Scope. It should still fail because b isn't defined. err = Err(); setup.scope()->SetValue( - "a", Value(nullptr, std::unique_ptr<Scope>(new Scope(setup.scope()))), - nullptr); + "a", Value(nullptr, std::make_unique<Scope>(setup.scope())), nullptr); result = accessor.Execute(setup.scope(), &err); EXPECT_TRUE(err.has_error()); EXPECT_EQ(Value::NONE, result.type());
diff --git a/tools/gn/parser.cc b/tools/gn/parser.cc index 7e2c7f43..cc146e4 100644 --- a/tools/gn/parser.cc +++ b/tools/gn/parser.cc
@@ -4,10 +4,10 @@ #include "tools/gn/parser.h" +#include <memory> #include <utility> #include "base/logging.h" -#include "base/memory/ptr_util.h" #include "tools/gn/functions.h" #include "tools/gn/operators.h" #include "tools/gn/token.h" @@ -460,7 +460,7 @@ } std::unique_ptr<ParseNode> Parser::Literal(const Token& token) { - return base::MakeUnique<LiteralNode>(token); + return std::make_unique<LiteralNode>(token); } std::unique_ptr<ParseNode> Parser::Name(const Token& token) { @@ -468,7 +468,8 @@ } std::unique_ptr<ParseNode> Parser::BlockComment(const Token& token) { - std::unique_ptr<BlockCommentNode> comment(new BlockCommentNode()); + std::unique_ptr<BlockCommentNode> comment = + std::make_unique<BlockCommentNode>(); comment->set_comment(token); return std::move(comment); } @@ -490,7 +491,7 @@ *err_ = Err(token, "Expected right-hand side for '!'."); return std::unique_ptr<ParseNode>(); } - std::unique_ptr<UnaryOpNode> unary_op(new UnaryOpNode); + std::unique_ptr<UnaryOpNode> unary_op = std::make_unique<UnaryOpNode>(); unary_op->set_op(token); unary_op->set_operand(std::move(expr)); return std::move(unary_op); @@ -515,7 +516,7 @@ } return std::unique_ptr<ParseNode>(); } - std::unique_ptr<BinaryOpNode> binary_op(new BinaryOpNode); + std::unique_ptr<BinaryOpNode> binary_op = std::make_unique<BinaryOpNode>(); binary_op->set_op(token); binary_op->set_left(std::move(left)); binary_op->set_right(std::move(right)); @@ -525,9 +526,9 @@ std::unique_ptr<ParseNode> Parser::IdentifierOrCall( std::unique_ptr<ParseNode> left, const Token& token) { - std::unique_ptr<ListNode> list(new ListNode); + std::unique_ptr<ListNode> list = std::make_unique<ListNode>(); list->set_begin_token(token); - list->set_end(base::MakeUnique<EndNode>(token)); + list->set_end(std::make_unique<EndNode>(token)); std::unique_ptr<BlockNode> block; bool has_arg = false; if (LookAhead(Token::LEFT_PAREN)) { @@ -552,9 +553,10 @@ if (!left && !has_arg) { // Not a function call, just a standalone identifier. - return std::unique_ptr<ParseNode>(new IdentifierNode(token)); + return std::make_unique<IdentifierNode>(token); } - std::unique_ptr<FunctionCallNode> func_call(new FunctionCallNode); + std::unique_ptr<FunctionCallNode> func_call = + std::make_unique<FunctionCallNode>(); func_call->set_function(token); func_call->set_args(std::move(list)); if (block) @@ -576,7 +578,7 @@ *err_ = Err(token, "Expected right-hand side for assignment."); return std::unique_ptr<ParseNode>(); } - std::unique_ptr<BinaryOpNode> assign(new BinaryOpNode); + std::unique_ptr<BinaryOpNode> assign = std::make_unique<BinaryOpNode>(); assign->set_op(token); assign->set_left(std::move(left)); assign->set_right(std::move(value)); @@ -596,7 +598,7 @@ } std::unique_ptr<ParseNode> value = ParseExpression(); Consume(Token::RIGHT_BRACKET, "Expecting ']' after subscript."); - std::unique_ptr<AccessorNode> accessor(new AccessorNode); + std::unique_ptr<AccessorNode> accessor = std::make_unique<AccessorNode>(); accessor->set_base(left->AsIdentifier()->value()); accessor->set_index(std::move(value)); return std::move(accessor); @@ -619,7 +621,7 @@ return std::unique_ptr<ParseNode>(); } - std::unique_ptr<AccessorNode> accessor(new AccessorNode); + std::unique_ptr<AccessorNode> accessor = std::make_unique<AccessorNode>(); accessor->set_base(left->AsIdentifier()->value()); accessor->set_member(std::unique_ptr<IdentifierNode>( static_cast<IdentifierNode*>(right.release()))); @@ -630,7 +632,7 @@ std::unique_ptr<ListNode> Parser::ParseList(const Token& start_token, Token::Type stop_before, bool allow_trailing_comma) { - std::unique_ptr<ListNode> list(new ListNode); + std::unique_ptr<ListNode> list = std::make_unique<ListNode>(); list->set_begin_token(start_token); bool just_got_comma = false; bool first_time = true; @@ -667,12 +669,13 @@ *err_ = Err(cur_token(), "Trailing comma"); return std::unique_ptr<ListNode>(); } - list->set_end(base::MakeUnique<EndNode>(cur_token())); + list->set_end(std::make_unique<EndNode>(cur_token())); return list; } std::unique_ptr<ParseNode> Parser::ParseFile() { - std::unique_ptr<BlockNode> file(new BlockNode(BlockNode::DISCARDS_RESULT)); + std::unique_ptr<BlockNode> file = + std::make_unique<BlockNode>(BlockNode::DISCARDS_RESULT); for (;;) { if (at_end()) break; @@ -721,12 +724,12 @@ BlockNode::ResultMode result_mode) { if (has_error()) return std::unique_ptr<BlockNode>(); - std::unique_ptr<BlockNode> block(new BlockNode(result_mode)); + std::unique_ptr<BlockNode> block = std::make_unique<BlockNode>(result_mode); block->set_begin_token(begin_brace); for (;;) { if (LookAhead(Token::RIGHT_BRACE)) { - block->set_end(base::MakeUnique<EndNode>(Consume())); + block->set_end(std::make_unique<EndNode>(Consume())); break; } @@ -739,7 +742,7 @@ } std::unique_ptr<ParseNode> Parser::ParseCondition() { - std::unique_ptr<ConditionNode> condition(new ConditionNode); + std::unique_ptr<ConditionNode> condition = std::make_unique<ConditionNode>(); condition->set_if_token(Consume(Token::IF, "Expected 'if'")); Consume(Token::LEFT_PAREN, "Expected '(' after 'if'."); condition->set_condition(ParseExpression());
diff --git a/tools/gn/scope.cc b/tools/gn/scope.cc index 024d5ec..6802a5a 100644 --- a/tools/gn/scope.cc +++ b/tools/gn/scope.cc
@@ -4,8 +4,9 @@ #include "tools/gn/scope.h" +#include <memory> + #include "base/logging.h" -#include "base/memory/ptr_util.h" #include "tools/gn/parse_tree.h" #include "tools/gn/template.h" @@ -346,7 +347,7 @@ } std::unique_ptr<Scope>& dest_scope = dest->target_defaults_[current_name]; - dest_scope = base::MakeUnique<Scope>(settings_); + dest_scope = std::make_unique<Scope>(settings_); pair.second->NonRecursiveMergeTo(dest_scope.get(), options, node_for_err, "<SHOULDN'T HAPPEN>", err); } @@ -363,8 +364,8 @@ return false; } } - dest->sources_assignment_filter_.reset( - new PatternList(*sources_assignment_filter_)); + dest->sources_assignment_filter_ = + std::make_unique<PatternList>(*sources_assignment_filter_); } // Templates. @@ -412,14 +413,14 @@ if (const_containing_) { // We reached the top of the mutable scope stack. The result scope just // references the const scope (which will never change). - result.reset(new Scope(const_containing_)); + result = std::make_unique<Scope>(const_containing_); } else if (mutable_containing_) { // There are more nested mutable scopes. Recursively go up the stack to // get the closure. result = mutable_containing_->MakeClosure(); } else { // This is a standalone scope, just copy it. - result.reset(new Scope(settings_)); + result = std::make_unique<Scope>(settings_); } // Want to clobber since we've flattened some nested scopes, and our parent @@ -437,7 +438,7 @@ Scope* Scope::MakeTargetDefaults(const std::string& target_type) { std::unique_ptr<Scope>& dest = target_defaults_[target_type]; - dest = base::MakeUnique<Scope>(settings_); + dest = std::make_unique<Scope>(settings_); return dest.get(); }
diff --git a/tools/gn/scope_per_file_provider.cc b/tools/gn/scope_per_file_provider.cc index 737a5cd..f8c6026 100644 --- a/tools/gn/scope_per_file_provider.cc +++ b/tools/gn/scope_per_file_provider.cc
@@ -4,6 +4,8 @@ #include "tools/gn/scope_per_file_provider.h" +#include <memory> + #include "tools/gn/filesystem_utils.h" #include "tools/gn/settings.h" #include "tools/gn/source_file.h" @@ -46,77 +48,73 @@ const Value* ScopePerFileProvider::GetCurrentToolchain() { if (!current_toolchain_) { - current_toolchain_.reset(new Value( + current_toolchain_ = std::make_unique<Value>( nullptr, - scope_->settings()->toolchain_label().GetUserVisibleName(false))); + scope_->settings()->toolchain_label().GetUserVisibleName(false)); } return current_toolchain_.get(); } const Value* ScopePerFileProvider::GetDefaultToolchain() { if (!default_toolchain_) { - default_toolchain_.reset(new Value( + default_toolchain_ = std::make_unique<Value>( nullptr, scope_->settings()->default_toolchain_label().GetUserVisibleName( - false))); + false)); } return default_toolchain_.get(); } const Value* ScopePerFileProvider::GetPythonPath() { if (!python_path_) { - python_path_.reset(new Value( + python_path_ = std::make_unique<Value>( nullptr, - FilePathToUTF8(scope_->settings()->build_settings()->python_path()))); + FilePathToUTF8(scope_->settings()->build_settings()->python_path())); } return python_path_.get(); } const Value* ScopePerFileProvider::GetRootBuildDir() { if (!root_build_dir_) { - root_build_dir_.reset(new Value( + root_build_dir_ = std::make_unique<Value>( nullptr, DirectoryWithNoLastSlash( - scope_->settings()->build_settings()->build_dir()))); + scope_->settings()->build_settings()->build_dir())); } return root_build_dir_.get(); } const Value* ScopePerFileProvider::GetRootGenDir() { if (!root_gen_dir_) { - root_gen_dir_.reset(new Value( - nullptr, - DirectoryWithNoLastSlash(GetBuildDirAsSourceDir( - BuildDirContext(scope_), BuildDirType::GEN)))); + root_gen_dir_ = std::make_unique<Value>( + nullptr, DirectoryWithNoLastSlash(GetBuildDirAsSourceDir( + BuildDirContext(scope_), BuildDirType::GEN))); } return root_gen_dir_.get(); } const Value* ScopePerFileProvider::GetRootOutDir() { if (!root_out_dir_) { - root_out_dir_.reset(new Value( - nullptr, - DirectoryWithNoLastSlash(GetScopeCurrentBuildDirAsSourceDir( - scope_, BuildDirType::TOOLCHAIN_ROOT)))); + root_out_dir_ = std::make_unique<Value>( + nullptr, DirectoryWithNoLastSlash(GetScopeCurrentBuildDirAsSourceDir( + scope_, BuildDirType::TOOLCHAIN_ROOT))); } return root_out_dir_.get(); } const Value* ScopePerFileProvider::GetTargetGenDir() { if (!target_gen_dir_) { - target_gen_dir_.reset(new Value( - nullptr, - DirectoryWithNoLastSlash( - GetScopeCurrentBuildDirAsSourceDir(scope_, BuildDirType::GEN)))); + target_gen_dir_ = std::make_unique<Value>( + nullptr, DirectoryWithNoLastSlash(GetScopeCurrentBuildDirAsSourceDir( + scope_, BuildDirType::GEN))); } return target_gen_dir_.get(); } const Value* ScopePerFileProvider::GetTargetOutDir() { if (!target_out_dir_) { - target_out_dir_.reset(new Value( - nullptr, - DirectoryWithNoLastSlash( - GetScopeCurrentBuildDirAsSourceDir(scope_, BuildDirType::OBJ)))); + target_out_dir_ = std::make_unique<Value>( + nullptr, DirectoryWithNoLastSlash(GetScopeCurrentBuildDirAsSourceDir( + scope_, BuildDirType::OBJ))); } return target_out_dir_.get(); }
diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc index e3b01a4a..50a304f 100644 --- a/tools/gn/setup.cc +++ b/tools/gn/setup.cc
@@ -5,7 +5,9 @@ #include "tools/gn/setup.h" #include <stdlib.h> + #include <algorithm> +#include <memory> #include <sstream> #include <utility> @@ -423,7 +425,7 @@ } bool Setup::FillArgsFromCommandLine(const std::string& args) { - args_input_file_.reset(new InputFile(SourceFile())); + args_input_file_ = std::make_unique<InputFile>(SourceFile()); args_input_file_->SetContents(args); args_input_file_->set_friendly_name("the command-line \"--args\""); return FillArgsFromArgsInputFile(); @@ -447,7 +449,7 @@ if (contents.empty()) return true; // Empty file, do nothing. - args_input_file_.reset(new InputFile(build_arg_source_file)); + args_input_file_ = std::make_unique<InputFile>(build_arg_source_file); args_input_file_->SetContents(contents); args_input_file_->set_friendly_name( "build arg file (use \"gn args <out_dir>\" to edit)"); @@ -668,7 +670,7 @@ if (scheduler_.verbose_logging()) scheduler_.Log("Got dotfile", FilePathToUTF8(dotfile_name_)); - dotfile_input_file_.reset(new InputFile(SourceFile("//.gn"))); + dotfile_input_file_ = std::make_unique<InputFile>(SourceFile("//.gn")); if (!dotfile_input_file_->Load(dotfile_name_)) { Err(Location(), "Could not load dotfile.", "The file \"" + FilePathToUTF8(dotfile_name_) + "\" couldn't be loaded") @@ -771,7 +773,8 @@ err.PrintToStdout(); return false; } - std::unique_ptr<std::set<SourceFile>> whitelist(new std::set<SourceFile>); + std::unique_ptr<std::set<SourceFile>> whitelist = + std::make_unique<std::set<SourceFile>>(); for (const auto& item : exec_script_whitelist_value->list_value()) { if (!item.VerifyTypeIs(Value::STRING, &err)) { err.PrintToStdout();
diff --git a/tools/gn/string_utils_unittest.cc b/tools/gn/string_utils_unittest.cc index eb021a8..3e87c77 100644 --- a/tools/gn/string_utils_unittest.cc +++ b/tools/gn/string_utils_unittest.cc
@@ -5,6 +5,8 @@ #include "tools/gn/string_utils.h" #include <stdint.h> + +#include <memory> #include <utility> #include "testing/gtest/include/gtest/gtest.h" @@ -23,8 +25,8 @@ scope.SetValue("onestring", Value(nullptr, "one"), nullptr); // Nested scope called "onescope" with a value "one" inside it. - std::unique_ptr<Scope> onescope( - new Scope(static_cast<const Settings*>(nullptr))); + std::unique_ptr<Scope> onescope = + std::make_unique<Scope>(static_cast<const Settings*>(nullptr)); onescope->SetValue("one", Value(nullptr, one), nullptr); scope.SetValue("onescope", Value(nullptr, std::move(onescope)), nullptr);
diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc index d7511156..c31e754 100644 --- a/tools/gn/target_generator.cc +++ b/tools/gn/target_generator.cc
@@ -6,6 +6,7 @@ #include <stddef.h> +#include <memory> #include <utility> #include "tools/gn/action_target_generator.h" @@ -90,7 +91,8 @@ if (g_scheduler->verbose_logging()) g_scheduler->Log("Defining target", label.GetUserVisibleName(true)); - std::unique_ptr<Target> target(new Target(scope->settings(), label)); + std::unique_ptr<Target> target = + std::make_unique<Target>(scope->settings(), label); target->set_defined_from(function_call); // Create and call out to the proper generator.
diff --git a/tools/gn/target_unittest.cc b/tools/gn/target_unittest.cc index 9ddcf37..bf943e88 100644 --- a/tools/gn/target_unittest.cc +++ b/tools/gn/target_unittest.cc
@@ -4,6 +4,7 @@ #include "tools/gn/target.h" +#include <memory> #include <utility> #include "testing/gtest/include/gtest/gtest.h" @@ -589,7 +590,7 @@ Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc")); - std::unique_ptr<Tool> solink_tool(new Tool()); + std::unique_ptr<Tool> solink_tool = std::make_unique<Tool>(); solink_tool->set_output_prefix("lib"); solink_tool->set_default_output_extension(".so"); @@ -630,7 +631,7 @@ Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc")); - std::unique_ptr<Tool> solink_tool(new Tool()); + std::unique_ptr<Tool> solink_tool = std::make_unique<Tool>(); solink_tool->set_output_prefix(""); solink_tool->set_default_output_extension(".dll");
diff --git a/tools/gn/template.cc b/tools/gn/template.cc index 66d6745..0cc3131 100644 --- a/tools/gn/template.cc +++ b/tools/gn/template.cc
@@ -4,6 +4,7 @@ #include "tools/gn/template.h" +#include <memory> #include <utility> #include "tools/gn/err.h" @@ -38,7 +39,7 @@ // First run the invocation's block. Need to allocate the scope on the heap // so we can pass ownership to the template. - std::unique_ptr<Scope> invocation_scope(new Scope(scope)); + std::unique_ptr<Scope> invocation_scope = std::make_unique<Scope>(scope); if (!FillTargetBlockScope(scope, invocation, template_name, block, args, invocation_scope.get(), err)) return Value();
diff --git a/tools/gn/test_with_scope.cc b/tools/gn/test_with_scope.cc index b239c640..d5c80c2 100644 --- a/tools/gn/test_with_scope.cc +++ b/tools/gn/test_with_scope.cc
@@ -4,6 +4,7 @@ #include "tools/gn/test_with_scope.h" +#include <memory> #include <utility> #include "base/bind.h" @@ -74,7 +75,7 @@ Err err; // CC - std::unique_ptr<Tool> cc_tool(new Tool); + std::unique_ptr<Tool> cc_tool = std::make_unique<Tool>(); SetCommandForTool( "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} " "-o {{output}}", @@ -84,7 +85,7 @@ toolchain->SetTool(Toolchain::TYPE_CC, std::move(cc_tool)); // CXX - std::unique_ptr<Tool> cxx_tool(new Tool); + std::unique_ptr<Tool> cxx_tool = std::make_unique<Tool>(); SetCommandForTool( "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} " "-o {{output}}", @@ -94,7 +95,7 @@ toolchain->SetTool(Toolchain::TYPE_CXX, std::move(cxx_tool)); // OBJC - std::unique_ptr<Tool> objc_tool(new Tool); + std::unique_ptr<Tool> objc_tool = std::make_unique<Tool>(); SetCommandForTool( "objcc {{source}} {{cflags}} {{cflags_objc}} {{defines}} " "{{include_dirs}} -o {{output}}", @@ -104,7 +105,7 @@ toolchain->SetTool(Toolchain::TYPE_OBJC, std::move(objc_tool)); // OBJC - std::unique_ptr<Tool> objcxx_tool(new Tool); + std::unique_ptr<Tool> objcxx_tool = std::make_unique<Tool>(); SetCommandForTool( "objcxx {{source}} {{cflags}} {{cflags_objcc}} {{defines}} " "{{include_dirs}} -o {{output}}", @@ -116,7 +117,7 @@ // Don't use RC and ASM tools in unit tests yet. Add here if needed. // ALINK - std::unique_ptr<Tool> alink_tool(new Tool); + std::unique_ptr<Tool> alink_tool = std::make_unique<Tool>(); SetCommandForTool("ar {{output}} {{source}}", alink_tool.get()); alink_tool->set_lib_switch("-l"); alink_tool->set_lib_dir_switch("-L"); @@ -126,7 +127,7 @@ toolchain->SetTool(Toolchain::TYPE_ALINK, std::move(alink_tool)); // SOLINK - std::unique_ptr<Tool> solink_tool(new Tool); + std::unique_ptr<Tool> solink_tool = std::make_unique<Tool>(); SetCommandForTool("ld -shared -o {{target_output_name}}.so {{inputs}} " "{{ldflags}} {{libs}}", solink_tool.get()); solink_tool->set_lib_switch("-l"); @@ -138,7 +139,7 @@ toolchain->SetTool(Toolchain::TYPE_SOLINK, std::move(solink_tool)); // SOLINK_MODULE - std::unique_ptr<Tool> solink_module_tool(new Tool); + std::unique_ptr<Tool> solink_module_tool = std::make_unique<Tool>(); SetCommandForTool("ld -bundle -o {{target_output_name}}.so {{inputs}} " "{{ldflags}} {{libs}}", solink_module_tool.get()); solink_module_tool->set_lib_switch("-l"); @@ -151,7 +152,7 @@ std::move(solink_module_tool)); // LINK - std::unique_ptr<Tool> link_tool(new Tool); + std::unique_ptr<Tool> link_tool = std::make_unique<Tool>(); SetCommandForTool("ld -o {{target_output_name}} {{source}} " "{{ldflags}} {{libs}}", link_tool.get()); link_tool->set_lib_switch("-l"); @@ -161,23 +162,23 @@ toolchain->SetTool(Toolchain::TYPE_LINK, std::move(link_tool)); // STAMP - std::unique_ptr<Tool> stamp_tool(new Tool); + std::unique_ptr<Tool> stamp_tool = std::make_unique<Tool>(); SetCommandForTool("touch {{output}}", stamp_tool.get()); toolchain->SetTool(Toolchain::TYPE_STAMP, std::move(stamp_tool)); // COPY - std::unique_ptr<Tool> copy_tool(new Tool); + std::unique_ptr<Tool> copy_tool = std::make_unique<Tool>(); SetCommandForTool("cp {{source}} {{output}}", copy_tool.get()); toolchain->SetTool(Toolchain::TYPE_COPY, std::move(copy_tool)); // COPY_BUNDLE_DATA - std::unique_ptr<Tool> copy_bundle_data_tool(new Tool); + std::unique_ptr<Tool> copy_bundle_data_tool = std::make_unique<Tool>(); SetCommandForTool("cp {{source}} {{output}}", copy_bundle_data_tool.get()); toolchain->SetTool(Toolchain::TYPE_COPY_BUNDLE_DATA, std::move(copy_bundle_data_tool)); // COMPILE_XCASSETS - std::unique_ptr<Tool> compile_xcassets_tool(new Tool); + std::unique_ptr<Tool> compile_xcassets_tool = std::make_unique<Tool>(); SetCommandForTool("touch {{output}}", compile_xcassets_tool.get()); toolchain->SetTool(Toolchain::TYPE_COMPILE_XCASSETS, std::move(compile_xcassets_tool));
diff --git a/tools/gn/visibility.cc b/tools/gn/visibility.cc index b32586ce..d130caf 100644 --- a/tools/gn/visibility.cc +++ b/tools/gn/visibility.cc
@@ -4,7 +4,8 @@ #include "tools/gn/visibility.h" -#include "base/memory/ptr_util.h" +#include <memory> + #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/values.h" @@ -86,11 +87,10 @@ } std::unique_ptr<base::Value> Visibility::AsValue() const { - auto* res = new base::ListValue(); + auto res = std::make_unique<base::ListValue>(); for (const auto& pattern : patterns_) res->AppendString(pattern.Describe()); - - return WrapUnique(res); + return res; } // static
diff --git a/tools/gn/visual_studio_writer.cc b/tools/gn/visual_studio_writer.cc index bbb99c6f..4e56b77 100644 --- a/tools/gn/visual_studio_writer.cc +++ b/tools/gn/visual_studio_writer.cc
@@ -397,7 +397,7 @@ base::FilePath vcxproj_path = build_settings_->GetFullPath(target_file); std::string vcxproj_path_str = FilePathToUTF8(vcxproj_path); - projects_.emplace_back(new SolutionProject( + projects_.push_back(std::make_unique<SolutionProject>( project_name, vcxproj_path_str, MakeGuid(vcxproj_path_str, kGuidSeedProject), FilePathToUTF8(build_settings_->GetFullPath(target->label().dir())), @@ -817,9 +817,9 @@ project->parent_folder = it->second; } else { std::string folder_path_str = folder_path.as_string(); - std::unique_ptr<SolutionEntry> folder(new SolutionEntry( + std::unique_ptr<SolutionEntry> folder = std::make_unique<SolutionEntry>( FindLastDirComponent(SourceDir(folder_path)).as_string(), - folder_path_str, MakeGuid(folder_path_str, kGuidSeedFolder))); + folder_path_str, MakeGuid(folder_path_str, kGuidSeedFolder)); project->parent_folder = folder.get(); processed_paths[folder_path] = folder.get(); folders_.push_back(std::move(folder)); @@ -862,10 +862,11 @@ if (it != processed_paths.end()) { folder = it->second; } else { - std::unique_ptr<SolutionEntry> new_folder(new SolutionEntry( - FindLastDirComponent(SourceDir(parent_path)).as_string(), - parent_path.as_string(), - MakeGuid(parent_path.as_string(), kGuidSeedFolder))); + std::unique_ptr<SolutionEntry> new_folder = + std::make_unique<SolutionEntry>( + FindLastDirComponent(SourceDir(parent_path)).as_string(), + parent_path.as_string(), + MakeGuid(parent_path.as_string(), kGuidSeedFolder)); processed_paths[parent_path] = new_folder.get(); folder = new_folder.get(); additional_folders.push_back(std::move(new_folder));
diff --git a/tools/gn/visual_studio_writer_unittest.cc b/tools/gn/visual_studio_writer_unittest.cc index 6a7fbfc..b924182 100644 --- a/tools/gn/visual_studio_writer_unittest.cc +++ b/tools/gn/visual_studio_writer_unittest.cc
@@ -4,6 +4,8 @@ #include "tools/gn/visual_studio_writer.h" +#include <memory> + #include "base/strings/string_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "tools/gn/test_with_scope.h" @@ -33,24 +35,28 @@ std::string path = MakeTestPath("/foo/chromium/src/out/Debug/obj/base/base.vcxproj"); - writer.projects_.emplace_back(new VisualStudioWriter::SolutionProject( - "base", path, MakeGuid(path, "project"), - MakeTestPath("/foo/chromium/src/base"), "Win32")); + writer.projects_.push_back( + std::make_unique<VisualStudioWriter::SolutionProject>( + "base", path, MakeGuid(path, "project"), + MakeTestPath("/foo/chromium/src/base"), "Win32")); path = MakeTestPath("/foo/chromium/src/out/Debug/obj/tools/gn/gn.vcxproj"); - writer.projects_.emplace_back(new VisualStudioWriter::SolutionProject( - "gn", path, MakeGuid(path, "project"), - MakeTestPath("/foo/chromium/src/tools/gn"), "Win32")); + writer.projects_.push_back( + std::make_unique<VisualStudioWriter::SolutionProject>( + "gn", path, MakeGuid(path, "project"), + MakeTestPath("/foo/chromium/src/tools/gn"), "Win32")); path = MakeTestPath("/foo/chromium/src/out/Debug/obj/chrome/chrome.vcxproj"); - writer.projects_.emplace_back(new VisualStudioWriter::SolutionProject( - "chrome", path, MakeGuid(path, "project"), - MakeTestPath("/foo/chromium/src/chrome"), "Win32")); + writer.projects_.push_back( + std::make_unique<VisualStudioWriter::SolutionProject>( + "chrome", path, MakeGuid(path, "project"), + MakeTestPath("/foo/chromium/src/chrome"), "Win32")); path = MakeTestPath("/foo/chromium/src/out/Debug/obj/base/bar.vcxproj"); - writer.projects_.emplace_back(new VisualStudioWriter::SolutionProject( - "bar", path, MakeGuid(path, "project"), - MakeTestPath("/foo/chromium/src/base"), "Win32")); + writer.projects_.push_back( + std::make_unique<VisualStudioWriter::SolutionProject>( + "bar", path, MakeGuid(path, "project"), + MakeTestPath("/foo/chromium/src/base"), "Win32")); writer.ResolveSolutionFolders(); @@ -88,20 +94,23 @@ std::string path = MakeTestPath("/foo/chromium/src/out/Debug/obj/base/base.vcxproj"); - writer.projects_.emplace_back(new VisualStudioWriter::SolutionProject( - "base", path, MakeGuid(path, "project"), - MakeTestPath("/foo/chromium/src/base"), "Win32")); + writer.projects_.push_back( + std::make_unique<VisualStudioWriter::SolutionProject>( + "base", path, MakeGuid(path, "project"), + MakeTestPath("/foo/chromium/src/base"), "Win32")); path = MakeTestPath("/foo/chromium/src/out/Debug/obj/tools/gn/gn.vcxproj"); - writer.projects_.emplace_back(new VisualStudioWriter::SolutionProject( - "gn", path, MakeGuid(path, "project"), - MakeTestPath("/foo/chromium/src/tools/gn"), "Win32")); + writer.projects_.push_back( + std::make_unique<VisualStudioWriter::SolutionProject>( + "gn", path, MakeGuid(path, "project"), + MakeTestPath("/foo/chromium/src/tools/gn"), "Win32")); path = MakeTestPath( "/foo/chromium/src/out/Debug/obj/ABS_PATH/C/foo/bar/bar.vcxproj"); - writer.projects_.emplace_back(new VisualStudioWriter::SolutionProject( - "bar", path, MakeGuid(path, "project"), MakeTestPath("/foo/bar"), - "Win32")); + writer.projects_.push_back( + std::make_unique<VisualStudioWriter::SolutionProject>( + "bar", path, MakeGuid(path, "project"), MakeTestPath("/foo/bar"), + "Win32")); std::string baz_label_dir_path = MakeTestPath("/foo/bar/baz"); #if defined(OS_WIN) @@ -110,8 +119,9 @@ #endif path = MakeTestPath( "/foo/chromium/src/out/Debug/obj/ABS_PATH/C/foo/bar/baz/baz.vcxproj"); - writer.projects_.emplace_back(new VisualStudioWriter::SolutionProject( - "baz", path, MakeGuid(path, "project"), baz_label_dir_path, "Win32")); + writer.projects_.push_back( + std::make_unique<VisualStudioWriter::SolutionProject>( + "baz", path, MakeGuid(path, "project"), baz_label_dir_path, "Win32")); writer.ResolveSolutionFolders();
diff --git a/tools/gn/xcode_object.cc b/tools/gn/xcode_object.cc index 17d82e5..b229d2d3 100644 --- a/tools/gn/xcode_object.cc +++ b/tools/gn/xcode_object.cc
@@ -5,12 +5,12 @@ #include "tools/gn/xcode_object.h" #include <iomanip> +#include <memory> #include <sstream> #include <utility> #include "base/logging.h" #include "base/macros.h" -#include "base/memory/ptr_util.h" #include "base/strings/string_util.h" #include "tools/gn/filesystem_utils.h" @@ -321,7 +321,7 @@ name_(name) { if (!shell_script.empty()) { build_phases_.push_back( - base::MakeUnique<PBXShellScriptBuildPhase>(name, shell_script)); + std::make_unique<PBXShellScriptBuildPhase>(name, shell_script)); } } @@ -541,7 +541,7 @@ } } - children_.push_back(base::MakeUnique<PBXFileReference>( + children_.push_back(std::make_unique<PBXFileReference>( navigator_path, source_path, std::string())); return static_cast<PBXFileReference*>(children_.back().get()); } @@ -560,7 +560,7 @@ } if (!group) { - children_.push_back(base::MakeUnique<PBXGroup>(component.as_string(), + children_.push_back(std::make_unique<PBXGroup>(component.as_string(), component.as_string())); group = static_cast<PBXGroup*>(children_.back().get()); } @@ -617,11 +617,11 @@ product_type_(product_type), product_name_(product_name) { DCHECK(product_reference_); - build_phases_.push_back(base::MakeUnique<PBXSourcesBuildPhase>()); + build_phases_.push_back(std::make_unique<PBXSourcesBuildPhase>()); source_build_phase_ = static_cast<PBXSourcesBuildPhase*>(build_phases_.back().get()); - build_phases_.push_back(base::MakeUnique<PBXFrameworksBuildPhase>()); + build_phases_.push_back(std::make_unique<PBXFrameworksBuildPhase>()); } PBXNativeTarget::~PBXNativeTarget() {} @@ -629,7 +629,7 @@ void PBXNativeTarget::AddFileForIndexing(const PBXFileReference* file_reference, const CompilerFlags compiler_flag) { DCHECK(file_reference); - source_build_phase_->AddBuildFile(base::MakeUnique<PBXBuildFile>( + source_build_phase_->AddBuildFile(std::make_unique<PBXBuildFile>( file_reference, source_build_phase_, compiler_flag)); } @@ -664,11 +664,11 @@ main_group_.reset(new PBXGroup); sources_ = static_cast<PBXGroup*>( - main_group_->AddChild(base::MakeUnique<PBXGroup>(source_path, "Source"))); + main_group_->AddChild(std::make_unique<PBXGroup>(source_path, "Source"))); sources_->set_is_source(true); products_ = static_cast<PBXGroup*>(main_group_->AddChild( - base::MakeUnique<PBXGroup>(std::string(), "Product"))); - main_group_->AddChild(base::MakeUnique<PBXGroup>(std::string(), "Build")); + std::make_unique<PBXGroup>(std::string(), "Product"))); + main_group_->AddChild(std::make_unique<PBXGroup>(std::string(), "Build")); configurations_.reset(new XCConfigurationList(config_name, attributes, this)); } @@ -707,7 +707,7 @@ attributes["CONFIGURATION_BUILD_DIR"] = "."; attributes["PRODUCT_NAME"] = name; - targets_.push_back(base::MakeUnique<PBXAggregateTarget>( + targets_.push_back(std::make_unique<PBXAggregateTarget>( name, shell_script, config_name_, attributes)); } @@ -719,11 +719,11 @@ attributes["PRODUCT_NAME"] = "sources"; PBXFileReference* product_reference = static_cast<PBXFileReference*>( - products_->AddChild(base::MakeUnique<PBXFileReference>( + products_->AddChild(std::make_unique<PBXFileReference>( std::string(), "sources", "compiled.mach-o.executable"))); const char product_type[] = "com.apple.product-type.tool"; - targets_.push_back(base::MakeUnique<PBXNativeTarget>( + targets_.push_back(std::make_unique<PBXNativeTarget>( "sources", std::string(), config_name_, attributes, product_type, "sources", product_reference)); target_for_indexing_ = static_cast<PBXNativeTarget*>(targets_.back().get()); @@ -738,7 +738,7 @@ const PBXAttributes& extra_attributes) { base::StringPiece ext = FindExtension(&output_name); PBXFileReference* product = static_cast<PBXFileReference*>( - products_->AddChild(base::MakeUnique<PBXFileReference>( + products_->AddChild(std::make_unique<PBXFileReference>( std::string(), output_name, type.empty() ? GetSourceType(ext) : type))); @@ -760,7 +760,7 @@ attributes["CONFIGURATION_BUILD_DIR"] = "."; attributes["PRODUCT_NAME"] = product_name; - targets_.push_back(base::MakeUnique<PBXNativeTarget>( + targets_.push_back(std::make_unique<PBXNativeTarget>( name, shell_script, config_name_, attributes, output_type, product_name, product)); return static_cast<PBXNativeTarget*>(targets_.back().get()); @@ -953,7 +953,7 @@ : owner_reference_(owner_reference) { DCHECK(owner_reference_); configurations_.push_back( - base::MakeUnique<XCBuildConfiguration>(name, attributes)); + std::make_unique<XCBuildConfiguration>(name, attributes)); } XCConfigurationList::~XCConfigurationList() {}
diff --git a/tools/gn/xcode_object_unittest.cc b/tools/gn/xcode_object_unittest.cc index 52a98b9..656d0b74 100644 --- a/tools/gn/xcode_object_unittest.cc +++ b/tools/gn/xcode_object_unittest.cc
@@ -4,7 +4,6 @@ #include "tools/gn/xcode_object.h" -#include "base/memory/ptr_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -306,22 +305,23 @@ // Tests the mapping between PBXObjectClass and it's name as a string. TEST(XcodeObject, ClassToString) { - EXPECT_EQ("PBXAggregateTarget", ToString(PBXAggregateTargetClass)); - EXPECT_EQ("PBXBuildFile", ToString(PBXBuildFileClass)); - EXPECT_EQ("PBXAggregateTarget", ToString(PBXAggregateTargetClass)); - EXPECT_EQ("PBXBuildFile", ToString(PBXBuildFileClass)); - EXPECT_EQ("PBXContainerItemProxy", ToString(PBXContainerItemProxyClass)); - EXPECT_EQ("PBXFileReference", ToString(PBXFileReferenceClass)); - EXPECT_EQ("PBXFrameworksBuildPhase", ToString(PBXFrameworksBuildPhaseClass)); - EXPECT_EQ("PBXGroup", ToString(PBXGroupClass)); - EXPECT_EQ("PBXNativeTarget", ToString(PBXNativeTargetClass)); - EXPECT_EQ("PBXProject", ToString(PBXProjectClass)); - EXPECT_EQ("PBXSourcesBuildPhase", ToString(PBXSourcesBuildPhaseClass)); - EXPECT_EQ("PBXTargetDependency", ToString(PBXTargetDependencyClass)); - EXPECT_EQ("XCBuildConfiguration", ToString(XCBuildConfigurationClass)); - EXPECT_EQ("XCConfigurationList", ToString(XCConfigurationListClass)); - EXPECT_EQ("PBXShellScriptBuildPhase", - ToString(PBXShellScriptBuildPhaseClass)); + EXPECT_STREQ("PBXAggregateTarget", ToString(PBXAggregateTargetClass)); + EXPECT_STREQ("PBXBuildFile", ToString(PBXBuildFileClass)); + EXPECT_STREQ("PBXAggregateTarget", ToString(PBXAggregateTargetClass)); + EXPECT_STREQ("PBXBuildFile", ToString(PBXBuildFileClass)); + EXPECT_STREQ("PBXContainerItemProxy", ToString(PBXContainerItemProxyClass)); + EXPECT_STREQ("PBXFileReference", ToString(PBXFileReferenceClass)); + EXPECT_STREQ("PBXFrameworksBuildPhase", + ToString(PBXFrameworksBuildPhaseClass)); + EXPECT_STREQ("PBXGroup", ToString(PBXGroupClass)); + EXPECT_STREQ("PBXNativeTarget", ToString(PBXNativeTargetClass)); + EXPECT_STREQ("PBXProject", ToString(PBXProjectClass)); + EXPECT_STREQ("PBXSourcesBuildPhase", ToString(PBXSourcesBuildPhaseClass)); + EXPECT_STREQ("PBXTargetDependency", ToString(PBXTargetDependencyClass)); + EXPECT_STREQ("XCBuildConfiguration", ToString(XCBuildConfigurationClass)); + EXPECT_STREQ("XCConfigurationList", ToString(XCConfigurationListClass)); + EXPECT_STREQ("PBXShellScriptBuildPhase", + ToString(PBXShellScriptBuildPhaseClass)); } // Tests the mapping between PBXObject and it's name as a string.
diff --git a/tools/gn/xcode_writer.cc b/tools/gn/xcode_writer.cc index c10ebb4..3134b489 100644 --- a/tools/gn/xcode_writer.cc +++ b/tools/gn/xcode_writer.cc
@@ -13,7 +13,6 @@ #include "base/environment.h" #include "base/logging.h" -#include "base/memory/ptr_util.h" #include "base/sha1.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -151,8 +150,8 @@ PBXTarget* dependent_pbxtarget, const PBXProject* project) { auto container_item_proxy = - base::MakeUnique<PBXContainerItemProxy>(project, base_pbxtarget); - auto dependency = base::MakeUnique<PBXTargetDependency>( + std::make_unique<PBXContainerItemProxy>(project, base_pbxtarget); + auto dependency = std::make_unique<PBXTargetDependency>( base_pbxtarget, std::move(container_item_proxy)); dependent_pbxtarget->AddDependency(std::move(dependency));
diff --git a/tools/gn/xml_element_writer.cc b/tools/gn/xml_element_writer.cc index ecc4f7b..127766c 100644 --- a/tools/gn/xml_element_writer.cc +++ b/tools/gn/xml_element_writer.cc
@@ -4,7 +4,7 @@ #include "tools/gn/xml_element_writer.h" -#include "base/memory/ptr_util.h" +#include <memory> XmlAttributes::XmlAttributes() {} @@ -64,7 +64,7 @@ const std::string& tag, const XmlAttributes& attributes) { StartContent(true); - return base::MakeUnique<XmlElementWriter>(out_, tag, attributes, indent_ + 2); + return std::make_unique<XmlElementWriter>(out_, tag, attributes, indent_ + 2); } std::ostream& XmlElementWriter::StartContent(bool start_new_line) {
diff --git a/tools/gn/xml_element_writer.h b/tools/gn/xml_element_writer.h index 0e8fa01f..4aa5f7e3 100644 --- a/tools/gn/xml_element_writer.h +++ b/tools/gn/xml_element_writer.h
@@ -12,7 +12,6 @@ #include <vector> #include "base/macros.h" -#include "base/memory/ptr_util.h" #include "base/strings/string_piece.h" // Vector of XML attribute key-value pairs. @@ -116,7 +115,7 @@ const std::string& attribute_name, const Writer& attribute_value_writer) { StartContent(true); - return base::MakeUnique<XmlElementWriter>( + return std::make_unique<XmlElementWriter>( out_, tag, attribute_name, attribute_value_writer, indent_ + 2); }
diff --git a/tools/gritsettings/startup_resources_mac.txt b/tools/gritsettings/startup_resources_mac.txt index f9daa12..dbfbe4a 100644 --- a/tools/gritsettings/startup_resources_mac.txt +++ b/tools/gritsettings/startup_resources_mac.txt
@@ -261,6 +261,5 @@ IDS_AUTOCOMPLETE_SEARCH_DESCRIPTION 361 IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR 362 IDR_OVERLAY_DROP_SHADOW 363 -IDS_ANNOUNCEMENT_COMPLETION_AVAILABLE_MAC 364 -IDS_EXTENSION_PROMPT_WARNING_CLIPBOARD_READWRITE 365 -IDS_EXTENSION_PROMPT_WARNING_NOTIFICATIONS 366 +IDS_EXTENSION_PROMPT_WARNING_CLIPBOARD_READWRITE 364 +IDS_EXTENSION_PROMPT_WARNING_NOTIFICATIONS 365
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index cab1031..b14791c 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -847,7 +847,7 @@ <description>Please enter the description of this user action.</description> </action> -<action name="Accel_Search_LWin"> +<action name="Accel_Search_LWin" not_user_triggered="true"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description> </action> @@ -1583,6 +1583,14 @@ <description>Promo banner for an instant app has been dismissed.</description> </action> +<action name="Android.InstantApps.BannerDismissedAppIsDefault"> + <owner>thildebr@chromium.org</owner> + <description> + A promo banner shown when opening the instant app is default has been + dismissed. + </description> +</action> + <action name="Android.InstantApps.BannerOpen"> <owner>mariakhomenko@chromium.org</owner> <description> @@ -1590,11 +1598,29 @@ </description> </action> +<action name="Android.InstantApps.BannerOpenAppIsDefault"> + <owner>thildebr@chromium.org</owner> + <description> + User clicked "Open App" button on an instant apps banner that was + shown when opening the app was default, signaling that they were using the + mobile web first, and decided to switch over to the instant app. + </description> +</action> + <action name="Android.InstantApps.BannerShown" not_user_triggered="true"> <owner>mariakhomenko@chromium.org</owner> <description>Promo banner for an instant app has been displayed.</description> </action> +<action name="Android.InstantApps.BannerShownAppIsDefault" + not_user_triggered="true"> + <owner>thildebr@chromium.org</owner> + <description> + Promo banner for an instant app has been displayed when opening the app is + default. + </description> +</action> + <action name="Android.InstantApps.InstantAppsEligiblePageLoaded"> <owner>mariakhomenko@chromium.org</owner> <description> @@ -12362,7 +12388,7 @@ <description>Please enter the description of this user action.</description> </action> -<action name="Mouse_Down"> +<action name="Mouse_Down" not_user_triggered="true"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description> </action> @@ -12955,12 +12981,12 @@ <description>Please enter the description of this user action.</description> </action> -<action name="OpenFileSystemPersistent"> +<action name="OpenFileSystemPersistent" not_user_triggered="true"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description> </action> -<action name="OpenFileSystemTemporary"> +<action name="OpenFileSystemTemporary" not_user_triggered="true"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description> </action> @@ -17509,7 +17535,7 @@ <description>Please enter the description of this user action.</description> </action> -<action name="StatusArea_BrightnessChanged"> +<action name="StatusArea_BrightnessChanged" not_user_triggered="true"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description> </action> @@ -18477,7 +18503,7 @@ </description> </action> -<action name="TextToSpeech.Stop"> +<action name="TextToSpeech.Stop" not_user_triggered="true"> <owner>dmazzoni@chromium.org</owner> <description>Synthesized speech is stopped.</description> </action> @@ -18662,7 +18688,7 @@ </description> </action> -<action name="TrackpadScrollFling"> +<action name="TrackpadScrollFling" not_user_triggered="true"> <owner>tdresser@chromium.org</owner> <description>Logged on an ET_SCROLL_FLING_START scroll event.</description> </action> @@ -19048,7 +19074,7 @@ </description> </action> -<action name="WebView.PermissionAllow.FileSystem"> +<action name="WebView.PermissionAllow.FileSystem" not_user_triggered="true"> <owner>fsamuel@chromium.org</owner> <owner>hanxi@chromium.org</owner> <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 43a4faf..b3a6c2a 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -16976,6 +16976,8 @@ <int value="2233" label="PerformanceMeasurePassedInObject"/> <int value="2234" label="PerformanceMeasurePassedInNavigationTiming"/> <int value="2235" label="HTMLFrameSetElementNonNullAnonymousNamedGetter"/> + <int value="2236" label="CSPWithUnsafeEval"/> + <int value="2237" label="WebAssemblyInstantiation"/> </enum> <enum name="FeedbackSource"> @@ -22388,6 +22390,12 @@ <int value="50" label="CRASH"/> </enum> +<enum name="InterstitialTypeEnum"> + <int value="0" label="Loud"/> + <int value="1" label="Quiet small"/> + <int value="2" label="Quiet giant"/> +</enum> + <enum name="InvalidationNetworkChannel"> <int value="0" label="PushClientChannel"/> <int value="1" label="GCMNetworkChannel"/> @@ -22574,6 +22582,10 @@ <int value="7" label="Tab navigated"> The user navigated the tab (e.g. back/forward, reload) </int> + <int value="8" label="Tab switched out"> + The page displaying the dialog was switched out of its tab (e.g. tab + discarding) + </int> </enum> <enum name="JumplisticonsDeleteCategory"> @@ -27750,6 +27762,7 @@ <int value="11" label="AC3"/> <int value="12" label="DOLBYVISION"/> <int value="13" label="FLAC"/> + <int value="14" label="AV1"/> </enum> <enum name="MultiAccountUpdateBubbleUserAction"> @@ -30813,6 +30826,25 @@ <int value="3" label="Cookie contains both control chars and is invalid"/> </enum> +<enum name="PartnerBookmark.FaviconFetchResult"> + <int value="0" label="SUCCESS"> + Success - favicon found in local cache or fetched from server. + </int> + <int value="1" label="FAILURE_SERVER_ERROR"> + Received a server error fetching the favicon. + </int> + <int value="2" label="FAILURE_ICON_SERVICE_UNAVAILABLE"> + The icon service was unavailable. + </int> + <int value="3" label="FAILURE_NOT_IN_CACHE"> + There was nothing in the cache, but we opted out of retrieving from server. + </int> + <int value="4" label="FAILURE_CONNECTION_ERROR"> + Request sent out and a connection error occurred (no valid HTTP response + received). + </int> +</enum> + <enum name="PassiveForcedListenerResultType"> <int value="0" label="PreventDefaultNotCalled"/> <int value="1" label="DocumentLevelTouchPreventDefaultCalled"/> @@ -34896,6 +34928,8 @@ <int value="1" label="RESOLVE_FAIL"/> <int value="2" label="RESOLVE_SPECULATIVE_SUCCESS"/> <int value="3" label="RESOLVE_SPECULATIVE_FAIL"/> + <int value="4" label="RESOLVE_ABORT"/> + <int value="5" label="RESOLVE_SPECULATIVE_ABORT"/> </enum> <enum name="ResolutionUnspecWasteCategory">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 48f41ba..9b4b377c 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -57674,6 +57674,15 @@ </summary> </histogram> +<histogram name="PartnerBookmark.FaviconThrottleFetchResult" + enum="PartnerBookmark.FaviconFetchResult"> + <owner>thildebr@chromium.org</owner> + <summary> + The response we got back from our favicon fetching throttler, once for each + bookmark at each cold start. Only recorded on Android. + </summary> +</histogram> + <histogram name="PartnerBookmark.Null" enum="BooleanNull"> <owner>wychen@chromium.org</owner> <summary> @@ -57692,6 +57701,15 @@ </summary> </histogram> +<histogram name="PartnerBookmarksFaviconThrottle.NumEntries" units="entries"> + <owner>thildebr@chromium.org</owner> + <summary> + Number of elements read from the partner bookmarks favicon cache, recorded + once per cold start when reading partner bookmarks. Only recorded on + Android. + </summary> +</histogram> + <histogram name="PasswordBubble.DisplayDisposition" enum="PasswordBubbleDisplayDisposition"> <owner>vasilii@chromium.org</owner> @@ -70677,6 +70695,14 @@ </summary> </histogram> +<histogram name="SafeBrowsing.Interstitial.Type" enum="InterstitialTypeEnum"> + <owner>ntfschr@chromium.org</owner> + <summary> + Which interstitial type is being displayed to the user? This currently + applies only to WebView (where we show Loud vs. Quiet interstitials). + </summary> +</histogram> + <histogram name="SafeBrowsing.ModuleBaseRelocation" units="BaseRelocationType"> <owner>csharp@chromium.org</owner> <owner>krstnmnlsn@chromium.org</owner> @@ -71477,6 +71503,16 @@ </summary> </histogram> +<histogram name="SafeBrowsing.WebView.Viewable" enum="BooleanVisible"> + <owner>ntfschr@chromium.org</owner> + <summary> + When encountering an unsafe resource, this indicates whether the WebView is + considered to be viewable or not. Currently, we define "viewable" + as getVisibility() == View.VISIBLE and attached to the Android View + hierarchy. + </summary> +</histogram> + <histogram name="SB.BloomFilter" units="ms"> <obsolete> Has not been generated for years (7/8/14). @@ -76397,6 +76433,25 @@ </summary> </histogram> +<histogram name="ServiceWorker.CacheStorageInstalledScript.CachedMetadataSize" + units="bytes"> + <owner>horo@chromium.org</owner> + <summary> + The length of cached metadata of scripts which are stored to the + CacheStorage by the installing service worker. + </summary> +</histogram> + +<histogram + name="ServiceWorker.CacheStorageInstalledScript.CachedMetadataTotalSize" + units="bytes"> + <owner>horo@chromium.org</owner> + <summary> + The total length of cached metadata of scripts which are stored to the + CacheStorage by the installing service worker. + </summary> +</histogram> + <histogram name="ServiceWorker.CacheStorageInstalledScript.Count" units="count"> <owner>horo@chromium.org</owner> <summary>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 75f3164f..c0b4b5b09 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -772,6 +772,14 @@ means this was a SRC playback. </summary> </metric> + <metric name="IsTopFrame"> + <summary> + Flag indicating whether the report comes from the top frame or some inner + frame. For privacy, metrics from inner frames are recorded with the top + frame's origin, so this flag helps separate top frame vs. embedded + playbacks. + </summary> + </metric> <metric name="LastPipelineStatus"> <summary> media::PipelineStatus enum value. Always 0 if the playback succeeded; all
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py index 25c41015..0d8be642 100644 --- a/tools/perf/benchmarks/blink_perf.py +++ b/tools/perf/benchmarks/blink_perf.py
@@ -455,8 +455,7 @@ def GetExpectations(self): class StoryExpectations(story.expectations.StoryExpectations): def SetExpectations(self): - self.DisableStory('select-long-word.html', - [story.expectations.ALL], 'crbug.com/783345') + pass # Nothing disabled. return StoryExpectations()
diff --git a/tools/perf/chromium.perf.fyi.extras.json b/tools/perf/chromium.perf.fyi.extras.json index 9dee64d..f75feda 100644 --- a/tools/perf/chromium.perf.fyi.extras.json +++ b/tools/perf/chromium.perf.fyi.extras.json
@@ -138,6 +138,12 @@ ], "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "id": "build34-a1", + "pool": "Chrome-perf-fyi" + } + ], "expiration": 36000, "hard_timeout": 10800, "ignore_task_failure": false,
diff --git a/tools/valgrind/gtest_exclude/browser_tests.gtest-memcheck.txt b/tools/valgrind/gtest_exclude/browser_tests.gtest-memcheck.txt index 337b367..e3bc87e 100644 --- a/tools/valgrind/gtest_exclude/browser_tests.gtest-memcheck.txt +++ b/tools/valgrind/gtest_exclude/browser_tests.gtest-memcheck.txt
@@ -54,5 +54,4 @@ SafeBrowsingInterstitialVersions/SafeBrowsingBlockingPageBrowserTest.ProceedDisabled* SocketApiTest.SocketTCPExtension SocketApiTest.SocketUDPExtension -SSLUITest.TestWSSInvalidCertAndGoForward WebViewTest.Shim
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h index 1fba473..0e1a293 100644 --- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h +++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
@@ -94,20 +94,17 @@ RootLayer* old_layer, float scale_factor); - // Check to see if the CALayer tree can be represented entirely by a video - // layer on a black background. If so, then commit the layer, assign it to - // |low_power_layer|, and return true. Otherwise return false. This is to - // be called by CommitToCA(). - bool CommitFullscreenLowPowerLayer(ContentLayer* old_low_power_layer, - float scale_factor); + // Check to see if the CALayer tree is just a video layer on a black + // background. If so, return true and set background_rect to the + // background's bounding rect, otherwise return false. CommitToCA() calls + // this function and, based on its return value, either gives the root + // layer this frame and a black background color or clears them. + bool WantsFullcreenLowPowerBackdrop(float scale_factor, + gfx::RectF* background_rect); std::vector<ClipAndSortingLayer> clip_and_sorting_layers; base::scoped_nsobject<CALayer> ca_layer; - // Weak pointer to a child ContentLayer, if any, which is presented alone - // for fullscreen low power mode. Set by CommitFullscreenLowPowerLayer(). - ContentLayer* low_power_layer = nullptr; - private: DISALLOW_COPY_AND_ASSIGN(RootLayer); };
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm index 93faba5..05cbfe9 100644 --- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm +++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
@@ -218,31 +218,24 @@ scale_factor_ = scale_factor; } -bool CARendererLayerTree::RootLayer::CommitFullscreenLowPowerLayer( - ContentLayer* old_low_power_layer, - float scale_factor) { - ContentLayer* video_layer = nullptr; - CGRect clip_rect; - CGRect frame_rect; +bool CARendererLayerTree::RootLayer::WantsFullcreenLowPowerBackdrop( + float scale_factor, + gfx::RectF* background_rect) { + bool found_video_layer = false; for (auto& clip_layer : clip_and_sorting_layers) { for (auto& transform_layer : clip_layer.transform_layers) { for (auto& content_layer : transform_layer.content_layers) { // Detached mode requires that no layers be on top of the video layer. - if (video_layer) + if (found_video_layer) return false; // See if this is the video layer. if (content_layer.use_av_layer) { - video_layer = &content_layer; + found_video_layer = true; if (!transform_layer.transform.IsPositiveScaleOrTranslation()) return false; if (content_layer.opacity != 1) return false; - clip_rect = clip_layer.clip_rect.ToCGRect(); - gfx::RectF frame_rect_f(video_layer->rect); - transform_layer.transform.TransformRect(&frame_rect_f); - frame_rect_f.Scale(1 / scale_factor); - frame_rect = frame_rect_f.ToCGRect(); continue; } @@ -250,25 +243,16 @@ // solid black or transparent if (content_layer.io_surface) return false; - if (content_layer.background_color != SK_ColorBLACK && - content_layer.background_color != SK_ColorTRANSPARENT) { + if (content_layer.background_color == SK_ColorBLACK) { + background_rect->Union(gfx::RectF(content_layer.rect)); + } else if (content_layer.background_color != SK_ColorTRANSPARENT) { return false; } } } } - if (!video_layer) - return false; - low_power_layer = video_layer; - - low_power_layer->CommitToCA(ca_layer, old_low_power_layer, scale_factor); - if (![ca_layer backgroundColor]) - [ca_layer setBackgroundColor:CGColorGetConstantColor(kCGColorBlack)]; - if (!CGRectEqualToRect([ca_layer frame], clip_rect)) - [ca_layer setFrame:clip_rect]; - if (!CGRectEqualToRect([low_power_layer->ca_layer frame], frame_rect)) - [low_power_layer->ca_layer setFrame:frame_rect]; - return true; + background_rect->Scale(1 / scale_factor); + return found_video_layer; } id CARendererLayerTree::ContentsForSolidColorForTesting(SkColor color) { @@ -377,9 +361,13 @@ // output monitor color space, but IOSurface-backed layers are color // corrected. Note that this is only the case when the CALayers are shared // across processes. To make colors consistent across both solid color and - // IOSurface-backed layers, use a cache of solid-color IOSurfaces as contents. + // IOSurface-backed layers, use a cache of solid-color IOSurfaces as + // contents. Black and transparent layers must use real colors to be eligible + // for low power detachment in fullscreen. // https://crbug.com/633805 - if (!io_surface && !tree->allow_solid_color_layers_) { + if (!io_surface && !tree->allow_solid_color_layers_ && + background_color != SK_ColorBLACK && + background_color != SK_ColorTRANSPARENT) { solid_color_contents = SolidColorContents::Get(background_color); ContentLayer::contents_rect = gfx::RectF(0, 0, 1, 1); } @@ -529,18 +517,17 @@ DLOG(ERROR) << "CARendererLayerTree root layer not attached to tree."; } - ContentLayer* old_low_power_layer = - old_layer ? old_layer->low_power_layer : nullptr; - - if (CommitFullscreenLowPowerLayer(old_low_power_layer, scale_factor)) { - return; - } else if (old_low_power_layer) { - // Transitioning out of fullscreen low power mode, so: - // 1. Reset the root CALayer's background color and frame. - [ca_layer setBackgroundColor:nil]; - [ca_layer setFrame:CGRectZero]; - // 2. Reset old_layer so that the CALayer tree is rebuilt from scratch. - old_layer = nullptr; + gfx::RectF bg_rect; + if (WantsFullcreenLowPowerBackdrop(scale_factor, &bg_rect)) { + if (gfx::RectF([ca_layer frame]) != bg_rect) + [ca_layer setFrame:bg_rect.ToCGRect()]; + if (![ca_layer backgroundColor]) + [ca_layer setBackgroundColor:CGColorGetConstantColor(kCGColorBlack)]; + } else { + if (gfx::RectF([ca_layer frame]) != gfx::RectF()) + [ca_layer setFrame:CGRectZero]; + if ([ca_layer backgroundColor]) + [ca_layer setBackgroundColor:nil]; } for (size_t i = 0; i < clip_and_sorting_layers.size(); ++i) {
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc index 708489b5..6cfd00c1 100644 --- a/ui/accessibility/ax_event_generator.cc +++ b/ui/accessibility/ax_event_generator.cc
@@ -274,11 +274,6 @@ } void AXEventGenerator::OnNodeWillBeDeleted(AXTree* tree, AXNode* node) { - if (node->data().HasStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS) && - node->data().HasStringAttribute(ui::AX_ATTR_NAME)) { - FireLiveRegionEvents(node); - } - DCHECK_EQ(tree_, tree); tree_events_.erase(node); }
diff --git a/ui/accessibility/platform/ax_platform_node.cc b/ui/accessibility/platform/ax_platform_node.cc index d7f68012f..18bc0be2 100644 --- a/ui/accessibility/platform/ax_platform_node.cc +++ b/ui/accessibility/platform/ax_platform_node.cc
@@ -9,6 +9,7 @@ #include "build/build_config.h" #include "ui/accessibility/ax_node_data.h" #include "ui/accessibility/platform/ax_platform_node_delegate.h" +#include "ui/base/ui_features.h" namespace ui { @@ -16,6 +17,32 @@ base::LazyInstance<base::ObserverList<AXModeObserver>>::Leaky AXPlatformNode::ax_mode_observers_ = LAZY_INSTANCE_INITIALIZER; +// static +base::LazyInstance<AXPlatformNode::NativeWindowHandlerCallback>::Leaky + AXPlatformNode::native_window_handler_ = LAZY_INSTANCE_INITIALIZER; + +// static +AXPlatformNode* AXPlatformNode::FromNativeWindow( + gfx::NativeWindow native_window) { + if (native_window_handler_.Get()) + return native_window_handler_.Get().Run(native_window); + return nullptr; +} + +#if !BUILDFLAG_INTERNAL_HAS_NATIVE_ACCESSIBILITY() +// static +AXPlatformNode* AXPlatformNode::FromNativeViewAccessible( + gfx::NativeViewAccessible accessible) { + return nullptr; +} +#endif // !BUILDFLAG_INTERNAL_HAS_NATIVE_ACCESSIBILITY() + +// static +void AXPlatformNode::RegisterNativeWindowHandler( + AXPlatformNode::NativeWindowHandlerCallback handler) { + native_window_handler_.Get() = handler; +} + AXPlatformNode::AXPlatformNode() {} AXPlatformNode::~AXPlatformNode() {
diff --git a/ui/accessibility/platform/ax_platform_node.h b/ui/accessibility/platform/ax_platform_node.h index 8aa38ad..56a0664 100644 --- a/ui/accessibility/platform/ax_platform_node.h +++ b/ui/accessibility/platform/ax_platform_node.h
@@ -5,6 +5,7 @@ #ifndef UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_H_ #define UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_H_ +#include "base/callback.h" #include "base/lazy_instance.h" #include "base/observer_list.h" #include "build/build_config.h" @@ -24,6 +25,9 @@ // own the AXPlatformNode instance (or otherwise manage its lifecycle). class AX_EXPORT AXPlatformNode { public: + using NativeWindowHandlerCallback = + base::RepeatingCallback<AXPlatformNode*(gfx::NativeWindow)>; + // Create an appropriate platform-specific instance. The delegate owns the // AXPlatformNode instance (or manages its lifecycle in some other way). static AXPlatformNode* Create(AXPlatformNodeDelegate* delegate); @@ -33,6 +37,13 @@ static AXPlatformNode* FromNativeViewAccessible( gfx::NativeViewAccessible accessible); + // Return the AXPlatformNode at the root of the tree for a native window. + static AXPlatformNode* FromNativeWindow(gfx::NativeWindow native_window); + + // Provide a function that returns the AXPlatformNode at the root of the + // tree for a native window. + static void RegisterNativeWindowHandler(NativeWindowHandlerCallback handler); + // Register and unregister to receive notifications about AXMode changes // for this node. static void AddAXModeObserver(AXModeObserver* observer); @@ -66,6 +77,9 @@ // Global ObserverList for AXMode changes. static base::LazyInstance<base::ObserverList<AXModeObserver>>::Leaky ax_mode_observers_; + + static base::LazyInstance<NativeWindowHandlerCallback>::Leaky + native_window_handler_; }; } // namespace ui
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn index 397b11a..6039287f9 100644 --- a/ui/app_list/BUILD.gn +++ b/ui/app_list/BUILD.gn
@@ -12,25 +12,11 @@ "app_list_export.h", "app_list_features.cc", "app_list_features.h", - "app_list_folder_item.cc", - "app_list_folder_item.h", - "app_list_item.cc", - "app_list_item.h", - "app_list_item_list.cc", - "app_list_item_list.h", - "app_list_item_list_observer.h", - "app_list_item_observer.h", - "app_list_model.cc", - "app_list_model.h", - "app_list_model_observer.h", "app_list_switches.cc", "app_list_switches.h", "app_list_util.cc", "app_list_util.h", "app_list_view_delegate.h", - "app_list_view_state.h", - "folder_image.cc", - "folder_image.h", "pagination_controller.cc", "pagination_controller.h", "pagination_model.cc", @@ -48,24 +34,10 @@ "search/history_types.h", "search/mixer.cc", "search/mixer.h", - "search/term_break_iterator.cc", - "search/term_break_iterator.h", - "search/tokenized_string.cc", - "search/tokenized_string.h", - "search/tokenized_string_char_iterator.cc", - "search/tokenized_string_char_iterator.h", - "search/tokenized_string_match.cc", - "search/tokenized_string_match.h", - "search_box_model.cc", - "search_box_model.h", - "search_box_model_observer.h", "search_controller.cc", "search_controller.h", "search_provider.cc", "search_provider.h", - "search_result.cc", - "search_result.h", - "search_result_observer.h", "speech_ui_model.cc", "speech_ui_model.h", "speech_ui_model_observer.h", @@ -167,6 +139,11 @@ "//ui/views", "//ui/wm", ] + + # TODO(hejq): Remove this once app_list is migrated. http://crbug.com/733662 + public_deps = [ + "//ash/app_list/model:app_list_model", + ] } static_library("test_support") {
diff --git a/ui/app_list/DEPS b/ui/app_list/DEPS index e8eebfa..a366401 100644 --- a/ui/app_list/DEPS +++ b/ui/app_list/DEPS
@@ -19,4 +19,7 @@ "+ui/strings/grit/ui_strings.h", "+ui/views", "+ui/wm/core", + + # TODO(hejq): Remove this once app_list is migrated. http://crbug.com/733662 + "+ash/app_list", ]
diff --git a/ui/app_list/app_list_item_list_unittest.cc b/ui/app_list/app_list_item_list_unittest.cc index 38c4ec3..ded8740 100644 --- a/ui/app_list/app_list_item_list_unittest.cc +++ b/ui/app_list/app_list_item_list_unittest.cc
@@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/app_list/app_list_item_list.h" +#include "ash/app_list/model/app_list_item_list.h" #include <stddef.h> #include <memory> #include <utility> +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_item_list_observer.h" #include "base/macros.h" #include "base/strings/stringprintf.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_item_list_observer.h" namespace app_list {
diff --git a/ui/app_list/app_list_model_unittest.cc b/ui/app_list/app_list_model_unittest.cc index 12ebcce..564e66ed 100644 --- a/ui/app_list/app_list_model_unittest.cc +++ b/ui/app_list/app_list_model_unittest.cc
@@ -2,20 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/app_list/app_list_model.h" +#include "ash/app_list/model/app_list_model.h" #include <stddef.h> #include <map> #include <string> +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model_observer.h" #include "base/command_line.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model_observer.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/test/app_list_test_model.h" #include "ui/base/models/list_model_observer.h"
diff --git a/ui/app_list/app_list_util.h b/ui/app_list/app_list_util.h index 6832e29..cda7acb 100644 --- a/ui/app_list/app_list_util.h +++ b/ui/app_list/app_list_util.h
@@ -5,8 +5,8 @@ #ifndef UI_APP_LIST_APP_LIST_UTIL_H_ #define UI_APP_LIST_APP_LIST_UTIL_H_ +#include "ash/app_list/model/search_result.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/search_result.h" #include "ui/events/event.h" namespace views {
diff --git a/ui/app_list/folder_image_unittest.cc b/ui/app_list/folder_image_unittest.cc index 5900249..954f15cd 100644 --- a/ui/app_list/folder_image_unittest.cc +++ b/ui/app_list/folder_image_unittest.cc
@@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/app_list/folder_image.h" +#include "ash/app_list/model/folder_image.h" #include <string> #include <utility> +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_item_list.h" +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/app_list/app_list_constants.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_item_list.h" -#include "ui/app_list/app_list_model.h" #include "ui/gfx/skia_util.h" namespace app_list {
diff --git a/ui/app_list/search/history.cc b/ui/app_list/search/history.cc index 7277ad38..0e43257 100644 --- a/ui/app_list/search/history.cc +++ b/ui/app_list/search/history.cc
@@ -6,11 +6,11 @@ #include <stddef.h> +#include "ash/app_list/model/search/tokenized_string.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "ui/app_list/search/history_data.h" #include "ui/app_list/search/history_data_store.h" -#include "ui/app_list/search/tokenized_string.h" namespace app_list {
diff --git a/ui/app_list/search/mixer.cc b/ui/app_list/search/mixer.cc index 709e829f..8f71ba6 100644 --- a/ui/app_list/search/mixer.cc +++ b/ui/app_list/search/mixer.cc
@@ -10,11 +10,11 @@ #include <string> #include <vector> +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/search_provider.h" -#include "ui/app_list/search_result.h" namespace app_list {
diff --git a/ui/app_list/search/mixer.h b/ui/app_list/search/mixer.h index 41818396..1387a774 100644 --- a/ui/app_list/search/mixer.h +++ b/ui/app_list/search/mixer.h
@@ -10,10 +10,10 @@ #include <memory> #include <vector> +#include "ash/app_list/model/app_list_model.h" #include "base/gtest_prod_util.h" #include "base/macros.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/search/history_types.h" namespace app_list {
diff --git a/ui/app_list/search/mixer_unittest.cc b/ui/app_list/search/mixer_unittest.cc index bdc1b3d..9a69302 100644 --- a/ui/app_list/search/mixer_unittest.cc +++ b/ui/app_list/search/mixer_unittest.cc
@@ -11,6 +11,8 @@ #include <string> #include <vector> +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/search_result.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/strings/string16.h" @@ -19,10 +21,8 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/search/history_types.h" #include "ui/app_list/search_provider.h" -#include "ui/app_list/search_result.h" namespace app_list { namespace test {
diff --git a/ui/app_list/search/term_break_iterator_unittest.cc b/ui/app_list/search/term_break_iterator_unittest.cc index f9c586f..f21046a 100644 --- a/ui/app_list/search/term_break_iterator_unittest.cc +++ b/ui/app_list/search/term_break_iterator_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 "ui/app_list/search/term_break_iterator.h" +#include "ash/app_list/model/search/term_break_iterator.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ui/app_list/search/tokenized_string_char_iterator_unittest.cc b/ui/app_list/search/tokenized_string_char_iterator_unittest.cc index d5fe1b3..3b8b7b8 100644 --- a/ui/app_list/search/tokenized_string_char_iterator_unittest.cc +++ b/ui/app_list/search/tokenized_string_char_iterator_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 "ui/app_list/search/tokenized_string_char_iterator.h" +#include "ash/app_list/model/search/tokenized_string_char_iterator.h" #include <string> #include <vector>
diff --git a/ui/app_list/search/tokenized_string_match_unittest.cc b/ui/app_list/search/tokenized_string_match_unittest.cc index 6cf5be8..bf7cab0 100644 --- a/ui/app_list/search/tokenized_string_match_unittest.cc +++ b/ui/app_list/search/tokenized_string_match_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 "ui/app_list/search/tokenized_string_match.h" +#include "ash/app_list/model/search/tokenized_string_match.h" #include <stddef.h>
diff --git a/ui/app_list/search/tokenized_string_unittest.cc b/ui/app_list/search/tokenized_string_unittest.cc index c8c965b8..ca09b83 100644 --- a/ui/app_list/search/tokenized_string_unittest.cc +++ b/ui/app_list/search/tokenized_string_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 "ui/app_list/search/tokenized_string.h" +#include "ash/app_list/model/search/tokenized_string.h" #include <stddef.h>
diff --git a/ui/app_list/search_controller.cc b/ui/app_list/search_controller.cc index 8cb77e92..f29b64b6 100644 --- a/ui/app_list/search_controller.cc +++ b/ui/app_list/search_controller.cc
@@ -9,6 +9,8 @@ #include <utility> #include <vector> +#include "ash/app_list/model/search_box_model.h" +#include "ash/app_list/model/search_result.h" #include "base/bind.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" @@ -16,9 +18,7 @@ #include "base/strings/utf_string_conversions.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/search/history.h" -#include "ui/app_list/search_box_model.h" #include "ui/app_list/search_provider.h" -#include "ui/app_list/search_result.h" namespace app_list {
diff --git a/ui/app_list/search_controller.h b/ui/app_list/search_controller.h index ee6640bed..8c3c01fd 100644 --- a/ui/app_list/search_controller.h +++ b/ui/app_list/search_controller.h
@@ -9,9 +9,9 @@ #include <memory> +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/search/mixer.h" #include "ui/app_list/speech_ui_model_observer.h"
diff --git a/ui/app_list/search_provider.cc b/ui/app_list/search_provider.cc index a8887ee..38ee52a 100644 --- a/ui/app_list/search_provider.cc +++ b/ui/app_list/search_provider.cc
@@ -6,7 +6,7 @@ #include <utility> -#include "ui/app_list/search_result.h" +#include "ash/app_list/model/search_result.h" namespace app_list {
diff --git a/ui/app_list/test/app_list_test_model.h b/ui/app_list/test/app_list_test_model.h index 56480b0..e10b8a4 100644 --- a/ui/app_list/test/app_list_test_model.h +++ b/ui/app_list/test/app_list_test_model.h
@@ -7,10 +7,10 @@ #include <string> +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" namespace app_list {
diff --git a/ui/app_list/test/app_list_test_view_delegate.cc b/ui/app_list/test/app_list_test_view_delegate.cc index 6133b93..31dce54 100644 --- a/ui/app_list/test/app_list_test_view_delegate.cc +++ b/ui/app_list/test/app_list_test_view_delegate.cc
@@ -7,9 +7,9 @@ #include <string> #include <vector> +#include "ash/app_list/model/app_list_model.h" #include "base/callback.h" #include "base/files/file_path.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/test/app_list_test_model.h" #include "ui/gfx/image/image_skia.h"
diff --git a/ui/app_list/test/test_search_result.h b/ui/app_list/test/test_search_result.h index 8ee5489..bd69371 100644 --- a/ui/app_list/test/test_search_result.h +++ b/ui/app_list/test/test_search_result.h
@@ -5,8 +5,8 @@ #ifndef UI_APP_LIST_TEST_TEST_SEARCH_RESULT_H_ #define UI_APP_LIST_TEST_TEST_SEARCH_RESULT_H_ +#include "ash/app_list/model/search_result.h" #include "base/macros.h" -#include "ui/app_list/search_result.h" namespace app_list {
diff --git a/ui/app_list/views/app_list_folder_view.cc b/ui/app_list/views/app_list_folder_view.cc index 577b0e5b..f764e2a 100644 --- a/ui/app_list/views/app_list_folder_view.cc +++ b/ui/app_list/views/app_list_folder_view.cc
@@ -6,11 +6,11 @@ #include <algorithm> +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_model.h" #include "ui/accessibility/ax_node_data.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/views/app_list_item_view.h" #include "ui/app_list/views/app_list_main_view.h" #include "ui/app_list/views/apps_container_view.h"
diff --git a/ui/app_list/views/app_list_folder_view.h b/ui/app_list/views/app_list_folder_view.h index 95346cbf..ea20c069 100644 --- a/ui/app_list/views/app_list_folder_view.h +++ b/ui/app_list/views/app_list_folder_view.h
@@ -7,8 +7,8 @@ #include <string> +#include "ash/app_list/model/app_list_item_list_observer.h" #include "base/macros.h" -#include "ui/app_list/app_list_item_list_observer.h" #include "ui/app_list/views/apps_grid_view.h" #include "ui/app_list/views/apps_grid_view_folder_delegate.h" #include "ui/app_list/views/folder_header_view.h"
diff --git a/ui/app_list/views/app_list_item_view.cc b/ui/app_list/views/app_list_item_view.cc index 0c95bdd..df07325 100644 --- a/ui/app_list/views/app_list_item_view.cc +++ b/ui/app_list/views/app_list_item_view.cc
@@ -6,13 +6,13 @@ #include <algorithm> +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "ui/accessibility/ax_node_data.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/views/apps_grid_view.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/ui/app_list/views/app_list_item_view.h b/ui/app_list/views/app_list_item_view.h index 0ad68c6..6f39764 100644 --- a/ui/app_list/views/app_list_item_view.h +++ b/ui/app_list/views/app_list_item_view.h
@@ -8,12 +8,12 @@ #include <memory> #include <string> +#include "ash/app_list/model/app_list_item_observer.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/strings/string16.h" #include "base/timer/timer.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_item_observer.h" #include "ui/app_list/views/image_shadow_animator.h" #include "ui/views/context_menu_controller.h" #include "ui/views/controls/button/button.h"
diff --git a/ui/app_list/views/app_list_main_view.cc b/ui/app_list/views/app_list_main_view.cc index 6373f31..51f7634 100644 --- a/ui/app_list/views/app_list_main_view.cc +++ b/ui/app_list/views/app_list_main_view.cc
@@ -6,6 +6,10 @@ #include <algorithm> +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/search_box_model.h" #include "base/bind.h" #include "base/callback.h" #include "base/files/file_path.h" @@ -15,12 +19,8 @@ #include "base/strings/string_util.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/pagination_model.h" -#include "ui/app_list/search_box_model.h" #include "ui/app_list/views/app_list_folder_view.h" #include "ui/app_list/views/app_list_item_view.h" #include "ui/app_list/views/apps_container_view.h"
diff --git a/ui/app_list/views/app_list_main_view.h b/ui/app_list/views/app_list_main_view.h index 2df927a..a658172 100644 --- a/ui/app_list/views/app_list_main_view.h +++ b/ui/app_list/views/app_list_main_view.h
@@ -7,11 +7,11 @@ #include <string> +#include "ash/app_list/model/app_list_model_observer.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_model_observer.h" #include "ui/app_list/views/search_box_view_delegate.h" #include "ui/views/view.h"
diff --git a/ui/app_list/views/app_list_page.h b/ui/app_list/views/app_list_page.h index 9133c26..0424f30b 100644 --- a/ui/app_list/views/app_list_page.h +++ b/ui/app_list/views/app_list_page.h
@@ -5,9 +5,9 @@ #ifndef UI_APP_LIST_VIEWS_APP_LIST_PAGE_H_ #define UI_APP_LIST_VIEWS_APP_LIST_PAGE_H_ +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_model.h" #include "ui/views/view.h" namespace app_list {
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc index 285a5af3..045d8f74 100644 --- a/ui/app_list/views/app_list_view.cc +++ b/ui/app_list/views/app_list_view.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include <vector> +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" @@ -20,7 +21,6 @@ #include "ui/accessibility/platform/aura_window_properties.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_util.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/speech_ui_model.h"
diff --git a/ui/app_list/views/app_list_view.h b/ui/app_list/views/app_list_view.h index bf550bf4..57ba2164 100644 --- a/ui/app_list/views/app_list_view.h +++ b/ui/app_list/views/app_list_view.h
@@ -7,6 +7,7 @@ #include <memory> +#include "ash/app_list/model/app_list_view_state.h" #include "base/callback.h" #include "base/macros.h" #include "base/scoped_observer.h" @@ -14,7 +15,6 @@ #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_export.h" #include "ui/app_list/app_list_view_delegate_observer.h" -#include "ui/app_list/app_list_view_state.h" #include "ui/app_list/speech_ui_model_observer.h" #include "ui/display/display_observer.h" #include "ui/views/bubble/bubble_dialog_delegate.h"
diff --git a/ui/app_list/views/app_list_view_unittest.cc b/ui/app_list/views/app_list_view_unittest.cc index 834ef09..3568f92 100644 --- a/ui/app_list/views/app_list_view_unittest.cc +++ b/ui/app_list/views/app_list_view_unittest.cc
@@ -10,6 +10,7 @@ #include <string> #include <vector> +#include "ash/app_list/model/search_box_model.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" @@ -21,7 +22,6 @@ #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/pagination_model.h" -#include "ui/app_list/search_box_model.h" #include "ui/app_list/test/app_list_test_model.h" #include "ui/app_list/test/app_list_test_view_delegate.h" #include "ui/app_list/test/test_search_result.h"
diff --git a/ui/app_list/views/apps_container_view.h b/ui/app_list/views/apps_container_view.h index d07e50b..fc66ffbdc 100644 --- a/ui/app_list/views/apps_container_view.h +++ b/ui/app_list/views/apps_container_view.h
@@ -9,8 +9,8 @@ #include <vector> +#include "ash/app_list/model/app_list_folder_item.h" #include "base/macros.h" -#include "ui/app_list/app_list_folder_item.h" #include "ui/app_list/views/app_list_page.h" #include "ui/app_list/views/top_icon_animation_view.h"
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc index 004dc751..b40888c 100644 --- a/ui/app_list/views/apps_grid_view.cc +++ b/ui/app_list/views/apps_grid_view.cc
@@ -8,6 +8,8 @@ #include <set> #include <string> +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" #include "base/guid.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" @@ -15,8 +17,6 @@ #include "build/build_config.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/app_list_util.h" #include "ui/app_list/app_list_view_delegate.h" @@ -302,7 +302,6 @@ SK_ColorTRANSPARENT)); canvas->DrawRect(bottom_rect, flags); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {}
diff --git a/ui/app_list/views/apps_grid_view.h b/ui/app_list/views/apps_grid_view.h index ddf4e80f..af83449 100644 --- a/ui/app_list/views/apps_grid_view.h +++ b/ui/app_list/views/apps_grid_view.h
@@ -11,14 +11,14 @@ #include <string> #include <tuple> +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/app_list_model_observer.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/timer/timer.h" #include "build/build_config.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_model.h" -#include "ui/app_list/app_list_model_observer.h" #include "ui/app_list/pagination_model.h" #include "ui/app_list/pagination_model_observer.h" #include "ui/app_list/views/app_list_view.h"
diff --git a/ui/app_list/views/apps_grid_view_unittest.cc b/ui/app_list/views/apps_grid_view_unittest.cc index 50e3acae..7b6a551 100644 --- a/ui/app_list/views/apps_grid_view_unittest.cc +++ b/ui/app_list/views/apps_grid_view_unittest.cc
@@ -9,6 +9,9 @@ #include <memory> #include <string> +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" #include "base/command_line.h" #include "base/compiler_specific.h" #include "base/macros.h" @@ -22,9 +25,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/pagination_model.h" #include "ui/app_list/test/app_list_test_model.h"
diff --git a/ui/app_list/views/contents_view.h b/ui/app_list/views/contents_view.h index be3e01d..38e51ac 100644 --- a/ui/app_list/views/contents_view.h +++ b/ui/app_list/views/contents_view.h
@@ -9,10 +9,10 @@ #include <memory> #include <utility> +#include "ash/app_list/model/app_list_model.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/pagination_model.h" #include "ui/app_list/pagination_model_observer.h" #include "ui/views/view.h"
diff --git a/ui/app_list/views/folder_header_view.cc b/ui/app_list/views/folder_header_view.cc index a7b0893..40ed489 100644 --- a/ui/app_list/views/folder_header_view.cc +++ b/ui/app_list/views/folder_header_view.cc
@@ -6,11 +6,11 @@ #include <algorithm> +#include "ash/app_list/model/app_list_folder_item.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_folder_item.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/app_list_util.h" #include "ui/app_list/views/app_list_folder_view.h"
diff --git a/ui/app_list/views/folder_header_view.h b/ui/app_list/views/folder_header_view.h index 89ec638..9e2813b 100644 --- a/ui/app_list/views/folder_header_view.h +++ b/ui/app_list/views/folder_header_view.h
@@ -7,9 +7,9 @@ #include <string> +#include "ash/app_list/model/app_list_item_observer.h" #include "base/macros.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_item_observer.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/view.h"
diff --git a/ui/app_list/views/folder_header_view_unittest.cc b/ui/app_list/views/folder_header_view_unittest.cc index ea15026..1e9ea456 100644 --- a/ui/app_list/views/folder_header_view_unittest.cc +++ b/ui/app_list/views/folder_header_view_unittest.cc
@@ -9,15 +9,15 @@ #include <memory> #include <string> +#include "ash/app_list/model/app_list_folder_item.h" +#include "ash/app_list/model/app_list_item.h" +#include "ash/app_list/model/app_list_model.h" #include "base/command_line.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/app_list/app_list_constants.h" -#include "ui/app_list/app_list_folder_item.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/test/app_list_test_model.h" #include "ui/app_list/views/folder_header_view_delegate.h" #include "ui/views/test/views_test_base.h"
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc index ff642440..7fdd291 100644 --- a/ui/app_list/views/search_box_view.cc +++ b/ui/app_list/views/search_box_view.cc
@@ -6,6 +6,7 @@ #include <algorithm> +#include "ash/app_list/model/search_box_model.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "build/build_config.h" @@ -17,7 +18,6 @@ #include "ui/app_list/app_list_util.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/resources/grit/app_list_resources.h" -#include "ui/app_list/search_box_model.h" #include "ui/app_list/speech_ui_model.h" #include "ui/app_list/vector_icons/vector_icons.h" #include "ui/app_list/views/app_list_view.h"
diff --git a/ui/app_list/views/search_box_view.h b/ui/app_list/views/search_box_view.h index f703e54..dce9acb7 100644 --- a/ui/app_list/views/search_box_view.h +++ b/ui/app_list/views/search_box_view.h
@@ -7,11 +7,11 @@ #include <string> +#include "ash/app_list/model/app_list_model.h" +#include "ash/app_list/model/search_box_model_observer.h" #include "base/macros.h" #include "ui/app_list/app_list_constants.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_view_delegate_observer.h" -#include "ui/app_list/search_box_model_observer.h" #include "ui/app_list/speech_ui_model_observer.h" #include "ui/gfx/shadow_value.h" #include "ui/views/controls/button/image_button.h"
diff --git a/ui/app_list/views/search_result_actions_view.h b/ui/app_list/views/search_result_actions_view.h index ecbd984..71d8517 100644 --- a/ui/app_list/views/search_result_actions_view.h +++ b/ui/app_list/views/search_result_actions_view.h
@@ -5,8 +5,8 @@ #ifndef UI_APP_LIST_VIEWS_SEARCH_RESULT_ACTIONS_VIEW_H_ #define UI_APP_LIST_VIEWS_SEARCH_RESULT_ACTIONS_VIEW_H_ +#include "ash/app_list/model/search_result.h" #include "base/macros.h" -#include "ui/app_list/search_result.h" #include "ui/views/controls/button/button.h" #include "ui/views/view.h"
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 f9c8680..f1be44ed 100644 --- a/ui/app_list/views/search_result_answer_card_view.cc +++ b/ui/app_list/views/search_result_answer_card_view.cc
@@ -4,12 +4,12 @@ #include "ui/app_list/views/search_result_answer_card_view.h" +#include "ash/app_list/model/search_result_observer.h" #include "ui/accessibility/ax_node.h" #include "ui/accessibility/ax_node_data.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_view_delegate.h" -#include "ui/app_list/search_result_observer.h" #include "ui/views/background.h" #include "ui/views/controls/button/button.h" #include "ui/views/layout/box_layout.h"
diff --git a/ui/app_list/views/search_result_container_view.h b/ui/app_list/views/search_result_container_view.h index c8d6fc4..1fe4a38 100644 --- a/ui/app_list/views/search_result_container_view.h +++ b/ui/app_list/views/search_result_container_view.h
@@ -7,9 +7,10 @@ #include <stddef.h> +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "ui/app_list/app_list_model.h" +#include "ui/app_list/app_list_export.h" #include "ui/views/view.h" namespace app_list {
diff --git a/ui/app_list/views/search_result_list_view.cc b/ui/app_list/views/search_result_list_view.cc index d4020fb..bbc0e2a0 100644 --- a/ui/app_list/views/search_result_list_view.cc +++ b/ui/app_list/views/search_result_list_view.cc
@@ -7,13 +7,13 @@ #include <algorithm> #include <vector> +#include "ash/app_list/model/search_result.h" #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "base/time/time.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_view_delegate.h" -#include "ui/app_list/search_result.h" #include "ui/app_list/views/app_list_main_view.h" #include "ui/app_list/views/search_result_view.h" #include "ui/events/event.h"
diff --git a/ui/app_list/views/search_result_list_view_unittest.cc b/ui/app_list/views/search_result_list_view_unittest.cc index 1c9909f54..7eb3f617 100644 --- a/ui/app_list/views/search_result_list_view_unittest.cc +++ b/ui/app_list/views/search_result_list_view_unittest.cc
@@ -9,12 +9,12 @@ #include <map> #include <memory> +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/test/app_list_test_view_delegate.h" #include "ui/app_list/test/test_search_result.h" #include "ui/app_list/views/search_result_view.h"
diff --git a/ui/app_list/views/search_result_page_view.cc b/ui/app_list/views/search_result_page_view.cc index 78dfc07..0fe3a43 100644 --- a/ui/app_list/views/search_result_page_view.cc +++ b/ui/app_list/views/search_result_page_view.cc
@@ -406,10 +406,15 @@ gfx::Rect SearchResultPageView::GetPageBoundsForState( AppListModel::State state) const { - return ( - state == AppListModel::STATE_SEARCH_RESULTS - ? GetDefaultContentsBounds() - : GetAboveContentsOffscreenBounds(GetDefaultContentsBounds().size())); + if (state != AppListModel::STATE_SEARCH_RESULTS) { + // Hides this view behind the search box by using the same bounds. + return AppListPage::contents_view()->GetSearchBoxBoundsForState(state); + } + + gfx::Rect onscreen_bounds(AppListPage::GetSearchBoxBounds()); + onscreen_bounds.Offset((onscreen_bounds.width() - kWidth) / 2, 0); + onscreen_bounds.set_size(GetPreferredSize()); + return onscreen_bounds; } void SearchResultPageView::OnAnimationUpdated(double progress,
diff --git a/ui/app_list/views/search_result_page_view.h b/ui/app_list/views/search_result_page_view.h index 69b906f01..082f9d7 100644 --- a/ui/app_list/views/search_result_page_view.h +++ b/ui/app_list/views/search_result_page_view.h
@@ -7,10 +7,10 @@ #include <vector> +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/views/app_list_page.h" #include "ui/app_list/views/search_result_container_view.h"
diff --git a/ui/app_list/views/search_result_page_view_unittest.cc b/ui/app_list/views/search_result_page_view_unittest.cc index fb551a52..6e4d42e 100644 --- a/ui/app_list/views/search_result_page_view_unittest.cc +++ b/ui/app_list/views/search_result_page_view_unittest.cc
@@ -8,12 +8,12 @@ #include <utility> #include <vector> +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/test/scoped_feature_list.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/test/app_list_test_view_delegate.h" #include "ui/app_list/test/test_search_result.h" #include "ui/app_list/views/app_list_main_view.h"
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 5423a3b..b66f31a 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
@@ -6,12 +6,12 @@ #include <stddef.h> +#include "ash/app_list/model/search_result.h" #include "base/i18n/rtl.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_util.h" #include "ui/app_list/app_list_view_delegate.h" -#include "ui/app_list/search_result.h" #include "ui/app_list/views/search_result_page_view.h" #include "ui/app_list/views/search_result_tile_item_view.h" #include "ui/gfx/geometry/insets.h"
diff --git a/ui/app_list/views/search_result_tile_item_list_view_unittest.cc b/ui/app_list/views/search_result_tile_item_list_view_unittest.cc index 41c4c406..171e760 100644 --- a/ui/app_list/views/search_result_tile_item_list_view_unittest.cc +++ b/ui/app_list/views/search_result_tile_item_list_view_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" @@ -15,7 +16,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/accessibility/ax_node_data.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/test/app_list_test_view_delegate.h" #include "ui/app_list/test/test_search_result.h" #include "ui/app_list/views/search_result_tile_item_view.h"
diff --git a/ui/app_list/views/search_result_tile_item_view.cc b/ui/app_list/views/search_result_tile_item_view.cc index e7459a5..1f3c710 100644 --- a/ui/app_list/views/search_result_tile_item_view.cc +++ b/ui/app_list/views/search_result_tile_item_view.cc
@@ -4,6 +4,7 @@ #include "ui/app_list/views/search_result_tile_item_view.h" +#include "ash/app_list/model/search_result.h" #include "base/i18n/number_formatting.h" #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" @@ -11,7 +12,6 @@ #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/pagination_model.h" -#include "ui/app_list/search_result.h" #include "ui/app_list/vector_icons/vector_icons.h" #include "ui/app_list/views/search_result_container_view.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/ui/app_list/views/search_result_tile_item_view.h b/ui/app_list/views/search_result_tile_item_view.h index c3222f8..28745c4 100644 --- a/ui/app_list/views/search_result_tile_item_view.h +++ b/ui/app_list/views/search_result_tile_item_view.h
@@ -7,8 +7,8 @@ #include <memory> +#include "ash/app_list/model/search_result_observer.h" #include "base/macros.h" -#include "ui/app_list/search_result_observer.h" #include "ui/app_list/views/tile_item_view.h" #include "ui/views/context_menu_controller.h"
diff --git a/ui/app_list/views/search_result_view.cc b/ui/app_list/views/search_result_view.cc index 3d91794..322113c 100644 --- a/ui/app_list/views/search_result_view.cc +++ b/ui/app_list/views/search_result_view.cc
@@ -6,11 +6,11 @@ #include <algorithm> +#include "ash/app_list/model/search_result.h" #include "base/strings/utf_string_conversions.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_switches.h" -#include "ui/app_list/search_result.h" #include "ui/app_list/views/search_result_actions_view.h" #include "ui/app_list/views/search_result_list_view.h" #include "ui/gfx/canvas.h"
diff --git a/ui/app_list/views/search_result_view.h b/ui/app_list/views/search_result_view.h index bcb8be1..de67ba0 100644 --- a/ui/app_list/views/search_result_view.h +++ b/ui/app_list/views/search_result_view.h
@@ -11,10 +11,11 @@ #include <string> #include <vector> +#include "ash/app_list/model/search_result_observer.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "base/strings/string16.h" -#include "ui/app_list/search_result_observer.h" +#include "ui/app_list/app_list_export.h" #include "ui/app_list/views/search_result_actions_view_delegate.h" #include "ui/views/context_menu_controller.h" #include "ui/views/controls/button/button.h"
diff --git a/ui/app_list/views/speech_view.cc b/ui/app_list/views/speech_view.cc index 419b9f4..a2d9772 100644 --- a/ui/app_list/views/speech_view.cc +++ b/ui/app_list/views/speech_view.cc
@@ -8,11 +8,11 @@ #include <limits> +#include "ash/app_list/model/app_list_model.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "third_party/skia/include/core/SkPath.h" #include "ui/app_list/app_list_constants.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/resources/grit/app_list_resources.h" #include "ui/app_list/speech_ui_model.h"
diff --git a/ui/aura/env.cc b/ui/aura/env.cc index 08d1d4d..2c101c0 100644 --- a/ui/aura/env.cc +++ b/ui/aura/env.cc
@@ -145,6 +145,11 @@ window_tree_client_ = window_tree_client; } +ui::Gpu* Env::GetGpuConnection() { + DCHECK(window_tree_client_); + return window_tree_client_->gpu(); +} + void Env::ScheduleEmbed( ui::mojom::WindowTreeClientPtr client, base::OnceCallback<void(const base::UnguessableToken&)> callback) {
diff --git a/ui/aura/env.h b/ui/aura/env.h index 52b2c9e..1882bf0 100644 --- a/ui/aura/env.h +++ b/ui/aura/env.h
@@ -40,6 +40,7 @@ namespace ui { class ContextFactory; class ContextFactoryPrivate; +class Gpu; class PlatformEventSource; namespace mojom { class WindowTreeClient; @@ -129,6 +130,8 @@ void SetWindowTreeClient(WindowTreeClient* window_tree_client); bool HasWindowTreeClient() const { return window_tree_client_ != nullptr; } + ui::Gpu* GetGpuConnection(); + // Schedules an embed of a client. See // mojom::WindowTreeClient::ScheduleEmbed() for details. void ScheduleEmbed(
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc index f29ce026..26c1a98 100644 --- a/ui/aura/mus/window_tree_client.cc +++ b/ui/aura/mus/window_tree_client.cc
@@ -1714,6 +1714,12 @@ window_manager_delegate_->OnWmConnected(); } +void WindowTreeClient::WmOnAcceleratedWidgetForDisplay( + int64_t display, + gpu::SurfaceHandle surface_handle) { + // TODO(crbug.com/786453): Implement this. +} + void WindowTreeClient::WmNewDisplayAdded( const display::Display& display, ui::mojom::WindowDataPtr root_data,
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h index a031093..8a1a136 100644 --- a/ui/aura/mus/window_tree_client.h +++ b/ui/aura/mus/window_tree_client.h
@@ -191,6 +191,8 @@ void AddTestObserver(WindowTreeClientTestObserver* observer); void RemoveTestObserver(WindowTreeClientTestObserver* observer); + ui::Gpu* gpu() { return gpu_.get(); } + private: friend class InFlightBoundsChange; friend class InFlightFocusChange; @@ -454,6 +456,9 @@ // Overridden from WindowManager: void OnConnect() override; + void WmOnAcceleratedWidgetForDisplay( + int64_t display, + gpu::SurfaceHandle surface_handle) override; void WmNewDisplayAdded( const display::Display& display, ui::mojom::WindowDataPtr root_data,
diff --git a/ui/aura/window.cc b/ui/aura/window.cc index 3ff26f1..9fb8a7a 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc
@@ -1078,12 +1078,6 @@ Paint(context); } -void Window::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) { - DCHECK(layer()); - for (WindowObserver& observer : observers_) - observer.OnDelegatedFrameDamage(this, damage_rect_in_dip); -} - void Window::OnLayerBoundsChanged(const gfx::Rect& old_bounds, ui::PropertyChangeReason reason) { WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
diff --git a/ui/aura/window.h b/ui/aura/window.h index 8b9e45a4..18b733e 100644 --- a/ui/aura/window.h +++ b/ui/aura/window.h
@@ -480,7 +480,6 @@ // Overridden from ui::LayerDelegate: void OnPaintLayer(const ui::PaintContext& context) override; - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; void OnLayerBoundsChanged(const gfx::Rect& old_bounds, ui::PropertyChangeReason reason) override; void OnLayerTransformed(ui::PropertyChangeReason reason) override;
diff --git a/ui/aura/window_observer.h b/ui/aura/window_observer.h index a59ea86..9d830db 100644 --- a/ui/aura/window_observer.h +++ b/ui/aura/window_observer.h
@@ -120,10 +120,6 @@ // has changed. virtual void OnWindowStackingChanged(Window* window) {} - // Invoked when a region of |window| has damage from a new delegated frame. - virtual void OnDelegatedFrameDamage(Window* window, - const gfx::Rect& damage_rect_in_dip) {} - // Invoked when the Window is being destroyed (i.e. from the start of its // destructor). This is called before the window is removed from its parent. virtual void OnWindowDestroying(Window* window) {}
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index aba9042..1989b63 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -73,7 +73,6 @@ if (auto* delegate = source_->delegate()) delegate->OnPaintLayer(context); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {} @@ -965,12 +964,6 @@ layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor); } -void Layer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) { - DCHECK(surface_layer_.get()); - if (delegate_) - delegate_->OnDelegatedFrameDamage(damage_rect_in_dip); -} - void Layer::SetDidScrollCallback( base::Callback<void(const gfx::ScrollOffset&, const cc::ElementId&)> callback) { @@ -1040,12 +1033,12 @@ return 0; } -bool Layer::PrepareTextureMailbox( - viz::TextureMailbox* mailbox, +bool Layer::PrepareTransferableResource( + viz::TransferableResource* resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback) { if (!mailbox_release_callback_) return false; - *mailbox = mailbox_; + *resource = mailbox_.ToTransferableResource(); *release_callback = std::move(mailbox_release_callback_); return true; }
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index d37678d..47897e3 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -42,6 +42,7 @@ namespace viz { class CopyOutputRequest; +struct TransferableResource; } namespace ui { @@ -367,10 +368,6 @@ // Notifies the layer that the device scale factor has changed. void OnDeviceScaleFactorChanged(float device_scale_factor); - // Notifies the layer that one of its children has received a new - // delegated frame. - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip); - // Requets a copy of the layer's output as a texture or bitmap. void RequestCopyOfOutput(std::unique_ptr<viz::CopyOutputRequest> request); @@ -391,7 +388,7 @@ gfx::ScrollOffset CurrentScrollOffset() const; void SetScrollOffset(const gfx::ScrollOffset& offset); - // ContentLayerClient + // ContentLayerClient implementation. gfx::Rect PaintableRegion() override; scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList( ContentLayerClient::PaintingControlSetting painting_control) override; @@ -400,14 +397,14 @@ cc::Layer* cc_layer_for_testing() { return cc_layer_; } - // TextureLayerClient - bool PrepareTextureMailbox( - viz::TextureMailbox* mailbox, + // TextureLayerClient implementation. + bool PrepareTransferableResource( + viz::TransferableResource* resource, std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override; float device_scale_factor() const { return device_scale_factor_; } - // LayerClient + // LayerClient implementation. std::unique_ptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo( cc::Layer* layer) override; void didUpdateMainThreadScrollingReasons() override;
diff --git a/ui/compositor/layer_delegate.h b/ui/compositor/layer_delegate.h index 70b8044..eb8dc71 100644 --- a/ui/compositor/layer_delegate.h +++ b/ui/compositor/layer_delegate.h
@@ -21,10 +21,6 @@ // Paint content for the layer to the specified context. virtual void OnPaintLayer(const PaintContext& context) = 0; - // A notification that this layer has had a delegated frame swap and - // will be repainted. - virtual void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) = 0; - // Called when the layer's device scale factor has changed. virtual void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) = 0;
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index 7b3e980..3d094af 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc
@@ -94,8 +94,6 @@ recorder.canvas()->DrawColor(color_); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} - void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {} @@ -121,8 +119,6 @@ 0); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} - void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {} @@ -313,8 +309,6 @@ color_index_ = (color_index_ + 1) % static_cast<int>(colors_.size()); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} - void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override { device_scale_factor_ = new_device_scale_factor; @@ -359,7 +353,6 @@ ui::PaintRecorder recorder(context, layer_bounds_.size()); recorder.canvas()->DrawColor(SK_ColorWHITE); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {} @@ -384,7 +377,6 @@ void OnPaintLayer(const ui::PaintContext& context) override { invalidation_ = context.InvalidationForTesting(); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {} @@ -1642,8 +1634,6 @@ last_clip_rect_ = context.InvalidationForTesting(); } - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} - void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override {} @@ -2258,44 +2248,6 @@ Vector2dFTo100thPercisionString(c11->subpixel_position_offset())); } -class FrameDamageCheckingDelegate : public TestLayerDelegate { - public: - FrameDamageCheckingDelegate() : delegated_frame_damage_called_(false) {} - - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override { - delegated_frame_damage_called_ = true; - delegated_frame_damage_rect_ = damage_rect_in_dip; - } - - const gfx::Rect& delegated_frame_damage_rect() const { - return delegated_frame_damage_rect_; - } - bool delegated_frame_damage_called() const { - return delegated_frame_damage_called_; - } - - private: - gfx::Rect delegated_frame_damage_rect_; - bool delegated_frame_damage_called_; - - DISALLOW_COPY_AND_ASSIGN(FrameDamageCheckingDelegate); -}; - -TEST(LayerDelegateTest, DelegatedFrameDamage) { - std::unique_ptr<Layer> layer(new Layer(LAYER_TEXTURED)); - gfx::Rect damage_rect(2, 1, 5, 3); - - FrameDamageCheckingDelegate delegate; - layer->set_delegate(&delegate); - layer->SetShowPrimarySurface(viz::SurfaceId(), gfx::Size(10, 10), - new TestSurfaceReferenceFactory()); - - EXPECT_FALSE(delegate.delegated_frame_damage_called()); - layer->OnDelegatedFrameDamage(damage_rect); - EXPECT_TRUE(delegate.delegated_frame_damage_called()); - EXPECT_EQ(damage_rect, delegate.delegated_frame_damage_rect()); -} - // Verify that LayerDelegate::OnLayerBoundsChanged() is called when the bounds // are set without an animation. TEST(LayerDelegateTest, OnLayerBoundsChanged) {
diff --git a/ui/events/devices/x11/device_data_manager_x11.cc b/ui/events/devices/x11/device_data_manager_x11.cc index 45ae658..16237f30 100644 --- a/ui/events/devices/x11/device_data_manager_x11.cc +++ b/ui/events/devices/x11/device_data_manager_x11.cc
@@ -79,32 +79,35 @@ // When you add new data types, please make sure the order here is aligned // with the order in the DataType enum in the header file because we assume // they are in sync when updating the device list (see UpdateDeviceList). -const char* kCachedAtoms[] = { - AXIS_LABEL_PROP_REL_HWHEEL, - AXIS_LABEL_PROP_REL_WHEEL, - AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X, - AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y, - AXIS_LABEL_PROP_ABS_DBL_START_TIME, - AXIS_LABEL_PROP_ABS_DBL_END_TIME, - AXIS_LABEL_PROP_ABS_DBL_FLING_VX, - AXIS_LABEL_PROP_ABS_DBL_FLING_VY, - AXIS_LABEL_PROP_ABS_FLING_STATE, - AXIS_LABEL_PROP_ABS_METRICS_TYPE, - AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1, - AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2, - AXIS_LABEL_PROP_ABS_FINGER_COUNT, - AXIS_LABEL_ABS_MT_TOUCH_MAJOR, - AXIS_LABEL_ABS_MT_TOUCH_MINOR, - AXIS_LABEL_ABS_MT_ORIENTATION, - AXIS_LABEL_ABS_MT_PRESSURE, - AXIS_LABEL_ABS_MT_POSITION_X, - AXIS_LABEL_ABS_MT_POSITION_Y, - AXIS_LABEL_ABS_MT_TRACKING_ID, - AXIS_LABEL_TOUCH_TIMESTAMP, - - NULL +constexpr const char* kCachedAtoms[] = { + AXIS_LABEL_PROP_REL_HWHEEL, + AXIS_LABEL_PROP_REL_WHEEL, + AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X, + AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y, + AXIS_LABEL_PROP_ABS_DBL_START_TIME, + AXIS_LABEL_PROP_ABS_DBL_END_TIME, + AXIS_LABEL_PROP_ABS_DBL_FLING_VX, + AXIS_LABEL_PROP_ABS_DBL_FLING_VY, + AXIS_LABEL_PROP_ABS_FLING_STATE, + AXIS_LABEL_PROP_ABS_METRICS_TYPE, + AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1, + AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2, + AXIS_LABEL_PROP_ABS_FINGER_COUNT, + AXIS_LABEL_ABS_MT_TOUCH_MAJOR, + AXIS_LABEL_ABS_MT_TOUCH_MINOR, + AXIS_LABEL_ABS_MT_ORIENTATION, + AXIS_LABEL_ABS_MT_PRESSURE, + AXIS_LABEL_ABS_MT_POSITION_X, + AXIS_LABEL_ABS_MT_POSITION_Y, + AXIS_LABEL_ABS_MT_TRACKING_ID, + AXIS_LABEL_TOUCH_TIMESTAMP, }; +// Make sure the sizes of enum and |kCachedAtoms| are aligned. +static_assert(arraysize(kCachedAtoms) == + ui::DeviceDataManagerX11::DT_LAST_ENTRY, + "kCachedAtoms count / enum mismatch"); + // Constants for checking if a data type lies in the range of CMT/Touch data // types. const int kCMTDataTypeStart = ui::DeviceDataManagerX11::DT_CMT_SCROLL_X; @@ -170,8 +173,6 @@ CHECK(gfx::GetXDisplay()); InitializeXInputInternal(); - // Make sure the sizes of enum and kCachedAtoms are aligned. - CHECK(arraysize(kCachedAtoms) == static_cast<size_t>(DT_LAST_ENTRY) + 1); UpdateDeviceList(gfx::GetXDisplay()); UpdateButtonMap(); }
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js index bbd29cbd5..036c01e 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks.js +++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -74,7 +74,7 @@ * @const */ this.taskHistory_ = taskHistory; -}; +} FileTasks.prototype = { /** @@ -430,13 +430,13 @@ // Add verb to title. if (task.verb) { - var verb_button_label = ''; + var verbButtonLabel = ''; switch (task.verb) { case chrome.fileManagerPrivate.Verb.ADD_TO: - verb_button_label = 'ADD_TO_VERB_BUTTON_LABEL'; + verbButtonLabel = 'ADD_TO_VERB_BUTTON_LABEL'; break; case chrome.fileManagerPrivate.Verb.PACK_WITH: - verb_button_label = 'PACK_WITH_VERB_BUTTON_LABEL'; + verbButtonLabel = 'PACK_WITH_VERB_BUTTON_LABEL'; break; case chrome.fileManagerPrivate.Verb.SHARE_WITH: // Even when the task has SHARE_WITH verb, we don't prefix the title @@ -445,17 +445,17 @@ // appropriate verb. if (!(taskParts[1] == 'arc' && (taskParts[2] == 'send' || taskParts[2] == 'send_multiple'))) { - verb_button_label = 'SHARE_WITH_VERB_BUTTON_LABEL'; + verbButtonLabel = 'SHARE_WITH_VERB_BUTTON_LABEL'; } break; case chrome.fileManagerPrivate.Verb.OPEN_WITH: - verb_button_label = 'OPEN_WITH_VERB_BUTTON_LABEL'; + verbButtonLabel = 'OPEN_WITH_VERB_BUTTON_LABEL'; break; default: console.error('Invalid task verb: ' + task.verb + '.'); } - if (verb_button_label) - task.title = loadTimeData.getStringF(verb_button_label, task.title); + if (verbButtonLabel) + task.title = loadTimeData.getStringF(verbButtonLabel, task.title); } result.push(task); @@ -766,17 +766,21 @@ tracker.stop(); return; } - volumeInfo.resolveDisplayRoot(function(displayRoot) { - if (tracker.hasChanged) { - tracker.stop(); - return; - } - this.directoryModel_.changeDirectoryEntry(displayRoot); - }, function() { - console.warn('Failed to resolve the display root after mounting.'); - tracker.stop(); - }); - }, function(url, error) { + volumeInfo.resolveDisplayRoot( + function(displayRoot) { + if (tracker.hasChanged) { + tracker.stop(); + return; + } + this.directoryModel_.changeDirectoryEntry(displayRoot); + }.bind(this), + function() { + console.warn( + 'Failed to resolve the display root after mounting.'); + tracker.stop(); + }); + }.bind(this), + function(url, error) { tracker.stop(); var path = util.extractFilePath(url); var namePos = path.lastIndexOf('/');
diff --git a/ui/gfx/x/x11_atom_cache.cc b/ui/gfx/x/x11_atom_cache.cc index 6601886f..1b1d333 100644 --- a/ui/gfx/x/x11_atom_cache.cc +++ b/ui/gfx/x/x11_atom_cache.cc
@@ -7,7 +7,8 @@ #include <X11/Xatom.h> #include <X11/Xlib.h> -#include <memory> +#include <utility> +#include <vector> #include "base/logging.h" #include "base/memory/singleton.h" @@ -88,142 +89,145 @@ // {"WM_TRANSIENT_FOR", XA_WM_TRANSIENT_FOR}, }; -const char* kAtomsToCache[] = {"Abs Dbl End Timestamp", - "Abs Dbl Fling X Velocity", - "Abs Dbl Fling Y Velocity", - "Abs Dbl Metrics Data 1", - "Abs Dbl Metrics Data 2", - "Abs Dbl Ordinal X", - "Abs Dbl Ordinal Y", - "Abs Dbl Start Timestamp", - "Abs Finger Count", - "Abs Fling State", - "Abs Metrics Type", - "Abs MT Orientation", - "Abs MT Position X", - "Abs MT Position Y", - "Abs MT Pressure", - "Abs MT Touch Major", - "Abs MT Touch Minor", - "Abs MT Tracking ID", - "application/octet-stream", - "application/vnd.chromium.test", - "ATOM_PAIR", - "CHECK", - "_CHROME_DISPLAY_INTERNAL", - "_CHROME_DISPLAY_ROTATION", - "_CHROME_DISPLAY_SCALE_FACTOR", - "CHOME_SELECTION", - "CHROME_SELECTION", - "_CHROMIUM_DRAG_RECEIVER", - "chromium/filename", - "CHROMIUM_TIMESTAMP", - "chromium/x-bookmark-entries", - "chromium/x-browser-actions", - "chromium/x-file-system-files", - "chromium/x-pepper-custom-data", - "chromium/x-renderer-taint", - "chromium/x-web-custom-data", - "chromium/x-webkit-paste", - "CLIPBOARD", - "CLIPBOARD_MANAGER", - "Content Protection", - "Desired", - "Device Node", - "Device Product ID", - "EDID", - "Enabled", - "FAKE_SELECTION", - "Full aspect", - "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED", - "_GTK_THEME_VARIANT", - "_ICC_PROFILE", - "image/png", - "INCR", - "KEYBOARD", - "LOCK", - "marker_event", - "_MOTIF_WM_HINTS", - "MOUSE", - "MULTIPLE", - "_NET_ACTIVE_WINDOW", - "_NET_CLIENT_LIST_STACKING", - "_NET_CURRENT_DESKTOP", - "_NET_FRAME_EXTENTS", - "_NETSCAPE_URL", - "_NET_SUPPORTED", - "_NET_SUPPORTING_WM_CHECK", - "_NET_WM_CM_S0", - "_NET_WM_DESKTOP", - "_NET_WM_ICON", - "_NET_WM_MOVERESIZE", - "_NET_WM_NAME", - "_NET_WM_PID", - "_NET_WM_PING", - "_NET_WM_STATE", - "_NET_WM_STATE_ABOVE", - "_NET_WM_STATE_FOCUSED", - "_NET_WM_STATE_FULLSCREEN", - "_NET_WM_STATE_HIDDEN", - "_NET_WM_STATE_MAXIMIZED_HORZ", - "_NET_WM_STATE_MAXIMIZED_VERT", - "_NET_WM_STATE_SKIP_TASKBAR", - "_NET_WM_STATE_STICKY", - "_NET_WM_USER_TIME", - "_NET_WM_WINDOW_OPACITY", - "_NET_WM_WINDOW_TYPE", - "_NET_WM_WINDOW_TYPE_DND", - "_NET_WM_WINDOW_TYPE_MENU", - "_NET_WM_WINDOW_TYPE_NORMAL", - "_NET_WM_WINDOW_TYPE_NOTIFICATION", - "_NET_WM_WINDOW_TYPE_TOOLTIP", - "_NET_WORKAREA", - "Rel Horiz Wheel", - "Rel Vert Wheel", - "SAVE_TARGETS", - "_SCREENSAVER_STATUS", - "_SCREENSAVER_VERSION", - "scaling mode", - "SELECTION_STRING", - "Tap Paused", - "TARGETS", - "TARGET1", - "TARGET2", - "TEXT", - "text/html", - "text/plain", - "text/plain;charset=utf-8", - "text/uri-list", - "text/rtf", - "text/x-moz-url", - "TIMESTAMP", - "TOUCHPAD", - "TOUCHSCREEN", - "Touch Timestamp", - "Undesired", - "UTF8_STRING", - "WM_DELETE_WINDOW", - "WM_PROTOCOLS", - "WM_WINDOW_ROLE", - "XdndActionAsk", - "XdndActionCopy", - "XdndActionDirectSave", - "XdndActionLink", - "XdndActionList", - "XdndActionMove", - "XdndActionPrivate", - "XdndAware", - "XdndDirectSave0", - "XdndDrop", - "XdndEnter", - "XdndFinished", - "XdndLeave", - "XdndPosition", - "XdndProxy", - "XdndSelection", - "XdndStatus", - "XdndTypeList", - nullptr}; +constexpr const char* kAtomsToCache[] = { + "Abs Dbl End Timestamp", + "Abs Dbl Fling X Velocity", + "Abs Dbl Fling Y Velocity", + "Abs Dbl Metrics Data 1", + "Abs Dbl Metrics Data 2", + "Abs Dbl Ordinal X", + "Abs Dbl Ordinal Y", + "Abs Dbl Start Timestamp", + "Abs Finger Count", + "Abs Fling State", + "Abs Metrics Type", + "Abs MT Orientation", + "Abs MT Position X", + "Abs MT Position Y", + "Abs MT Pressure", + "Abs MT Touch Major", + "Abs MT Touch Minor", + "Abs MT Tracking ID", + "application/octet-stream", + "application/vnd.chromium.test", + "ATOM_PAIR", + "CHECK", + "_CHROME_DISPLAY_INTERNAL", + "_CHROME_DISPLAY_ROTATION", + "_CHROME_DISPLAY_SCALE_FACTOR", + "CHOME_SELECTION", + "CHROME_SELECTION", + "_CHROMIUM_DRAG_RECEIVER", + "chromium/filename", + "CHROMIUM_TIMESTAMP", + "chromium/x-bookmark-entries", + "chromium/x-browser-actions", + "chromium/x-file-system-files", + "chromium/x-pepper-custom-data", + "chromium/x-renderer-taint", + "chromium/x-web-custom-data", + "chromium/x-webkit-paste", + "CLIPBOARD", + "CLIPBOARD_MANAGER", + "Content Protection", + "Desired", + "Device Node", + "Device Product ID", + "EDID", + "Enabled", + "FAKE_SELECTION", + "Full aspect", + "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED", + "_GTK_THEME_VARIANT", + "_ICC_PROFILE", + "image/png", + "INCR", + "KEYBOARD", + "LOCK", + "marker_event", + "_MOTIF_WM_HINTS", + "MOUSE", + "MULTIPLE", + "_NET_ACTIVE_WINDOW", + "_NET_CLIENT_LIST_STACKING", + "_NET_CURRENT_DESKTOP", + "_NET_FRAME_EXTENTS", + "_NETSCAPE_URL", + "_NET_SUPPORTED", + "_NET_SUPPORTING_WM_CHECK", + "_NET_WM_CM_S0", + "_NET_WM_DESKTOP", + "_NET_WM_ICON", + "_NET_WM_MOVERESIZE", + "_NET_WM_NAME", + "_NET_WM_PID", + "_NET_WM_PING", + "_NET_WM_STATE", + "_NET_WM_STATE_ABOVE", + "_NET_WM_STATE_FOCUSED", + "_NET_WM_STATE_FULLSCREEN", + "_NET_WM_STATE_HIDDEN", + "_NET_WM_STATE_MAXIMIZED_HORZ", + "_NET_WM_STATE_MAXIMIZED_VERT", + "_NET_WM_STATE_SKIP_TASKBAR", + "_NET_WM_STATE_STICKY", + "_NET_WM_USER_TIME", + "_NET_WM_WINDOW_OPACITY", + "_NET_WM_WINDOW_TYPE", + "_NET_WM_WINDOW_TYPE_DND", + "_NET_WM_WINDOW_TYPE_MENU", + "_NET_WM_WINDOW_TYPE_NORMAL", + "_NET_WM_WINDOW_TYPE_NOTIFICATION", + "_NET_WM_WINDOW_TYPE_TOOLTIP", + "_NET_WORKAREA", + "Rel Horiz Wheel", + "Rel Vert Wheel", + "SAVE_TARGETS", + "_SCREENSAVER_STATUS", + "_SCREENSAVER_VERSION", + "scaling mode", + "SELECTION_STRING", + "Tap Paused", + "TARGETS", + "TARGET1", + "TARGET2", + "TEXT", + "text/html", + "text/plain", + "text/plain;charset=utf-8", + "text/uri-list", + "text/rtf", + "text/x-moz-url", + "TIMESTAMP", + "TOUCHPAD", + "TOUCHSCREEN", + "Touch Timestamp", + "Undesired", + "UTF8_STRING", + "WM_DELETE_WINDOW", + "WM_PROTOCOLS", + "WM_WINDOW_ROLE", + "XdndActionAsk", + "XdndActionCopy", + "XdndActionDirectSave", + "XdndActionLink", + "XdndActionList", + "XdndActionMove", + "XdndActionPrivate", + "XdndAware", + "XdndDirectSave0", + "XdndDrop", + "XdndEnter", + "XdndFinished", + "XdndLeave", + "XdndPosition", + "XdndProxy", + "XdndSelection", + "XdndStatus", + "XdndTypeList", +}; + +constexpr int kCacheCount = arraysize(kAtomsToCache); } // namespace @@ -241,13 +245,10 @@ for (const auto& predefined_atom : kPredefinedAtoms) cached_atoms_[predefined_atom.atom_name] = predefined_atom.atom_value; - const int kCacheCount = arraysize(kAtomsToCache) - 1; - - std::unique_ptr<XAtom[]> cached_atoms(new XAtom[kCacheCount]); - // Grab all the atoms we need now to minimize roundtrips to the X11 server. + std::vector<XAtom> cached_atoms(kCacheCount); XInternAtoms(xdisplay_, const_cast<char**>(kAtomsToCache), kCacheCount, False, - cached_atoms.get()); + cached_atoms.data()); for (int i = 0; i < kCacheCount; ++i) cached_atoms_[kAtomsToCache[i]] = cached_atoms[i]; @@ -256,15 +257,13 @@ X11AtomCache::~X11AtomCache() {} XAtom X11AtomCache::GetAtom(const char* name) const { - std::map<std::string, Atom>::const_iterator it = cached_atoms_.find(name); + const auto it = cached_atoms_.find(name); + if (it != cached_atoms_.end()) + return it->second; - if (it == cached_atoms_.end()) { - XAtom atom = XInternAtom(xdisplay_, name, false); - cached_atoms_.insert(std::make_pair(name, atom)); - return atom; - } - - return it->second; + XAtom atom = XInternAtom(xdisplay_, name, False); + cached_atoms_.insert(std::make_pair(name, atom)); + return atom; } } // namespace gfx
diff --git a/ui/keyboard/container_floating_behavior.cc b/ui/keyboard/container_floating_behavior.cc index 58dcc9d..3f49607 100644 --- a/ui/keyboard/container_floating_behavior.cc +++ b/ui/keyboard/container_floating_behavior.cc
@@ -29,11 +29,6 @@ // Distance the keyboard moves during the animation constexpr int kAnimationDistance = 30; -// Temporary value designating the size of the square in the top left corner of -// the keyboard that should be a drag handle. This will be replaced once real -// drag handles are added to the extension. -constexpr int kDragHandleSquareMargin = 60; - ContainerFloatingBehavior::ContainerFloatingBehavior( KeyboardController* controller) { controller_ = controller; @@ -169,8 +164,7 @@ bool ContainerFloatingBehavior::IsDragHandle( const gfx::Vector2d& offset, const gfx::Size& keyboard_size) const { - return offset.x() < kDragHandleSquareMargin && - offset.y() < kDragHandleSquareMargin; + return false; } void ContainerFloatingBehavior::HandlePointerEvent(
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc index 38ad6cb..33cec4f 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc +++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -136,7 +136,7 @@ } uint32_t GbmBuffer::GetHandle() const { - return gbm_bo_get_handle(bo_).u32; + return bo() ? gbm_bo_get_handle(bo()).u32 : 0; } // TODO(reveman): This should not be needed once crbug.com/597932 is fixed,
diff --git a/ui/ozone/platform/wayland/wayland_cursor.cc b/ui/ozone/platform/wayland/wayland_cursor.cc index 74681ed6..9cb9aab 100644 --- a/ui/ozone/platform/wayland/wayland_cursor.cc +++ b/ui/ozone/platform/wayland/wayland_cursor.cc
@@ -9,7 +9,7 @@ #include "base/memory/shared_memory.h" #include "third_party/skia/include/core/SkCanvas.h" -#include "ui/gfx/skia_util.cc" +#include "ui/gfx/skia_util.h" #include "ui/ozone/platform/wayland/wayland_connection.h" #include "ui/ozone/platform/wayland/wayland_pointer.h"
diff --git a/ui/views/accessibility/native_view_accessibility_base.cc b/ui/views/accessibility/native_view_accessibility_base.cc index 3534cff..7571efc3 100644 --- a/ui/views/accessibility/native_view_accessibility_base.cc +++ b/ui/views/accessibility/native_view_accessibility_base.cc
@@ -37,12 +37,36 @@ return false; } +ui::AXPlatformNode* FromNativeWindow(gfx::NativeWindow native_window) { + Widget* widget = Widget::GetWidgetForNativeWindow(native_window); + if (!widget) + return nullptr; + + View* view = widget->GetRootView(); + if (!view) + return nullptr; + + gfx::NativeViewAccessible native_view_accessible = + view->GetNativeViewAccessible(); + if (!native_view_accessible) + return nullptr; + + return ui::AXPlatformNode::FromNativeViewAccessible(native_view_accessible); +} + } // namespace NativeViewAccessibilityBase::NativeViewAccessibilityBase(View* view) : view_(view) { ax_node_ = ui::AXPlatformNode::Create(this); DCHECK(ax_node_); + + static bool first_time = true; + if (first_time) { + ui::AXPlatformNode::RegisterNativeWindowHandler( + base::BindRepeating(&FromNativeWindow)); + first_time = false; + } } NativeViewAccessibilityBase::~NativeViewAccessibilityBase() {
diff --git a/ui/views/animation/ink_drop_mask.cc b/ui/views/animation/ink_drop_mask.cc index bd35df3..05bd983c 100644 --- a/ui/views/animation/ink_drop_mask.cc +++ b/ui/views/animation/ink_drop_mask.cc
@@ -28,8 +28,6 @@ layer_.SetBounds(gfx::Rect(new_layer_size)); } -void InkDropMask::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {} - void InkDropMask::OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) {}
diff --git a/ui/views/animation/ink_drop_mask.h b/ui/views/animation/ink_drop_mask.h index 40cb327..8899e5b 100644 --- a/ui/views/animation/ink_drop_mask.h +++ b/ui/views/animation/ink_drop_mask.h
@@ -34,7 +34,6 @@ private: // Overriden from ui::LayerDelegate: - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override;
diff --git a/ui/views/animation/ink_drop_painted_layer_delegates.cc b/ui/views/animation/ink_drop_painted_layer_delegates.cc index ab1ef9c..7ea1068a 100644 --- a/ui/views/animation/ink_drop_painted_layer_delegates.cc +++ b/ui/views/animation/ink_drop_painted_layer_delegates.cc
@@ -37,9 +37,6 @@ return gfx::RectF(GetPaintedBounds()).CenterPoint().OffsetFromOrigin(); } -void BasePaintedLayerDelegate::OnDelegatedFrameDamage( - const gfx::Rect& damage_rect_in_dip) {} - void BasePaintedLayerDelegate::OnDeviceScaleFactorChanged( float old_device_scale_factor, float new_device_scale_factor) {}
diff --git a/ui/views/animation/ink_drop_painted_layer_delegates.h b/ui/views/animation/ink_drop_painted_layer_delegates.h index a54f6dd2..c7817cf 100644 --- a/ui/views/animation/ink_drop_painted_layer_delegates.h +++ b/ui/views/animation/ink_drop_painted_layer_delegates.h
@@ -30,7 +30,6 @@ virtual gfx::Vector2dF GetCenteringOffset() const; // ui::LayerDelegate: - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override;
diff --git a/ui/views/cocoa/bridged_native_widget.h b/ui/views/cocoa/bridged_native_widget.h index c70e59f..67a0d56 100644 --- a/ui/views/cocoa/bridged_native_widget.h +++ b/ui/views/cocoa/bridged_native_widget.h
@@ -287,7 +287,6 @@ // Overridden from ui::LayerDelegate: void OnPaintLayer(const ui::PaintContext& context) override; - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override;
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm index 31d2a6d7..c6384ed 100644 --- a/ui/views/cocoa/bridged_native_widget.mm +++ b/ui/views/cocoa/bridged_native_widget.mm
@@ -1237,11 +1237,6 @@ native_widget_mac_->GetWidget()->OnNativeWidgetPaint(context); } -void BridgedNativeWidget::OnDelegatedFrameDamage( - const gfx::Rect& damage_rect_in_dip) { - NOTIMPLEMENTED(); -} - void BridgedNativeWidget::OnDeviceScaleFactorChanged( float old_device_scale_factor, float new_device_scale_factor) {
diff --git a/ui/views/controls/tree/tree_view.cc b/ui/views/controls/tree/tree_view.cc index 6e8a81ca..ddd139f 100644 --- a/ui/views/controls/tree/tree_view.cc +++ b/ui/views/controls/tree/tree_view.cc
@@ -890,8 +890,7 @@ gfx::Rect TreeView::GetBoundsForNode(InternalNode* node) { int row, ignored_depth; row = GetRowForInternalNode(node, &ignored_depth); - return gfx::Rect(bounds().x(), row * row_height_, bounds().width(), - row_height_); + return gfx::Rect(0, row * row_height_, width(), row_height_); } gfx::Rect TreeView::GetBackgroundBoundsForNode(InternalNode* node) { @@ -927,7 +926,7 @@ if (width < 0) return gfx::Rect(); int x = base::i18n::IsRTL() - ? bounds().x() + kTextHorizontalPadding + ? kTextHorizontalPadding : bounds().right() - width - kTextHorizontalPadding; return gfx::Rect(x, text_bounds.y(), width, text_bounds.height()); } @@ -1094,10 +1093,10 @@ int row = GetRowForInternalNode(node, &depth); int arrow_dx = depth * kIndent + kHorizontalInset; - gfx::Rect arrow_bounds(bounds().x() + arrow_dx, row * row_height_, - kArrowRegionSize, row_height_); + gfx::Rect arrow_bounds(arrow_dx, row * row_height_, kArrowRegionSize, + row_height_); if (base::i18n::IsRTL()) - arrow_bounds.set_x(bounds().width() - arrow_dx - kArrowRegionSize); + arrow_bounds.set_x(width() - arrow_dx - kArrowRegionSize); return arrow_bounds.Contains(point); }
diff --git a/ui/views/painter.cc b/ui/views/painter.cc index ddeaf60..85ee094 100644 --- a/ui/views/painter.cc +++ b/ui/views/painter.cc
@@ -197,7 +197,6 @@ // LayerDelegate: void OnPaintLayer(const ui::PaintContext& context) override; - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override; @@ -220,9 +219,6 @@ painter_->Paint(recorder.canvas(), layer()->size()); } -void PaintedLayer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) { -} - void PaintedLayer::OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) {}
diff --git a/ui/views/view.cc b/ui/views/view.cc index 0b91b86..9710786b 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -1703,10 +1703,6 @@ PaintFromPaintRoot(context); } -void View::OnDelegatedFrameDamage( - const gfx::Rect& damage_rect_in_dip) { -} - void View::OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) { snap_layer_to_pixel_boundary_ =
diff --git a/ui/views/view.h b/ui/views/view.h index 0c9a28de..da4b110 100644 --- a/ui/views/view.h +++ b/ui/views/view.h
@@ -1287,7 +1287,6 @@ // Overridden from ui::LayerDelegate: void OnPaintLayer(const ui::PaintContext& context) override; - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; void OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) override;