diff --git a/DEPS b/DEPS index 9850e9d..69aa88f 100644 --- a/DEPS +++ b/DEPS
@@ -116,11 +116,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': '44764000b49cddcec8b6733375078404f97a00fc', + 'skia_revision': 'e36f46461df623d551dc6ba4ef66042d9bbba20b', # 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': 'c10b42544e3c97ecb259ede63fa2ccb78c8396dc', + 'v8_revision': 'b0e3bc7d7fd4655b488fd916eea1a3601ab3bede', # 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. @@ -128,7 +128,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'ccad5e333472572ecda3c0ec80a702c7dcc5e95f', + 'angle_revision': 'f3acb8c133fa825d5f25159eaf4ebf303bfef7a6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -176,7 +176,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '4925b069e1cfc5b50ead614e28d3367bfcd72349', + 'catapult_revision': '8a6451c727a27d061b9a886207996f0a079c6433', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -408,15 +408,15 @@ 'packages': [ { 'package': 'infra/tools/luci/isolate/${{platform}}', - 'version': 'git_revision:b47dd589aae9f538adeaecc096a8dd1948d08012', + 'version': 'git_revision:b4183943efee5d2a2d444c8551877ae96b78d8b2', }, { 'package': 'infra/tools/luci/isolated/${{platform}}', - 'version': 'git_revision:b47dd589aae9f538adeaecc096a8dd1948d08012', + 'version': 'git_revision:b4183943efee5d2a2d444c8551877ae96b78d8b2', }, { 'package': 'infra/tools/luci/swarming/${{platform}}', - 'version': 'git_revision:b47dd589aae9f538adeaecc096a8dd1948d08012', + 'version': 'git_revision:b4183943efee5d2a2d444c8551877ae96b78d8b2', }, ], 'dep_type': 'cipd', @@ -655,7 +655,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '88c15c341d97a21a2fe5511bc9f91d207cd570f4', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'ece712e727b4aae6848cca527a2f99f24c1c82a4', 'condition': 'checkout_linux', }, @@ -680,7 +680,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ef71a5f047daf72a6017c14f46b198f24521fefc', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '91de11099dcd8c37e308992ccfe26dd14cee5f64', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1014,7 +1014,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '74096ec8f277c79fd2e85f8880a848ad49b63791', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'cd83dda45843fcd4e87face3195452a0d5c70b38', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1166,7 +1166,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '0d55c887e92b645f6effe753528323ab2ffd94c2', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '83aa5ace99a52bbe85055d89ed6837930f8d1f2c', + Var('webrtc_git') + '/src.git' + '@' + 'c25d2344574830a3f73a934ba5b4662e0475cbbb', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1197,7 +1197,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e04de3408e65f698419363302c17410eb78bb42d', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@bb18f19dce17e6ac5fe8529964978458d600525b', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc index 730e0623..cccd77c 100644 --- a/android_webview/browser/hardware_renderer.cc +++ b/android_webview/browser/hardware_renderer.cc
@@ -184,11 +184,9 @@ last_submitted_layer_tree_frame_sink_id_); } -void HardwareRenderer::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) {} - -void HardwareRenderer::OnBeginFrame(const viz::BeginFrameArgs& args) { +void HardwareRenderer::OnBeginFrame( + const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) { // TODO(tansell): Hook this up. }
diff --git a/android_webview/browser/hardware_renderer.h b/android_webview/browser/hardware_renderer.h index 083ee091..42710458 100644 --- a/android_webview/browser/hardware_renderer.h +++ b/android_webview/browser/hardware_renderer.h
@@ -51,10 +51,9 @@ // viz::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override; - void OnBeginFrame(const viz::BeginFrameArgs& args) override; + void OnBeginFrame(const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) override; void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override; void OnBeginFramePausedChanged(bool paused) override;
diff --git a/android_webview/browser/surfaces_instance.cc b/android_webview/browser/surfaces_instance.cc index 89f331d..9e6a653 100644 --- a/android_webview/browser/surfaces_instance.cc +++ b/android_webview/browser/surfaces_instance.cc
@@ -220,7 +220,9 @@ return child_ranges; } -void SurfacesInstance::OnBeginFrame(const viz::BeginFrameArgs& args) {} +void SurfacesInstance::OnBeginFrame( + const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) {} void SurfacesInstance::ReclaimResources( const std::vector<viz::ReturnedResource>& resources) {
diff --git a/android_webview/browser/surfaces_instance.h b/android_webview/browser/surfaces_instance.h index c828894..570defe 100644 --- a/android_webview/browser/surfaces_instance.h +++ b/android_webview/browser/surfaces_instance.h
@@ -72,10 +72,9 @@ // viz::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override {} - void OnBeginFrame(const viz::BeginFrameArgs& args) override; + void OnBeginFrame(const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) override; void OnBeginFramePausedChanged(bool paused) override; void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override;
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index 33727ac..85b9d55 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -105,6 +105,7 @@ import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.Callable; +import java.util.regex.Pattern; /** * Exposes the native AwContents class, and together these classes wrap the WebContents @@ -142,6 +143,13 @@ public static final String DATA_BASE_URL_SCHEME_HISTOGRAM_NAME = "Android.WebView.LoadDataWithBaseUrl.BaseUrl"; + @VisibleForTesting + public static final String LOAD_URL_SCHEME_HISTOGRAM_NAME = "Android.WebView.LoadUrl.UrlScheme"; + + // Permit any number of slashes, since chromium seems to canonicalize bad values. + private static final Pattern sFileAndroidAssetPattern = + Pattern.compile("^file:/*android_(asset|res).*"); + private static class ForceAuxiliaryBitmapRendering { private static final boolean sResult = lazyCheck(); private static boolean lazyCheck() { @@ -166,7 +174,7 @@ UrlScheme.HTTPS_SCHEME, UrlScheme.FILE_SCHEME, UrlScheme.FTP_SCHEME, UrlScheme.DATA_SCHEME, UrlScheme.JAVASCRIPT_SCHEME, UrlScheme.ABOUT_SCHEME, UrlScheme.CHROME_SCHEME, UrlScheme.BLOB_SCHEME, UrlScheme.CONTENT_SCHEME, - UrlScheme.INTENT_SCHEME}) + UrlScheme.INTENT_SCHEME, UrlScheme.FILE_ANDROID_ASSET_SCHEME}) public @interface UrlScheme { int EMPTY = 0; int UNKNOWN_SCHEME = 1; @@ -181,7 +189,8 @@ int BLOB_SCHEME = 10; int CONTENT_SCHEME = 11; int INTENT_SCHEME = 12; - int COUNT = 13; + int FILE_ANDROID_ASSET_SCHEME = 13; // Covers android_asset and android_res URLs + int COUNT = 14; } /** @@ -1690,6 +1699,11 @@ DATA_BASE_URL_SCHEME_HISTOGRAM_NAME, value, UrlScheme.COUNT); } + private static void recordLoadUrlScheme(@UrlScheme int value) { + RecordHistogram.recordEnumeratedHistogram( + LOAD_URL_SCHEME_HISTOGRAM_NAME, value, UrlScheme.COUNT); + } + /** * WebView.loadData. */ @@ -1703,6 +1717,37 @@ fixupData(data), fixupMimeType(mimeType), isBase64Encoded(encoding))); } + private @UrlScheme int schemeForUrl(String url) { + if (url == null || url.equals(ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL)) { + return (UrlScheme.EMPTY); + } else if (url.startsWith("http:")) { + return (UrlScheme.HTTP_SCHEME); + } else if (url.startsWith("https:")) { + return (UrlScheme.HTTPS_SCHEME); + } else if (sFileAndroidAssetPattern.matcher(url).matches()) { + return (UrlScheme.FILE_ANDROID_ASSET_SCHEME); + } else if (url.startsWith("file:")) { + return (UrlScheme.FILE_SCHEME); + } else if (url.startsWith("ftp:")) { + return (UrlScheme.FTP_SCHEME); + } else if (url.startsWith("data:")) { + return (UrlScheme.DATA_SCHEME); + } else if (url.startsWith("javascript:")) { + return (UrlScheme.JAVASCRIPT_SCHEME); + } else if (url.startsWith("about:")) { + return (UrlScheme.ABOUT_SCHEME); + } else if (url.startsWith("chrome:")) { + return (UrlScheme.CHROME_SCHEME); + } else if (url.startsWith("blob:")) { + return (UrlScheme.BLOB_SCHEME); + } else if (url.startsWith("content:")) { + return (UrlScheme.CONTENT_SCHEME); + } else if (url.startsWith("intent:")) { + return (UrlScheme.INTENT_SCHEME); + } + return (UrlScheme.UNKNOWN_SCHEME); + } + /** * WebView.loadDataWithBaseURL. */ @@ -1725,33 +1770,7 @@ recordHistoryUrl(HistoryUrl.DIFFERENT); } - if (baseUrl.equals(ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL)) { - recordBaseUrl(UrlScheme.EMPTY); - } else if (baseUrl.startsWith("http:")) { - recordBaseUrl(UrlScheme.HTTP_SCHEME); - } else if (baseUrl.startsWith("https:")) { - recordBaseUrl(UrlScheme.HTTPS_SCHEME); - } else if (baseUrl.startsWith("file:")) { - recordBaseUrl(UrlScheme.FILE_SCHEME); - } else if (baseUrl.startsWith("ftp:")) { - recordBaseUrl(UrlScheme.FTP_SCHEME); - } else if (baseUrl.startsWith("data:")) { - recordBaseUrl(UrlScheme.DATA_SCHEME); - } else if (baseUrl.startsWith("javascript:")) { - recordBaseUrl(UrlScheme.JAVASCRIPT_SCHEME); - } else if (baseUrl.startsWith("about:")) { - recordBaseUrl(UrlScheme.ABOUT_SCHEME); - } else if (baseUrl.startsWith("chrome:")) { - recordBaseUrl(UrlScheme.CHROME_SCHEME); - } else if (baseUrl.startsWith("blob:")) { - recordBaseUrl(UrlScheme.BLOB_SCHEME); - } else if (baseUrl.startsWith("content:")) { - recordBaseUrl(UrlScheme.CONTENT_SCHEME); - } else if (baseUrl.startsWith("intent:")) { - recordBaseUrl(UrlScheme.INTENT_SCHEME); - } else { - recordBaseUrl(UrlScheme.UNKNOWN_SCHEME); - } + recordBaseUrl(schemeForUrl(baseUrl)); if (baseUrl.startsWith("data:")) { // We record only for this branch, because the other branch assumes unencoded content. @@ -1797,6 +1816,12 @@ */ @VisibleForTesting public void loadUrl(LoadUrlParams params) { + if (params.getBaseUrl() == null) { + // Don't record the URL if this was loaded via loadDataWithBaseURL(). That API is + // tracked separately under Android.WebView.LoadDataWithBaseUrl.BaseUrl. + recordLoadUrlScheme(schemeForUrl(params.getUrl())); + } + if (params.getLoadUrlType() == LoadURLType.DATA && !params.isBaseUrlDataScheme()) { // This allows data URLs with a non-data base URL access to file:///android_asset/ and // file:///android_res/ URLs. If AwSettings.getAllowFileAccess permits, it will also
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java index cb0bdbc..90b31d16 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
@@ -903,4 +903,71 @@ // |loadUrl| doesn't allow a null url, so it is not necessary to check that for this API. // See http://crbug.com/864708. } + + @Test + @Feature({"AndroidWebView"}) + @SmallTest + public void testLoadUrlRecordsScheme_http() throws Throwable { + // No need to spin up a web server, since we don't care if the load ever succeeds. + final String httpUrlWithNoRealPage = "http://some.origin/some/path.html"; + loadUrlAndCheckScheme(httpUrlWithNoRealPage, AwContents.UrlScheme.HTTP_SCHEME); + } + + @Test + @Feature({"AndroidWebView"}) + @SmallTest + public void testLoadUrlRecordsScheme_javascript() throws Throwable { + loadUrlAndCheckScheme( + "javascript:console.log('message')", AwContents.UrlScheme.JAVASCRIPT_SCHEME); + } + + @Test + @Feature({"AndroidWebView"}) + @SmallTest + public void testLoadUrlRecordsScheme_fileAndroidAsset() throws Throwable { + loadUrlAndCheckScheme("file:///android_asset/some/asset/page.html", + AwContents.UrlScheme.FILE_ANDROID_ASSET_SCHEME); + } + + @Test + @Feature({"AndroidWebView"}) + @SmallTest + public void testLoadUrlRecordsScheme_fileRegular() throws Throwable { + loadUrlAndCheckScheme("file:///some/path/on/disk.html", AwContents.UrlScheme.FILE_SCHEME); + } + + @Test + @Feature({"AndroidWebView"}) + @SmallTest + public void testLoadUrlRecordsScheme_data() throws Throwable { + loadUrlAndCheckScheme( + "data:text/html,<html><body>foo</body></html>", AwContents.UrlScheme.DATA_SCHEME); + } + + @Test + @Feature({"AndroidWebView"}) + @SmallTest + public void testLoadUrlRecordsScheme_blank() throws Throwable { + loadUrlAndCheckScheme("about:blank", AwContents.UrlScheme.EMPTY); + } + + private void loadUrlAndCheckScheme(String url, @AwContents.UrlScheme int expectedSchemeEnum) + throws Throwable { + AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); + final AwContents awContents = testView.getAwContents(); + + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + AwContents.LOAD_URL_SCHEME_HISTOGRAM_NAME)); + // Note: we use async because not all loads emit onPageFinished. This relies on the UMA + // metric being logged in the synchronous part of loadUrl(). + mActivityTestRule.loadUrlAsync(awContents, url); + Assert.assertEquals(1, + RecordHistogram.getHistogramTotalCountForTesting( + AwContents.LOAD_URL_SCHEME_HISTOGRAM_NAME)); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + AwContents.LOAD_URL_SCHEME_HISTOGRAM_NAME, expectedSchemeEnum)); + } }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index dcf1ee7..150df5b2 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -48,11 +48,6 @@ "frame/wide_frame_view.h", "login/ui/lock_window.h", "magnifier/magnification_controller.h", - - # TODO: move MultiUserWindowManager (and delegate) to sources: - # https://crbug.com/756085 - "multi_user/multi_user_window_manager.h", - "multi_user/multi_user_window_manager_delegate.h", "new_window_controller.h", "root_window_controller.h", "screenshot_delegate.h", @@ -523,9 +518,6 @@ "multi_device_setup/multi_device_notification_presenter.h", "multi_profile_uma.cc", "multi_profile_uma.h", - "multi_user/multi_user_window_manager.cc", - "multi_user/user_switch_animator.cc", - "multi_user/user_switch_animator.h", "network_connect_delegate_mus.cc", "network_connect_delegate_mus.h", "new_window_controller.cc", @@ -770,6 +762,8 @@ "system/network/network_icon_animation.cc", "system/network/network_icon_animation.h", "system/network/network_icon_animation_observer.h", + "system/network/network_icon_purger.cc", + "system/network/network_icon_purger.h", "system/network/network_info.cc", "system/network/network_info.h", "system/network/network_list.cc",
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index eb93e55..f0805cf 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -809,8 +809,7 @@ return home_launcher_gesture_handler_->OnScrollEvent( screen_location, event->details().scroll_y()); case ui::ET_GESTURE_END: - return home_launcher_gesture_handler_->OnReleaseEvent( - screen_location, /*out_dragged_down=*/nullptr); + return home_launcher_gesture_handler_->OnReleaseEvent(screen_location); default: break; }
diff --git a/ash/app_list/home_launcher_gesture_handler.cc b/ash/app_list/home_launcher_gesture_handler.cc index 53129af7..f067f95 100644 --- a/ash/app_list/home_launcher_gesture_handler.cc +++ b/ash/app_list/home_launcher_gesture_handler.cc
@@ -74,6 +74,7 @@ if (window->type() == aura::client::WINDOW_TYPE_POPUP) return false; + // Do not process if |window| is not the root of a transient tree. if (::wm::GetTransientParent(window)) return false; @@ -181,7 +182,6 @@ return false; mode_ = mode; - initial_event_location_ = location; last_event_location_ = base::make_optional(location); UpdateWindows(0.0, /*animate=*/false); @@ -198,11 +198,6 @@ last_event_location_ = base::make_optional(location); last_scroll_y_ = scroll_y; - if (mode_ == Mode::kSlideUpToShow && - (*last_event_location_ - initial_event_location_).y() > 0) { - UpdateWindows(0.0, /*animate=*/false); - return true; - } DCHECK(display_.is_valid()); UpdateWindows(GetHeightInWorkAreaAsRatio(location, display_.work_area()), @@ -210,8 +205,7 @@ return true; } -bool HomeLauncherGestureHandler::OnReleaseEvent(const gfx::Point& location, - bool* out_dragged_down) { +bool HomeLauncherGestureHandler::OnReleaseEvent(const gfx::Point& location) { if (IsAnimating()) return false; @@ -228,11 +222,6 @@ } last_event_location_ = base::make_optional(location); - if (out_dragged_down) { - DCHECK_EQ(mode_, Mode::kSlideUpToShow); - *out_dragged_down = - (*last_event_location_ - initial_event_location_).y() > 0; - } AnimateToFinalState(); return true; }
diff --git a/ash/app_list/home_launcher_gesture_handler.h b/ash/app_list/home_launcher_gesture_handler.h index 112d6736..f0ec8472 100644 --- a/ash/app_list/home_launcher_gesture_handler.h +++ b/ash/app_list/home_launcher_gesture_handler.h
@@ -53,7 +53,7 @@ // was not processed. bool OnPressEvent(Mode mode, const gfx::Point& location); bool OnScrollEvent(const gfx::Point& location, float scroll_y); - bool OnReleaseEvent(const gfx::Point& location, bool* out_dragged_down); + bool OnReleaseEvent(const gfx::Point& location); // Cancel a current drag and animates the items to their final state based on // |last_event_location_|. @@ -158,8 +158,6 @@ // hidden so the home launcher is visible when swiping up. std::vector<aura::Window*> hidden_windows_; - gfx::Point initial_event_location_; - // Tracks the location of the last received event in screen coordinates. Empty // if there is currently no window being processed. base::Optional<gfx::Point> last_event_location_;
diff --git a/ash/app_list/home_launcher_gesture_handler_unittest.cc b/ash/app_list/home_launcher_gesture_handler_unittest.cc index 962b98c..6c5e3b0 100644 --- a/ash/app_list/home_launcher_gesture_handler_unittest.cc +++ b/ash/app_list/home_launcher_gesture_handler_unittest.cc
@@ -141,14 +141,14 @@ // Tests that flinging down in this mode will keep the window visible. DoPress(Mode::kSlideUpToShow); GetGestureHandler()->OnScrollEvent(gfx::Point(0, 300), 10.f); - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300)); ASSERT_TRUE(window->IsVisible()); // Tests that flinging up in this mode will hide the window and show the // home launcher. DoPress(Mode::kSlideUpToShow); GetGestureHandler()->OnScrollEvent(gfx::Point(0, 300), -10.f); - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300)); EXPECT_FALSE(window->IsVisible()); } @@ -164,13 +164,13 @@ // Tests that flinging up in this mode will not show the mru window. DoPress(Mode::kSlideDownToHide); GetGestureHandler()->OnScrollEvent(gfx::Point(0, 100), -10.f); - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100)); ASSERT_FALSE(window->IsVisible()); // Tests that flinging down in this mode will show the mru window. DoPress(Mode::kSlideDownToHide); GetGestureHandler()->OnScrollEvent(gfx::Point(0, 100), 10.f); - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100)); EXPECT_TRUE(window->IsVisible()); } @@ -185,12 +185,6 @@ GetGestureHandler()->OnPressEvent(Mode::kSlideUpToShow, gfx::Point(0, 400)); GetGestureHandler()->OnScrollEvent(gfx::Point(0, 420), 1.f); EXPECT_EQ(gfx::Transform(), window->transform()); - - // Tests that OnReleaseEvent returns true when checking if the release point - // is below the press point. - bool released_below; - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 420), &released_below); - EXPECT_TRUE(released_below); } // Tests that the home launcher gestures work with overview mode as expected. @@ -221,7 +215,7 @@ // Tests that after releasing at below the halfway point, we remain in // overview mode. - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300)); EXPECT_TRUE(controller->IsSelecting()); EXPECT_EQ(window1_initial_translation, window1->transform().To2dTranslation().y()); @@ -231,7 +225,7 @@ // Tests that after releasing on the bottom half, overview mode has been // exited, and the two windows have been minimized to show the home launcher. DoPress(Mode::kSlideUpToShow); - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100)); EXPECT_FALSE(controller->IsSelecting()); EXPECT_TRUE(wm::GetWindowState(window1.get())->IsMinimized()); EXPECT_TRUE(wm::GetWindowState(window2.get())->IsMinimized()); @@ -268,7 +262,7 @@ // Tests that after releasing at below the halfway point, we remain in // both splitview and overview mode. - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300)); EXPECT_EQ(window1->transform(), gfx::Transform()); EXPECT_EQ(window2_initial_translation, window2->transform().To2dTranslation().y()); @@ -278,7 +272,7 @@ // Tests that after releasing on the bottom half, overivew and splitview have // both been exited, and both windows are minimized to show the home launcher. DoPress(Mode::kSlideUpToShow); - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100)); EXPECT_FALSE(window_selector_controller->IsSelecting()); EXPECT_FALSE(split_view_controller->IsSplitViewModeActive()); EXPECT_TRUE(wm::GetWindowState(window1.get())->IsMinimized()); @@ -314,7 +308,7 @@ // Tests that after releasing at below the halfway point, we remain in // splitview. - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300)); EXPECT_EQ(window1->transform(), gfx::Transform()); EXPECT_EQ(window2->transform(), gfx::Transform()); EXPECT_TRUE(split_view_controller->IsSplitViewModeActive()); @@ -322,7 +316,7 @@ // Tests that after releasing on the bottom half, splitview has been ended, // and the two windows have been minimized to show the home launcher. DoPress(Mode::kSlideUpToShow); - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100)); EXPECT_FALSE(split_view_controller->IsSplitViewModeActive()); EXPECT_TRUE(wm::GetWindowState(window1.get())->IsMinimized()); EXPECT_TRUE(wm::GetWindowState(window2.get())->IsMinimized()); @@ -399,7 +393,7 @@ EXPECT_NE(1.f, window1->layer()->opacity()); // Tests the transform and opacity have returned to the identity and 1. - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300)); EXPECT_EQ(gfx::Transform(), window1->transform()); EXPECT_EQ(1.f, window1->layer()->opacity()); @@ -426,7 +420,7 @@ ASSERT_FALSE(window3->IsVisible()); // Test that |window1| is minimized on release. - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 100)); EXPECT_TRUE(wm::GetWindowState(window1.get())->IsMinimized()); // The rest of the windows remain invisible, to show the home launcher. @@ -460,7 +454,7 @@ // Tests that after releasing on the bottom half, the transient child reverts // to its original values. - GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(0, 300)); EXPECT_EQ(1.0f, child->layer()->opacity()); EXPECT_EQ(gfx::Transform(), child->transform()); } @@ -514,7 +508,7 @@ EXPECT_FALSE(GetGestureHandler()->transient_descendants_values_.empty()); // Tests that after a drag, the variables are either null or empty. - GetGestureHandler()->OnReleaseEvent(gfx::Point(10, 10), nullptr); + GetGestureHandler()->OnReleaseEvent(gfx::Point(10, 10)); EXPECT_FALSE(GetGestureHandler()->window()); EXPECT_FALSE(GetGestureHandler()->last_event_location_); EXPECT_EQ(Mode::kNone, GetGestureHandler()->mode_);
diff --git a/ash/app_list/model/app_list_model_unittest.cc b/ash/app_list/model/app_list_model_unittest.cc index 526c393..e0f228d9 100644 --- a/ash/app_list/model/app_list_model_unittest.cc +++ b/ash/app_list/model/app_list_model_unittest.cc
@@ -227,7 +227,6 @@ // testing::Test overrides: void SetUp() override { AppListModelTest::SetUp(); } - void TearDown() override { AppListModelTest::TearDown(); } private: DISALLOW_COPY_AND_ASSIGN(AppListModelFolderTest);
diff --git a/ash/assistant/ui/caption_bar.cc b/ash/assistant/ui/caption_bar.cc index 01b1861..1261e6e2 100644 --- a/ash/assistant/ui/caption_bar.cc +++ b/ash/assistant/ui/caption_bar.cc
@@ -13,7 +13,6 @@ #include "ui/gfx/color_palette.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/strings/grit/ui_strings.h" -#include "ui/views/background.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/layout/box_layout.h" #include "ui/views/widget/widget.h" @@ -24,7 +23,7 @@ // Appearance. constexpr int kCaptionButtonSizeDip = 32; -constexpr int kPreferredHeightDip = 32; +constexpr int kPreferredHeightDip = 48; constexpr int kVectorIconSizeDip = 12; // CaptionButton ---------------------------------------------------------------
diff --git a/ash/bluetooth_devices_observer.cc b/ash/bluetooth_devices_observer.cc index e301b12a..7b7ce1d 100644 --- a/ash/bluetooth_devices_observer.cc +++ b/ash/bluetooth_devices_observer.cc
@@ -10,11 +10,16 @@ namespace ash { BluetoothDevicesObserver::BluetoothDevicesObserver( - const DeviceChangedCallback& device_changed_callback) - : device_changed_callback_(device_changed_callback), weak_factory_(this) { - device::BluetoothAdapterFactory::GetAdapter( - base::Bind(&BluetoothDevicesObserver::InitializeOnAdapterReady, - weak_factory_.GetWeakPtr())); + const AdapterOrDeviceChangedCallback& device_changed_callback) + : adapter_or_device_changed_callback_(device_changed_callback), + weak_factory_(this) { + if (device::BluetoothAdapterFactory::IsBluetoothSupported()) { + device::BluetoothAdapterFactory::GetAdapter( + base::Bind(&BluetoothDevicesObserver::InitializeOnAdapterReady, + weak_factory_.GetWeakPtr())); + } else { + adapter_or_device_changed_callback_.Run(/*device=*/nullptr); + } } BluetoothDevicesObserver::~BluetoothDevicesObserver() { @@ -22,9 +27,21 @@ bluetooth_adapter_->RemoveObserver(this); } +void BluetoothDevicesObserver::AdapterPresentChanged( + device::BluetoothAdapter* adapter, + bool present) { + adapter_or_device_changed_callback_.Run(/*device=*/nullptr); +} + +void BluetoothDevicesObserver::AdapterPoweredChanged( + device::BluetoothAdapter* adapter, + bool powered) { + adapter_or_device_changed_callback_.Run(/*device=*/nullptr); +} + void BluetoothDevicesObserver::DeviceChanged(device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { - device_changed_callback_.Run(device); + adapter_or_device_changed_callback_.Run(device); } void BluetoothDevicesObserver::InitializeOnAdapterReady( @@ -35,8 +52,11 @@ bool BluetoothDevicesObserver::IsConnectedBluetoothDevice( const ui::InputDevice& input_device) const { - if (!bluetooth_adapter_ || !bluetooth_adapter_->IsPowered()) + if (!bluetooth_adapter_ || !bluetooth_adapter_->IsPresent() || + !bluetooth_adapter_->IsInitialized() || + !bluetooth_adapter_->IsPowered()) { return false; + } // Since there is no map from an InputDevice to a BluetoothDevice. We just // comparing their vendor id and product id to guess a match.
diff --git a/ash/bluetooth_devices_observer.h b/ash/bluetooth_devices_observer.h index 5612ec1c..3b8a7bb 100644 --- a/ash/bluetooth_devices_observer.h +++ b/ash/bluetooth_devices_observer.h
@@ -20,14 +20,20 @@ // bluetooth device changes. class BluetoothDevicesObserver : public device::BluetoothAdapter::Observer { public: - using DeviceChangedCallback = + // Note |device| can be nullptr here if only the bluetooth adapter status + // changes. + using AdapterOrDeviceChangedCallback = base::RepeatingCallback<void(device::BluetoothDevice* device)>; explicit BluetoothDevicesObserver( - const DeviceChangedCallback& device_changed_callback); + const AdapterOrDeviceChangedCallback& device_changed_callback); ~BluetoothDevicesObserver() override; // device::BluetoothAdapter::Observer: + void AdapterPresentChanged(device::BluetoothAdapter* adapter, + bool present) override; + void AdapterPoweredChanged(device::BluetoothAdapter* adapter, + bool powered) override; void DeviceChanged(device::BluetoothAdapter* adapter, device::BluetoothDevice* device) override; @@ -50,8 +56,9 @@ // device change event. scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_; - // Callback function to be called when a bluetooth device status changes. - DeviceChangedCallback device_changed_callback_; + // Callback function to be called when the bluetooth adapter's status or a + // bluetooth device's status changes. + AdapterOrDeviceChangedCallback adapter_or_device_changed_callback_; base::WeakPtrFactory<BluetoothDevicesObserver> weak_factory_;
diff --git a/ash/display/mirror_window_controller_unittest.cc b/ash/display/mirror_window_controller_unittest.cc index 7477f7e..cfa48321 100644 --- a/ash/display/mirror_window_controller_unittest.cc +++ b/ash/display/mirror_window_controller_unittest.cc
@@ -27,6 +27,7 @@ namespace ash { namespace { + display::ManagedDisplayInfo CreateDisplayInfo(int64_t id, const gfx::Rect& bounds, float scale = 1.f) { @@ -49,7 +50,6 @@ ::switches::kEnableSoftwareMirroring); AshTestBase::SetUp(); } - void TearDown() override { AshTestBase::TearDown(); } private: DISALLOW_COPY_AND_ASSIGN(MirrorOnBootTest);
diff --git a/ash/keyboard/virtual_keyboard_controller.cc b/ash/keyboard/virtual_keyboard_controller.cc index 85e0be7..36010e8 100644 --- a/ash/keyboard/virtual_keyboard_controller.cc +++ b/ash/keyboard/virtual_keyboard_controller.cc
@@ -103,9 +103,10 @@ keyboard::KeyboardController::Get()->AddObserver(this); - bluetooth_devices_observer_ = std::make_unique<BluetoothDevicesObserver>( - base::BindRepeating(&VirtualKeyboardController::UpdateBluetoothDevice, - base::Unretained(this))); + bluetooth_devices_observer_ = + std::make_unique<BluetoothDevicesObserver>(base::BindRepeating( + &VirtualKeyboardController::OnBluetoothAdapterOrDeviceChanged, + base::Unretained(this))); } VirtualKeyboardController::~VirtualKeyboardController() { @@ -301,16 +302,15 @@ Shell::Get()->EnableKeyboard(); } -void VirtualKeyboardController::UpdateBluetoothDevice( +void VirtualKeyboardController::OnBluetoothAdapterOrDeviceChanged( device::BluetoothDevice* device) { // We only care about keyboard type bluetooth device change. - if (device->GetDeviceType() != device::BluetoothDeviceType::KEYBOARD && - device->GetDeviceType() != + if (!device || + device->GetDeviceType() == device::BluetoothDeviceType::KEYBOARD || + device->GetDeviceType() == device::BluetoothDeviceType::KEYBOARD_MOUSE_COMBO) { - return; + UpdateDevices(); } - - UpdateDevices(); } } // namespace ash
diff --git a/ash/keyboard/virtual_keyboard_controller.h b/ash/keyboard/virtual_keyboard_controller.h index 0583ea4..fcaa6a0 100644 --- a/ash/keyboard/virtual_keyboard_controller.h +++ b/ash/keyboard/virtual_keyboard_controller.h
@@ -73,9 +73,9 @@ // Force enable the keyboard and show it, even in laptop mode. void ForceShowKeyboard(); - // Callback function of |bluetooth_devices_observer_|. Called when |device| - // changes. - void UpdateBluetoothDevice(device::BluetoothDevice* device); + // Callback function of |bluetooth_devices_observer_|. Called when the + // bluetooth adapter or |device| changes. + void OnBluetoothAdapterOrDeviceChanged(device::BluetoothDevice* device); // True if an external keyboard is connected. bool has_external_keyboard_;
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc index ab10dec..1dca8ab 100644 --- a/ash/login/login_screen_controller.cc +++ b/ash/login/login_screen_controller.cc
@@ -495,8 +495,8 @@ Shelf* shelf = Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow()); // Tell the focus direction to the status area or the shelf so they can focus // the correct child view. - if (reverse && !ShelfWidget::IsUsingViewsShelf()) { - if (Shell::GetPrimaryRootWindowController()->IsSystemTrayVisible()) + if (reverse || !ShelfWidget::IsUsingViewsShelf()) { + if (!Shell::GetPrimaryRootWindowController()->IsSystemTrayVisible()) return; shelf->GetStatusAreaWidget() ->status_area_widget_delegate()
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 20eb722..43be2f3 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -695,7 +695,7 @@ auth_error_bubble_->ShowErrorBubble( container, big_view->auth_user()->password_view() /*anchor_view*/, - true /*show_persistently*/); + LoginBubble::kFlagPersistent); } } @@ -814,7 +814,7 @@ label->SetEnabledColor(SK_ColorWHITE); warning_banner_bubble_->ShowErrorBubble( label, CurrentBigUserView()->auth_user()->password_view() /*anchor_view*/, - true /*show_persistently*/); + LoginBubble::kFlagPersistent); } void LockContentsView::OnHideWarningBanner() { @@ -973,7 +973,7 @@ detachable_base_error_bubble_->ShowErrorBubble( label, CurrentBigUserView()->auth_user()->password_view() /*anchor_view*/, - true /*show_persistently*/); + LoginBubble::kFlagPersistent); // Remove the focus from the password field, to make user less likely to enter // the password without seeing the warning about detachable base change. @@ -1487,7 +1487,7 @@ supervised_user_deprecation_bubble_->ShowErrorBubble( label, CurrentBigUserView()->auth_user()->password_view() /*anchor_view*/, - true /*show_persistently*/); + LoginBubble::kFlagPersistent); } // The new auth user might have different last used detachable base - make @@ -1593,7 +1593,7 @@ auth_error_bubble_->ShowErrorBubble( container, big_view->auth_user()->password_view() /*anchor_view*/, - false /*show_persistently*/); + LoginBubble::kFlagsNone); } void LockContentsView::OnEasyUnlockIconHovered() {
diff --git a/ash/login/ui/login_base_bubble_view.cc b/ash/login/ui/login_base_bubble_view.cc index 6aa1919f..bc1dd484 100644 --- a/ash/login/ui/login_base_bubble_view.cc +++ b/ash/login/ui/login_base_bubble_view.cc
@@ -46,10 +46,6 @@ LoginBaseBubbleView::~LoginBaseBubbleView() = default; -bool LoginBaseBubbleView::IsPersistent() const { - return false; -} - void LoginBaseBubbleView::OnBeforeBubbleWidgetInit( views::Widget::InitParams* params, views::Widget* widget) const {
diff --git a/ash/login/ui/login_base_bubble_view.h b/ash/login/ui/login_base_bubble_view.h index 1dbc008..5dfd3ef3 100644 --- a/ash/login/ui/login_base_bubble_view.h +++ b/ash/login/ui/login_base_bubble_view.h
@@ -21,9 +21,6 @@ gfx::NativeView parent_window); ~LoginBaseBubbleView() override; - // Returns whether or not this bubble should show persistently. - virtual bool IsPersistent() const; - // views::BubbleDialogDelegateView: void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, views::Widget* widget) const override;
diff --git a/ash/login/ui/login_bubble.cc b/ash/login/ui/login_bubble.cc index 23a8f04..5af28309 100644 --- a/ash/login/ui/login_bubble.cc +++ b/ash/login/ui/login_bubble.cc
@@ -96,10 +96,8 @@ public: LoginErrorBubbleView(views::View* content, views::View* anchor_view, - aura::Window* container, - bool show_persistently) - : LoginBaseBubbleView(anchor_view, container), - show_persistently_(show_persistently) { + aura::Window* container) + : LoginBaseBubbleView(anchor_view, container) { set_anchor_view_insets( gfx::Insets(kAnchorViewErrorBubbleVerticalSpacingDp, 0)); @@ -127,9 +125,6 @@ ~LoginErrorBubbleView() override = default; - // LoginBaseBubbleView: - bool IsPersistent() const override { return show_persistently_; } - // views::View: const char* GetClassName() const override { return "LoginErrorBubbleView"; } void GetAccessibleNodeData(ui::AXNodeData* node_data) override { @@ -137,8 +132,6 @@ } private: - bool show_persistently_; - DISALLOW_COPY_AND_ASSIGN(LoginErrorBubbleView); }; @@ -454,14 +447,14 @@ void LoginBubble::ShowErrorBubble(views::View* content, views::View* anchor_view, - bool show_persistently) { + uint32_t flags) { if (bubble_view_) CloseImmediately(); + flags_ = flags; aura::Window* menu_container = Shell::GetContainer( Shell::GetPrimaryRootWindow(), kShellWindowId_MenuContainer); - bubble_view_ = new LoginErrorBubbleView(content, anchor_view, menu_container, - show_persistently); + bubble_view_ = new LoginErrorBubbleView(content, anchor_view, menu_container); Show(); } @@ -478,6 +471,7 @@ if (bubble_view_) CloseImmediately(); + flags_ = kFlagsNone; bubble_opener_ = bubble_opener; bubble_view_ = new LoginUserMenuView(this, username, email, type, is_owner, anchor_view, show_remove_user, @@ -496,6 +490,7 @@ if (bubble_view_) CloseImmediately(); + flags_ = kFlagsNone; bubble_view_ = new LoginTooltipView(message, anchor_view); Show(); } @@ -505,6 +500,7 @@ if (bubble_view_) CloseImmediately(); + flags_ = kFlagsNone; bubble_opener_ = bubble_opener; const bool had_focus = bubble_opener_->HasFocus(); @@ -577,7 +573,7 @@ if (bubble_view_->GetWidget()->IsActive()) return; - if (!bubble_view_->IsPersistent()) { + if (!(flags_ & kFlagPersistent)) { Close(); } } @@ -601,7 +597,7 @@ if (gained_focus && bubble_window->Contains(gained_focus)) return; - if (!bubble_view_->IsPersistent()) + if (!(flags_ & kFlagPersistent)) Close(); } @@ -642,7 +638,7 @@ return; } - if (!bubble_view_->IsPersistent()) + if (!(flags_ & kFlagPersistent)) Close(); } @@ -691,6 +687,7 @@ is_visible_ = false; bubble_opener_ = nullptr; bubble_view_ = nullptr; + flags_ = kFlagsNone; } void LoginBubble::EnsureBubbleInScreen() {
diff --git a/ash/login/ui/login_bubble.h b/ash/login/ui/login_bubble.h index e7f77941..48bb440 100644 --- a/ash/login/ui/login_bubble.h +++ b/ash/login/ui/login_bubble.h
@@ -40,6 +40,12 @@ static const int kUserMenuRemoveUserButtonIdForTest; + // Flags passed to ShowErrorBubble(). + static constexpr uint32_t kFlagsNone = 0; + // If set, the shown error bubble will not be closed due to an unrelated user + // action - e.g. the bubble will not be closed if the user starts typing. + static constexpr uint32_t kFlagPersistent = 1 << 0; + LoginBubble(); ~LoginBubble() override; @@ -47,7 +53,7 @@ // |anchor_view| is the anchor for placing the bubble view. void ShowErrorBubble(views::View* content, views::View* anchor_view, - bool show_persistently); + uint32_t flags); // Shows a user menu bubble. // |anchor_view| is the anchor for placing the bubble view. @@ -122,6 +128,9 @@ // Repositions the bubble view if it extends too far right or down. void EnsureBubbleInScreen(); + // Flags passed to ShowErrorBubble(). + uint32_t flags_ = kFlagsNone; + LoginBaseBubbleView* bubble_view_ = nullptr; // A button that could open/close the bubble.
diff --git a/ash/login/ui/login_bubble_unittest.cc b/ash/login/ui/login_bubble_unittest.cc index b93cba5..1934f6a 100644 --- a/ash/login/ui/login_bubble_unittest.cc +++ b/ash/login/ui/login_bubble_unittest.cc
@@ -288,7 +288,7 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, false /*show_persistently*/); + bubble_->ShowErrorBubble(error_text, container_, LoginBubble::kFlagsNone); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that key event on a view other than error closes the error bubble. @@ -302,7 +302,7 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, false /*show_persistently*/); + bubble_->ShowErrorBubble(error_text, container_, LoginBubble::kFlagsNone); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that mouse event on the bubble itself won't close the bubble. @@ -322,7 +322,7 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, false /*show_persistently*/); + bubble_->ShowErrorBubble(error_text, container_, LoginBubble::kFlagsNone); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that gesture event on the bubble itself won't close the bubble. @@ -340,7 +340,8 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, true /*show_persistently*/); + bubble_->ShowErrorBubble(error_text, container_, + LoginBubble::kFlagPersistent); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that mouse event on the bubble itself won't close the bubble.
diff --git a/ash/metrics/login_metrics_recorder_unittest.cc b/ash/metrics/login_metrics_recorder_unittest.cc index ba84451..f328ced 100644 --- a/ash/metrics/login_metrics_recorder_unittest.cc +++ b/ash/metrics/login_metrics_recorder_unittest.cc
@@ -46,8 +46,6 @@ histogram_tester_.reset(new base::HistogramTester()); } - void TearDown() override { LoginTestBase::TearDown(); } - protected: void EnableTabletMode(bool enable) { Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(
diff --git a/ash/multi_user/multi_user_window_manager.cc b/ash/multi_user/multi_user_window_manager.cc index 09e16917..723fd247 100644 --- a/ash/multi_user/multi_user_window_manager.cc +++ b/ash/multi_user/multi_user_window_manager.cc
@@ -7,20 +7,21 @@ #include <set> #include <vector> -#include "ash/media_controller.h" -#include "ash/multi_user/multi_user_window_manager.h" -#include "ash/multi_user/multi_user_window_manager_delegate.h" -#include "ash/multi_user/user_switch_animator.h" #include "ash/public/cpp/shell_window_ids.h" -#include "ash/session/session_controller.h" +#include "ash/public/interfaces/ash_window_manager.mojom.h" #include "ash/shell.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/auto_reset.h" #include "base/macros.h" +#include "base/metrics/histogram_macros.h" +#include "base/strings/string_util.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/mus/window_mus.h" +#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_tree_host.h" +#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_types.h" #include "ui/events/event.h" #include "ui/views/mus/mus_client.h" @@ -28,22 +29,67 @@ #include "ui/wm/core/window_animations.h" #include "ui/wm/core/window_util.h" -namespace ash { namespace { -// The animation time for a single window that is fading in / out. -constexpr base::TimeDelta kAnimationTime = - base::TimeDelta::FromMilliseconds(100); +// The animation time in milliseconds for a single window which is fading +// in / out. +const int kAnimationTimeMS = 100; -// The animation time for the fade in and / or out when switching users. -constexpr base::TimeDelta kUserFadeTime = - base::TimeDelta::FromMilliseconds(110); +// The animation time in milliseconds for the fade in and / or out when +// switching users. +const int kUserFadeTimeMS = 110; // The animation time in ms for a window which get teleported to another screen. -constexpr base::TimeDelta kTeleportAnimationTime = - base::TimeDelta::FromMilliseconds(300); +const int kTeleportAnimationTimeMS = 300; -MultiUserWindowManager* g_instance = nullptr; +// Used for UMA metrics. Do not reorder. +enum TeleportWindowType { + TELEPORT_WINDOW_BROWSER = 0, + TELEPORT_WINDOW_INCOGNITO_BROWSER, + TELEPORT_WINDOW_V1_APP, + TELEPORT_WINDOW_V2_APP, + DEPRECATED_TELEPORT_WINDOW_PANEL, + TELEPORT_WINDOW_POPUP, + TELEPORT_WINDOW_UNKNOWN, + NUM_TELEPORT_WINDOW_TYPES +}; + +// Records the type of window which was transferred to another desktop. +void RecordUMAForTransferredWindowType(aura::Window* window) { + // We need to figure out what kind of window this is to record the transfer. + Browser* browser = chrome::FindBrowserWithWindow(window); + TeleportWindowType window_type = TELEPORT_WINDOW_UNKNOWN; + if (browser) { + if (browser->profile()->IsOffTheRecord()) { + window_type = TELEPORT_WINDOW_INCOGNITO_BROWSER; + } else if (browser->is_app()) { + window_type = TELEPORT_WINDOW_V1_APP; + } else if (browser->is_type_popup()) { + window_type = TELEPORT_WINDOW_POPUP; + } else { + window_type = TELEPORT_WINDOW_BROWSER; + } + } else { + // Unit tests might come here without a profile manager. + if (!g_browser_process->profile_manager()) + return; + // If it is not a browser, it is probably be a V2 application. In that case + // one of the AppWindowRegistry instances should know about it. + extensions::AppWindow* app_window = NULL; + std::vector<Profile*> profiles = + g_browser_process->profile_manager()->GetLoadedProfiles(); + for (std::vector<Profile*>::iterator it = profiles.begin(); + it != profiles.end() && app_window == NULL; it++) { + app_window = + extensions::AppWindowRegistry::Get(*it)->GetAppWindowForNativeWindow( + window); + } + if (app_window) + window_type = TELEPORT_WINDOW_V2_APP; + } + UMA_HISTOGRAM_ENUMERATION("MultiProfile.TeleportWindowType", window_type, + NUM_TELEPORT_WINDOW_TYPES); +} bool HasSystemModalTransientChildWindow(aura::Window* window) { if (window == nullptr) @@ -54,54 +100,34 @@ if (window->parent() == system_modal_container) return true; - for (aura::Window* transient_child : ::wm::GetTransientChildren(window)) { - if (HasSystemModalTransientChildWindow(transient_child)) + aura::Window::Windows::const_iterator it = + wm::GetTransientChildren(window).begin(); + for (; it != wm::GetTransientChildren(window).end(); ++it) { + if (HasSystemModalTransientChildWindow(*it)) return true; } return false; } -mojom::WallpaperUserInfoPtr WallpaperUserInfoForAccount( - const AccountId& account_id) { - DCHECK(account_id.is_valid()); - mojom::WallpaperUserInfoPtr wallpaper_user_info = - mojom::WallpaperUserInfo::New(); - SessionController* session_controller = Shell::Get()->session_controller(); - for (const mojom::UserSessionPtr& user_session : - session_controller->GetUserSessions()) { - if (user_session->user_info->account_id == account_id) { - wallpaper_user_info->account_id = account_id; - wallpaper_user_info->type = user_session->user_info->type; - wallpaper_user_info->is_ephemeral = user_session->user_info->is_ephemeral; - wallpaper_user_info->has_gaia_account = - user_session->user_info->has_gaia_account; - return wallpaper_user_info; - } - } - NOTREACHED(); - return wallpaper_user_info; -} - } // namespace // A class to temporarily change the animation properties for a window. class AnimationSetter { public: - AnimationSetter(aura::Window* window, base::TimeDelta animation_time) + AnimationSetter(aura::Window* window, int animation_time_in_ms) : window_(window), - previous_animation_type_( - ::wm::GetWindowVisibilityAnimationType(window_)), + previous_animation_type_(wm::GetWindowVisibilityAnimationType(window_)), previous_animation_time_( - ::wm::GetWindowVisibilityAnimationDuration(*window_)) { - ::wm::SetWindowVisibilityAnimationType( - window_, ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); - ::wm::SetWindowVisibilityAnimationDuration(window_, animation_time); + wm::GetWindowVisibilityAnimationDuration(*window_)) { + wm::SetWindowVisibilityAnimationType( + window_, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); + wm::SetWindowVisibilityAnimationDuration( + window_, base::TimeDelta::FromMilliseconds(animation_time_in_ms)); } ~AnimationSetter() { - ::wm::SetWindowVisibilityAnimationType(window_, previous_animation_type_); - ::wm::SetWindowVisibilityAnimationDuration(window_, - previous_animation_time_); + wm::SetWindowVisibilityAnimationType(window_, previous_animation_type_); + wm::SetWindowVisibilityAnimationDuration(window_, previous_animation_time_); } private: @@ -117,16 +143,46 @@ DISALLOW_COPY_AND_ASSIGN(AnimationSetter); }; -MultiUserWindowManager::MultiUserWindowManager( - MultiUserWindowManagerDelegate* delegate, - const AccountId& account_id) - : delegate_(delegate), current_account_id_(account_id) { - g_instance = this; - Shell::Get()->tablet_mode_controller()->AddObserver(this); - Shell::Get()->session_controller()->AddObserver(this); +// This class keeps track of all applications which were started for a user. +// When an app gets created, the window will be tagged for that user. Note +// that the destruction does not need to be tracked here since the universal +// window observer will take care of that. +class AppObserver : public extensions::AppWindowRegistry::Observer { + public: + explicit AppObserver(const std::string& user_id) : user_id_(user_id) {} + ~AppObserver() override {} + + // AppWindowRegistry::Observer overrides: + void OnAppWindowAdded(extensions::AppWindow* app_window) override { + aura::Window* window = app_window->GetNativeWindow(); + DCHECK(window); + MultiUserWindowManagerChromeOS::GetInstance()->SetWindowOwner( + window, AccountId::FromUserEmail(user_id_)); + } + + private: + std::string user_id_; + + DISALLOW_COPY_AND_ASSIGN(AppObserver); +}; + +MultiUserWindowManagerChromeOS::MultiUserWindowManagerChromeOS( + const AccountId& current_account_id) + : current_account_id_(current_account_id), + suppress_visibility_changes_(false), + animation_speed_(ANIMATION_SPEED_NORMAL) { + if (features::IsUsingWindowService()) { + ash_window_manager_ = + views::MusClient::Get() + ->window_tree_client() + ->BindWindowManagerInterface<ash::mojom::AshWindowManager>(); + } + + if (TabletModeClient::Get()) + tablet_mode_observer_.Add(TabletModeClient::Get()); } -MultiUserWindowManager::~MultiUserWindowManager() { +MultiUserWindowManagerChromeOS::~MultiUserWindowManagerChromeOS() { // When the MultiUserWindowManager gets destroyed, ash::Shell is mostly gone. // As such we should not try to finalize any outstanding user animations. // Note that the destruction of the object can be done later. @@ -143,22 +199,57 @@ window = window_to_entry_.begin(); } - Shell::Get()->session_controller()->RemoveObserver(this); - Shell::Get()->tablet_mode_controller()->RemoveObserver(this); - g_instance = nullptr; + if (user_manager::UserManager::IsInitialized()) + user_manager::UserManager::Get()->RemoveSessionStateObserver(this); + + // Remove all app observers. + ProfileManager* profile_manager = g_browser_process->profile_manager(); + // might be nullptr in unit tests. + if (!profile_manager) + return; + + std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles(); + for (auto it = profiles.begin(); it != profiles.end(); ++it) { + const AccountId account_id = multi_user_util::GetAccountIdFromProfile(*it); + AccountIdToAppWindowObserver::iterator app_observer_iterator = + account_id_to_app_observer_.find(account_id); + if (app_observer_iterator != account_id_to_app_observer_.end()) { + extensions::AppWindowRegistry::Get(*it)->RemoveObserver( + app_observer_iterator->second); + delete app_observer_iterator->second; + account_id_to_app_observer_.erase(app_observer_iterator); + } + } } -// static -MultiUserWindowManager* MultiUserWindowManager::Get() { - return g_instance; +void MultiUserWindowManagerChromeOS::Init() { + // Since we are setting the SessionStateObserver and adding the user, this + // function should get called only once. + DCHECK(account_id_to_app_observer_.find(current_account_id_) == + account_id_to_app_observer_.end()); + + // Add a session state observer to be able to monitor session changes. + if (user_manager::UserManager::IsInitialized()) + user_manager::UserManager::Get()->AddSessionStateObserver(this); + + // The BrowserListObserver would have been better to use then the old + // notification system, but that observer fires before the window got created. + registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED, + content::NotificationService::AllSources()); + + // Add an app window observer & all already running apps. + Profile* profile = + multi_user_util::GetProfileFromAccountId(current_account_id_); + if (profile) + AddUser(profile); } -void MultiUserWindowManager::SetWindowOwner(aura::Window* window, - const AccountId& account_id) { +void MultiUserWindowManagerChromeOS::SetWindowOwner( + aura::Window* window, + const AccountId& account_id) { // Make sure the window is valid and there was no owner yet. DCHECK(window); DCHECK(account_id.is_valid()); - if (GetWindowOwner(window) == account_id) return; DCHECK(GetWindowOwner(window).empty()); @@ -169,7 +260,7 @@ // Add observers to track state changes. window->AddObserver(this); - ::wm::TransientWindowManager::GetOrCreate(window)->AddObserver(this); + wm::TransientWindowManager::GetOrCreate(window)->AddObserver(this); // Check if this window was created due to a user interaction. If it was, // transfer it to the current user. @@ -180,18 +271,23 @@ // will add the children but not the owner to the transient children map. AddTransientOwnerRecursive(window, window); + // Notify entry adding. + for (Observer& observer : observers_) + observer.OnOwnerEntryAdded(window); + if (!IsWindowOnDesktopOfUser(window, current_account_id_)) - SetWindowVisibility(window, false); + SetWindowVisibility(window, false, 0); } -const AccountId& MultiUserWindowManager::GetWindowOwner( +const AccountId& MultiUserWindowManagerChromeOS::GetWindowOwner( aura::Window* window) const { WindowToEntryMap::const_iterator it = window_to_entry_.find(window); return it != window_to_entry_.end() ? it->second->owner() : EmptyAccountId(); } -void MultiUserWindowManager::ShowWindowForUser(aura::Window* window, - const AccountId& account_id) { +void MultiUserWindowManagerChromeOS::ShowWindowForUser( + aura::Window* window, + const AccountId& account_id) { const AccountId previous_owner(GetUserPresentingWindow(window)); if (!ShowWindowForUserIntern(window, account_id)) return; @@ -202,10 +298,10 @@ previous_owner != current_account_id_) return; - Shell::Get()->session_controller()->SwitchActiveUser(account_id); + SessionControllerClient::DoSwitchActiveUser(account_id); } -bool MultiUserWindowManager::AreWindowsSharedAmongUsers() const { +bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() const { WindowToEntryMap::const_iterator it = window_to_entry_.begin(); for (; it != window_to_entry_.end(); ++it) { if (it->second->owner() != it->second->show_for_user()) @@ -214,14 +310,23 @@ return false; } -bool MultiUserWindowManager::IsWindowOnDesktopOfUser( +void MultiUserWindowManagerChromeOS::GetOwnersOfVisibleWindows( + std::set<AccountId>* account_ids) const { + for (WindowToEntryMap::const_iterator it = window_to_entry_.begin(); + it != window_to_entry_.end(); ++it) { + if (it->first->IsVisible()) + account_ids->insert(it->second->owner()); + } +} + +bool MultiUserWindowManagerChromeOS::IsWindowOnDesktopOfUser( aura::Window* window, const AccountId& account_id) const { const AccountId& presenting_user = GetUserPresentingWindow(window); return (!presenting_user.is_valid()) || presenting_user == account_id; } -const AccountId& MultiUserWindowManager::GetUserPresentingWindow( +const AccountId& MultiUserWindowManagerChromeOS::GetUserPresentingWindow( aura::Window* window) const { WindowToEntryMap::const_iterator it = window_to_entry_.find(window); // If the window is not owned by anyone it is shown on all desktops and we @@ -232,41 +337,82 @@ return it->second->show_for_user(); } -void MultiUserWindowManager::OnActiveUserSessionChanged( - const AccountId& account_id) { +void MultiUserWindowManagerChromeOS::AddUser(content::BrowserContext* context) { + Profile* profile = Profile::FromBrowserContext(context); + const AccountId& account_id( + multi_user_util::GetAccountIdFromProfile(profile)); + if (account_id_to_app_observer_.find(account_id) != + account_id_to_app_observer_.end()) + return; + + account_id_to_app_observer_[account_id] = + new AppObserver(account_id.GetUserEmail()); + extensions::AppWindowRegistry::Get(profile)->AddObserver( + account_id_to_app_observer_[account_id]); + + // Account all existing application windows of this user accordingly. + const extensions::AppWindowRegistry::AppWindowList& app_windows = + extensions::AppWindowRegistry::Get(profile)->app_windows(); + extensions::AppWindowRegistry::AppWindowList::const_iterator it = + app_windows.begin(); + for (; it != app_windows.end(); ++it) + account_id_to_app_observer_[account_id]->OnAppWindowAdded(*it); + + // Account all existing browser windows of this user accordingly. + BrowserList* browser_list = BrowserList::GetInstance(); + BrowserList::const_iterator browser_it = browser_list->begin(); + for (; browser_it != browser_list->end(); ++browser_it) { + if ((*browser_it)->profile()->GetOriginalProfile() == profile) + AddBrowserWindow(*browser_it); + } +} + +void MultiUserWindowManagerChromeOS::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void MultiUserWindowManagerChromeOS::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +void MultiUserWindowManagerChromeOS::ActiveUserChanged( + const user_manager::User* active_user) { // This needs to be set before the animation starts. - current_account_id_ = account_id; + current_account_id_ = active_user->GetAccountId(); // Here to avoid a very nasty race condition, we must destruct any previously // created animation before creating a new one. Otherwise, the newly // constructed will hide all windows of the old user in the first step of the // animation only to be reshown again by the destructor of the old animation. animation_.reset(); - animation_ = std::make_unique<UserSwitchAnimator>( - this, WallpaperUserInfoForAccount(current_account_id_), - GetAdjustedAnimationTime(kUserFadeTime)); + animation_.reset(new UserSwitchAnimatorChromeOS( + this, current_account_id_, + GetAdjustedAnimationTimeInMS(kUserFadeTimeMS))); // Call RequestCaptureState here instead of having MediaClient observe // ActiveUserChanged because it must happen after - // MultiUserWindowManager is notified. - Shell::Get()->media_controller()->RequestCaptureState(); + // MultiUserWindowManagerChromeOS is notified. The MediaClient may be null in + // tests. + if (MediaClient::Get()) + MediaClient::Get()->RequestCaptureState(); } -void MultiUserWindowManager::OnWindowDestroyed(aura::Window* window) { +void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) { if (GetWindowOwner(window).empty()) { // This must be a window in the transient chain - remove it and its // children from the owner. RemoveTransientOwnerRecursive(window); return; } - ::wm::TransientWindowManager::GetOrCreate(window)->RemoveObserver(this); + wm::TransientWindowManager::GetOrCreate(window)->RemoveObserver(this); // Remove the window from the owners list. delete window_to_entry_[window]; window_to_entry_.erase(window); } -void MultiUserWindowManager::OnWindowVisibilityChanging(aura::Window* window, - bool visible) { +void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanging( + aura::Window* window, + bool visible) { // This command gets called first and immediately when show or hide gets // called. We remember here the desired state for restoration IF we were // not ourselves issuing the call. @@ -289,23 +435,24 @@ } } -void MultiUserWindowManager::OnWindowVisibilityChanged(aura::Window* window, - bool visible) { +void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanged( + aura::Window* window, + bool visible) { if (suppress_visibility_changes_) return; // Don't allow to make the window visible if it shouldn't be. if (visible && !IsWindowOnDesktopOfUser(window, current_account_id_)) { - SetWindowVisibility(window, false); + SetWindowVisibility(window, false, 0); return; } aura::Window* owned_parent = GetOwningWindowInTransientChain(window); if (owned_parent && owned_parent != window && visible && !IsWindowOnDesktopOfUser(owned_parent, current_account_id_)) - SetWindowVisibility(window, false); + SetWindowVisibility(window, false, 0); } -void MultiUserWindowManager::OnTransientChildAdded( +void MultiUserWindowManagerChromeOS::OnTransientChildAdded( aura::Window* window, aura::Window* transient_window) { if (!GetWindowOwner(window).empty()) { @@ -320,7 +467,7 @@ AddTransientOwnerRecursive(transient_window, owned_parent); } -void MultiUserWindowManager::OnTransientChildRemoved( +void MultiUserWindowManagerChromeOS::OnTransientChildRemoved( aura::Window* window, aura::Window* transient_window) { // Remove the transient child if the window itself is owned, or one of the @@ -330,25 +477,43 @@ RemoveTransientOwnerRecursive(transient_window); } -void MultiUserWindowManager::OnTabletModeStarted() { - for (auto entry : window_to_entry_) - Shell::Get()->tablet_mode_controller()->AddWindow(entry.first); +void MultiUserWindowManagerChromeOS::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK_EQ(chrome::NOTIFICATION_BROWSER_OPENED, type); + AddBrowserWindow(content::Source<Browser>(source).ptr()); } -void MultiUserWindowManager::SetAnimationSpeedForTest( - MultiUserWindowManager::AnimationSpeed speed) { +void MultiUserWindowManagerChromeOS::OnTabletModeToggled(bool enabled) { + if (!enabled) + return; + + for (auto entry : window_to_entry_) { + aura::Window* window = entry.first; + if (ash_window_manager_) { + ash_window_manager_->AddWindowToTabletMode( + aura::WindowMus::Get(window)->server_id()); + } else { + ash::Shell::Get()->tablet_mode_controller()->AddWindow(window); + } + } +} + +void MultiUserWindowManagerChromeOS::SetAnimationSpeedForTest( + MultiUserWindowManagerChromeOS::AnimationSpeed speed) { animation_speed_ = speed; } -bool MultiUserWindowManager::IsAnimationRunningForTest() { +bool MultiUserWindowManagerChromeOS::IsAnimationRunningForTest() { return animation_ && !animation_->IsAnimationFinished(); } -const AccountId& MultiUserWindowManager::GetCurrentUserForTest() const { +const AccountId& MultiUserWindowManagerChromeOS::GetCurrentUserForTest() const { return current_account_id_; } -bool MultiUserWindowManager::ShowWindowForUserIntern( +bool MultiUserWindowManagerChromeOS::ShowWindowForUserIntern( aura::Window* window, const AccountId& account_id) { // If there is either no owner, or the owner is the current user, no action @@ -358,35 +523,55 @@ (owner == account_id && IsWindowOnDesktopOfUser(window, account_id))) return false; - bool minimized = ::wm::WindowStateIs(window, ui::SHOW_STATE_MINIMIZED); + bool minimized = wm::WindowStateIs(window, ui::SHOW_STATE_MINIMIZED); // Check that we are not trying to transfer ownership of a minimized window. if (account_id != owner && minimized) return false; + if (!minimized) { + // If the window was transferred without getting minimized, we should record + // the window type. Otherwise it falls back to the original desktop. + RecordUMAForTransferredWindowType(window); + } + WindowToEntryMap::iterator it = window_to_entry_.find(window); it->second->set_show_for_user(account_id); + // Tests could either not have a UserManager or the UserManager does not + // know the window owner. + const user_manager::User* const window_owner = + user_manager::UserManager::IsInitialized() + ? user_manager::UserManager::Get()->FindUser(owner) + : nullptr; + const bool teleported = !IsWindowOnDesktopOfUser(window, owner); + if (window_owner && teleported) { + window->SetProperty( + aura::client::kAvatarIconKey, + new gfx::ImageSkia(GetAvatarImageForUser(window_owner))); + } else { + window->ClearProperty(aura::client::kAvatarIconKey); + } // Show the window if the added user is the current one. if (account_id == current_account_id_) { // Only show the window if it should be shown according to its state. if (it->second->show()) - SetWindowVisibility(window, true, kTeleportAnimationTime); + SetWindowVisibility(window, true, kTeleportAnimationTimeMS); } else { - SetWindowVisibility(window, false, kTeleportAnimationTime); + SetWindowVisibility(window, false, kTeleportAnimationTimeMS); } // Notify entry change. - if (delegate_) - delegate_->OnOwnerEntryChanged(window, account_id, minimized, teleported); + for (Observer& observer : observers_) + observer.OnOwnerEntryChanged(window); return true; } -void MultiUserWindowManager::SetWindowVisibility( +void MultiUserWindowManagerChromeOS::SetWindowVisibility( aura::Window* window, bool visible, - base::TimeDelta animation_time) { + int animation_time_in_ms) { if (window->IsVisible() == visible) return; @@ -405,7 +590,7 @@ account_id = GetUserPresentingWindow(owning_window); DCHECK(account_id.is_valid()); } - Shell::Get()->session_controller()->SwitchActiveUser(account_id); + SessionControllerClient::DoSwitchActiveUser(account_id); return; } } @@ -415,43 +600,61 @@ base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true); if (visible) - ShowWithTransientChildrenRecursive(window, animation_time); + ShowWithTransientChildrenRecursive(window, animation_time_in_ms); else - SetWindowVisible(window, false, animation_time); + SetWindowVisible(window, false, animation_time_in_ms); } -void MultiUserWindowManager::ShowWithTransientChildrenRecursive( +void MultiUserWindowManagerChromeOS::NotifyAfterUserSwitchAnimationFinished() { + for (Observer& observer : observers_) + observer.OnUserSwitchAnimationFinished(); +} + +void MultiUserWindowManagerChromeOS::AddBrowserWindow(Browser* browser) { + // A unit test (e.g. CrashRestoreComplexTest.RestoreSessionForThreeUsers) can + // come here with no valid window. + if (!browser->window() || !browser->window()->GetNativeWindow()) + return; + SetWindowOwner(browser->window()->GetNativeWindow(), + multi_user_util::GetAccountIdFromProfile(browser->profile())); +} + +void MultiUserWindowManagerChromeOS::ShowWithTransientChildrenRecursive( aura::Window* window, - base::TimeDelta animation_time) { - for (aura::Window* transient_child : ::wm::GetTransientChildren(window)) - ShowWithTransientChildrenRecursive(transient_child, animation_time); + int animation_time_in_ms) { + aura::Window::Windows::const_iterator it = + wm::GetTransientChildren(window).begin(); + for (; it != wm::GetTransientChildren(window).end(); ++it) + ShowWithTransientChildrenRecursive(*it, animation_time_in_ms); // We show all children which were not explicitly hidden. - TransientWindowToVisibility::iterator it = + TransientWindowToVisibility::iterator it2 = transient_window_to_visibility_.find(window); - if (it == transient_window_to_visibility_.end() || it->second) - SetWindowVisible(window, true, animation_time); + if (it2 == transient_window_to_visibility_.end() || it2->second) + SetWindowVisible(window, true, animation_time_in_ms); } -aura::Window* MultiUserWindowManager::GetOwningWindowInTransientChain( +aura::Window* MultiUserWindowManagerChromeOS::GetOwningWindowInTransientChain( aura::Window* window) const { if (!GetWindowOwner(window).empty()) - return nullptr; - aura::Window* parent = ::wm::GetTransientParent(window); + return NULL; + aura::Window* parent = wm::GetTransientParent(window); while (parent) { if (!GetWindowOwner(parent).empty()) return parent; - parent = ::wm::GetTransientParent(parent); + parent = wm::GetTransientParent(parent); } - return nullptr; + return NULL; } -void MultiUserWindowManager::AddTransientOwnerRecursive( +void MultiUserWindowManagerChromeOS::AddTransientOwnerRecursive( aura::Window* window, aura::Window* owned_parent) { // First add all child windows. - for (aura::Window* transient_child : ::wm::GetTransientChildren(window)) - AddTransientOwnerRecursive(transient_child, owned_parent); + aura::Window::Windows::const_iterator it = + wm::GetTransientChildren(window).begin(); + for (; it != wm::GetTransientChildren(window).end(); ++it) + AddTransientOwnerRecursive(*it, owned_parent); // If this window is the owned window, we do not have to handle it again. if (window == owned_parent) @@ -464,20 +667,22 @@ // Add observers to track state changes. window->AddObserver(this); - ::wm::TransientWindowManager::GetOrCreate(window)->AddObserver(this); + wm::TransientWindowManager::GetOrCreate(window)->AddObserver(this); // Hide the window if it should not be shown. Note that this hide operation // will hide recursively this and all children - but we have already collected // their initial view state. if (!IsWindowOnDesktopOfUser(owned_parent, current_account_id_)) - SetWindowVisibility(window, false, kAnimationTime); + SetWindowVisibility(window, false, kAnimationTimeMS); } -void MultiUserWindowManager::RemoveTransientOwnerRecursive( +void MultiUserWindowManagerChromeOS::RemoveTransientOwnerRecursive( aura::Window* window) { // First remove all child windows. - for (aura::Window* transient_child : ::wm::GetTransientChildren(window)) - RemoveTransientOwnerRecursive(transient_child); + aura::Window::Windows::const_iterator it = + wm::GetTransientChildren(window).begin(); + for (; it != wm::GetTransientChildren(window).end(); ++it) + RemoveTransientOwnerRecursive(*it); // Find from transient window storage the visibility for the given window, // set the visibility accordingly and delete the window from the map. @@ -486,7 +691,7 @@ DCHECK(visibility_item != transient_window_to_visibility_.end()); window->RemoveObserver(this); - ::wm::TransientWindowManager::GetOrCreate(window)->RemoveObserver(this); + wm::TransientWindowManager::GetOrCreate(window)->RemoveObserver(this); bool unowned_view_state = visibility_item->second; transient_window_to_visibility_.erase(visibility_item); @@ -500,31 +705,40 @@ } } -void MultiUserWindowManager::SetWindowVisible(aura::Window* window, - bool visible, - base::TimeDelta animation_time) { +void MultiUserWindowManagerChromeOS::SetWindowVisible( + aura::Window* window, + bool visible, + int animation_time_in_ms) { // The TabletModeWindowManager will not handle invisible windows since they // are not user activatable. Since invisible windows are not being tracked, // we tell it to maximize / track this window now before it gets shown, to // reduce animation jank from multiple resizes. - if (visible) - Shell::Get()->tablet_mode_controller()->AddWindow(window); + if (visible) { + if (ash_window_manager_) { + ash_window_manager_->AddWindowToTabletMode( + aura::WindowMus::Get(window)->server_id()); + } else { + ash::Shell::Get()->tablet_mode_controller()->AddWindow(window); + } + } - AnimationSetter animation_setter(window, - GetAdjustedAnimationTime(animation_time)); + // Under mash we apply visibility changes to the root so both the window frame + // and contents hide together. + if (features::IsUsingWindowService()) + window = window->GetRootWindow(); + + AnimationSetter animation_setter( + window, GetAdjustedAnimationTimeInMS(animation_time_in_ms)); + if (visible) window->Show(); else window->Hide(); } -base::TimeDelta MultiUserWindowManager::GetAdjustedAnimationTime( - base::TimeDelta default_time) const { +int MultiUserWindowManagerChromeOS::GetAdjustedAnimationTimeInMS( + int default_time_in_ms) const { return animation_speed_ == ANIMATION_SPEED_NORMAL - ? default_time - : (animation_speed_ == ANIMATION_SPEED_FAST - ? base::TimeDelta::FromMilliseconds(10) - : base::TimeDelta()); + ? default_time_in_ms + : (animation_speed_ == ANIMATION_SPEED_FAST ? 10 : 0); } - -} // namespace ash
diff --git a/ash/multi_user/multi_user_window_manager.h b/ash/multi_user/multi_user_window_manager.h index e336b5d..d1861a32 100644 --- a/ash/multi_user/multi_user_window_manager.h +++ b/ash/multi_user/multi_user_window_manager.h
@@ -1,4 +1,4 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,35 +7,39 @@ #include <map> #include <memory> -#include <set> #include <string> -#include "ash/ash_export.h" -#include "ash/session/session_observer.h" -#include "ash/wm/tablet_mode/tablet_mode_observer.h" -#include "base/containers/flat_map.h" +#include "ash/public/interfaces/ash_window_manager.mojom.h" +#include "base/compiler_specific.h" #include "base/macros.h" -#include "base/time/time.h" +#include "base/observer_list.h" +#include "base/scoped_observer.h" #include "components/account_id/account_id.h" #include "ui/aura/window_observer.h" #include "ui/wm/core/transient_window_observer.h" +class Browser; + +namespace content { +class BrowserContext; +} + +namespace aura { +class Window; +} // namespace aura + namespace ash { +class MultiUserWindowManagerChromeOSTest; +} // namespace ash -class MultiUserWindowManagerDelegate; -class UserSwitchAnimator; +class AppObserver; +class UserSwitchAnimatorChromeOS; -// MultiUserWindowManager associates windows with users and ensures the -// appropriate set of windows are visible at the right time. -// MultiUserWindowManager must be explicitly told about the windows to manage. -// This is done by way of SetWindowOwner(). -// -// Each window may be associated with two accounts. The owning account (the -// account supplied to SetWindowOwner()), and an account the window is shown -// with when the account is active. Typically the 'shown' account and 'owning' -// account are the same, but the user may choose to show a window from an other -// account, in which case the 'shown' account changes. -// +// This ChromeOS implementation of the MultiUserWindowManager interface is +// detecting app and browser creations, tagging their windows automatically and +// using (currently) show and hide to make the owned windows visible - or not. +// If it becomes necessary, the function |SetWindowVisibility| can be +// overwritten to match new ways of doing this. // Note: // - aura::Window::Hide() is currently hiding the window and all owned transient // children. However aura::Window::Show() is only showing the window itself. @@ -44,10 +48,13 @@ // visibility changes from the owning user. This way the visibility can be // changed back to its requested state upon showing by us - or when the window // gets detached from its current owning parent. -class ASH_EXPORT MultiUserWindowManager : public SessionObserver, - public aura::WindowObserver, - public ::wm::TransientWindowObserver, - public TabletModeObserver { +class MultiUserWindowManagerChromeOS + : public MultiUserWindowManager, + public user_manager::UserManager::UserSessionStateObserver, + public aura::WindowObserver, + public content::NotificationObserver, + public wm::TransientWindowObserver, + public TabletModeClientObserver { public: // The speed which should be used to perform animations. enum AnimationSpeed { @@ -56,25 +63,31 @@ ANIMATION_SPEED_DISABLED // Unit tests which do not require animations. }; - MultiUserWindowManager(MultiUserWindowManagerDelegate* delegate, - const AccountId& account_id); - ~MultiUserWindowManager() override; + // Create the manager and use |active_account_id| as the active user. + explicit MultiUserWindowManagerChromeOS(const AccountId& active_account_id); + ~MultiUserWindowManagerChromeOS() override; - static MultiUserWindowManager* Get(); + // Initializes the manager after its creation. Should only be called once. + void Init(); - // Associates a window with a particular account. This may result in hiding - // |window|. This should *not* be called more than once with a different - // account. - void SetWindowOwner(aura::Window* window, const AccountId& account_id); + // MultiUserWindowManager overrides: + void SetWindowOwner(aura::Window* window, + const AccountId& account_id) override; + const AccountId& GetWindowOwner(aura::Window* window) const override; + void ShowWindowForUser(aura::Window* window, + const AccountId& account_id) override; + bool AreWindowsSharedAmongUsers() const override; + void GetOwnersOfVisibleWindows( + std::set<AccountId>* account_ids) const override; + bool IsWindowOnDesktopOfUser(aura::Window* window, + const AccountId& account_id) const override; + const AccountId& GetUserPresentingWindow(aura::Window* window) const override; + void AddUser(content::BrowserContext* context) override; + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; - // Sets the 'shown' account for a window. See class description for details on - // what the 'shown' account is. This function may trigger changing the active - // user. When the window is minimized, the 'shown' account is reset to the - // 'owning' account. - void ShowWindowForUser(aura::Window* window, const AccountId& account_id); - - // SessionObserver: - void OnActiveUserSessionChanged(const AccountId& account_id) override; + // user_manager::UserManager::UserSessionStateObserver overrides: + void ActiveUserChanged(const user_manager::User* active_user) override; // WindowObserver overrides: void OnWindowDestroyed(aura::Window* window) override; @@ -87,8 +100,13 @@ void OnTransientChildRemoved(aura::Window* window, aura::Window* transient) override; - // TabletModeObserver: - void OnTabletModeStarted() override; + // content::NotificationObserver overrides: + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; + + // TabletModeClientObserver: + void OnTabletModeToggled(bool enabled) override; // Disable any animations for unit tests. void SetAnimationSpeedForTest(AnimationSpeed speed); @@ -100,11 +118,13 @@ const AccountId& GetCurrentUserForTest() const; protected: + friend class UserSwitchAnimatorChromeOS; + class WindowEntry { public: explicit WindowEntry(const AccountId& account_id) - : owner_(account_id), show_for_user_(account_id) {} - ~WindowEntry() {} + : owner_(account_id), show_for_user_(account_id), show_(true) {} + virtual ~WindowEntry() {} // Returns the owner of this window. This cannot be changed. const AccountId& owner() const { return owner_; } @@ -132,27 +152,12 @@ AccountId show_for_user_; // True if the window should be visible for the user which shows the window. - bool show_ = true; + bool show_; DISALLOW_COPY_AND_ASSIGN(WindowEntry); }; - // TODO: make map to std::unique_ptr<WindowEntry>. - using WindowToEntryMap = std::map<aura::Window*, WindowEntry*>; - - const AccountId& GetWindowOwner(aura::Window* window) const; - - // Returns true if at least one window's 'owner' account differs from its - // 'shown' account. In other words, a window from one account is shown with - // windows from another account. - bool AreWindowsSharedAmongUsers() const; - - // Returns true if the 'shown' owner of |window| is |account_id|. - bool IsWindowOnDesktopOfUser(aura::Window* window, - const AccountId& account_id) const; - - // Returns the 'shown' owner. - const AccountId& GetUserPresentingWindow(aura::Window* window) const; + typedef std::map<aura::Window*, WindowEntry*> WindowToEntryMap; // Show a window for a user without switching the user. // Returns true when the window moved to a new desktop. @@ -164,25 +169,31 @@ // distinguish state changes performed by this class vs. state changes // performed by the others. Note furthermore that system modal dialogs will // not get hidden. We will switch instead to the owners desktop. - // The |animation_time| is the time the animation should take, an empty value - // switches instantly. + // The |animation_time_in_ms| is the time the animation should take. Set to 0 + // if it should get set instantly. void SetWindowVisibility(aura::Window* window, bool visible, - base::TimeDelta animation_time = base::TimeDelta()); + int animation_time_in_ms); + + // Notify the observers after the user switching animation is finished. + void NotifyAfterUserSwitchAnimationFinished(); const WindowToEntryMap& window_to_entry() { return window_to_entry_; } private: - friend class MultiUserWindowManagerChromeOSTest; - friend class UserSwitchAnimator; + friend class ash::MultiUserWindowManagerChromeOSTest; - using TransientWindowToVisibility = base::flat_map<aura::Window*, bool>; + typedef std::map<AccountId, AppObserver*> AccountIdToAppWindowObserver; + typedef std::map<aura::Window*, bool> TransientWindowToVisibility; + + // Add a browser window to the system so that the owner can be remembered. + void AddBrowserWindow(Browser* browser); // Show the window and its transient children. However - if a transient child // was turned invisible by some other operation, it will stay invisible. - // |animation_time| is the amount of time to animate. + // Use the given |animation_time_in_ms| for transitioning. void ShowWithTransientChildrenRecursive(aura::Window* window, - base::TimeDelta animation_time); + int animation_time_in_ms); // Find the first owned window in the chain. // Returns NULL when the window itself is owned. @@ -198,20 +209,25 @@ // unregistered. void RemoveTransientOwnerRecursive(aura::Window* window); - // Animate a |window| to be |visible| over a time of |animation_time|. + // Animate a |window| to be |visible| in |animation_time_in_ms|. void SetWindowVisible(aura::Window* window, bool visible, - base::TimeDelta aimation_time); + int aimation_time_in_ms); - // Returns the time for an animation. - base::TimeDelta GetAdjustedAnimationTime(base::TimeDelta default_time) const; - - MultiUserWindowManagerDelegate* delegate_; + // Get the animation time in milliseconds dependent on the |AnimationSpeed| + // from the passed |default_time_in_ms|. + int GetAdjustedAnimationTimeInMS(int default_time_in_ms) const; // A lookup to see to which user the given window belongs to, where and if it // should get shown. WindowToEntryMap window_to_entry_; + // A list of all known users and their app window observers. + AccountIdToAppWindowObserver account_id_to_app_observer_; + + // An observer list to be notified upon window owner changes. + base::ObserverList<Observer>::Unchecked observers_; + // A map which remembers for owned transient windows their own visibility. TransientWindowToVisibility transient_window_to_visibility_; @@ -220,18 +236,25 @@ // being read from the user manager to be in sync while a switch occurs. AccountId current_account_id_; + // The notification registrar to track the creation of browser windows. + content::NotificationRegistrar registrar_; + // Suppress changes to the visibility flag while we are changing it ourselves. - bool suppress_visibility_changes_ = false; + bool suppress_visibility_changes_; // The speed which is used to perform any animations. - AnimationSpeed animation_speed_ = ANIMATION_SPEED_NORMAL; + AnimationSpeed animation_speed_; // The animation between users. - std::unique_ptr<UserSwitchAnimator> animation_; + std::unique_ptr<UserSwitchAnimatorChromeOS> animation_; - DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManager); + // Only used in mash. + ash::mojom::AshWindowManagerAssociatedPtr ash_window_manager_; + + ScopedObserver<TabletModeClient, TabletModeClientObserver> + tablet_mode_observer_{this}; + + DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManagerChromeOS); }; -} // namespace ash - #endif // ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_H_
diff --git a/ash/multi_user/multi_user_window_manager_delegate.h b/ash/multi_user/multi_user_window_manager_delegate.h deleted file mode 100644 index 4df91f87..0000000 --- a/ash/multi_user/multi_user_window_manager_delegate.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_DELEGATE_H_ -#define ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_DELEGATE_H_ - -#include "ash/ash_export.h" - -class AccountId; - -namespace aura { -class Window; -} // namespace aura - -namespace ash { - -class ASH_EXPORT MultiUserWindowManagerDelegate { - public: - // Called when the owner of the window tracked by the manager is changed. - // |was_minimized| is true if the window was minimized. |teleported| is true - // if the window was not on the desktop of the current user. - virtual void OnOwnerEntryChanged(aura::Window* window, - const AccountId& account_id, - bool was_minimized, - bool teleported) {} - - // Called when the active account changes. This is followed by - // OnTransitionUserShelfToNewAccount() and OnDidSwitchActiveAccount(). - virtual void OnWillSwitchActiveAccount(const AccountId& account_id) {} - - // Called at the time when the user's shelf should transition to the account - // supplied to OnWillSwitchActiveAccount(). - virtual void OnTransitionUserShelfToNewAccount() {} - - // Called when the active account change is complete. - virtual void OnDidSwitchActiveAccount() {} - - protected: - virtual ~MultiUserWindowManagerDelegate() {} -}; - -} // namespace ash - -#endif // ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_DELEGATE_H_
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index 7d5e072..093bdd7 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -1318,16 +1318,8 @@ HomeLauncherGestureHandler* home_launcher_handler = Shell::Get()->app_list_controller()->home_launcher_gesture_handler(); - bool dragged_down; if (home_launcher_handler && - home_launcher_handler->OnReleaseEvent(gesture_in_screen.location(), - &dragged_down)) { - if (dragged_down && visibility_state() == SHELF_AUTO_HIDE) { - DCHECK_EQ(SHELF_AUTO_HIDE_SHOWN, gesture_drag_auto_hide_state_); - gesture_drag_auto_hide_state_ = SHELF_AUTO_HIDE_HIDDEN; - gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS; - UpdateVisibilityState(); - } + home_launcher_handler->OnReleaseEvent(gesture_in_screen.location())) { gesture_drag_status_ = GESTURE_DRAG_NONE; return; }
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 62947c56..a961b70 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -9,6 +9,8 @@ #include "ash/accelerators/accelerator_controller.h" #include "ash/accelerators/accelerator_table.h" +#include "ash/app_list/app_list_controller_impl.h" +#include "ash/app_list/home_launcher_gesture_handler.h" #include "ash/app_list/test/app_list_test_helper.h" #include "ash/focus_cycler.h" #include "ash/public/cpp/app_list/app_list_features.h" @@ -2481,6 +2483,70 @@ EXPECT_EQ(gfx::Point(500, 400), status_area_bounds.bottom_right()); } +// Tests that the shelf forwards the appropriate events to the home launcher +// gesture handler to handle. +TEST_F(ShelfLayoutManagerTest, HomeLauncherGestureHandler) { + // Home launcher is only available in tablet mode. + Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); + + // Home launcher gesture handler needs at least one window. + std::unique_ptr<aura::Window> window = + AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400)); + wm::ActivateWindow(window.get()); + + const gfx::Point shelf_center = + GetVisibleShelfWidgetBoundsInScreen().CenterPoint(); + + // Helper to create a scroll event for this test. + auto create_scroll_event = [&shelf_center](ui::EventType type, + float scroll_y) { + ui::GestureEventDetails details = + type == ui::ET_GESTURE_SCROLL_END + ? ui::GestureEventDetails(type) + : ui::GestureEventDetails(type, 0, scroll_y); + return ui::GestureEvent(shelf_center.x(), shelf_center.y(), 0, + base::TimeTicks(), details); + }; + + // The home launcher gesture handler should not be handling any window + // initially. + ShelfLayoutManager* manager = GetShelfLayoutManager(); + HomeLauncherGestureHandler* gesture_handler = + Shell::Get()->app_list_controller()->home_launcher_gesture_handler(); + ASSERT_TRUE(gesture_handler); + ASSERT_FALSE(gesture_handler->window()); + + // Tests that after scrolling up on the shelf, the home launcher gesture + // handler will be acting on |window|. + manager->ProcessGestureEvent( + create_scroll_event(ui::ET_GESTURE_SCROLL_BEGIN, -1.f)); + EXPECT_EQ(window.get(), gesture_handler->window()); + + // Tests that since the initial scroll event was scrolled up, the home + // launcher gesture handler will continue to act on |window| regardless of + // direction of scroll updates. + manager->ProcessGestureEvent( + create_scroll_event(ui::ET_GESTURE_SCROLL_UPDATE, -1.f)); + EXPECT_EQ(window.get(), gesture_handler->window()); + manager->ProcessGestureEvent( + create_scroll_event(ui::ET_GESTURE_SCROLL_UPDATE, 1.f)); + EXPECT_EQ(window.get(), gesture_handler->window()); + + // End the scroll. + manager->ProcessGestureEvent( + create_scroll_event(ui::ET_GESTURE_SCROLL_END, 1.f)); + ASSERT_FALSE(gesture_handler->window()); + + // Tests that if the initial scroll event is directed downwards, the home + // launcher gesture handler will not act on |window|. + manager->ProcessGestureEvent( + create_scroll_event(ui::ET_GESTURE_SCROLL_BEGIN, 1.f)); + EXPECT_FALSE(gesture_handler->window()); + manager->ProcessGestureEvent( + create_scroll_event(ui::ET_GESTURE_SCROLL_UPDATE, -1.f)); + EXPECT_FALSE(gesture_handler->window()); +} + class ShelfLayoutManagerKeyboardTest : public AshTestBase { public: ShelfLayoutManagerKeyboardTest() = default;
diff --git a/ash/sticky_keys/sticky_keys_unittest.cc b/ash/sticky_keys/sticky_keys_unittest.cc index 24309ad..bff297d 100644 --- a/ash/sticky_keys/sticky_keys_unittest.cc +++ b/ash/sticky_keys/sticky_keys_unittest.cc
@@ -28,8 +28,6 @@ root_window_ = target_->GetRootWindow(); } - void TearDown() override { AshTestBase::TearDown(); } - virtual void OnShortcutPressed() { if (target_) { delete target_;
diff --git a/ash/system/network/network_icon_purger.cc b/ash/system/network/network_icon_purger.cc new file mode 100644 index 0000000..f202013 --- /dev/null +++ b/ash/system/network/network_icon_purger.cc
@@ -0,0 +1,42 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/network/network_icon_purger.h" + +#include "ash/system/network/network_icon.h" +#include "base/bind.h" +#include "chromeos/network/network_state_handler.h" + +using chromeos::NetworkHandler; + +namespace { +const int kPurgeDelayMs = 300; +} // namespace + +namespace ash { + +NetworkIconPurger::NetworkIconPurger() { + // NetworkHandler may not be initialized in tests. + if (NetworkHandler::IsInitialized()) { + auto* network_handler = NetworkHandler::Get(); + network_handler->network_state_handler()->AddObserver(this, FROM_HERE); + } +} + +NetworkIconPurger::~NetworkIconPurger() { + // NetworkHandler may not be initialized in tests. + if (NetworkHandler::IsInitialized()) { + auto* network_handler = NetworkHandler::Get(); + network_handler->network_state_handler()->RemoveObserver(this, FROM_HERE); + } +} + +void NetworkIconPurger::NetworkListChanged() { + if (timer_.IsRunning()) + return; + timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kPurgeDelayMs), + base::BindOnce(&network_icon::PurgeNetworkIconCache)); +} + +} // namespace ash
diff --git a/ash/system/network/network_icon_purger.h b/ash/system/network/network_icon_purger.h new file mode 100644 index 0000000..2ff32ef --- /dev/null +++ b/ash/system/network/network_icon_purger.h
@@ -0,0 +1,34 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_NETWORK_NETWORK_ICON_PURGER_H_ +#define ASH_SYSTEM_NETWORK_NETWORK_ICON_PURGER_H_ + +#include "base/macros.h" +#include "base/timer/timer.h" +#include "chromeos/network/network_state_handler_observer.h" + +namespace ash { + +// Purges network icon caches when the network list is updated. +// Introduces a small delay before purging the cache. This prevents +// us from excessively purging icon caches when receiving updates +// in quick succession. +class NetworkIconPurger : public chromeos::NetworkStateHandlerObserver { + public: + NetworkIconPurger(); + ~NetworkIconPurger() override; + + // chromeos::NetworkStateHandlerObserver + void NetworkListChanged() override; + + private: + base::OneShotTimer timer_; + + DISALLOW_COPY_AND_ASSIGN(NetworkIconPurger); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_NETWORK_NETWORK_ICON_PURGER_H_
diff --git a/ash/system/network/tray_network_state_observer.cc b/ash/system/network/tray_network_state_observer.cc index 4bdc206..f002def 100644 --- a/ash/system/network/tray_network_state_observer.cc +++ b/ash/system/network/tray_network_state_observer.cc
@@ -7,7 +7,6 @@ #include <set> #include <string> -#include "ash/system/network/network_icon.h" #include "base/location.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" @@ -31,7 +30,6 @@ TrayNetworkStateObserver::TrayNetworkStateObserver(Delegate* delegate) : delegate_(delegate), - purge_icons_(false), update_frequency_(kUpdateFrequencyMs) { if (ui::ScopedAnimationDurationScaleMode::duration_scale_mode() != ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION) { @@ -58,7 +56,6 @@ } void TrayNetworkStateObserver::NetworkListChanged() { - purge_icons_ = true; SignalUpdate(false /* notify_a11y */); } @@ -119,10 +116,6 @@ void TrayNetworkStateObserver::SendNetworkStateChanged(bool notify_a11y) { delegate_->NetworkStateChanged(notify_a11y); - if (purge_icons_) { - network_icon::PurgeNetworkIconCache(); - purge_icons_ = false; - } } } // namespace ash
diff --git a/ash/system/network/tray_network_state_observer.h b/ash/system/network/tray_network_state_observer.h index f560c79c..7716cf8 100644 --- a/ash/system/network/tray_network_state_observer.h +++ b/ash/system/network/tray_network_state_observer.h
@@ -52,9 +52,6 @@ // Unowned Delegate pointer (must outlive this instance). Delegate* delegate_; - // Set to true when we should purge stale icons in the cache. - bool purge_icons_; - // Frequency at which to push NetworkStateChanged updates. This avoids // unnecessarily frequent UI updates (which can be expensive). We set this // to 0 for tests to eliminate timing variance.
diff --git a/ash/system/overview/overview_button_tray.cc b/ash/system/overview/overview_button_tray.cc index 72a6b3b..bb42830 100644 --- a/ash/system/overview/overview_button_tray.cc +++ b/ash/system/overview/overview_button_tray.cc
@@ -13,6 +13,7 @@ #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_container.h" #include "ash/wm/mru_window_tracker.h" +#include "ash/wm/overview/window_selector.h" #include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" @@ -79,7 +80,9 @@ kDoubleTapThresholdMs) { // Second taps should not be processed outside of overview mode. (First // taps should be outside of overview). - DCHECK(Shell::Get()->window_selector_controller()->IsSelecting()); + WindowSelectorController* window_selector_controller = + Shell::Get()->window_selector_controller(); + DCHECK(window_selector_controller->IsSelecting()); base::RecordAction(base::UserMetricsAction("Tablet_QuickSwitch")); @@ -89,8 +92,12 @@ Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(); // Switch to the second most recently used window (most recent is the - // current window) if it exists, unless splitview mode is active. - if (mru_window_list.size() > 1u) { + // current window) if it exists, unless splitview mode is active. Do not + // switch we entered overview mode will all windows minimized. + if (mru_window_list.size() > 1u && + window_selector_controller->window_selector() + ->enter_exit_overview_type() != + WindowSelector::EnterExitOverviewType::kWindowsMinimized) { aura::Window* new_active_window = mru_window_list[1]; // In splitview mode, quick switch will only affect the windows on the non @@ -110,7 +117,7 @@ } AnimateInkDrop(views::InkDropState::DEACTIVATED, nullptr); - wm::GetWindowState(new_active_window)->Activate(); + ::wm::ActivateWindow(new_active_window); last_press_event_time_ = base::nullopt; return true; }
diff --git a/ash/system/overview/overview_button_tray_unittest.cc b/ash/system/overview/overview_button_tray_unittest.cc index 7a2f2af8..cab20b7 100644 --- a/ash/system/overview/overview_button_tray_unittest.cc +++ b/ash/system/overview/overview_button_tray_unittest.cc
@@ -133,6 +133,8 @@ } TEST_F(OverviewButtonTrayTest, PerformDoubleTapAction) { + TabletModeControllerTestApi().EnterTabletMode(); + ASSERT_FALSE(Shell::Get()->window_selector_controller()->IsSelecting()); // Add two windows and activate the second one to test quick switch. @@ -167,6 +169,15 @@ PerformDoubleTap(); EXPECT_EQ(window2->layer()->GetTargetOpacity(), 1.0); EXPECT_TRUE(wm::IsActiveWindow(window2.get())); + + // Verify that if all windows are minimized, double tapping the tray will have + // no effect. + ASSERT_TRUE(!Shell::Get()->window_selector_controller()->IsSelecting()); + wm::GetWindowState(window1.get())->Minimize(); + wm::GetWindowState(window2.get())->Minimize(); + PerformDoubleTap(); + EXPECT_FALSE(wm::IsActiveWindow(window1.get())); + EXPECT_FALSE(wm::IsActiveWindow(window2.get())); } // Tests that tapping on the control will record the user action Tray_Overview.
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc index aca7029..9c7743c 100644 --- a/ash/system/unified/unified_system_tray.cc +++ b/ash/system/unified/unified_system_tray.cc
@@ -14,6 +14,7 @@ #include "ash/system/message_center/message_center_ui_delegate.h" #include "ash/system/model/clock_model.h" #include "ash/system/model/system_tray_model.h" +#include "ash/system/network/network_icon_purger.h" #include "ash/system/network/network_tray_view.h" #include "ash/system/power/tray_power.h" #include "ash/system/status_area_widget.h" @@ -118,6 +119,7 @@ model_(std::make_unique<UnifiedSystemTrayModel>()), slider_bubble_controller_( std::make_unique<UnifiedSliderBubbleController>(this)), + network_icon_purger_(std::make_unique<NetworkIconPurger>()), ime_mode_view_(new ImeModeView(shelf)), managed_device_view_(new ManagedDeviceView(shelf)), notification_counter_item_(new NotificationCounterView(shelf)),
diff --git a/ash/system/unified/unified_system_tray.h b/ash/system/unified/unified_system_tray.h index d712984..bc6911e 100644 --- a/ash/system/unified/unified_system_tray.h +++ b/ash/system/unified/unified_system_tray.h
@@ -25,6 +25,7 @@ class UnifiedSliderBubbleController; class UnifiedSystemTrayBubble; class UnifiedSystemTrayModel; +class NetworkIconPurger; // UnifiedSystemTray is system menu of Chromium OS, which is typically // accessible from the button on the right bottom of the screen (Status Area). @@ -123,6 +124,8 @@ const std::unique_ptr<UnifiedSliderBubbleController> slider_bubble_controller_; + const std::unique_ptr<NetworkIconPurger> network_icon_purger_; + ImeModeView* const ime_mode_view_; ManagedDeviceView* const managed_device_view_; NotificationCounterView* const notification_counter_item_;
diff --git a/ash/wm/ash_focus_rules_unittest.cc b/ash/wm/ash_focus_rules_unittest.cc index d801460..fea4a3ec 100644 --- a/ash/wm/ash_focus_rules_unittest.cc +++ b/ash/wm/ash_focus_rules_unittest.cc
@@ -97,8 +97,6 @@ Shell::Get()->session_controller())); } - void TearDown() override { AshTestBase::TearDown(); } - aura::Window* CreateWindowInDefaultContainer() { return CreateWindowInContainer(kShellWindowId_DefaultContainer); }
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.cc b/ash/wm/tablet_mode/tablet_mode_controller.cc index 1a3732ea..2bf3e3e 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller.cc +++ b/ash/wm/tablet_mode/tablet_mode_controller.cc
@@ -135,9 +135,10 @@ Shell::Get()->window_tree_host_manager()->AddObserver(this); chromeos::AccelerometerReader::GetInstance()->AddObserver(this); ui::InputDeviceManager::GetInstance()->AddObserver(this); - bluetooth_devices_observer_ = std::make_unique<BluetoothDevicesObserver>( - base::BindRepeating(&TabletModeController::UpdateBluetoothDevice, - base::Unretained(this))); + bluetooth_devices_observer_ = + std::make_unique<BluetoothDevicesObserver>(base::BindRepeating( + &TabletModeController::OnBluetoothAdapterOrDeviceChanged, + base::Unretained(this))); } chromeos::PowerManagerClient* power_manager_client = chromeos::DBusThreadManager::Get()->GetPowerManagerClient(); @@ -613,20 +614,19 @@ } } -void TabletModeController::UpdateBluetoothDevice( +void TabletModeController::OnBluetoothAdapterOrDeviceChanged( device::BluetoothDevice* device) { // We only care about pointing type bluetooth device change. Note KEYBOARD // type is also included here as sometimes a bluetooth keyboard comes with a // touch pad. - if (device->GetDeviceType() != device::BluetoothDeviceType::MOUSE && - device->GetDeviceType() != - device::BluetoothDeviceType::KEYBOARD_MOUSE_COMBO && - device->GetDeviceType() != device::BluetoothDeviceType::KEYBOARD && - device->GetDeviceType() != device::BluetoothDeviceType::TABLET) { - return; + if (!device || + device->GetDeviceType() == device::BluetoothDeviceType::MOUSE || + device->GetDeviceType() == + device::BluetoothDeviceType::KEYBOARD_MOUSE_COMBO || + device->GetDeviceType() == device::BluetoothDeviceType::KEYBOARD || + device->GetDeviceType() == device::BluetoothDeviceType::TABLET) { + HandlePointingDeviceAddedOrRemoved(); } - - HandlePointingDeviceAddedOrRemoved(); } void TabletModeController::UpdateInternalInputDevicesEventBlocker() {
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.h b/ash/wm/tablet_mode/tablet_mode_controller.h index 83a479ec..8ee3f3f0 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller.h +++ b/ash/wm/tablet_mode/tablet_mode_controller.h
@@ -205,9 +205,9 @@ // sent from device manager. This will exit tablet mode if needed. void HandlePointingDeviceAddedOrRemoved(); - // Callback function for |bluetooth_devices_observer_|. Called when |device| - // changes. - void UpdateBluetoothDevice(device::BluetoothDevice* device); + // Callback function of |bluetooth_devices_observer_|. Called when the + // bluetooth adapter or |device| changes. + void OnBluetoothAdapterOrDeviceChanged(device::BluetoothDevice* device); // Update the internal mouse and keyboard event blocker |event_blocker_| // according to current configuration. The internal input events should be
diff --git a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc index f443bf3b..b36b6f6 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc +++ b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
@@ -902,6 +902,7 @@ // Set the current list of devices to empty so that they don't interfere // with the test. base::RunLoop().RunUntilIdle(); + ws::InputDeviceClientTestApi().SetMouseDevices({}); ws::InputDeviceClientTestApi().SetTouchpadDevices({}); base::RunLoop().RunUntilIdle();
diff --git a/ash/wm/window_animations_unittest.cc b/ash/wm/window_animations_unittest.cc index 1242b24a..e054197 100644 --- a/ash/wm/window_animations_unittest.cc +++ b/ash/wm/window_animations_unittest.cc
@@ -36,8 +36,6 @@ AshTestBase::SetUp(); } - void TearDown() override { AshTestBase::TearDown(); } - private: DISALLOW_COPY_AND_ASSIGN(WindowAnimationsTest); }; @@ -51,7 +49,7 @@ animator_->AddObserver(this); // RemoveObserver is called when the first animation is scheduled and so // there should be no need for now to remove it in destructor. - }; + } base::TimeDelta duration() { return duration_; } protected:
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index 6cbe394..5a77373c 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn
@@ -91,7 +91,7 @@ if (is_component_build) { cflags += [ # Do not export inline member functions. This makes component builds - # faster. This is similar to -fviisibility-inlines-hidden. + # faster. This is similar to -fvisibility-inlines-hidden. "/Zc:dllexportInlines-", ] }
diff --git a/build/toolchain/OWNERS b/build/toolchain/OWNERS index 85d8d311..b329d48 100644 --- a/build/toolchain/OWNERS +++ b/build/toolchain/OWNERS
@@ -1,2 +1,8 @@ dpranke@chromium.org scottmg@chromium.org + +# Clang Static Analyzer. +per-file clang_static_analyzer*=mmoroz@chromium.org + +# Code Coverage. +per-file *code_coverage*=mmoroz@chromium.org
diff --git a/build/toolchain/clang_static_analyzer_wrapper.py b/build/toolchain/clang_static_analyzer_wrapper.py index 1c54d72..a9882a3 100755 --- a/build/toolchain/clang_static_analyzer_wrapper.py +++ b/build/toolchain/clang_static_analyzer_wrapper.py
@@ -25,7 +25,6 @@ '-fdiagnostics-show-option', '-analyzer-checker=cplusplus', '-analyzer-opt-analyze-nested-blocks', - '-analyzer-eagerly-assume', '-analyzer-output=text', '-analyzer-config', 'suppress-c++-stdlib=true',
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.cc b/cc/mojo_embedder/async_layer_tree_frame_sink.cc index 2e6c67c..c62acab 100644 --- a/cc/mojo_embedder/async_layer_tree_frame_sink.cc +++ b/cc/mojo_embedder/async_layer_tree_frame_sink.cc
@@ -276,14 +276,13 @@ client_->DidReceiveCompositorFrameAck(); } -void AsyncLayerTreeFrameSink::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - client_->DidPresentCompositorFrame(presentation_token, feedback); -} +void AsyncLayerTreeFrameSink::OnBeginFrame( + const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) { + for (const auto& pair : feedbacks) { + client_->DidPresentCompositorFrame(pair.first, pair.second); + } -void AsyncLayerTreeFrameSink::OnBeginFrame(const viz::BeginFrameArgs& args) { DCHECK_LE(pipeline_reporting_frame_times_.size(), 25u); if (args.trace_id != -1) { base::TimeTicks current_time = base::TimeTicks::Now();
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.h b/cc/mojo_embedder/async_layer_tree_frame_sink.h index 3eea4d96..f3f3be12 100644 --- a/cc/mojo_embedder/async_layer_tree_frame_sink.h +++ b/cc/mojo_embedder/async_layer_tree_frame_sink.h
@@ -129,10 +129,9 @@ // mojom::CompositorFrameSinkClient implementation: void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override; - void OnBeginFrame(const viz::BeginFrameArgs& begin_frame_args) override; + void OnBeginFrame(const viz::BeginFrameArgs& begin_frame_args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) override; void OnBeginFramePausedChanged(bool paused) override; void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override;
diff --git a/cc/tiles/image_controller.cc b/cc/tiles/image_controller.cc index 99e977f..d6a91504 100644 --- a/cc/tiles/image_controller.cc +++ b/cc/tiles/image_controller.cc
@@ -117,7 +117,9 @@ request.task->DidComplete(); } } - cache_->UnrefImage(request.draw_image); + + if (request.need_unref) + cache_->UnrefImage(request.draw_image); // Orphan the request so that we can still run it when a new cache is set. request.task = nullptr;
diff --git a/cc/tiles/image_controller_unittest.cc b/cc/tiles/image_controller_unittest.cc index 9a52430..473c7c2 100644 --- a/cc/tiles/image_controller_unittest.cc +++ b/cc/tiles/image_controller_unittest.cc
@@ -232,6 +232,12 @@ PaintImage::kDefaultFrameIndex); } +DrawImage CreateBitmapDrawImage(gfx::Size size) { + return DrawImage( + CreateBitmapImage(size), SkIRect::MakeWH(size.width(), size.height()), + kNone_SkFilterQuality, SkMatrix::I(), PaintImage::kDefaultFrameIndex); +} + class ImageControllerTest : public testing::Test { public: ImageControllerTest() @@ -322,15 +328,7 @@ base::RunLoop run_loop; DecodeClient decode_client; - SkBitmap bitmap; - bitmap.allocN32Pixels(1, 1); - DrawImage image = DrawImage(PaintImageBuilder::WithDefault() - .set_id(PaintImage::GetNextId()) - .set_image(SkImage::MakeFromBitmap(bitmap), - PaintImage::GetNextContentId()) - .TakePaintImage(), - SkIRect::MakeWH(1, 1), kNone_SkFilterQuality, - SkMatrix::I(), PaintImage::kDefaultFrameIndex); + DrawImage image = CreateBitmapDrawImage(gfx::Size(1, 1)); ImageController::ImageDecodeRequestId expected_id = controller()->QueueImageDecode( @@ -606,5 +604,92 @@ ResetController(); } +TEST_F(ImageControllerTest, QueueImageDecodeLazyCancelImmediately) { + DecodeClient decode_client1; + DecodeClient decode_client2; + + // Create two images so that there is always one that is queued up and + // not run yet. This prevents raciness in this test. + DrawImage image1 = CreateDiscardableDrawImage(gfx::Size(1, 1)); + DrawImage image2 = CreateDiscardableDrawImage(gfx::Size(1, 1)); + + ImageController::ImageDecodeRequestId expected_id1 = + controller()->QueueImageDecode( + image(), + base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), + base::Bind([]() {}))); + + ImageController::ImageDecodeRequestId expected_id2 = + controller()->QueueImageDecode( + image(), + base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), + base::Bind([]() {}))); + + // This needs a ref because it is lazy. + EXPECT_EQ(2, cache()->number_of_refs()); + + // Instead of running, immediately cancel everything. + controller()->SetImageDecodeCache(nullptr); + + // This should not crash, and nothing should have run. + EXPECT_NE(expected_id1, decode_client1.id()); + EXPECT_NE(expected_id2, decode_client2.id()); + EXPECT_EQ(0u, decode_client1.id()); + EXPECT_EQ(0u, decode_client2.id()); + EXPECT_EQ(ImageController::ImageDecodeResult::FAILURE, + decode_client1.result()); + EXPECT_EQ(ImageController::ImageDecodeResult::FAILURE, + decode_client2.result()); + + // Refs should still be cleaned up. + EXPECT_EQ(0, cache()->number_of_refs()); + + // Explicitly reset the controller so that orphaned task callbacks run + // while the decode clients still exist. + ResetController(); +} + +TEST_F(ImageControllerTest, QueueImageDecodeNonLazyCancelImmediately) { + DecodeClient decode_client1; + DecodeClient decode_client2; + + // Create two images so that there is always one that is queued up and + // not run yet. This prevents raciness in this test. + DrawImage image1 = CreateBitmapDrawImage(gfx::Size(1, 1)); + DrawImage image2 = CreateBitmapDrawImage(gfx::Size(1, 1)); + + ImageController::ImageDecodeRequestId expected_id1 = + controller()->QueueImageDecode( + image1, + base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), + base::Bind([]() {}))); + ImageController::ImageDecodeRequestId expected_id2 = + controller()->QueueImageDecode( + image2, + base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), + base::Bind([]() {}))); + + // No ref needed here, because it is non-lazy. + EXPECT_EQ(0, cache()->number_of_refs()); + + // Instead of running, immediately cancel everything. + controller()->SetImageDecodeCache(nullptr); + + // This should not crash, and nothing should have run. + EXPECT_NE(expected_id1, decode_client1.id()); + EXPECT_NE(expected_id2, decode_client2.id()); + EXPECT_EQ(0u, decode_client1.id()); + EXPECT_EQ(0u, decode_client2.id()); + EXPECT_EQ(ImageController::ImageDecodeResult::FAILURE, + decode_client1.result()); + EXPECT_EQ(ImageController::ImageDecodeResult::FAILURE, + decode_client2.result()); + EXPECT_EQ(0, cache()->number_of_refs()); + + // Explicitly reset the controller so that orphaned task callbacks run + // while the decode clients still exist. + ResetController(); +} + } // namespace } // namespace cc
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 640bad5..6af26d03 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -312,6 +312,7 @@ pending_presentation_time_callbacks_.push_back(base::DoNothing()); sync_tree->AddPresentationCallbacks( std::move(pending_presentation_time_callbacks_)); + pending_presentation_time_callbacks_.clear(); if (needs_full_tree_sync_) TreeSynchronizer::SynchronizeTrees(root_layer(), sync_tree);
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index bc03927..98c10f8 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -8420,8 +8420,7 @@ SkBitmap bitmap_; }; -// TODO(enne): disabled until http://crbug.com/902644 is fixed -// SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestQueueImageDecodeNonLazy); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestQueueImageDecodeNonLazy); class LayerTreeHostTestHudLayerWithLayerLists : public LayerTreeHostTest { public:
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index ff0eaf35..d17163f5 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -526,6 +526,7 @@ target_tree->HandleTickmarksVisibilityChange(); target_tree->HandleScrollbarShowRequestsFromMain(); target_tree->AddPresentationCallbacks(std::move(presentation_callbacks_)); + presentation_callbacks_.clear(); } void LayerTreeImpl::HandleTickmarksVisibilityChange() {
diff --git a/chrome/VERSION b/chrome/VERSION index 358a0b2..1d2c894 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=72 MINOR=0 -BUILD=3611 +BUILD=3612 PATCH=0
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java index f69d7e5..a8dc1433 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java
@@ -31,7 +31,7 @@ /** Flag that tracks whether we've ever been disabled via enterprise policy. Should only be * accessed through isFeedProcessScopeEnabled(). */ - private static boolean sEverDisabledForPolicy = false; + private static boolean sEverDisabledForPolicy; private static PrefChangeRegistrar sPrefChangeRegistrar; private static FeedAppLifecycle sFeedAppLifecycle; private static FeedProcessScope sFeedProcessScope;
diff --git a/chrome/android/java/res/drawable/contextual_suggestions_placeholder_thumbnail.xml b/chrome/android/java/res/drawable/contextual_suggestions_placeholder_thumbnail.xml index d25dcfe..59ad487 100644 --- a/chrome/android/java/res/drawable/contextual_suggestions_placeholder_thumbnail.xml +++ b/chrome/android/java/res/drawable/contextual_suggestions_placeholder_thumbnail.xml
@@ -5,7 +5,7 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid - android:color="@color/placeholder_thumbnail_bg_color" /> + android:color="@color/thumbnail_placeholder_on_white_bg" /> <corners android:radius="@dimen/snippets_thumbnail_small_corner_radius" /> </shape> \ No newline at end of file
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index 049d6ff..0b38c30 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -198,7 +198,7 @@ <color name="bottom_system_nav_color">@android:color/white</color> <color name="bottom_system_nav_divider_color">@color/black_alpha_12</color> <color name="search_box_hint">@color/default_text_color_secondary</color> - <color name="placeholder_thumbnail_bg_color">#DADCE0</color> + <color name="thumbnail_placeholder_on_white_bg">@color/modern_grey_100</color> <color name="clear_browsing_data_selected_tab_color">@color/modern_blue_600</color> </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java index 763a7e7..e202820 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java
@@ -45,7 +45,7 @@ implements KeyboardAccessoryCoordinator.VisibilityDelegate, View.OnLayoutChangeListener { private WindowAndroid mWindowAndroid; private Supplier<InsetObserverView> mInsetObserverViewSupplier; - private boolean mShouldShow = false; + private boolean mShouldShow; private final KeyboardExtensionSizeManager mKeyboardExtensionSizeManager = new KeyboardExtensionSizeManager();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AnimatedProgressBar.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AnimatedProgressBar.java index 242dc208..663178a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AnimatedProgressBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AnimatedProgressBar.java
@@ -29,10 +29,10 @@ private final int mNormalColor; private final int mPulsedColor; - private boolean mIsRunningProgressAnimation = false; - private int mLastProgress = 0; + private boolean mIsRunningProgressAnimation; + private int mLastProgress; private Queue<ValueAnimator> mPendingIncreaseAnimations = new ArrayDeque<>(); - private ValueAnimator mPulseAnimation = null; + private ValueAnimator mPulseAnimation; public AnimatedProgressBar(MaterialProgressBar progressBar, int normalColor, int pulsedColor) { mProgressBar = progressBar;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java index c0b3d18..448f116 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java
@@ -101,7 +101,7 @@ private final BottomBarAnimations mBottomBarAnimations; private final boolean mIsRightToLeftLayout; - private ValueAnimator mDetailsPulseAnimation = null; + private ValueAnimator mDetailsPulseAnimation; private AutofillAssistantPaymentRequest mPaymentRequest;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java index 04991821..ef25178d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
@@ -290,11 +290,14 @@ */ public boolean handleKeyEvent(int keyCode, KeyEvent event) { boolean isShowingList = mListView != null && mListView.isShown(); - if (isShowingList && mMediator.getSuggestionCount() > 0 - && (KeyNavigationUtil.isGoDown(event) || KeyNavigationUtil.isGoUp(event))) { + + boolean isUpOrDown = KeyNavigationUtil.isGoUpOrDown(event); + if (isShowingList && mMediator.getSuggestionCount() > 0 && isUpOrDown) { mMediator.allowPendingItemSelection(); } - if (isShowingList && mListView.onKeyDown(keyCode, event)) return true; + boolean isValidListKey = isUpOrDown || KeyNavigationUtil.isGoRight(event) + || KeyNavigationUtil.isEnter(event); + if (isShowingList && isValidListKey && mListView.onKeyDown(keyCode, event)) return true; if (KeyNavigationUtil.isEnter(event) && mParent.getVisibility() == View.VISIBLE) { mMediator.loadTypedOmniboxText(event.getEventTime()); return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/NotificationsPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/NotificationsPreferences.java index 10c03cd..e97b22a7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/NotificationsPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/NotificationsPreferences.java
@@ -33,7 +33,7 @@ // The following fields are only set if Feed is disabled, and should be null checked before // being used. private ChromeSwitchPreference mSuggestionsPref; - private SnippetsBridge mSnippetsBridge = null; + private SnippetsBridge mSnippetsBridge; @Override public void onCreate(Bundle savedInstanceState) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java index 73d3493..22afec75 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java
@@ -238,7 +238,7 @@ new ColorDrawable(mSuggestion.getThumbnailDominantColor() != null ? mSuggestion.getThumbnailDominantColor() : ApiCompatibilityUtils.getColor(mThumbnailView.getResources(), - R.color.modern_grey_100)); + R.color.thumbnail_placeholder_on_white_bg)); mThumbnailView.setImageDrawable(colorDrawable); } else { mThumbnailView.setImageResource(R.drawable.ic_snippet_thumbnail_placeholder);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java index ddd50c61..c2e4e239 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java
@@ -41,9 +41,9 @@ */ private TabModelSelectorTabModelObserver mTabModelSelectorTabModelObserver; - private int mTabCount = 0; + private int mTabCount; - private boolean mIsIncognito = false; + private boolean mIsIncognito; TabCountProvider() { mTabCountObservers = new ObserverList<TabCountObserver>();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index a5d55a37..b1f5d18 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -140,7 +140,7 @@ UrlUtils.getIsolatedTestFilePath("/chrome/test/data/android/feed/hello_world.gcl.bin"); // Anything not parameterized runs with Feed disabled. - private boolean mInterestFeedEnabled = false; + private boolean mInterestFeedEnabled; private Tab mTab; private NewTabPage mNtp; private View mFakebox;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/action/FeedActionHandlerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/action/FeedActionHandlerTest.java index 54f7f35..94b6b30 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/action/FeedActionHandlerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/action/FeedActionHandlerTest.java
@@ -87,7 +87,7 @@ @Captor ArgumentCaptor<WebContentsObserver> mWebContentsObserverCaptor; - int mLastCommittedEntryIndex = 0; + int mLastCommittedEntryIndex; private FeedActionHandler mActionHandler; private void verifyOpenedOffline(int expectedDisposition) {
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index c23e2f6..b4dd9d1 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -3225,8 +3225,8 @@ <message name="IDS_ASSISTANT_READY_SCREEN_TITLE" desc="Title for assistant ready screen."> Your Assistant is ready </message> - <message name="IDS_ASSISTANT_READY_SCREEN_MESSAGE" desc="Message for assistant ready screen."> - When your Chromebook is set up, press the Assistant button or say "Ok Google" to get help from your Assistant anytime. + <message name="IDS_ASSISTANT_READY_SCREEN_MESSAGE" desc="Message for Assistant ready screen."> + When your Chromebook is set up, press the Assistant button or say "Ok Google", if turned on, to get help from your Assistant anytime. </message> <message name="IDS_ASSISTANT_CONTINUE_BUTTON" desc="Continue button for asssitant optin flow."> Continue @@ -3243,8 +3243,8 @@ <message name="IDS_ASSISTANT_VOICE_MATCH_TITLE" desc="Title for assistant voice match screen."> Access your Assistant with Voice Match </message> - <message name="IDS_ASSISTANT_VOICE_MATCH_MESSAGE" desc="Message for assistant voice match screen."> - Your Assisatant uses these recordings to create your voice model, which is stored in your device. Delete or retrain the model in assistant settings. View or delete voice commands in your Google activity controls. + <message name="IDS_ASSISTANT_VOICE_MATCH_MESSAGE" desc="Message for Assistant voice match screen."> + Your Assistant uses these recordings to create your voice model, which is stored in your device. Delete or retrain the model in Assistant settings. View or delete voice commands in your Google activity controls. </message> <message name="IDS_ASSISTANT_VOICE_MATCH_RECORDING" desc="Title for recording in assistant voice match screen."> Teach the Assistant to recognize your voice @@ -3252,8 +3252,8 @@ <message name="IDS_ASSISTANT_VOICE_MATCH_COMPLETED" desc="Title for completed assistant voice match screen."> Ok Google is all set </message> - <message name="IDS_ASSISTANT_VOICE_MATCH_FOOTER" desc="Footer message for assistant voice match screen."> - Recording "Ok Google" 3 times creates your voice model, which is stored on your device. Delete or retrain the model in assistant settings. View or delete voice commands in your Google activity controls. + <message name="IDS_ASSISTANT_VOICE_MATCH_FOOTER" desc="Footer message for Assistant voice match screen."> + Recording "Ok Google" 3 times creates your voice model, which is stored on your device. Delete or retrain the model in Assistant settings. View or delete voice commands in your Google activity controls. </message> <message name="IDS_ASSISTANT_VOICE_MATCH_INSTRUCTION0" desc="Instruction message for assistant voice match recording."> Say "Ok Google"
diff --git a/chrome/app/file_manager_strings.grdp b/chrome/app/file_manager_strings.grdp index 86ee050..4096441d 100644 --- a/chrome/app/file_manager_strings.grdp +++ b/chrome/app/file_manager_strings.grdp
@@ -1066,6 +1066,15 @@ <message name="IDS_FILE_BROWSER_UNABLE_TO_OPEN_CROSTINI" desc="Message shown when a user tries to use a crostini app to open a file which cannot be shared with the crostini container (e.g. in Play or USB). This message will be removed once we support this action."> To open files with $1, first copy to Linux files folder. </message> + <message name="IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE" desc="Message title shown when a user shares the root of a volume such as Downloads with the crostini container."> + Share folder with Linux + </message> + <message name="IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI" desc="Confirmation message shown when a user shares the root of a volume such as Downloads with the crostini container."> + Give Linux apps permission to open files in the $1 folder + </message> + <message name="IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE" desc="Confirmation message shown when a user shares the root of a Drive volume (My Drive, Team Drives, Computers) with the crostini container."> + Give Linux apps permission to open files in your Google Drive. Changes will sync to your other devices. + </message> <message name="IDS_FILE_BROWSER_FOLDER" desc="Folder entry type"> Folder
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI.png.sha1 b/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI.png.sha1 new file mode 100644 index 0000000..781ef44 --- /dev/null +++ b/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI.png.sha1
@@ -0,0 +1 @@ +3c6b5ddde8e73fb4c40afefbdbb2a65303fa5f3b \ No newline at end of file
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE.png.sha1 b/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE.png.sha1 new file mode 100644 index 0000000..4fc6560 --- /dev/null +++ b/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE.png.sha1
@@ -0,0 +1 @@ +b1d798df58f52d7710837c7e233319e162d85d8f \ No newline at end of file
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE.png.sha1 b/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE.png.sha1 new file mode 100644 index 0000000..781ef44 --- /dev/null +++ b/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE.png.sha1
@@ -0,0 +1 @@ +3c6b5ddde8e73fb4c40afefbdbb2a65303fa5f3b \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index bef2776b..4c19639 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3171,6 +3171,7 @@ "//ash/public/cpp", "//chrome/browser/chromeos", "//chrome/browser/chromeos/android_sms:android_sms", + "//chromeos/services/assistant/public:feature_flags", "//chromeos/services/device_sync", "//chromeos/services/device_sync/public/mojom", "//chromeos/services/ime/public/mojom",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index e670ad2..c54b83d 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -160,6 +160,7 @@ #include "ash/public/cpp/ash_switches.h" #include "chromeos/chromeos_features.h" #include "chromeos/chromeos_switches.h" +#include "chromeos/services/assistant/public/features.h" #include "components/arc/arc_features.h" #include "third_party/cros_system_api/switches/chrome_switches.h" #endif // OS_CHROMEOS @@ -4478,6 +4479,11 @@ flag_descriptions::kEnableMediaSessionAshMediaKeysName, flag_descriptions::kEnableMediaSessionAshMediaKeysDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kMediaSessionAccelerators)}, + + {"enable-assistant-voice-match", + flag_descriptions::kEnableAssistantVoiceMatchName, + flag_descriptions::kEnableAssistantVoiceMatchDescription, kOsCrOS, + FEATURE_VALUE_TYPE(chromeos::assistant::features::kAssistantVoiceMatch)}, #endif // defined(OS_CHROMEOS) {"enable-blink-heap-unified-garbage-collection",
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc index 290b051..eb5e2a2 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -140,6 +140,7 @@ using domain_reliability::CLEAR_BEACONS; using domain_reliability::CLEAR_CONTEXTS; using domain_reliability::DomainReliabilityClearMode; +using domain_reliability::DomainReliabilityKeyedServiceWrapper; using domain_reliability::DomainReliabilityMonitor; using domain_reliability::DomainReliabilityService; using domain_reliability::DomainReliabilityServiceFactory; @@ -546,21 +547,6 @@ base::Callback<bool(const GURL&)> last_filter_; }; -class DomainReliablityKeyedServiceWrapper : public KeyedService { - public: - explicit DomainReliablityKeyedServiceWrapper( - std::unique_ptr<DomainReliabilityService> service) - : service_(std::move(service)) {} - ~DomainReliablityKeyedServiceWrapper() override = default; - - DomainReliabilityService* service() { return service_.get(); } - - private: - std::unique_ptr<DomainReliabilityService> service_; - - DISALLOW_COPY_AND_ASSIGN(DomainReliablityKeyedServiceWrapper); -}; - struct TestingDomainReliabilityServiceFactoryUserData : public base::SupportsUserData::Data { TestingDomainReliabilityServiceFactoryUserData( @@ -594,8 +580,7 @@ EXPECT_FALSE(data->attached); data->attached = true; - return std::make_unique<DomainReliablityKeyedServiceWrapper>( - base::WrapUnique(data->service)); + return std::make_unique<DomainReliabilityKeyedServiceWrapper>(data->service); } std::unique_ptr<KeyedService> BuildProtocolHandlerRegistry( @@ -607,20 +592,19 @@ class ClearDomainReliabilityTester { public: - explicit ClearDomainReliabilityTester(TestingProfile* profile) : - profile_(profile), - mock_service_(new MockDomainReliabilityService()) { + explicit ClearDomainReliabilityTester(TestingProfile* profile) + : profile_(profile) { AttachService(); } - unsigned clear_count() const { return mock_service_->clear_count(); } + unsigned clear_count() const { return mock_service_.clear_count(); } DomainReliabilityClearMode last_clear_mode() const { - return mock_service_->last_clear_mode(); + return mock_service_.last_clear_mode(); } const base::Callback<bool(const GURL&)>& last_filter() const { - return mock_service_->last_filter(); + return mock_service_.last_filter(); } private: @@ -630,7 +614,7 @@ // Attach kludgey UserData struct to profile. TestingDomainReliabilityServiceFactoryUserData* data = new TestingDomainReliabilityServiceFactoryUserData(profile_, - mock_service_); + &mock_service_); EXPECT_FALSE(profile_->GetUserData(kKey)); profile_->SetUserData(kKey, base::WrapUnique(data)); @@ -646,7 +630,7 @@ } TestingProfile* profile_; - MockDomainReliabilityService* mock_service_; + MockDomainReliabilityService mock_service_; }; class RemovePasswordsTester {
diff --git a/chrome/browser/chrome_service_worker_browsertest.cc b/chrome/browser/chrome_service_worker_browsertest.cc index 9c5f702..13cb333 100644 --- a/chrome/browser/chrome_service_worker_browsertest.cc +++ b/chrome/browser/chrome_service_worker_browsertest.cc
@@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/files/scoped_temp_dir.h" #include "base/numerics/safe_conversions.h" +#include "base/path_service.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -22,10 +23,13 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/favicon/content/content_favicon_driver.h" +#include "components/favicon/core/favicon_driver_observer.h" #include "components/nacl/common/buildflags.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" @@ -34,6 +38,7 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" +#include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "ppapi/shared_impl/ppapi_switches.h" #include "third_party/blink/public/common/messaging/string_message_codec.h" @@ -331,12 +336,51 @@ DISALLOW_COPY_AND_ASSIGN(ChromeServiceWorkerFetchTest); }; -class ChromeServiceWorkerManifestFetchTest - : public ChromeServiceWorkerFetchTest { - protected: - ChromeServiceWorkerManifestFetchTest() {} - ~ChromeServiceWorkerManifestFetchTest() override {} +class FaviconUpdateWaiter : public favicon::FaviconDriverObserver { + public: + explicit FaviconUpdateWaiter(content::WebContents* web_contents) + : updated_(false), scoped_observer_(this) { + scoped_observer_.Add( + favicon::ContentFaviconDriver::FromWebContents(web_contents)); + } + void Wait() { + if (updated_) + return; + + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + } + + private: + void OnFaviconUpdated(favicon::FaviconDriver* favicon_driver, + NotificationIconType notification_icon_type, + const GURL& icon_url, + bool icon_url_changed, + const gfx::Image& image) override { + updated_ = true; + if (!quit_closure_.is_null()) + std::move(quit_closure_).Run(); + } + + bool updated_; + ScopedObserver<favicon::FaviconDriver, FaviconUpdateWaiter> scoped_observer_; + base::OnceClosure quit_closure_; + + DISALLOW_COPY_AND_ASSIGN(FaviconUpdateWaiter); +}; + +class ChromeServiceWorkerLinkFetchTest : public ChromeServiceWorkerFetchTest { + protected: + ChromeServiceWorkerLinkFetchTest() {} + ~ChromeServiceWorkerLinkFetchTest() override {} + void SetUpOnMainThread() override { + // Map all hosts to localhost and setup the EmbeddedTestServer for + // redirects. + host_resolver()->AddRule("*", "127.0.0.1"); + ChromeServiceWorkerFetchTest::SetUpOnMainThread(); + } std::string ExecuteManifestFetchTest(const std::string& url, const std::string& cross_origin) { std::string js( @@ -354,6 +398,29 @@ return GetManifestAndIssuedRequests(); } + std::string ExecuteFaviconFetchTest(const std::string& url) { + FaviconUpdateWaiter waiter( + browser()->tab_strip_model()->GetActiveWebContents()); + std::string js( + base::StringPrintf("reportOnFetch = false;" + "var link = document.createElement('link');" + "link.rel = 'icon';" + "link.href = '%s';" + "document.head.appendChild(link);", + url.c_str())); + ExecuteJavaScriptForTests(js); + waiter.Wait(); + return ExecuteScriptAndExtractString("reportRequests();"); + } + + void CopyTestFile(const std::string& src, const std::string& dst) { + base::ScopedAllowBlockingForTesting allow_blocking; + base::FilePath test_data_dir; + base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); + EXPECT_TRUE(base::CopyFile(test_data_dir.AppendASCII(src), + service_worker_dir_.GetPath().AppendASCII(dst))); + } + private: void ExecuteJavaScriptForTests(const std::string& js) { base::RunLoop run_loop; @@ -385,37 +452,55 @@ continuation.Run(); } - DISALLOW_COPY_AND_ASSIGN(ChromeServiceWorkerManifestFetchTest); + DISALLOW_COPY_AND_ASSIGN(ChromeServiceWorkerLinkFetchTest); }; -IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerManifestFetchTest, SameOrigin) { +IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest, ManifestSameOrigin) { // <link rel="manifest" href="manifest.json"> EXPECT_EQ(RequestString(GetURL("/manifest.json"), "cors", "omit"), ExecuteManifestFetchTest("manifest.json", "")); } -IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerManifestFetchTest, - SameOriginUseCredentials) { +IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest, + ManifestSameOriginUseCredentials) { // <link rel="manifest" href="manifest.json" crossorigin="use-credentials"> EXPECT_EQ(RequestString(GetURL("/manifest.json"), "cors", "include"), ExecuteManifestFetchTest("manifest.json", "use-credentials")); } -IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerManifestFetchTest, OtherOrigin) { - // <link rel="manifest" href="https://www.example.com/manifest.json"> - EXPECT_EQ( - RequestString("https://www.example.com/manifest.json", "cors", "omit"), - ExecuteManifestFetchTest("https://www.example.com/manifest.json", "")); +IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest, ManifestOtherOrigin) { + // <link rel="manifest" href="http://www.example.com:PORT/manifest.json"> + const std::string url = embedded_test_server() + ->GetURL("www.example.com", "/manifest.json") + .spec(); + EXPECT_EQ(RequestString(url, "cors", "omit"), + ExecuteManifestFetchTest(url, "")); } -IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerManifestFetchTest, - OtherOriginUseCredentials) { - // <link rel="manifest" href="https://www.example.com/manifest.json" +IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest, + ManifestOtherOriginUseCredentials) { + // <link rel="manifest" href="http://www.example.com:PORT/manifest.json" // crossorigin="use-credentials"> - EXPECT_EQ( - RequestString("https://www.example.com/manifest.json", "cors", "include"), - ExecuteManifestFetchTest("https://www.example.com/manifest.json", - "use-credentials")); + const std::string url = embedded_test_server() + ->GetURL("www.example.com", "/manifest.json") + .spec(); + EXPECT_EQ(RequestString(url, "cors", "include"), + ExecuteManifestFetchTest(url, "use-credentials")); +} + +IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest, FaviconSameOrigin) { + // <link rel="favicon" href="fav.png"> + CopyTestFile("favicon/icon.png", "fav.png"); + EXPECT_EQ(RequestString(GetURL("/fav.png"), "no-cors", "include"), + ExecuteFaviconFetchTest("/fav.png")); +} + +IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest, FaviconOtherOrigin) { + // <link rel="favicon" href="http://www.example.com:PORT/fav.png"> + CopyTestFile("favicon/icon.png", "fav.png"); + const std::string url = + embedded_test_server()->GetURL("www.example.com", "/fav.png").spec(); + EXPECT_EQ("", ExecuteFaviconFetchTest(url)); } #if BUILDFLAG(ENABLE_NACL)
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index ab847df..883ce209 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1006,6 +1006,8 @@ "login/demo_mode/demo_mode_detector.h", "login/demo_mode/demo_mode_resources_remover.cc", "login/demo_mode/demo_mode_resources_remover.h", + "login/demo_mode/demo_resources.cc", + "login/demo_mode/demo_resources.h", "login/demo_mode/demo_session.cc", "login/demo_mode/demo_session.h", "login/demo_mode/demo_setup_controller.cc", @@ -1396,6 +1398,8 @@ "net/wake_on_wifi_connection_observer.h", "net/wake_on_wifi_manager.cc", "net/wake_on_wifi_manager.h", + "network_change_manager_client.cc", + "network_change_manager_client.h", "night_light/night_light_client.cc", "night_light/night_light_client.h", "note_taking_controller_client.cc", @@ -2213,6 +2217,7 @@ "login/demo_mode/demo_extensions_external_loader_unittest.cc", "login/demo_mode/demo_mode_detector_unittest.cc", "login/demo_mode/demo_mode_resources_remover_unittest.cc", + "login/demo_mode/demo_resources_unittest.cc", "login/demo_mode/demo_session_unittest.cc", "login/demo_mode/demo_setup_controller_unittest.cc", "login/demo_mode/demo_setup_test_utils.cc", @@ -2246,6 +2251,7 @@ "net/network_pref_state_observer_unittest.cc", "net/network_throttling_observer_unittest.cc", "net/wake_on_wifi_manager_unittest.cc", + "network_change_manager_client_unittest.cc", "night_light/night_light_client_unittest.cc", "note_taking_helper_unittest.cc", "oauth2_token_service_delegate_unittest.cc",
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc index f7c9b2a..73272a9 100644 --- a/chrome/browser/chromeos/arc/arc_session_manager.cc +++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -23,6 +23,7 @@ #include "chrome/browser/chromeos/arc/optin/arc_terms_of_service_default_negotiator.h" #include "chrome/browser/chromeos/arc/optin/arc_terms_of_service_oobe_negotiator.h" #include "chrome/browser/chromeos/arc/policy/arc_android_management_checker.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_resources.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/lifetime/application_lifetime.h" @@ -337,12 +338,16 @@ scoped_opt_in_tracker_.reset(); } - if (profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn)) + PrefService* const prefs = profile_->GetPrefs(); + + if (prefs->GetBoolean(prefs::kArcSignedIn)) return; - profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true); + prefs->SetBoolean(prefs::kArcSignedIn, true); - if (ShouldLaunchPlayStoreApp(profile_, oobe_or_assistant_wizard_start_)) { + if (ShouldLaunchPlayStoreApp( + profile_, + prefs->GetBoolean(prefs::kArcProvisioningInitiatedFromOobe))) { playstore_launcher_ = std::make_unique<ArcAppLauncher>( profile_, kPlayStoreAppId, GetLaunchIntent(kPlayStorePackage, kPlayStoreActivity, @@ -351,6 +356,8 @@ arc::UserInteractionType::NOT_USER_INITIATED); } + prefs->ClearPref(prefs::kArcProvisioningInitiatedFromOobe); + for (auto& observer : observer_list_) observer.OnArcInitialStart(); return; @@ -664,11 +671,22 @@ return false; } - oobe_or_assistant_wizard_start_ = - IsArcOobeOptInActive() || IsArcOptInWizardForAssistantActive(); - PrefService* const prefs = profile_->GetPrefs(); + // |prefs::kArcProvisioningInitiatedFromOobe| is used to remember + // |IsArcOobeOptInActive| or |IsArcOptInWizardForAssistantActive| state when + // ARC start request was made initially. |IsArcOobeOptInActive| or + // |IsArcOptInWizardForAssistantActive| will be changed by the time when + // decision to auto-launch the Play Store would be made. + // |IsArcOobeOptInActive| and |IsArcOptInWizardForAssistantActive| are not + // preserved on Chrome restart also and in last case + // |prefs::kArcProvisioningInitiatedFromOobe| is used to remember the state of + // the initial request. + // |prefs::kArcProvisioningInitiatedFromOobe| is reset when provisioning is + // done or ARC is opted out. + if (IsArcOobeOptInActive() || IsArcOptInWizardForAssistantActive()) + prefs->SetBoolean(prefs::kArcProvisioningInitiatedFromOobe, true); + // If it is marked that sign in has been successfully done or if Play Store is // not available, then directly start ARC with skipping Play Store ToS. // For Kiosk mode, skip ToS because it is very likely that near the device @@ -733,7 +751,6 @@ return; } - oobe_or_assistant_wizard_start_ = false; directly_started_ = false; enable_requested_ = false; scoped_opt_in_tracker_.reset(); @@ -845,6 +862,7 @@ terms_of_service_negotiator_.reset(); if (!accepted) { + VLOG(1) << "Terms of services declined"; // User does not accept the Terms of Service. Disable Google Play Store. MaybeUpdateOptInCancelUMA(support_host_.get()); SetArcPlayStoreEnabledForProfile(profile_, false); @@ -852,6 +870,7 @@ } // Terms were accepted. + VLOG(1) << "Terms of services accepted"; profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true); StartAndroidManagementCheck(); } @@ -993,9 +1012,9 @@ const chromeos::DemoSession* demo_session = chromeos::DemoSession::Get(); params.is_demo_session = demo_session && demo_session->started(); if (params.is_demo_session) { - DCHECK(demo_session->offline_resources_loaded()); - base::FilePath demo_session_apps_path; - params.demo_session_apps_path = demo_session->GetDemoAppsPath(); + DCHECK(demo_session->resources()->loaded()); + params.demo_session_apps_path = + demo_session->resources()->GetDemoAppsPath(); } params.supervision_transition = GetSupervisionTransition(profile_); @@ -1016,6 +1035,8 @@ profile_->GetPrefs()->SetBoolean(prefs::kArcPaiStarted, false); profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, false); profile_->GetPrefs()->SetBoolean(prefs::kArcFastAppReinstallStarted, false); + profile_->GetPrefs()->SetBoolean(prefs::kArcProvisioningInitiatedFromOobe, + false); } ShutdownSession();
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.h b/chrome/browser/chromeos/arc/arc_session_manager.h index e9a3d69e..5d89286 100644 --- a/chrome/browser/chromeos/arc/arc_session_manager.h +++ b/chrome/browser/chromeos/arc/arc_session_manager.h
@@ -365,13 +365,6 @@ std::unique_ptr<ArcAppLauncher> playstore_launcher_; bool reenable_arc_ = false; bool provisioning_reported_ = false; - // In case ARC is started from OOBE |oobe_start_|, set to true. This flag is - // used to remember |IsArcOobeOptInActive| or - // |IsArcOptInWizardForAssistantActive| state when ARC start request was made. - // |IsArcOobeOptInActive| or |IsArcOptInWizardForAssistantActive| will be - // changed by the time when |oobe_or_opa_start_| is checked to prevent the - // Play Store auto-launch. - bool oobe_or_assistant_wizard_start_ = false; bool directly_started_ = false; base::OneShotTimer arc_sign_in_timer_;
diff --git a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc index 41b8c95..15edbd5 100644 --- a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc +++ b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
@@ -492,6 +492,55 @@ EXPECT_TRUE(arc_session_manager()->IsPlaystoreLaunchRequestedForTesting()); } +// Verifies that Play Store shown is suppressed on restart when required. +TEST_F(ArcSessionManagerTest, PlayStoreSuppressed) { + // Set up the situation that terms were accepted in the previous session. + PrefService* const prefs = profile()->GetPrefs(); + prefs->SetBoolean(prefs::kArcTermsAccepted, true); + // Set the flag indicating that the provisioning was initiated from OOBE in + // the previous session. + prefs->SetBoolean(prefs::kArcProvisioningInitiatedFromOobe, true); + + arc_session_manager()->SetProfile(profile()); + arc_session_manager()->Initialize(); + arc_session_manager()->RequestEnable(); + arc_session_manager()->StartArcForTesting(); + + // Second start, no fetching code is expected. + EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); + EXPECT_FALSE(arc_session_manager()->IsPlaystoreLaunchRequestedForTesting()); + arc_session_manager()->OnProvisioningFinished(ProvisioningResult::SUCCESS); + // Completing the provisioning resets this flag. + EXPECT_FALSE(prefs->GetBoolean(prefs::kArcProvisioningInitiatedFromOobe)); + EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); + // |prefs::kArcProvisioningInitiatedFromOobe| flag prevents opening the + // Play Store. + EXPECT_FALSE(arc_session_manager()->IsPlaystoreLaunchRequestedForTesting()); + + // Correctly stop service. + arc_session_manager()->Shutdown(); +} + +TEST_F(ArcSessionManagerTest, InitiatedFromOobeIsResetOnOptOut) { + // Set up the situation that terms were accepted in the previous session. + PrefService* const prefs = profile()->GetPrefs(); + prefs->SetBoolean(prefs::kArcTermsAccepted, true); + // Set the flag indicating that the provisioning was initiated from OOBE in + // the previous session. + prefs->SetBoolean(prefs::kArcProvisioningInitiatedFromOobe, true); + + arc_session_manager()->SetProfile(profile()); + arc_session_manager()->Initialize(); + arc_session_manager()->RequestEnable(); + EXPECT_TRUE(prefs->GetBoolean(prefs::kArcProvisioningInitiatedFromOobe)); + // Disabling ARC resets suppress state + arc_session_manager()->RequestDisable(); + EXPECT_FALSE(prefs->GetBoolean(prefs::kArcProvisioningInitiatedFromOobe)); + + // Correctly stop service. + arc_session_manager()->Shutdown(); +} + TEST_F(ArcSessionManagerTest, Provisioning_Restart) { // Set up the situation that provisioning is successfully done in the // previous session.
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index aa195b8e..fe60578 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -78,6 +78,7 @@ #include "chrome/browser/chromeos/net/network_pref_state_observer.h" #include "chrome/browser/chromeos/net/network_throttling_observer.h" #include "chrome/browser/chromeos/net/wake_on_wifi_manager.h" +#include "chrome/browser/chromeos/network_change_manager_client.h" #include "chrome/browser/chromeos/note_taking_helper.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" @@ -136,8 +137,6 @@ #include "chromeos/login/login_state.h" #include "chromeos/login_event_recorder.h" #include "chromeos/network/network_cert_loader.h" -#include "chromeos/network/network_change_notifier_chromeos.h" -#include "chromeos/network/network_change_notifier_factory_chromeos.h" #include "chromeos/network/network_handler.h" #include "chromeos/network/portal_detector/network_portal_detector_stub.h" #include "chromeos/settings/install_attributes.h" @@ -157,6 +156,7 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/media_capture_devices.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/notification_service.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" @@ -168,6 +168,7 @@ #include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "media/audio/sounds/sounds_manager.h" #include "net/base/network_change_notifier.h" +#include "net/base/network_change_notifier_chromeos.h" #include "net/cert/nss_cert_database.h" #include "net/cert/nss_cert_database_chromeos.h" #include "printing/backend/print_backend.h" @@ -350,11 +351,6 @@ NetworkHandler::Initialize(); - // Initialize the network change notifier for Chrome OS. The network - // change notifier starts to monitor changes from the power manager and - // the network manager. - NetworkChangeNotifierFactoryChromeos::GetInstance()->Initialize(); - // Likewise, initialize the upgrade detector for Chrome OS. The upgrade // detector starts to monitor changes from the update engine. UpgradeDetectorChromeos::GetInstance()->Init(); @@ -573,11 +569,6 @@ // to session state change right after browser is started. g_browser_process->platform_part()->InitializeSessionManager(); - // Replace the default NetworkChangeNotifierFactory with ChromeOS specific - // implementation. This must be done before BrowserMainLoop calls - // net::NetworkChangeNotifier::Create() in MainMessageLoopStart(). - net::NetworkChangeNotifier::SetFactory( - new NetworkChangeNotifierFactoryChromeos()); ChromeBrowserMainPartsLinux::PreMainMessageLoopStart(); } @@ -600,6 +591,10 @@ // Threads are initialized between MainMessageLoopStart and MainMessageLoopRun. // about_flags settings are applied in ChromeBrowserMainParts::PreCreateThreads. void ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun() { + network_change_manager_client_.reset(new NetworkChangeManagerClient( + static_cast<net::NetworkChangeNotifierChromeos*>( + content::GetNetworkChangeNotifier()))); + // Set the crypto thread after the IO thread has been created/started. TPMTokenLoader::Get()->SetCryptoTaskRunner( base::CreateSingleThreadTaskRunnerWithTraits( @@ -1061,12 +1056,6 @@ if (UpgradeDetectorChromeos::GetInstance()) UpgradeDetectorChromeos::GetInstance()->Shutdown(); - // Shutdown the network change notifier for Chrome OS. The network - // change notifier stops monitoring changes from the power manager and - // the network manager. - if (NetworkChangeNotifierFactoryChromeos::GetInstance()) - NetworkChangeNotifierFactoryChromeos::GetInstance()->Shutdown(); - // Tell DeviceSettingsService to stop talking to session_manager. Do not // shutdown DeviceSettingsService yet, it might still be accessed by // BrowserPolicyConnector (owned by g_browser_process). @@ -1176,6 +1165,8 @@ // held by any task. crosvm_metrics_.reset(); + network_change_manager_client_.reset(); + // Destroy DBus services immediately after threads are stopped. dbus_services_.reset();
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h index 8af7124..680b0749 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -40,6 +40,7 @@ class EventRewriterDelegateImpl; class IdleActionWarningObserver; class LowDiskNotification; +class NetworkChangeManagerClient; class NetworkPrefStateObserver; class NetworkThrottlingObserver; class PowerMetricsReporter; @@ -102,6 +103,7 @@ std::unique_ptr<PowerMetricsReporter> power_metrics_reporter_; std::unique_ptr<WakeOnWifiManager> wake_on_wifi_manager_; std::unique_ptr<NetworkThrottlingObserver> network_throttling_observer_; + std::unique_ptr<NetworkChangeManagerClient> network_change_manager_client_; // Indicates whether the DBus has been initialized before. It is possible that // the DBus has been initialized in ChromeFeatureListCreator.
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc index 5277d11..e669df2 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
@@ -749,7 +749,12 @@ SET_STRING("SET_WALLPAPER_BUTTON_LABEL", IDS_FILE_BROWSER_SET_WALLPAPER_BUTTON_LABEL); SET_STRING("SHARE_ERROR", IDS_FILE_BROWSER_SHARE_ERROR); - + SET_STRING("SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE", + IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE); + SET_STRING("SHARE_ROOT_FOLDER_WITH_CROSTINI", + IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI); + SET_STRING("SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE", + IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE); SET_STRING("SIZE_BYTES", IDS_FILE_BROWSER_SIZE_BYTES); SET_STRING("SIZE_COLUMN_LABEL", IDS_FILE_BROWSER_SIZE_COLUMN_LABEL); SET_STRING("SIZE_GB", IDS_FILE_BROWSER_SIZE_GB);
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index c58ccac..e0306608 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -46,6 +46,11 @@ return *this; } + TestCase& EnableMyFilesVolume() { + enable_myfiles_volume.emplace(true); + return *this; + } + TestCase& DisableDriveFs() { enable_drivefs.emplace(false); return *this; @@ -83,6 +88,9 @@ if (test.enable_drivefs.value_or(false)) name.append("_DriveFs"); + if (test.enable_myfiles_volume.value_or(false)) + name.append("_MyFilesVolume"); + return name; } @@ -91,6 +99,7 @@ bool trusted_events = false; bool tablet_mode = false; base::Optional<bool> enable_drivefs; + base::Optional<bool> enable_myfiles_volume; bool with_browser = false; bool needs_zip = false; bool offline = false; @@ -153,6 +162,11 @@ bool GetTabletMode() const override { return GetParam().tablet_mode; } + bool GetEnableMyFilesVolume() const override { + return GetParam().enable_myfiles_volume.value_or( + FileManagerBrowserTestBase::GetEnableMyFilesVolume()); + } + bool GetEnableDriveFs() const override { return GetParam().enable_drivefs.value_or( FileManagerBrowserTestBase::GetEnableDriveFs()); @@ -687,12 +701,13 @@ WRAPPED_INSTANTIATE_TEST_CASE_P( MyFiles, /* my_files.js */ FilesAppBrowserTest, - ::testing::Values(TestCase("showMyFiles"), - TestCase("hideSearchButton"), - TestCase("myFilesDisplaysAndOpensEntries"), - TestCase("directoryTreeRefresh"), - TestCase("myFilesFolderRename"), - TestCase("myFilesUpdatesChildren"))); + ::testing::Values( + TestCase("showMyFiles"), + TestCase("hideSearchButton"), + TestCase("myFilesDisplaysAndOpensEntries"), + TestCase("directoryTreeRefresh"), + TestCase("myFilesFolderRename"), + TestCase("myFilesUpdatesChildren").EnableMyFilesVolume())); WRAPPED_INSTANTIATE_TEST_CASE_P( InstallLinuxPackageDialog, /* install_linux_package_dialog.js */
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc index 6bff963..db8075a 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -514,10 +514,12 @@ // Adds this local volume. Returns true on success. virtual bool Mount(Profile* profile) = 0; - void CreateEntry(const AddEntriesMessage::TestEntryInfo& entry) { - const base::FilePath target_path = - root_path().AppendASCII(entry.target_path); + virtual void CreateEntry(const AddEntriesMessage::TestEntryInfo& entry) { + CreateEntryImpl(entry, root_path().AppendASCII(entry.target_path)); + } + void CreateEntryImpl(const AddEntriesMessage::TestEntryInfo& entry, + const base::FilePath& target_path) { entries_.insert(std::make_pair(target_path, entry)); switch (entry.type) { case AddEntriesMessage::FILE: { @@ -540,16 +542,18 @@ NOTREACHED() << "Can't create a computer in a local volume: " << target_path.value(); break; + default: + NOTREACHED() << "Unsupported entry type for: " << target_path.value(); } - ASSERT_TRUE(UpdateModifiedTime(entry)); + ASSERT_TRUE(UpdateModifiedTime(entry, target_path)); } private: // Updates the ModifiedTime of the entry, and its parent directories if // needed. Returns true on success. - bool UpdateModifiedTime(const AddEntriesMessage::TestEntryInfo& entry) { - const base::FilePath path = root_path().AppendASCII(entry.target_path); + bool UpdateModifiedTime(const AddEntriesMessage::TestEntryInfo& entry, + const base::FilePath& path) { if (!base::TouchFile(path, entry.last_modified_time, entry.last_modified_time)) { return false; @@ -561,7 +565,7 @@ const auto& it = entries_.find(path.DirName()); if (it == entries_.end()) return false; - return UpdateModifiedTime(it->second); + return UpdateModifiedTime(it->second, path.DirName()); } return true; @@ -578,13 +582,42 @@ DownloadsTestVolume() : LocalTestVolume("Downloads") {} ~DownloadsTestVolume() override = default; + void EnsureDownloadsFolderExists() { + if (!base::FeatureList::IsEnabled(chromeos::features::kMyFilesVolume)) + return; + + // When MyFiles is the volume create the Downloads folder under it. + auto downloads_folder = root_path().Append("Downloads"); + if (!base::PathExists(downloads_folder)) { + CreateEntryImpl(AddEntriesMessage::TestEntryInfo( + AddEntriesMessage::DIRECTORY, "", "Downloads"), + downloads_folder); + } + } + // Forces the content to be created inside MyFiles/Downloads when MyFiles is + // the Volume, so tests are compatible with volume being MyFiles or Downloads. + // TODO(lucmult): Remove this special case once MyFiles volume has been + // rolled out. + base::FilePath base_path() const { + if (base::FeatureList::IsEnabled(chromeos::features::kMyFilesVolume)) + return root_path().Append("Downloads"); + + return root_path(); + } + bool Mount(Profile* profile) override { if (!CreateRootDirectory(profile)) return false; + EnsureDownloadsFolderExists(); auto* volume = VolumeManager::Get(profile); return volume->RegisterDownloadsDirectoryForTesting(root_path()); } + void CreateEntry(const AddEntriesMessage::TestEntryInfo& entry) override { + base::FilePath target_path = base_path().Append(entry.target_path); + CreateEntryImpl(entry, target_path); + } + void Unmount(Profile* profile) { auto* volume = VolumeManager::Get(profile); volume->RemoveDownloadsDirectoryForTesting(); @@ -1151,6 +1184,10 @@ } else { disabled_features.emplace_back(chromeos::features::kDriveFs); } + + if (IsMyFilesVolume()) + enabled_features.emplace_back(chromeos::features::kMyFilesVolume); + feature_list_.InitWithFeatures(enabled_features, disabled_features); extensions::ExtensionApiTest::SetUpCommandLine(command_line); @@ -1241,6 +1278,10 @@ return false; } +bool FileManagerBrowserTestBase::GetEnableMyFilesVolume() const { + return false; +} + bool FileManagerBrowserTestBase::GetEnableDriveFs() const { return true; }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h index b39ddc0..c337598 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h
@@ -49,6 +49,7 @@ // Optional overrides for each File Manager test extension type. virtual bool GetTabletMode() const; virtual bool GetEnableDriveFs() const; + virtual bool GetEnableMyFilesVolume() const; virtual bool GetRequiresStartupBrowser() const; virtual bool GetNeedsZipSupport() const; virtual bool GetIsOffline() const; @@ -71,6 +72,9 @@ // Returns true if the test requires DriveFS. bool IsDriveFsTest() const { return GetEnableDriveFs(); } + // Returns true if the test MyFilesVolume feature is enabled. + bool IsMyFilesVolume() const { return GetEnableMyFilesVolume(); } + // Returns true if the test requires zip/unzip support. bool IsZipTest() const { return GetNeedsZipSupport(); }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc index 62b78e84..1a83e247 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc
@@ -215,5 +215,5 @@ } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, Crostini) { - RunGeneratedTest("/foreground/js/crostini_unittest.html"); + RunGeneratedTest("/background/js/crostini_unittest.html"); }
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.cc b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.cc index c9ef1e5a..0758dc35 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.cc
@@ -17,6 +17,7 @@ #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/extensions/external_cache_impl.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_resources.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/extensions/external_provider_impl.h" @@ -126,10 +127,10 @@ void DemoExtensionsExternalLoader::StartLoadingFromOfflineDemoResources() { DemoSession* demo_session = DemoSession::Get(); - DCHECK(demo_session->offline_resources_loaded()); + DCHECK(demo_session->resources()->loaded()); base::FilePath demo_extension_list = - demo_session->GetExternalExtensionsPrefsPath(); + demo_session->resources()->GetExternalExtensionsPrefsPath(); if (demo_extension_list.empty()) { LoadFinished(std::make_unique<base::DictionaryValue>()); return; @@ -180,8 +181,8 @@ dict_item.second.SetKey( extensions::ExternalProviderImpl::kExternalCrx, - base::Value(demo_session->GetOfflineResourceAbsolutePath(relative_path) - .value())); + base::Value( + demo_session->resources()->GetAbsolutePath(relative_path).value())); } LoadFinished(base::DictionaryValue::From(
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_mode_resources_remover.cc b/chrome/browser/chromeos/login/demo_mode/demo_mode_resources_remover.cc index 3b43966..27a3a02 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_mode_resources_remover.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_mode_resources_remover.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chromeos/idle_detector.h" #include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_resources.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" @@ -234,8 +235,7 @@ base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, - base::BindOnce(&RemoveDirectory, - DemoSession::GetPreInstalledDemoResourcesPath()), + base::BindOnce(&RemoveDirectory, DemoResources::GetPreInstalledPath()), base::BindOnce(&DemoModeResourcesRemover::OnRemovalDone, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_mode_test_helper.cc b/chrome/browser/chromeos/login/demo_mode/demo_mode_test_helper.cc index 1ab036d..cba1ad78 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_mode_test_helper.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_mode_test_helper.cc
@@ -12,6 +12,7 @@ #include "base/logging.h" #include "base/test/scoped_path_override.h" #include "chrome/browser/browser_process_platform_part.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_resources.h" #include "chrome/browser/component_updater/fake_cros_component_manager.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/chromeos_paths.h" @@ -70,7 +71,7 @@ base::FilePath DemoModeTestHelper::GetDemoResourcesPath() { return components_temp_dir_.GetPath() .AppendASCII("cros-components") - .AppendASCII(DemoSession::kDemoModeResourcesComponentName); + .AppendASCII(DemoResources::kDemoModeResourcesComponentName); } void DemoModeTestHelper::InitializeCrosComponentManager() { @@ -82,7 +83,7 @@ // so components don't load instantly. cros_component_manager->set_queue_load_requests(true); cros_component_manager->set_supported_components( - {DemoSession::kDemoModeResourcesComponentName}); + {DemoResources::kDemoModeResourcesComponentName}); browser_process_platform_part_test_api_.InitializeCrosComponentManager( std::move(cros_component_manager)); @@ -95,13 +96,13 @@ // TODO(michaelpg): Update once offline Demo Mode also uses a CrOS component. if (DemoSession::GetDemoConfig() == DemoSession::DemoModeConfig::kOnline) { CHECK(fake_cros_component_manager_->FinishLoadRequest( - DemoSession::kDemoModeResourcesComponentName, + DemoResources::kDemoModeResourcesComponentName, component_updater::FakeCrOSComponentManager::ComponentInfo( component_updater::CrOSComponentManager::Error::NONE, base::FilePath("/dev/null"), GetDemoResourcesPath()))); } else { CHECK(!fake_cros_component_manager_->HasPendingInstall( - DemoSession::kDemoModeResourcesComponentName)); + DemoResources::kDemoModeResourcesComponentName)); } run_loop.Run(); @@ -114,7 +115,7 @@ // TODO(michaelpg): Update once offline Demo Mode also uses a CrOS component. if (DemoSession::GetDemoConfig() == DemoSession::DemoModeConfig::kOnline) { CHECK(fake_cros_component_manager_->FinishLoadRequest( - DemoSession::kDemoModeResourcesComponentName, + DemoResources::kDemoModeResourcesComponentName, component_updater::FakeCrOSComponentManager::ComponentInfo( component_updater::CrOSComponentManager::Error::INSTALL_FAILURE, base::FilePath(), base::FilePath())));
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_resources.cc b/chrome/browser/chromeos/login/demo_mode/demo_resources.cc new file mode 100644 index 0000000..dbd5b20 --- /dev/null +++ b/chrome/browser/chromeos/login/demo_mode/demo_resources.cc
@@ -0,0 +1,139 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/login/demo_mode/demo_resources.h" + +#include "base/logging.h" +#include "base/path_service.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_process_platform_part.h" +#include "chromeos/chromeos_paths.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/image_loader_client.h" + +namespace chromeos { +namespace { + +// Path relative to the path at which demo resources are loaded that +// contains image with demo Android apps. +constexpr base::FilePath::CharType kDemoAppsPath[] = + FILE_PATH_LITERAL("android_demo_apps.squash"); + +constexpr base::FilePath::CharType kExternalExtensionsPrefsPath[] = + FILE_PATH_LITERAL("demo_extensions.json"); + +} // namespace + +// static +const char DemoResources::kDemoModeResourcesComponentName[] = + "demo-mode-resources"; + +// static +base::FilePath DemoResources::GetPreInstalledPath() { + base::FilePath preinstalled_components_root; + base::PathService::Get(DIR_PREINSTALLED_COMPONENTS, + &preinstalled_components_root); + return preinstalled_components_root.AppendASCII("cros-components") + .AppendASCII(kDemoModeResourcesComponentName); +} + +DemoResources::DemoResources(DemoSession::DemoModeConfig config) + : config_(config), weak_ptr_factory_(this) { + DCHECK_NE(config_, DemoSession::DemoModeConfig::kNone); +} + +DemoResources::~DemoResources() = default; + +base::FilePath DemoResources::GetAbsolutePath( + const base::FilePath& relative_path) const { + if (path_.empty()) + return base::FilePath(); + if (relative_path.ReferencesParent()) + return base::FilePath(); + return path_.Append(relative_path); +} + +base::FilePath DemoResources::GetDemoAppsPath() const { + if (path_.empty()) + return base::FilePath(); + return path_.Append(kDemoAppsPath); +} + +base::FilePath DemoResources::GetExternalExtensionsPrefsPath() const { + if (path_.empty()) + return base::FilePath(); + return path_.Append(kExternalExtensionsPrefsPath); +} + +void DemoResources::EnsureLoaded(base::OnceClosure load_callback) { + if (loaded_) { + if (load_callback) + std::move(load_callback).Run(); + return; + } + + if (load_callback) + load_callbacks_.emplace_back(std::move(load_callback)); + + if (load_requested_) + return; + load_requested_ = true; + + if (config_ == DemoSession::DemoModeConfig::kOffline) { + LoadPreinstalledOfflineResources(); + return; + } + + component_updater::CrOSComponentManager* cros_component_manager = + g_browser_process->platform_part()->cros_component_manager(); + // In unit tests, DemoModeTestHelper should set up a fake + // CrOSComponentManager. + DCHECK(cros_component_manager); + + g_browser_process->platform_part()->cros_component_manager()->Load( + kDemoModeResourcesComponentName, + component_updater::CrOSComponentManager::MountPolicy::kMount, + component_updater::CrOSComponentManager::UpdatePolicy::kSkip, + base::BindOnce(&DemoResources::InstalledComponentLoaded, + weak_ptr_factory_.GetWeakPtr())); +} + +void DemoResources::SetLoadedForTesting(const base::FilePath& path) { + OnDemoResourcesLoaded(path); +} + +void DemoResources::InstalledComponentLoaded( + component_updater::CrOSComponentManager::Error error, + const base::FilePath& path) { + if (error == component_updater::CrOSComponentManager::Error::NONE) { + OnDemoResourcesLoaded(base::make_optional(path)); + return; + } + + LoadPreinstalledOfflineResources(); +} + +void DemoResources::LoadPreinstalledOfflineResources() { + chromeos::DBusThreadManager::Get() + ->GetImageLoaderClient() + ->LoadComponentAtPath( + kDemoModeResourcesComponentName, GetPreInstalledPath(), + base::BindOnce(&DemoResources::OnDemoResourcesLoaded, + weak_ptr_factory_.GetWeakPtr())); +} + +void DemoResources::OnDemoResourcesLoaded( + base::Optional<base::FilePath> mounted_path) { + loaded_ = true; + + if (mounted_path.has_value()) + path_ = mounted_path.value(); + + std::list<base::OnceClosure> load_callbacks; + load_callbacks.swap(load_callbacks_); + for (auto& callback : load_callbacks) + std::move(callback).Run(); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_resources.h b/chrome/browser/chromeos/login/demo_mode/demo_resources.h new file mode 100644 index 0000000..85858fb --- /dev/null +++ b/chrome/browser/chromeos/login/demo_mode/demo_resources.h
@@ -0,0 +1,95 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_RESOURCES_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_RESOURCES_H_ + +#include <list> + +#include "base/callback_forward.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_session.h" +#include "chrome/browser/component_updater/cros_component_installer_chromeos.h" + +namespace chromeos { + +class DemoResources { + public: + // The name of the demo mode resources CrOS component or preinstalled + // imageloader image. + static const char kDemoModeResourcesComponentName[]; + + // Location on disk where pre-installed demo mode resources are expected to be + // found. + static base::FilePath GetPreInstalledPath(); + + explicit DemoResources(DemoSession::DemoModeConfig config); + ~DemoResources(); + + // Converts a relative path to an absolute path under the demo + // resources mount. Returns an empty string if the demo resources are + // not loaded. + base::FilePath GetAbsolutePath(const base::FilePath& relative_path) const; + + // Gets the path of the image containing demo session Android apps. The path + // will be set when the demo resources get loaded. + base::FilePath GetDemoAppsPath() const; + + // Gets the path under demo resources mount point that contains + // external extensions prefs (JSON containing set of extensions to be loaded + // as external extensions into demo sessions - expected to map extension IDs + // to the associated CRX path and version). + base::FilePath GetExternalExtensionsPrefsPath() const; + + // Ensures that the load of demo session resources is requested. + // |load_callback| will be run once the resources finish loading. + void EnsureLoaded(base::OnceClosure load_callback); + + // Fakes demo session resources having been requested and mounted at + // the given path (or not mounted if |path| is empty). + void SetLoadedForTesting(const base::FilePath& path); + + bool loaded() const { return loaded_; } + const base::FilePath& path() const { return path_; } + + private: + // Called after load of a currently installed (if any) demo mode resources + // component has finished. + // On success, |path| is expected to contain the path as which the component + // is loaded. + void InstalledComponentLoaded( + component_updater::CrOSComponentManager::Error error, + const base::FilePath& path); + + // Loads the preinstalled offline resources image. + void LoadPreinstalledOfflineResources(); + + // Callback for the component or image loader request to load demo resources. + // |mount_path| is the path at which the resources were loaded. + void OnDemoResourcesLoaded(base::Optional<base::FilePath> mounted_path); + + // Which config the device is configured for. Determines which resources will + // be loaded. + DemoSession::DemoModeConfig config_; + + bool load_requested_ = false; + bool loaded_ = false; + + // Path at which demo mode resources were loaded. + base::FilePath path_; + + // List of pending callbacks passed to EnsureLoaded(). + std::list<base::OnceClosure> load_callbacks_; + + base::WeakPtrFactory<DemoResources> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(DemoResources); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_RESOURCES_H_
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_resources_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_resources_unittest.cc new file mode 100644 index 0000000..36225c7 --- /dev/null +++ b/chrome/browser/chromeos/login/demo_mode/demo_resources_unittest.cc
@@ -0,0 +1,236 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/login/demo_mode/demo_session.h" + +#include <memory> +#include <utility> + +#include "base/bind.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_process_platform_part.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_resources.h" +#include "chrome/browser/component_updater/fake_cros_component_manager.h" +#include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" + +using component_updater::FakeCrOSComponentManager; + +namespace chromeos { + +namespace { + +constexpr char kOfflineResourcesComponent[] = "demo-mode-resources"; +constexpr char kTestDemoModeResourcesMountPoint[] = + "/run/imageloader/demo_mode_resources"; +constexpr char kDemoAppsImageFile[] = "android_demo_apps.squash"; +constexpr char kExternalExtensionsPrefsFile[] = "demo_extensions.json"; + +void SetBoolean(bool* value) { + *value = true; +} + +} // namespace + +class DemoResourcesTest : public testing::Test { + public: + DemoResourcesTest() + : browser_process_platform_part_test_api_( + g_browser_process->platform_part()) {} + ~DemoResourcesTest() override = default; + + void SetUp() override { + chromeos::DBusThreadManager::Initialize(); + InitializeCrosComponentManager(); + } + + void TearDown() override { + chromeos::DBusThreadManager::Shutdown(); + + cros_component_manager_ = nullptr; + browser_process_platform_part_test_api_.ShutdownCrosComponentManager(); + } + + protected: + bool FinishResourcesComponentLoad(const base::FilePath& mount_path) { + EXPECT_TRUE( + cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); + EXPECT_FALSE( + cros_component_manager_->UpdateRequested(kOfflineResourcesComponent)); + + return cros_component_manager_->FinishLoadRequest( + kOfflineResourcesComponent, + FakeCrOSComponentManager::ComponentInfo( + component_updater::CrOSComponentManager::Error::NONE, + base::FilePath("/dev/null"), mount_path)); + } + + void InitializeCrosComponentManager() { + auto fake_cros_component_manager = + std::make_unique<FakeCrOSComponentManager>(); + fake_cros_component_manager->set_queue_load_requests(true); + fake_cros_component_manager->set_supported_components( + {kOfflineResourcesComponent}); + cros_component_manager_ = fake_cros_component_manager.get(); + + browser_process_platform_part_test_api_.InitializeCrosComponentManager( + std::move(fake_cros_component_manager)); + } + + FakeCrOSComponentManager* cros_component_manager_ = nullptr; + content::TestBrowserThreadBundle thread_bundle_; + + private: + BrowserProcessPlatformPartTestApi browser_process_platform_part_test_api_; + + DISALLOW_COPY_AND_ASSIGN(DemoResourcesTest); +}; + +TEST_F(DemoResourcesTest, GetPaths) { + DemoResources demo_resources(DemoSession::DemoModeConfig::kOnline); + demo_resources.EnsureLoaded(base::DoNothing()); + EXPECT_FALSE(demo_resources.loaded()); + + const base::FilePath component_mount_point = + base::FilePath(kTestDemoModeResourcesMountPoint); + ASSERT_TRUE(FinishResourcesComponentLoad(component_mount_point)); + + EXPECT_TRUE(demo_resources.loaded()); + EXPECT_EQ(component_mount_point.AppendASCII(kDemoAppsImageFile), + demo_resources.GetDemoAppsPath()); + EXPECT_EQ(component_mount_point.AppendASCII(kExternalExtensionsPrefsFile), + demo_resources.GetExternalExtensionsPrefsPath()); + EXPECT_EQ(component_mount_point.AppendASCII("foo.txt"), + demo_resources.GetAbsolutePath(base::FilePath("foo.txt"))); + EXPECT_EQ(component_mount_point.AppendASCII("foo/bar.txt"), + demo_resources.GetAbsolutePath(base::FilePath("foo/bar.txt"))); + EXPECT_EQ(component_mount_point.AppendASCII("foo/"), + demo_resources.GetAbsolutePath(base::FilePath("foo/"))); + EXPECT_TRUE( + demo_resources.GetAbsolutePath(base::FilePath("../foo/")).empty()); + EXPECT_TRUE( + demo_resources.GetAbsolutePath(base::FilePath("foo/../bar")).empty()); +} + +TEST_F(DemoResourcesTest, LoadResourcesOnline) { + DemoResources demo_resources(DemoSession::DemoModeConfig::kOnline); + demo_resources.EnsureLoaded(base::DoNothing()); + + EXPECT_FALSE(demo_resources.loaded()); + + ASSERT_TRUE(FinishResourcesComponentLoad( + base::FilePath(kTestDemoModeResourcesMountPoint))); + EXPECT_FALSE( + cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); + EXPECT_TRUE(demo_resources.loaded()); +} + +TEST_F(DemoResourcesTest, LoadResourcesOffline) { + DemoResources demo_resources(DemoSession::DemoModeConfig::kOffline); + demo_resources.EnsureLoaded(base::DoNothing()); + + EXPECT_FALSE(demo_resources.loaded()); + EXPECT_FALSE( + cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); + + demo_resources.SetLoadedForTesting( + base::FilePath(kTestDemoModeResourcesMountPoint)); + EXPECT_TRUE(demo_resources.loaded()); +} + +TEST_F(DemoResourcesTest, EnsureLoadedRepeatedlyOnline) { + DemoResources demo_resources(DemoSession::DemoModeConfig::kOnline); + + bool first_callback_called = false; + demo_resources.EnsureLoaded( + base::BindOnce(&SetBoolean, &first_callback_called)); + + bool second_callback_called = false; + demo_resources.EnsureLoaded( + base::BindOnce(&SetBoolean, &second_callback_called)); + + bool third_callback_called = false; + demo_resources.EnsureLoaded( + base::BindOnce(&SetBoolean, &third_callback_called)); + + EXPECT_FALSE(demo_resources.loaded()); + EXPECT_FALSE(first_callback_called); + EXPECT_FALSE(second_callback_called); + EXPECT_FALSE(third_callback_called); + + ASSERT_TRUE(FinishResourcesComponentLoad( + base::FilePath(kTestDemoModeResourcesMountPoint))); + EXPECT_FALSE( + cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); + + EXPECT_TRUE(demo_resources.loaded()); + EXPECT_TRUE(first_callback_called); + EXPECT_TRUE(second_callback_called); + EXPECT_TRUE(third_callback_called); + + bool fourth_callback_called = false; + demo_resources.EnsureLoaded( + base::BindOnce(&SetBoolean, &fourth_callback_called)); + EXPECT_TRUE(fourth_callback_called); + + bool fifth_callback_called = false; + demo_resources.EnsureLoaded( + base::BindOnce(&SetBoolean, &fifth_callback_called)); + EXPECT_TRUE(fifth_callback_called); + + EXPECT_TRUE(demo_resources.loaded()); +} + +TEST_F(DemoResourcesTest, EnsureLoadedRepeatedlyOffline) { + DemoResources demo_resources(DemoSession::DemoModeConfig::kOffline); + + bool first_callback_called = false; + demo_resources.EnsureLoaded( + base::BindOnce(&SetBoolean, &first_callback_called)); + + bool second_callback_called = false; + demo_resources.EnsureLoaded( + base::BindOnce(&SetBoolean, &second_callback_called)); + + bool third_callback_called = false; + demo_resources.EnsureLoaded( + base::BindOnce(&SetBoolean, &third_callback_called)); + + EXPECT_FALSE(demo_resources.loaded()); + EXPECT_FALSE(first_callback_called); + EXPECT_FALSE(second_callback_called); + EXPECT_FALSE(third_callback_called); + + const base::FilePath component_mount_point = + base::FilePath(kTestDemoModeResourcesMountPoint); + demo_resources.SetLoadedForTesting(component_mount_point); + + EXPECT_TRUE(demo_resources.loaded()); + EXPECT_TRUE(first_callback_called); + EXPECT_TRUE(second_callback_called); + EXPECT_TRUE(third_callback_called); + + EXPECT_EQ(component_mount_point.AppendASCII(kDemoAppsImageFile), + demo_resources.GetDemoAppsPath()); + EXPECT_EQ(component_mount_point.AppendASCII(kExternalExtensionsPrefsFile), + demo_resources.GetExternalExtensionsPrefsPath()); + + bool fourth_callback_called = false; + demo_resources.EnsureLoaded( + base::BindOnce(&SetBoolean, &fourth_callback_called)); + EXPECT_TRUE(fourth_callback_called); + + bool fifth_callback_called = false; + demo_resources.EnsureLoaded( + base::BindOnce(&SetBoolean, &fifth_callback_called)); + EXPECT_TRUE(fifth_callback_called); + + EXPECT_TRUE(demo_resources.loaded()); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session.cc b/chrome/browser/chromeos/login/demo_mode/demo_session.cc index 18c8960..43f3652 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_session.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_session.cc
@@ -10,9 +10,10 @@ #include "base/bind.h" #include "base/callback.h" #include "base/command_line.h" +#include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/logging.h" #include "base/optional.h" -#include "base/path_service.h" #include "base/stl_util.h" #include "base/system/sys_info.h" #include "base/task/post_task.h" @@ -20,17 +21,14 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chromeos/file_manager/path_util.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_resources.h" #include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/extensions/app_launch_params.h" #include "chrome/browser/ui/extensions/application_launch.h" -#include "chrome/common/chrome_paths.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/pref_names.h" -#include "chromeos/chromeos_paths.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/image_loader_client.h" #include "chromeos/settings/install_attributes.h" #include "components/language/core/browser/pref_names.h" #include "components/prefs/pref_registry_simple.h" @@ -54,14 +52,6 @@ base::Optional<DemoSession::DemoModeConfig> g_force_demo_config; // Path relative to the path at which offline demo resources are loaded that -// contains image with demo Android apps. -constexpr base::FilePath::CharType kDemoAppsPath[] = - FILE_PATH_LITERAL("android_demo_apps.squash"); - -constexpr base::FilePath::CharType kExternalExtensionsPrefsPath[] = - FILE_PATH_LITERAL("demo_extensions.json"); - -// Path relative to the path at which offline demo resources are loaded that // contains the highlights app. constexpr char kHighlightsAppPath[] = "chrome_apps/highlights"; @@ -161,19 +151,6 @@ } // namespace // static -const char DemoSession::kDemoModeResourcesComponentName[] = - "demo-mode-resources"; - -// static -base::FilePath DemoSession::GetPreInstalledDemoResourcesPath() { - base::FilePath preinstalled_components_root; - base::PathService::Get(DIR_PREINSTALLED_COMPONENTS, - &preinstalled_components_root); - return preinstalled_components_root.AppendASCII("cros-components") - .AppendASCII(kDemoModeResourcesComponentName); -} - -// static std::string DemoSession::DemoConfigToString( DemoSession::DemoModeConfig config) { switch (config) { @@ -316,62 +293,9 @@ void DemoSession::EnsureOfflineResourcesLoaded( base::OnceClosure load_callback) { - if (offline_resources_loaded_) { - if (load_callback) - std::move(load_callback).Run(); - return; - } - - if (load_callback) - offline_resources_load_callbacks_.emplace_back(std::move(load_callback)); - - if (offline_resources_load_requested_) - return; - offline_resources_load_requested_ = true; - - if (offline_enrolled_) { - LoadPreinstalledOfflineResources(); - return; - } - - component_updater::CrOSComponentManager* cros_component_manager = - g_browser_process->platform_part()->cros_component_manager(); - // In unit tests, DemoModeTestHelper should set up a fake - // CrOSComponentManager. - DCHECK(cros_component_manager); - - g_browser_process->platform_part()->cros_component_manager()->Load( - kDemoModeResourcesComponentName, - component_updater::CrOSComponentManager::MountPolicy::kMount, - component_updater::CrOSComponentManager::UpdatePolicy::kSkip, - base::BindOnce(&DemoSession::InstalledComponentLoaded, - weak_ptr_factory_.GetWeakPtr())); -} - -void DemoSession::SetOfflineResourcesLoadedForTesting( - const base::FilePath& path) { - OnOfflineResourcesLoaded(path); -} - -base::FilePath DemoSession::GetDemoAppsPath() const { - if (offline_resources_path_.empty()) - return base::FilePath(); - return offline_resources_path_.Append(kDemoAppsPath); -} - -base::FilePath DemoSession::GetExternalExtensionsPrefsPath() const { - if (offline_resources_path_.empty()) - return base::FilePath(); - return offline_resources_path_.Append(kExternalExtensionsPrefsPath); -} - -base::FilePath DemoSession::GetOfflineResourceAbsolutePath( - const base::FilePath& relative_path) const { - if (offline_resources_path_.empty()) - return base::FilePath(); - if (relative_path.ReferencesParent()) - return base::FilePath(); - return offline_resources_path_.Append(relative_path); + if (!demo_resources_) + demo_resources_ = std::make_unique<DemoResources>(GetDemoConfig()); + demo_resources_->EnsureLoaded(std::move(load_callback)); } bool DemoSession::ShouldIgnorePinPolicy(const std::string& app_id_or_package) { @@ -413,51 +337,18 @@ DemoSession::~DemoSession() = default; -void DemoSession::InstalledComponentLoaded( - component_updater::CrOSComponentManager::Error error, - const base::FilePath& path) { - if (error == component_updater::CrOSComponentManager::Error::NONE) { - OnOfflineResourcesLoaded(base::make_optional(path)); - return; - } - - LoadPreinstalledOfflineResources(); -} - -void DemoSession::LoadPreinstalledOfflineResources() { - chromeos::DBusThreadManager::Get() - ->GetImageLoaderClient() - ->LoadComponentAtPath( - kDemoModeResourcesComponentName, GetPreInstalledDemoResourcesPath(), - base::BindOnce(&DemoSession::OnOfflineResourcesLoaded, - weak_ptr_factory_.GetWeakPtr())); -} - -void DemoSession::OnOfflineResourcesLoaded( - base::Optional<base::FilePath> mounted_path) { - offline_resources_loaded_ = true; - - if (mounted_path.has_value()) - offline_resources_path_ = mounted_path.value(); - - std::list<base::OnceClosure> load_callbacks; - load_callbacks.swap(offline_resources_load_callbacks_); - for (auto& callback : load_callbacks) - std::move(callback).Run(); -} - void DemoSession::InstallDemoResources() { - DCHECK(offline_resources_loaded_); + DCHECK(demo_resources_->loaded()); if (offline_enrolled_) LoadAndLaunchHighlightsApp(); base::PostTaskWithTraits( FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()}, - base::BindOnce(&InstallDemoMedia, offline_resources_path_)); + base::BindOnce(&InstallDemoMedia, demo_resources_->path())); } void DemoSession::LoadAndLaunchHighlightsApp() { - DCHECK(offline_resources_loaded_); - if (offline_resources_path_.empty()) { + DCHECK(demo_resources_->loaded()); + if (demo_resources_->path().empty()) { LOG(ERROR) << "Offline resources not loaded - no highlights app available."; InstallAppFromUpdateUrl(GetHighlightsAppId()); return; @@ -465,7 +356,7 @@ Profile* profile = ProfileManager::GetActiveUserProfile(); DCHECK(profile); const base::FilePath resources_path = - offline_resources_path_.Append(kHighlightsAppPath); + demo_resources_->path().Append(kHighlightsAppPath); if (!apps::AppLoadService::Get(profile)->LoadAndLaunch( resources_path, base::CommandLine(base::CommandLine::NO_PROGRAM), base::FilePath() /* cur_dir */)) {
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session.h b/chrome/browser/chromeos/login/demo_mode/demo_session.h index 6edfffff..c08be2903 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_session.h +++ b/chrome/browser/chromeos/login/demo_mode/demo_session.h
@@ -5,31 +5,30 @@ #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_SESSION_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_SESSION_H_ -#include <list> #include <string> #include <vector> #include "base/callback_forward.h" -#include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" -#include "base/optional.h" #include "base/scoped_observer.h" #include "chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h" -#include "chrome/browser/component_updater/cros_component_installer_chromeos.h" #include "components/session_manager/core/session_manager_observer.h" #include "extensions/browser/extension_registry_observer.h" +class PrefRegistrySimple; + namespace session_manager { class SessionManager; } namespace chromeos { -// Tracks global demo session state. For example, whether the demo session has -// started, and whether the demo session offline resources have been loaded. -// TODO(michaelpg): Componentize the logic for providing offline resources. +class DemoResources; + +// Tracks global demo session state, such as whether the demo session has +// started and the state of demo mode resources. class DemoSession : public session_manager::SessionManagerObserver, extensions::ExtensionRegistryObserver { public: @@ -49,14 +48,6 @@ kLast = kOffline, }; - // The name of the demo mode resources CrOS component or preinstalled - // imageloader image. - static const char kDemoModeResourcesComponentName[]; - - // Location on disk where pre-installed demo mode resources are expected to be - // found. - static base::FilePath GetPreInstalledDemoResourcesPath(); - static std::string DemoConfigToString(DemoModeConfig config); // Whether the device is set up to run demo sessions. @@ -102,26 +93,6 @@ // |load_callback| will be run once the offline resource load finishes. void EnsureOfflineResourcesLoaded(base::OnceClosure load_callback); - // Fakes offline demo session resources having been requested and mounted at - // the given path (or not mounted if |path| is empty). - void SetOfflineResourcesLoadedForTesting(const base::FilePath& path); - - // Gets the path of the image containing demo session Android apps. The path - // will be set when the offline resources get loaded. - base::FilePath GetDemoAppsPath() const; - - // Gets the path under offline demo resources mount point that contains - // external extensions prefs (JSON containing set of extensions to be loaded - // as external extensions into demo sessions - expected to map extension IDs - // to the associated CRX path and version). - base::FilePath GetExternalExtensionsPrefsPath() const; - - // Converts a relative path to an absolute path under the offline demo - // resources mount. Returns an empty string if the offline demo resources are - // not loaded. - base::FilePath GetOfflineResourceAbsolutePath( - const base::FilePath& relative_path) const; - // Returns true if the Chrome app or ARC++ package, which is normally pinned // by policy, should actually not be force-pinned because the device is // in Demo Mode and offline. @@ -139,27 +110,12 @@ bool started() const { return started_; } - bool offline_resources_loaded() const { return offline_resources_loaded_; } + const DemoResources* resources() const { return demo_resources_.get(); } private: DemoSession(); ~DemoSession() override; - // Called after load of a currently installed (if any) demo mode resources - // component has finished. - // On success, |path| is expected to contain the path as which the component - // is loaded. - void InstalledComponentLoaded( - component_updater::CrOSComponentManager::Error error, - const base::FilePath& path); - - // Loads the preinstalled offline resources image. - void LoadPreinstalledOfflineResources(); - - // Callback for the image loader request to load offline demo mode resources. - // |mount_path| is the path at which the resources were loaded. - void OnOfflineResourcesLoaded(base::Optional<base::FilePath> mounted_path); - // Installs resources for Demo Mode from the offline demo mode resources, such // as apps and media. void InstallDemoResources(); @@ -188,17 +144,10 @@ // Whether demo session has been started. bool started_ = false; - bool offline_resources_load_requested_ = false; - bool offline_resources_loaded_ = false; - - // Path at which offline demo mode resources were loaded. - base::FilePath offline_resources_path_; - // Apps that ShouldIgnorePinPolicy() will check for if the device is offline. std::vector<std::string> ignore_pin_policy_offline_apps_; - // List of pending callbacks passed to EnsureOfflineResourcesLoaded(). - std::list<base::OnceClosure> offline_resources_load_callbacks_; + std::unique_ptr<DemoResources> demo_resources_; ScopedObserver<session_manager::SessionManager, session_manager::SessionManagerObserver>
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc index dba9af1b..ccdeed6b 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc
@@ -17,6 +17,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_resources.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/component_updater/fake_cros_component_manager.h" @@ -41,13 +42,9 @@ namespace { -// TODO(michaelpg): Clean up tests for offline resources and differentiate -// between the CrOS component and the preinstalled resources image. constexpr char kOfflineResourcesComponent[] = "demo-mode-resources"; constexpr char kTestDemoModeResourcesMountPoint[] = "/run/imageloader/demo_mode_resources"; -constexpr char kDemoAppsImageFile[] = "android_demo_apps.squash"; -constexpr char kExternalExtensionsPrefsFile[] = "demo_extensions.json"; void SetBoolean(bool* value) { *value = true; @@ -128,32 +125,16 @@ DemoSession* demo_session = DemoSession::StartIfInDemoMode(); ASSERT_TRUE(demo_session); - EXPECT_FALSE(demo_session->offline_resources_loaded()); + EXPECT_FALSE(demo_session->resources()->loaded()); const base::FilePath component_mount_point = base::FilePath(kTestDemoModeResourcesMountPoint); ASSERT_TRUE(FinishResourcesComponentLoad(component_mount_point)); - EXPECT_TRUE(demo_session->offline_resources_loaded()); - EXPECT_EQ(component_mount_point.AppendASCII(kDemoAppsImageFile), - demo_session->GetDemoAppsPath()); - EXPECT_EQ(component_mount_point.AppendASCII(kExternalExtensionsPrefsFile), - demo_session->GetExternalExtensionsPrefsPath()); + EXPECT_TRUE(demo_session->resources()->loaded()); EXPECT_EQ( component_mount_point.AppendASCII("foo.txt"), - demo_session->GetOfflineResourceAbsolutePath(base::FilePath("foo.txt"))); - EXPECT_EQ(component_mount_point.AppendASCII("foo/bar.txt"), - demo_session->GetOfflineResourceAbsolutePath( - base::FilePath("foo/bar.txt"))); - EXPECT_EQ( - component_mount_point.AppendASCII("foo/"), - demo_session->GetOfflineResourceAbsolutePath(base::FilePath("foo/"))); - EXPECT_TRUE( - demo_session->GetOfflineResourceAbsolutePath(base::FilePath("../foo/")) - .empty()); - EXPECT_TRUE( - demo_session->GetOfflineResourceAbsolutePath(base::FilePath("foo/../bar")) - .empty()); + demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); } TEST_F(DemoSessionTest, StartForDemoDeviceNotInDemoMode) { @@ -176,7 +157,7 @@ EXPECT_TRUE(demo_session->offline_enrolled()); EXPECT_EQ(demo_session, DemoSession::Get()); - EXPECT_FALSE(demo_session->offline_resources_loaded()); + EXPECT_FALSE(demo_session->resources()->loaded()); EXPECT_FALSE( cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); } @@ -189,7 +170,7 @@ EXPECT_FALSE(demo_session->started()); EXPECT_FALSE(demo_session->offline_enrolled()); - EXPECT_FALSE(demo_session->offline_resources_loaded()); + EXPECT_FALSE(demo_session->resources()->loaded()); const base::FilePath component_mount_point = base::FilePath(kTestDemoModeResourcesMountPoint); @@ -198,11 +179,7 @@ cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); EXPECT_FALSE(demo_session->started()); - EXPECT_TRUE(demo_session->offline_resources_loaded()); - EXPECT_EQ(component_mount_point.AppendASCII(kDemoAppsImageFile), - demo_session->GetDemoAppsPath()); - EXPECT_EQ(component_mount_point.AppendASCII(kExternalExtensionsPrefsFile), - demo_session->GetExternalExtensionsPrefsPath()); + EXPECT_TRUE(demo_session->resources()->loaded()); } TEST_F(DemoSessionTest, PreloadOfflineResourcesIfNotInDemoMode) { @@ -222,7 +199,7 @@ EXPECT_FALSE(demo_session->started()); EXPECT_TRUE(demo_session->offline_enrolled()); - EXPECT_FALSE(demo_session->offline_resources_loaded()); + EXPECT_FALSE(demo_session->resources()->loaded()); EXPECT_FALSE( cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); } @@ -248,7 +225,7 @@ ASSERT_TRUE(demo_session); EXPECT_TRUE(demo_session->started()); - EXPECT_FALSE(demo_session->offline_resources_loaded()); + EXPECT_FALSE(demo_session->resources()->loaded()); const base::FilePath component_mount_point = base::FilePath(kTestDemoModeResourcesMountPoint); @@ -257,11 +234,10 @@ cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); EXPECT_TRUE(demo_session->started()); - EXPECT_TRUE(demo_session->offline_resources_loaded()); - EXPECT_EQ(component_mount_point.AppendASCII(kDemoAppsImageFile), - demo_session->GetDemoAppsPath()); - EXPECT_EQ(component_mount_point.AppendASCII(kExternalExtensionsPrefsFile), - demo_session->GetExternalExtensionsPrefsPath()); + EXPECT_TRUE(demo_session->resources()->loaded()); + EXPECT_EQ( + component_mount_point.AppendASCII("foo.txt"), + demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); } TEST_F(DemoSessionTest, StartDemoSessionAfterPreloadingResources) { @@ -275,11 +251,10 @@ DemoSession* demo_session = DemoSession::StartIfInDemoMode(); EXPECT_TRUE(demo_session->started()); - EXPECT_TRUE(demo_session->offline_resources_loaded()); - EXPECT_EQ(component_mount_point.AppendASCII(kDemoAppsImageFile), - demo_session->GetDemoAppsPath()); - EXPECT_EQ(component_mount_point.AppendASCII(kExternalExtensionsPrefsFile), - demo_session->GetExternalExtensionsPrefsPath()); + EXPECT_TRUE(demo_session->resources()->loaded()); + EXPECT_EQ( + component_mount_point.AppendASCII("foo.txt"), + demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); EXPECT_FALSE( cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); @@ -294,7 +269,7 @@ base::BindOnce(&SetBoolean, &callback_called)); EXPECT_FALSE(callback_called); - EXPECT_FALSE(demo_session->offline_resources_loaded()); + EXPECT_FALSE(demo_session->resources()->loaded()); const base::FilePath component_mount_point = base::FilePath(kTestDemoModeResourcesMountPoint); @@ -303,11 +278,10 @@ cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); EXPECT_TRUE(callback_called); - EXPECT_TRUE(demo_session->offline_resources_loaded()); - EXPECT_EQ(component_mount_point.AppendASCII(kDemoAppsImageFile), - demo_session->GetDemoAppsPath()); - EXPECT_EQ(component_mount_point.AppendASCII(kExternalExtensionsPrefsFile), - demo_session->GetExternalExtensionsPrefsPath()); + EXPECT_TRUE(demo_session->resources()->loaded()); + EXPECT_EQ( + component_mount_point.AppendASCII("foo.txt"), + demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); } TEST_F(DemoSessionTest, EnsureOfflineResourcesLoadedAfterOfflineResourceLoad) { @@ -327,11 +301,10 @@ cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); EXPECT_TRUE(callback_called); - EXPECT_TRUE(demo_session->offline_resources_loaded()); - EXPECT_EQ(component_mount_point.AppendASCII(kDemoAppsImageFile), - demo_session->GetDemoAppsPath()); - EXPECT_EQ(component_mount_point.AppendASCII(kExternalExtensionsPrefsFile), - demo_session->GetExternalExtensionsPrefsPath()); + EXPECT_TRUE(demo_session->resources()->loaded()); + EXPECT_EQ( + component_mount_point.AppendASCII("foo.txt"), + demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); } TEST_F(DemoSessionTest, EnsureOfflineResourcesLoadedAfterPreload) { @@ -345,7 +318,7 @@ base::BindOnce(&SetBoolean, &callback_called)); EXPECT_FALSE(callback_called); - EXPECT_FALSE(demo_session->offline_resources_loaded()); + EXPECT_FALSE(demo_session->resources()->loaded()); const base::FilePath component_mount_point = base::FilePath(kTestDemoModeResourcesMountPoint); @@ -354,11 +327,10 @@ cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); EXPECT_TRUE(callback_called); - EXPECT_TRUE(demo_session->offline_resources_loaded()); - EXPECT_EQ(component_mount_point.AppendASCII(kDemoAppsImageFile), - demo_session->GetDemoAppsPath()); - EXPECT_EQ(component_mount_point.AppendASCII(kExternalExtensionsPrefsFile), - demo_session->GetExternalExtensionsPrefsPath()); + EXPECT_TRUE(demo_session->resources()->loaded()); + EXPECT_EQ( + component_mount_point.AppendASCII("foo.txt"), + demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); } TEST_F(DemoSessionTest, MultipleEnsureOfflineResourcesLoaded) { @@ -380,7 +352,7 @@ EXPECT_FALSE(first_callback_called); EXPECT_FALSE(second_callback_called); EXPECT_FALSE(third_callback_called); - EXPECT_FALSE(demo_session->offline_resources_loaded()); + EXPECT_FALSE(demo_session->resources()->loaded()); const base::FilePath component_mount_point = base::FilePath(kTestDemoModeResourcesMountPoint); @@ -391,9 +363,10 @@ EXPECT_TRUE(first_callback_called); EXPECT_TRUE(second_callback_called); EXPECT_TRUE(third_callback_called); - EXPECT_TRUE(demo_session->offline_resources_loaded()); - EXPECT_EQ(component_mount_point.AppendASCII(kDemoAppsImageFile), - demo_session->GetDemoAppsPath()); + EXPECT_TRUE(demo_session->resources()->loaded()); + EXPECT_EQ( + component_mount_point.AppendASCII("foo.txt"), + demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); } class DemoSessionLocaleTest : public DemoSessionTest {
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc index 3b8b1e6..7a38e33 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc
@@ -14,6 +14,7 @@ #include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_resources.h" #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h" #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/wizard_controller.h" @@ -545,7 +546,7 @@ } cros_component_manager->Load( - DemoSession::kDemoModeResourcesComponentName, + DemoResources::kDemoModeResourcesComponentName, component_updater::CrOSComponentManager::MountPolicy::kMount, component_updater::CrOSComponentManager::UpdatePolicy::kDontForce, base::BindOnce(&DemoSetupController::OnDemoResourcesCrOSComponentLoaded,
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager.cc b/chrome/browser/chromeos/login/session/chrome_session_manager.cc index 5b94800..326d5264 100644 --- a/chrome/browser/chromeos/login/session/chrome_session_manager.cc +++ b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/lock_screen_apps/state_controller.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_resources.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/login/lock/webui_screen_locker.h" #include "chrome/browser/chromeos/login/login_wizard.h" @@ -124,7 +125,7 @@ // In demo session, delay starting user session until the offline demo // session resources have been loaded. if (demo_session && demo_session->started() && - !demo_session->offline_resources_loaded()) { + !demo_session->resources()->loaded()) { demo_session->EnsureOfflineResourcesLoaded( base::BindOnce(&StartUserSession, user_profile, login_user_id)); LOG(WARNING) << "Delay demo user session start until offline demo "
diff --git a/chrome/browser/chromeos/network_change_manager_client.cc b/chrome/browser/chromeos/network_change_manager_client.cc new file mode 100644 index 0000000..f2236ac --- /dev/null +++ b/chrome/browser/chromeos/network_change_manager_client.cc
@@ -0,0 +1,267 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/network_change_manager_client.h" + +#include "base/feature_list.h" +#include "base/strings/stringprintf.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/network/network_event_log.h" +#include "chromeos/network/network_state.h" +#include "chromeos/network/network_state_handler.h" +#include "content/public/browser/network_service_instance.h" +#include "net/base/network_change_notifier_chromeos.h" +#include "services/network/public/cpp/features.h" +#include "services/network/public/mojom/network_service.mojom.h" + +namespace chromeos { + +NetworkChangeManagerClient::NetworkChangeManagerClient( + net::NetworkChangeNotifierChromeos* network_change_notifier) + : connection_type_(net::NetworkChangeNotifier::CONNECTION_NONE), + connection_subtype_(net::NetworkChangeNotifier::SUBTYPE_NONE), + network_change_notifier_(network_change_notifier) { + DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this); + NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE); + + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + ConnectToNetworkChangeManager(); + + // Update initial connection state. + DefaultNetworkChanged( + NetworkHandler::Get()->network_state_handler()->DefaultNetwork()); +} + +NetworkChangeManagerClient::~NetworkChangeManagerClient() { + NetworkHandler::Get()->network_state_handler()->RemoveObserver(this, + FROM_HERE); + DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this); +}; + +void NetworkChangeManagerClient::SuspendDone( + const base::TimeDelta& sleep_duration) { + // Force invalidation of network resources on resume. + network_change_notifier_->OnIPAddressChanged(); + if (network_change_manager_) { + network_change_manager_->OnNetworkChanged( + /*dns_changed=*/false, /*ip_address_changed=*/true, + /*connection_type_changed=*/false, + network::mojom::ConnectionType::CONNECTION_UNKNOWN, + /*connection_subtype_changed=*/false, + network::mojom::ConnectionSubtype::SUBTYPE_NONE); + } +} + +void NetworkChangeManagerClient::DefaultNetworkChanged( + const chromeos::NetworkState* default_network) { + bool connection_type_changed = false; + bool connection_subtype_changed = false; + bool ip_address_changed = false; + bool dns_changed = false; + + UpdateState(default_network, &dns_changed, &ip_address_changed, + &connection_type_changed, &connection_subtype_changed); + + if (ip_address_changed) + network_change_notifier_->OnIPAddressChanged(); + if (dns_changed) + network_change_notifier_->OnDNSChanged(); + if (connection_type_changed) + network_change_notifier_->OnConnectionChanged(connection_type_); + if (connection_subtype_changed || connection_type_changed) + network_change_notifier_->OnConnectionSubtypeChanged(connection_type_, + connection_subtype_); + + if (network_change_manager_) { + network_change_manager_->OnNetworkChanged( + dns_changed, ip_address_changed, connection_type_changed, + network::mojom::ConnectionType(connection_type_), + connection_subtype_changed, + network::mojom::ConnectionSubtype(connection_subtype_)); + } +} + +void NetworkChangeManagerClient::ConnectToNetworkChangeManager() { + network::mojom::NetworkChangeManagerRequest request( + mojo::MakeRequest(&network_change_manager_)); + content::GetNetworkService()->GetNetworkChangeManager(std::move(request)); + network_change_manager_.set_connection_error_handler(base::BindOnce( + &NetworkChangeManagerClient::ReconnectToNetworkChangeManager, + base::Unretained(this))); +} + +void NetworkChangeManagerClient::ReconnectToNetworkChangeManager() { + ConnectToNetworkChangeManager(); + + // When reconnecting to the network service, tell it everything changed to + // make sure it refreshes itself into the correct state. + network_change_manager_->OnNetworkChanged( + /*dns_changed=*/true, /*ip_address_changed=*/true, + /*connection_type_changed=*/true, + network::mojom::ConnectionType(connection_type_), + /*connection_subtype_changed=*/true, + network::mojom::ConnectionSubtype(connection_subtype_)); +} + +void NetworkChangeManagerClient::UpdateState( + const chromeos::NetworkState* default_network, + bool* dns_changed, + bool* ip_address_changed, + bool* connection_type_changed, + bool* connection_subtype_changed) { + *connection_type_changed = false; + *connection_subtype_changed = false; + *ip_address_changed = false; + *dns_changed = false; + + if (!default_network || !default_network->IsConnectedState()) { + // If we lost a default network, we must update our state and notify + // observers, otherwise we have nothing to do. + if (connection_type_ != net::NetworkChangeNotifier::CONNECTION_NONE) { + NET_LOG_EVENT("NCNDefaultNetworkLost", service_path_); + *ip_address_changed = true; + *dns_changed = true; + *connection_type_changed = true; + *connection_subtype_changed = true; + connection_type_ = net::NetworkChangeNotifier::CONNECTION_NONE; + connection_subtype_ = net::NetworkChangeNotifier::SUBTYPE_NONE; + service_path_.clear(); + ip_address_.clear(); + dns_servers_.clear(); + } + return; + } + + // We do have a default network and it is connected. + net::NetworkChangeNotifier::ConnectionType new_connection_type = + ConnectionTypeFromShill(default_network->type(), + default_network->network_technology()); + if (new_connection_type != connection_type_) { + NET_LOG_EVENT( + "NCNDefaultConnectionTypeChanged", + base::StringPrintf("%s -> %s", + net::NetworkChangeNotifier::ConnectionTypeToString( + connection_type_), + net::NetworkChangeNotifier::ConnectionTypeToString( + new_connection_type))); + *connection_type_changed = true; + } + if (default_network->path() != service_path_) { + NET_LOG_EVENT("NCNDefaultNetworkServicePathChanged", + base::StringPrintf("%s -> %s", service_path_.c_str(), + default_network->path().c_str())); + + // If we had a default network service change, network resources + // must always be invalidated. + *ip_address_changed = true; + *dns_changed = true; + } + + std::string new_ip_address = default_network->GetIpAddress(); + if (new_ip_address != ip_address_) { + // Is this a state update with an online->online transition? + bool stayed_online = + (!*connection_type_changed && + connection_type_ != net::NetworkChangeNotifier::CONNECTION_NONE); + + bool is_suppressed = true; + // Suppress IP address change signalling on online->online transitions + // when getting an IP address update for the first time. + if (!(stayed_online && ip_address_.empty())) { + is_suppressed = false; + *ip_address_changed = true; + } + NET_LOG_EVENT(base::StringPrintf("%s%s", "NCNDefaultIPAddressChanged", + is_suppressed ? " (Suppressed)" : ""), + base::StringPrintf("%s -> %s", ip_address_.c_str(), + new_ip_address.c_str())); + } + std::string new_dns_servers = default_network->GetDnsServersAsString(); + if (new_dns_servers != dns_servers_) { + NET_LOG_EVENT("NCNDefaultDNSServerChanged", + base::StringPrintf("%s -> %s", dns_servers_.c_str(), + new_dns_servers.c_str())); + *dns_changed = true; + } + + connection_type_ = new_connection_type; + service_path_ = default_network->path(); + ip_address_ = new_ip_address; + dns_servers_ = new_dns_servers; + net::NetworkChangeNotifier::ConnectionSubtype new_subtype = + GetConnectionSubtype(default_network->type(), + default_network->network_technology()); + if (new_subtype != connection_subtype_) { + connection_subtype_ = new_subtype; + *connection_subtype_changed = true; + } +} + +// static +net::NetworkChangeNotifier::ConnectionType +NetworkChangeManagerClient::ConnectionTypeFromShill( + const std::string& type, + const std::string& technology) { + if (NetworkTypePattern::Ethernet().MatchesType(type)) + return net::NetworkChangeNotifier::CONNECTION_ETHERNET; + if (type == shill::kTypeWifi) + return net::NetworkChangeNotifier::CONNECTION_WIFI; + if (type == shill::kTypeWimax) + return net::NetworkChangeNotifier::CONNECTION_4G; + if (type == shill::kTypeBluetooth) + return net::NetworkChangeNotifier::CONNECTION_BLUETOOTH; + + if (type != shill::kTypeCellular) + return net::NetworkChangeNotifier::CONNECTION_UNKNOWN; + + // For cellular types, mapping depends on the technology. + if (technology == shill::kNetworkTechnologyEvdo || + technology == shill::kNetworkTechnologyGsm || + technology == shill::kNetworkTechnologyUmts || + technology == shill::kNetworkTechnologyHspa) { + return net::NetworkChangeNotifier::CONNECTION_3G; + } + if (technology == shill::kNetworkTechnologyHspaPlus || + technology == shill::kNetworkTechnologyLte || + technology == shill::kNetworkTechnologyLteAdvanced) { + return net::NetworkChangeNotifier::CONNECTION_4G; + } + + // Default cellular type is 2G. + return net::NetworkChangeNotifier::CONNECTION_2G; +} + +// static +net::NetworkChangeNotifier::ConnectionSubtype +NetworkChangeManagerClient::GetConnectionSubtype( + const std::string& type, + const std::string& technology) { + if (type != shill::kTypeCellular) + return net::NetworkChangeNotifier::SUBTYPE_UNKNOWN; + + if (technology == shill::kNetworkTechnology1Xrtt) + return net::NetworkChangeNotifier::SUBTYPE_1XRTT; + if (technology == shill::kNetworkTechnologyEvdo) + return net::NetworkChangeNotifier::SUBTYPE_EVDO_REV_0; + if (technology == shill::kNetworkTechnologyGsm) + return net::NetworkChangeNotifier::SUBTYPE_GSM; + if (technology == shill::kNetworkTechnologyGprs) + return net::NetworkChangeNotifier::SUBTYPE_GPRS; + if (technology == shill::kNetworkTechnologyEdge) + return net::NetworkChangeNotifier::SUBTYPE_EDGE; + if (technology == shill::kNetworkTechnologyUmts) + return net::NetworkChangeNotifier::SUBTYPE_UMTS; + if (technology == shill::kNetworkTechnologyHspa) + return net::NetworkChangeNotifier::SUBTYPE_HSPA; + if (technology == shill::kNetworkTechnologyHspaPlus) + return net::NetworkChangeNotifier::SUBTYPE_HSPAP; + if (technology == shill::kNetworkTechnologyLte) + return net::NetworkChangeNotifier::SUBTYPE_LTE; + if (technology == shill::kNetworkTechnologyLteAdvanced) + return net::NetworkChangeNotifier::SUBTYPE_LTE_ADVANCED; + + return net::NetworkChangeNotifier::SUBTYPE_UNKNOWN; +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/network_change_manager_client.h b/chrome/browser/chromeos/network_change_manager_client.h new file mode 100644 index 0000000..a0a830c --- /dev/null +++ b/chrome/browser/chromeos/network_change_manager_client.h
@@ -0,0 +1,96 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_NETWORK_CHANGE_MANAGER_CLIENT_H_ +#define CHROME_BROWSER_CHROMEOS_NETWORK_CHANGE_MANAGER_CLIENT_H_ + +#include <string> + +#include "base/gtest_prod_util.h" +#include "base/macros.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/power_manager_client.h" +#include "chromeos/network/network_state_handler_observer.h" +#include "net/base/network_change_notifier.h" +#include "services/network/public/mojom/network_change_manager.mojom.h" + +namespace net { +class NetworkChangeNotifierChromeos; +} + +namespace chromeos { + +// This class listens to Shill for network change events and notifies both +// the local NetworkChangeNotifierChromeos, and the network service via +// the NetworkChangeManager if the network service is enabled. +class CHROMEOS_EXPORT NetworkChangeManagerClient + : public chromeos::PowerManagerClient::Observer, + public chromeos::NetworkStateHandlerObserver { + public: + NetworkChangeManagerClient( + net::NetworkChangeNotifierChromeos* network_change_notifier); + ~NetworkChangeManagerClient() override; + + // PowerManagerClient::Observer overrides. + void SuspendDone(const base::TimeDelta& sleep_duration) override; + + // NetworkStateHandlerObserver overrides. + void DefaultNetworkChanged( + const chromeos::NetworkState* default_network) override; + + private: + friend class NetworkChangeManagerClientUpdateTest; + FRIEND_TEST_ALL_PREFIXES(NetworkChangeManagerClientTest, + ConnectionTypeFromShill); + + void ConnectToNetworkChangeManager(); + void ReconnectToNetworkChangeManager(); + + // Updates the notifier state based on a default network update. + // |connection_type_changed| is set to true if we must report a connection + // type change. + // |ip_address_changed| is set to true if we must report an IP address change. + // |dns_changed| is set to true if we must report a DNS config change. + // |connection_subtype_changed| is set to true if we must report a connection + // subtype change. + void UpdateState(const chromeos::NetworkState* default_network, + bool* dns_changed, + bool* ip_address_changed, + bool* connection_type_changed, + bool* connection_subtype_changed); + + // Maps the shill network type and technology to its NetworkChangeNotifier + // equivalent. + // + // This is a static member function for testing. + static net::NetworkChangeNotifier::ConnectionType ConnectionTypeFromShill( + const std::string& type, + const std::string& technology); + + // Maps the shill network type and technology to its NetworkChangeNotifier + // subtype equivalent. + // + // This is a static member function for testing. + static net::NetworkChangeNotifier::ConnectionSubtype GetConnectionSubtype( + const std::string& type, + const std::string& technology); + + net::NetworkChangeNotifier::ConnectionType connection_type_; + net::NetworkChangeNotifier::ConnectionSubtype connection_subtype_; + // IP address for the current default network. + std::string ip_address_; + // DNS servers for the current default network. + std::string dns_servers_; + // Service path for the current default network. + std::string service_path_; + + net::NetworkChangeNotifierChromeos* network_change_notifier_; + network::mojom::NetworkChangeManagerPtr network_change_manager_; + + DISALLOW_COPY_AND_ASSIGN(NetworkChangeManagerClient); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_NETWORK_CHANGE_MANAGER_CLIENT_H_
diff --git a/chrome/browser/chromeos/network_change_manager_client_browsertest.cc b/chrome/browser/chromeos/network_change_manager_client_browsertest.cc new file mode 100644 index 0000000..d3daca69 --- /dev/null +++ b/chrome/browser/chromeos/network_change_manager_client_browsertest.cc
@@ -0,0 +1,172 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/run_loop.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill_device_client.h" +#include "chromeos/dbus/shill_service_client.h" +#include "content/public/browser/network_service_instance.h" +#include "net/base/network_change_notifier.h" +#include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/network_connection_tracker.h" +#include "third_party/cros_system_api/dbus/shill/dbus-constants.h" + +namespace chromeos { + +namespace { + +class NetObserver : public net::NetworkChangeNotifier::NetworkChangeObserver { + public: + NetObserver() { net::NetworkChangeNotifier::AddNetworkChangeObserver(this); } + + ~NetObserver() override { + net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); + } + + void WaitForConnectionType(net::NetworkChangeNotifier::ConnectionType type) { + while (last_connection_type != type) { + run_loop_.reset(new base::RunLoop()); + run_loop_->Run(); + run_loop_.reset(); + } + } + + // net::NetworkChangeNotifier:NetworkChangeObserver: + void OnNetworkChanged( + net::NetworkChangeNotifier::ConnectionType type) override { + change_count++; + last_connection_type = type; + if (run_loop_) + run_loop_->Quit(); + } + + int change_count = 0; + net::NetworkChangeNotifier::ConnectionType last_connection_type = + net::NetworkChangeNotifier::CONNECTION_UNKNOWN; + + private: + std::unique_ptr<base::RunLoop> run_loop_; +}; + +class NetworkServiceObserver + : public network::NetworkConnectionTracker::NetworkConnectionObserver { + public: + NetworkServiceObserver() { + content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); + } + + ~NetworkServiceObserver() override { + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver( + this); + } + + void WaitForConnectionType(network::mojom::ConnectionType type) { + while (last_connection_type != type) { + run_loop_.reset(new base::RunLoop()); + run_loop_->Run(); + run_loop_.reset(); + } + } + + // network::NetworkConnectionTracker::NetworkConnectionObserver: + void OnConnectionChanged(network::mojom::ConnectionType type) override { + change_count++; + last_connection_type = type; + if (run_loop_) + run_loop_->Quit(); + } + + int change_count = 0; + network::mojom::ConnectionType last_connection_type = + network::mojom::ConnectionType::CONNECTION_UNKNOWN; + + private: + std::unique_ptr<base::RunLoop> run_loop_; +}; + +} // namespace + +class NetworkChangeManagerClientBrowserTest : public InProcessBrowserTest { + public: + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + service_client_ = + DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); + service_client_->ClearServices(); + } + + ShillServiceClient::TestInterface* service_client() { + return service_client_; + } + + private: + ShillServiceClient::TestInterface* service_client_; +}; + +// Tests that network changes from shill are received by both the +// NetworkChangeNotifier and NetworkConnectionTracker. +IN_PROC_BROWSER_TEST_F(NetworkChangeManagerClientBrowserTest, + ReceiveNotifications) { + NetObserver net_observer; + NetworkServiceObserver network_service_observer; + + service_client()->AddService("wifi", "wifi", "wifi", shill::kTypeWifi, + shill::kStateOnline, true); + + net_observer.WaitForConnectionType( + net::NetworkChangeNotifier::CONNECTION_WIFI); + // NetworkChangeNotifier will send a CONNECTION_NONE notification before + // the CONNECTION_WIFI one. + EXPECT_EQ(2, net_observer.change_count); + EXPECT_EQ(net::NetworkChangeNotifier::CONNECTION_WIFI, + net_observer.last_connection_type); + + network_service_observer.WaitForConnectionType( + network::mojom::ConnectionType::CONNECTION_WIFI); + EXPECT_EQ(2, network_service_observer.change_count); + EXPECT_EQ(network::mojom::ConnectionType::CONNECTION_WIFI, + network_service_observer.last_connection_type); +}; + +// Tests that the NetworkChangeManagerClient reconnects to the network service +// after it gets disconnected. +IN_PROC_BROWSER_TEST_F(NetworkChangeManagerClientBrowserTest, + ReconnectToNetworkService) { + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; + + { + // Make sure everyone thinks we have an ethernet connection. + NetObserver net_observer; + NetworkServiceObserver network_service_observer; + net_observer.WaitForConnectionType( + net::NetworkChangeNotifier::CONNECTION_ETHERNET); + network_service_observer.WaitForConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); + } + + NetObserver net_observer; + NetworkServiceObserver network_service_observer; + + SimulateNetworkServiceCrash(); + service_client()->AddService("wifi", "wifi", "wifi", shill::kTypeWifi, + shill::kStateOnline, true); + + net_observer.WaitForConnectionType( + net::NetworkChangeNotifier::CONNECTION_WIFI); + // NetworkChangeNotifier will send a CONNECTION_NONE notification before + // the CONNECTION_WIFI one. + EXPECT_EQ(2, net_observer.change_count); + EXPECT_EQ(net::NetworkChangeNotifier::CONNECTION_WIFI, + net_observer.last_connection_type); + + network_service_observer.WaitForConnectionType( + network::mojom::ConnectionType::CONNECTION_WIFI); + EXPECT_EQ(2, network_service_observer.change_count); + EXPECT_EQ(network::mojom::ConnectionType::CONNECTION_WIFI, + network_service_observer.last_connection_type); +}; + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/network_change_manager_client_unittest.cc b/chrome/browser/chromeos/network_change_manager_client_unittest.cc new file mode 100644 index 0000000..c2ab2f1 --- /dev/null +++ b/chrome/browser/chromeos/network_change_manager_client_unittest.cc
@@ -0,0 +1,366 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/network_change_manager_client.h" + +#include <stddef.h> + +#include <string> + +#include "base/strings/string_split.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/network/network_handler.h" +#include "chromeos/network/network_state.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "net/base/network_change_notifier.h" +#include "net/base/network_change_notifier_chromeos.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +namespace { + +const char kDnsServers1[] = "192.168.0.1,192.168.0.2"; +const char kDnsServers2[] = "192.168.3.1,192.168.3.2"; +const char kIpAddress1[] = "192.168.1.1"; +const char kIpAddress2[] = "192.168.1.2"; +const char kService1[] = "/service/1"; +const char kService2[] = "/service/2"; +const char kService3[] = "/service/3"; + +struct NotifierState { + net::NetworkChangeNotifier::ConnectionType type; + net::NetworkChangeNotifier::ConnectionSubtype subtype; + const char* service_path; + const char* ip_address; + const char* dns_servers; +}; + +struct DefaultNetworkState { + bool is_connected; + const char* type; + const char* network_technology; + const char* service_path; + const char* ip_address; + const char* dns_servers; +}; + +struct NotifierUpdateTestCase { + const char* test_description; + NotifierState initial_state; + DefaultNetworkState default_network_state; + NotifierState expected_state; + bool expected_type_changed; + bool expected_subtype_changed; + bool expected_ip_changed; + bool expected_dns_changed; +}; + +} // namespace + +using net::NetworkChangeNotifier; + +TEST(NetworkChangeManagerClientTest, ConnectionTypeFromShill) { + struct TypeMapping { + const char* shill_type; + const char* technology; + NetworkChangeNotifier::ConnectionType connection_type; + }; + TypeMapping type_mappings[] = { + {shill::kTypeEthernet, "", NetworkChangeNotifier::CONNECTION_ETHERNET}, + {shill::kTypeWifi, "", NetworkChangeNotifier::CONNECTION_WIFI}, + {shill::kTypeWimax, "", NetworkChangeNotifier::CONNECTION_4G}, + {"unknown type", "unknown technology", + NetworkChangeNotifier::CONNECTION_UNKNOWN}, + {shill::kTypeCellular, shill::kNetworkTechnology1Xrtt, + NetworkChangeNotifier::CONNECTION_2G}, + {shill::kTypeCellular, shill::kNetworkTechnologyGprs, + NetworkChangeNotifier::CONNECTION_2G}, + {shill::kTypeCellular, shill::kNetworkTechnologyEdge, + NetworkChangeNotifier::CONNECTION_2G}, + {shill::kTypeCellular, shill::kNetworkTechnologyEvdo, + NetworkChangeNotifier::CONNECTION_3G}, + {shill::kTypeCellular, shill::kNetworkTechnologyGsm, + NetworkChangeNotifier::CONNECTION_3G}, + {shill::kTypeCellular, shill::kNetworkTechnologyUmts, + NetworkChangeNotifier::CONNECTION_3G}, + {shill::kTypeCellular, shill::kNetworkTechnologyHspa, + NetworkChangeNotifier::CONNECTION_3G}, + {shill::kTypeCellular, shill::kNetworkTechnologyHspaPlus, + NetworkChangeNotifier::CONNECTION_4G}, + {shill::kTypeCellular, shill::kNetworkTechnologyLte, + NetworkChangeNotifier::CONNECTION_4G}, + {shill::kTypeCellular, shill::kNetworkTechnologyLteAdvanced, + NetworkChangeNotifier::CONNECTION_4G}, + {shill::kTypeCellular, "unknown technology", + NetworkChangeNotifier::CONNECTION_2G}}; + + for (size_t i = 0; i < arraysize(type_mappings); ++i) { + NetworkChangeNotifier::ConnectionType type = + NetworkChangeManagerClient::ConnectionTypeFromShill( + type_mappings[i].shill_type, type_mappings[i].technology); + EXPECT_EQ(type_mappings[i].connection_type, type); + } +} + +class NetworkChangeManagerClientUpdateTest : public testing::Test { + protected: + NetworkChangeManagerClientUpdateTest() : default_network_("") { + network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); + DBusThreadManager::Initialize(); + NetworkHandler::Initialize(); + proxy_.reset(new NetworkChangeManagerClient( + static_cast<net::NetworkChangeNotifierChromeos*>( + network_change_notifier_.get()))); + } + + ~NetworkChangeManagerClientUpdateTest() override = default; + + void SetNotifierState(const NotifierState& notifier_state) { + proxy_->connection_type_ = notifier_state.type; + proxy_->connection_subtype_ = notifier_state.subtype; + proxy_->service_path_ = notifier_state.service_path; + proxy_->ip_address_ = notifier_state.ip_address; + proxy_->dns_servers_ = notifier_state.dns_servers; + } + + void VerifyNotifierState(const NotifierState& notifier_state) { + EXPECT_EQ(notifier_state.type, proxy_->connection_type_); + EXPECT_EQ(notifier_state.subtype, proxy_->connection_subtype_); + EXPECT_EQ(notifier_state.service_path, proxy_->service_path_); + EXPECT_EQ(notifier_state.ip_address, proxy_->ip_address_); + EXPECT_EQ(notifier_state.dns_servers, proxy_->dns_servers_); + } + + // Sets the default network state used for notifier updates. + void SetDefaultNetworkState( + const DefaultNetworkState& default_network_state) { + default_network_.set_visible(true); + if (default_network_state.is_connected) + default_network_.set_connection_state(shill::kStateOnline); + else + default_network_.set_connection_state(shill::kStateConfiguration); + default_network_.set_type_for_testing(default_network_state.type); + default_network_.set_network_technology_for_testing( + default_network_state.network_technology); + default_network_.set_path_for_testing(default_network_state.service_path); + base::Value ipv4_properties(base::Value::Type::DICTIONARY); + ipv4_properties.SetKey(shill::kAddressProperty, + base::Value(default_network_state.ip_address)); + std::vector<std::string> dns_servers = + base::SplitString(default_network_state.dns_servers, ",", + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + base::ListValue dns_servers_value; + dns_servers_value.AppendStrings(dns_servers); + ipv4_properties.SetKey(shill::kNameServersProperty, + std::move(dns_servers_value)); + default_network_.IPConfigPropertiesChanged(ipv4_properties); + } + + // Process an default network update based on the state of |default_network_|. + void ProcessDefaultNetworkUpdate(bool* dns_changed, + bool* ip_changed, + bool* type_changed, + bool* subtype_changed) { + proxy_->UpdateState(&default_network_, dns_changed, ip_changed, + type_changed, subtype_changed); + } + + private: + content::TestBrowserThreadBundle thread_bundle_; + NetworkState default_network_; + std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; + std::unique_ptr<NetworkChangeManagerClient> proxy_; +}; + +NotifierUpdateTestCase test_cases[] = { + {"Online -> Offline", + {NetworkChangeNotifier::CONNECTION_ETHERNET, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService1, + kIpAddress1, + kDnsServers1}, + {false, shill::kTypeEthernet, "", kService1, "", ""}, + {NetworkChangeNotifier::CONNECTION_NONE, + NetworkChangeNotifier::SUBTYPE_NONE, + "", + "", + ""}, + true, + true, + true, + true}, + {"Offline -> Offline", + {NetworkChangeNotifier::CONNECTION_NONE, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + "", + "", + ""}, + {false, shill::kTypeEthernet, "", kService1, kIpAddress1, kDnsServers1}, + {NetworkChangeNotifier::CONNECTION_NONE, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + "", + "", + ""}, + false, + false, + false, + false}, + {"Offline -> Online", + {NetworkChangeNotifier::CONNECTION_NONE, + NetworkChangeNotifier::SUBTYPE_NONE, + "", + "", + ""}, + {true, shill::kTypeEthernet, "", kService1, kIpAddress1, kDnsServers1}, + {NetworkChangeNotifier::CONNECTION_ETHERNET, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService1, + kIpAddress1, + kDnsServers1}, + true, + true, + true, + true}, + {"Online -> Online (new default service, different connection type)", + {NetworkChangeNotifier::CONNECTION_ETHERNET, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService1, + kIpAddress1, + kDnsServers1}, + {true, shill::kTypeWifi, "", kService2, kIpAddress1, kDnsServers1}, + {NetworkChangeNotifier::CONNECTION_WIFI, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService2, + kIpAddress1, + kDnsServers1}, + true, + false, + true, + true}, + {"Online -> Online (new default service, same connection type)", + {NetworkChangeNotifier::CONNECTION_WIFI, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService2, + kIpAddress1, + kDnsServers1}, + {true, shill::kTypeWifi, "", kService3, kIpAddress1, kDnsServers1}, + {NetworkChangeNotifier::CONNECTION_WIFI, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService3, + kIpAddress1, + kDnsServers1}, + false, + false, + true, + true}, + {"Online -> Online (same default service, first IP address update)", + {NetworkChangeNotifier::CONNECTION_WIFI, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService3, + "", + kDnsServers1}, + {true, shill::kTypeWifi, "", kService3, kIpAddress2, kDnsServers1}, + {NetworkChangeNotifier::CONNECTION_WIFI, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService3, + kIpAddress2, + kDnsServers1}, + false, + false, + false, + false}, + {"Online -> Online (same default service, new IP address, same DNS)", + {NetworkChangeNotifier::CONNECTION_WIFI, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService3, + kIpAddress1, + kDnsServers1}, + {true, shill::kTypeWifi, "", kService3, kIpAddress2, kDnsServers1}, + {NetworkChangeNotifier::CONNECTION_WIFI, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService3, + kIpAddress2, + kDnsServers1}, + false, + false, + true, + false}, + {"Online -> Online (same default service, same IP address, new DNS)", + {NetworkChangeNotifier::CONNECTION_WIFI, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService3, + kIpAddress2, + kDnsServers1}, + {true, shill::kTypeWifi, "", kService3, kIpAddress2, kDnsServers2}, + {NetworkChangeNotifier::CONNECTION_WIFI, + NetworkChangeNotifier::SUBTYPE_UNKNOWN, + kService3, + kIpAddress2, + kDnsServers2}, + false, + false, + false, + true}, + {"Online -> Online (change of technology but not connection type)", + {NetworkChangeNotifier::CONNECTION_3G, + NetworkChangeNotifier::SUBTYPE_EVDO_REV_0, + kService3, + kIpAddress2, + kDnsServers1}, + {true, + shill::kTypeCellular, + shill::kNetworkTechnologyHspa, + kService3, + kIpAddress2, + kDnsServers1}, + {NetworkChangeNotifier::CONNECTION_3G, + NetworkChangeNotifier::SUBTYPE_HSPA, + kService3, + kIpAddress2, + kDnsServers1}, + false, + true, + false, + false}, + {"Online -> Online (change of technology and connection type)", + {NetworkChangeNotifier::CONNECTION_3G, + NetworkChangeNotifier::SUBTYPE_EVDO_REV_0, + kService3, + kIpAddress2, + kDnsServers1}, + {true, + shill::kTypeCellular, + shill::kNetworkTechnologyLte, + kService3, + kIpAddress2, + kDnsServers1}, + {NetworkChangeNotifier::CONNECTION_4G, + NetworkChangeNotifier::SUBTYPE_LTE, + kService3, + kIpAddress2, + kDnsServers1}, + true, + true, + false, + false}}; + +TEST_F(NetworkChangeManagerClientUpdateTest, UpdateDefaultNetwork) { + for (size_t i = 0; i < arraysize(test_cases); ++i) { + SCOPED_TRACE(test_cases[i].test_description); + SetNotifierState(test_cases[i].initial_state); + SetDefaultNetworkState(test_cases[i].default_network_state); + bool dns_changed = false, ip_changed = false, type_changed = false, + subtype_changed = false; + ProcessDefaultNetworkUpdate(&dns_changed, &ip_changed, &type_changed, + &subtype_changed); + VerifyNotifierState(test_cases[i].expected_state); + EXPECT_EQ(test_cases[i].expected_dns_changed, dns_changed); + EXPECT_EQ(test_cases[i].expected_ip_changed, ip_changed); + EXPECT_EQ(test_cases[i].expected_type_changed, type_changed); + EXPECT_EQ(test_cases[i].expected_subtype_changed, subtype_changed); + } +} + +} // namespace chromeos
diff --git a/chrome/browser/domain_reliability/service_factory.cc b/chrome/browser/domain_reliability/service_factory.cc index d6d7c4c..8a715030 100644 --- a/chrome/browser/domain_reliability/service_factory.cc +++ b/chrome/browser/domain_reliability/service_factory.cc
@@ -11,7 +11,6 @@ #include "chrome/common/chrome_switches.h" #include "components/domain_reliability/service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" -#include "components/keyed_service/core/keyed_service.h" #include "content/public/browser/browser_context.h" #if defined(OS_CHROMEOS) @@ -32,27 +31,19 @@ // Identifies Chrome as the source of Domain Reliability uploads it sends. const char kUploadReporterString[] = "chrome"; -class KeyedServiceWrapper : public KeyedService { - public: - explicit KeyedServiceWrapper(DomainReliabilityService* service) - : service_(service) {} - ~KeyedServiceWrapper() override = default; - - DomainReliabilityService* service() { return service_; } - - private: - DomainReliabilityService* service_; - - DISALLOW_COPY_AND_ASSIGN(KeyedServiceWrapper); -}; - } // namespace +DomainReliabilityKeyedServiceWrapper::DomainReliabilityKeyedServiceWrapper( + DomainReliabilityService* service) + : service_(service) {} +DomainReliabilityKeyedServiceWrapper::~DomainReliabilityKeyedServiceWrapper() = + default; + // static DomainReliabilityService* DomainReliabilityServiceFactory::GetForBrowserContext( content::BrowserContext* context) { - auto* wrapper = static_cast<KeyedServiceWrapper*>( + auto* wrapper = static_cast<DomainReliabilityKeyedServiceWrapper*>( GetInstance()->GetServiceForBrowserContext(context, /* create = */ true)); if (!wrapper) @@ -78,7 +69,7 @@ if (!ShouldCreateService()) return NULL; - return new KeyedServiceWrapper( + return new DomainReliabilityKeyedServiceWrapper( DomainReliabilityService::Create(kUploadReporterString)); }
diff --git a/chrome/browser/domain_reliability/service_factory.h b/chrome/browser/domain_reliability/service_factory.h index 2a77b03..aa2d08c 100644 --- a/chrome/browser/domain_reliability/service_factory.h +++ b/chrome/browser/domain_reliability/service_factory.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "base/memory/singleton.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "components/keyed_service/core/keyed_service.h" namespace content { class BrowserContext; @@ -17,6 +18,20 @@ class DomainReliabilityService; +class DomainReliabilityKeyedServiceWrapper : public KeyedService { + public: + explicit DomainReliabilityKeyedServiceWrapper( + DomainReliabilityService* service); + ~DomainReliabilityKeyedServiceWrapper() override; + + DomainReliabilityService* service() { return service_; } + + private: + DomainReliabilityService* service_; + + DISALLOW_COPY_AND_ASSIGN(DomainReliabilityKeyedServiceWrapper); +}; + // Creates DomainReliabilityServices for BrowserContexts. Initializes them with // the hardcoded upload reporter string "chrome". class DomainReliabilityServiceFactory
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index a04a03d..dbeda831 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc
@@ -115,7 +115,6 @@ fail_install_if_unexpected_version_(false), extensions_enabled_(service_weak->extensions_enabled()), delete_source_(false), - create_app_shortcut_(false), service_weak_(service_weak), // See header file comment on |client_| for why we use a raw pointer here. client_(client.release()),
diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h index 681d741..76f3cc3 100644 --- a/chrome/browser/extensions/crx_installer.h +++ b/chrome/browser/extensions/crx_installer.h
@@ -395,11 +395,6 @@ // to false. bool delete_source_; - // Whether to create an app shortcut after successful installation. This is - // set based on the user's selection in the UI and can only ever be true for - // apps. - bool create_app_shortcut_; - // The ordinal of the NTP apps page |extension_| will be shown on. syncer::StringOrdinal page_ordinal_;
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index b70c920..f09fc2f 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3297,6 +3297,10 @@ "If audio focus is enabled in Chrome then this will delegate audio focus " "control in Android apps to Chrome."; +const char kEnableAssistantVoiceMatchName[] = "Enable Assistant Voice Match"; +const char kEnableAssistantVoiceMatchDescription[] = + "Enable the Assistant Voice Match feature"; + const char kEnableBackgroundBlurName[] = "Enable background blur."; const char kEnableBackgroundBlurDescription[] = "Enables background blur for the Peeking Launcher and Tab Switcher.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index ab10885..9e3b14d 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1992,6 +1992,9 @@ extern const char kEnableArcUnifiedAudioFocusName[]; extern const char kEnableArcUnifiedAudioFocusDescription[]; +extern const char kEnableAssistantVoiceMatchName[]; +extern const char kEnableAssistantVoiceMatchDescription[]; + extern const char kEnableBackgroundBlurName[]; extern const char kEnableBackgroundBlurDescription[];
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.cc b/chrome/browser/navigation_predictor/navigation_predictor.cc index 4b9492d..f67926b 100644 --- a/chrome/browser/navigation_predictor/navigation_predictor.cc +++ b/chrome/browser/navigation_predictor/navigation_predictor.cc
@@ -4,8 +4,11 @@ #include "chrome/browser/navigation_predictor/navigation_predictor.h" +#include <memory> + #include "base/logging.h" #include "base/metrics/field_trial_params.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/optional.h" #include "base/system/sys_info.h" @@ -19,6 +22,7 @@ #include "mojo/public/cpp/bindings/strong_binding.h" #include "third_party/blink/public/common/features.h" #include "url/gurl.h" +#include "url/origin.h" struct NavigationPredictor::NavigationScore { NavigationScore(const GURL& url, @@ -459,7 +463,9 @@ std::sort(navigation_scores.begin(), navigation_scores.end(), [](const auto& a, const auto& b) { return a->score > b->score; }); - MaybeTakeActionOnLoad(navigation_scores); + const url::Origin document_origin = + url::Origin::Create(metrics[0]->source_url); + MaybeTakeActionOnLoad(document_origin, navigation_scores); // Store navigation scores in |navigation_scores_map_| for fast look up upon // clicks. @@ -541,19 +547,58 @@ } void NavigationPredictor::MaybeTakeActionOnLoad( + const url::Origin& document_origin, const std::vector<std::unique_ptr<NavigationScore>>& - sorted_navigation_scores) const { + sorted_navigation_scores) { DCHECK(!browser_context_->IsOffTheRecord()); - // TODO(chelu): https://crbug.com/850624/. Given the calculated navigation - // scores, this function decides which action to take, or decides not to do - // anything. Example actions including preresolve, preload, prerendering, etc. - // |sorted_navigation_scores| are sorted in descending order, the first one // has the highest navigation score. UMA_HISTOGRAM_COUNTS_100( "AnchorElementMetrics.Visible.HighestNavigationScore", static_cast<int>(sorted_navigation_scores[0]->score)); + + std::string action_histogram_name = + source_is_default_search_engine_page_ + ? "NavigationPredictor.OnDSE.ActionTaken" + : "NavigationPredictor.OnNonDSE.ActionTaken"; + + DCHECK(!prefetch_url_.has_value()); + + prefetch_url_ = GetUrlToPrefetch(document_origin, sorted_navigation_scores); + if (prefetch_url_.has_value()) { + DCHECK_EQ(document_origin.host(), prefetch_url_->host()); + base::UmaHistogramEnumeration(action_histogram_name, Action::kPrefetch); + return; + } + + base::UmaHistogramEnumeration(action_histogram_name, Action::kNone); +} + +base::Optional<GURL> NavigationPredictor::GetUrlToPrefetch( + const url::Origin& document_origin, + const std::vector<std::unique_ptr<NavigationScore>>& + sorted_navigation_scores) const { + // Currently, prefetch is disabled on low-end devices since prefetch may + // increase memory usage. + if (is_low_end_device_) + return base::nullopt; + + // On search engine results page, next navigation is likely to be a different + // origin. Currently, the prefetch is only allowed for same orgins. Hence, + // prefetch is currently disabled on search engine results page. + if (source_is_default_search_engine_page_) + return base::nullopt; + + // Return the same-origin URL that has the highest navigation score. + for (const auto& navigation_score : sorted_navigation_scores) { + // Currently, only same origin URLs can be prefetched. + if (url::Origin::Create(navigation_score->url) != document_origin) + continue; + return navigation_score->url; + } + + return base::nullopt; } void NavigationPredictor::RecordMetricsOnLoad(
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.h b/chrome/browser/navigation_predictor/navigation_predictor.h index 3684ea0d..260bd0e 100644 --- a/chrome/browser/navigation_predictor/navigation_predictor.h +++ b/chrome/browser/navigation_predictor/navigation_predictor.h
@@ -10,6 +10,7 @@ #include <vector> #include "base/macros.h" +#include "base/optional.h" #include "base/sequence_checker.h" #include "base/time/time.h" #include "mojo/public/cpp/bindings/interface_request.h" @@ -20,6 +21,10 @@ class RenderFrameHost; } +namespace url { +class Origin; +} + class SiteEngagementService; class TemplateURLService; @@ -37,6 +42,21 @@ static void Create(mojo::InterfaceRequest<AnchorElementMetricsHost> request, content::RenderFrameHost* render_frame_host); + // This enum should remain synchronized with enum + // NavigationPredictorActionTaken in enums.xml. Order of enum values should + // not be changed since the values are recorded in UMA. + enum class Action { + kUnknown = 0, + kNone = 1, + kPreresolve = 2, + kPreconnect = 3, + kPrefetch = 4, + kMaxValue = kPrefetch, + }; + + protected: + base::Optional<GURL> prefetch_url_; + private: // Struct holding navigation score, rank and other info of the anchor element. // Used for look up when an anchor element is clicked. @@ -82,6 +102,12 @@ // action to take, or decide not to do anything. Example actions including // preresolve, preload, prerendering, etc. void MaybeTakeActionOnLoad( + const url::Origin& document_origin, + const std::vector<std::unique_ptr<NavigationScore>>& + sorted_navigation_scores); + + base::Optional<GURL> GetUrlToPrefetch( + const url::Origin& document_origin, const std::vector<std::unique_ptr<NavigationScore>>& sorted_navigation_scores) const;
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc index 031a907a..a6d293eb 100644 --- a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc +++ b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
@@ -8,6 +8,7 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/metrics/subprocess_metrics_provider.h" +#include "chrome/browser/navigation_predictor/navigation_predictor.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h" #include "chrome/browser/ui/browser.h" @@ -464,3 +465,51 @@ "AnchorElementMetrics.Clicked.OnNonDSE.SameHost", 0, 1); } } + +IN_PROC_BROWSER_TEST_P(NavigationPredictorBrowserTest, + ActionPrefetch_NoSameHostAnchorElement) { + base::HistogramTester histogram_tester; + + const GURL& url = GetTestURL("/simple_page_with_anchors.html"); + ui_test_utils::NavigateToURL(browser(), url); + base::RunLoop().RunUntilIdle(); + + if (base::FeatureList::IsEnabled( + blink::features::kRecordAnchorMetricsVisible)) { + histogram_tester.ExpectUniqueSample( + "AnchorElementMetrics.Visible.NumberOfAnchorElements", 3, 1); + // Same document anchor element should be removed after merge. + histogram_tester.ExpectUniqueSample( + "AnchorElementMetrics.Visible.NumberOfAnchorElementsAfterMerge", 2, 1); + histogram_tester.ExpectUniqueSample( + "NavigationPredictor.OnNonDSE.ActionTaken", + NavigationPredictor::Action::kNone, 1); + } else { + histogram_tester.ExpectTotalCount( + "AnchorElementMetrics.Visible.NumberOfAnchorElements", 0); + } +} + +IN_PROC_BROWSER_TEST_P(NavigationPredictorBrowserTest, + ActionPrefetch_SameHostAnchorElement) { + base::HistogramTester histogram_tester; + + const GURL& url = GetTestURL("/page_with_same_host_anchor_element.html"); + ui_test_utils::NavigateToURL(browser(), url); + base::RunLoop().RunUntilIdle(); + + if (base::FeatureList::IsEnabled( + blink::features::kRecordAnchorMetricsVisible)) { + histogram_tester.ExpectUniqueSample( + "AnchorElementMetrics.Visible.NumberOfAnchorElements", 2, 1); + // Same document anchor element should be removed after merge. + histogram_tester.ExpectUniqueSample( + "AnchorElementMetrics.Visible.NumberOfAnchorElementsAfterMerge", 2, 1); + histogram_tester.ExpectUniqueSample( + "NavigationPredictor.OnNonDSE.ActionTaken", + NavigationPredictor::Action::kPrefetch, 1); + } else { + histogram_tester.ExpectTotalCount( + "AnchorElementMetrics.Visible.NumberOfAnchorElements", 0); + } +}
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc b/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc index 9159295..0fcf6c3 100644 --- a/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc +++ b/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc
@@ -28,6 +28,8 @@ ~TestNavigationPredictor() override {} + base::Optional<GURL> prefetch_url() const { return prefetch_url_; } + const std::map<GURL, int>& GetAreaRankMap() const { return area_rank_map_; } private: @@ -79,6 +81,10 @@ return predictor_service_helper_.get(); } + base::Optional<GURL> prefetch_url() const { + return predictor_service_helper_->prefetch_url(); + } + private: blink::mojom::AnchorElementMetricsHostPtr predictor_service_; std::unique_ptr<TestNavigationPredictor> predictor_service_helper_; @@ -230,3 +236,59 @@ histogram_tester.ExpectTotalCount("AnchorElementMetrics.Visible.RatioArea", 5); } + +TEST_F(NavigationPredictorTest, ActionTaken_NoSameHost_Prefetch) { + const std::string source = "https://example.com"; + const std::string href_xlarge = "https://example2.com/xlarge"; + + std::vector<blink::mojom::AnchorElementMetricsPtr> metrics; + metrics.push_back(CreateMetricsPtr(source, href_xlarge, 0.1)); + + base::HistogramTester histogram_tester; + predictor_service()->ReportAnchorElementMetricsOnLoad(std::move(metrics)); + base::RunLoop().RunUntilIdle(); + + histogram_tester.ExpectUniqueSample( + "NavigationPredictor.OnNonDSE.ActionTaken", + NavigationPredictor::Action::kNone, 1); + EXPECT_FALSE(prefetch_url().has_value()); +} + +TEST_F(NavigationPredictorTest, ActionTaken_SameOrigin_Prefetch) { + const std::string source = "https://example.com"; + const std::string same_origin_href_small = "https://example.com/small"; + const std::string diff_origin_href_xlarge = "https://example2.com/xlarge"; + + std::vector<blink::mojom::AnchorElementMetricsPtr> metrics; + metrics.push_back(CreateMetricsPtr(source, same_origin_href_small, 0.01)); + metrics.push_back(CreateMetricsPtr(source, diff_origin_href_xlarge, 1)); + + base::HistogramTester histogram_tester; + predictor_service()->ReportAnchorElementMetricsOnLoad(std::move(metrics)); + base::RunLoop().RunUntilIdle(); + + histogram_tester.ExpectUniqueSample( + "NavigationPredictor.OnNonDSE.ActionTaken", + NavigationPredictor::Action::kPrefetch, 1); + EXPECT_EQ(GURL(same_origin_href_small), prefetch_url()); +} + +TEST_F(NavigationPredictorTest, + ActionTaken_SameOrigin_DifferentScheme_Prefetch) { + const std::string source = "https://example.com"; + const std::string same_origin_href_small = "http://example.com/small"; + const std::string diff_origin_href_xlarge = "https://example2.com/xlarge"; + + std::vector<blink::mojom::AnchorElementMetricsPtr> metrics; + metrics.push_back(CreateMetricsPtr(source, same_origin_href_small, 0.01)); + metrics.push_back(CreateMetricsPtr(source, diff_origin_href_xlarge, 1)); + + base::HistogramTester histogram_tester; + predictor_service()->ReportAnchorElementMetricsOnLoad(std::move(metrics)); + base::RunLoop().RunUntilIdle(); + + histogram_tester.ExpectUniqueSample( + "NavigationPredictor.OnNonDSE.ActionTaken", + NavigationPredictor::Action::kNone, 1); + EXPECT_FALSE(prefetch_url().has_value()); +}
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc index 8039a203..298e207d 100644 --- a/chrome/browser/net/network_context_configuration_browsertest.cc +++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -42,6 +42,7 @@ #include "components/proxy_config/proxy_config_pref_names.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" @@ -68,6 +69,7 @@ #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request.h" #include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/network_connection_tracker.h" #include "services/network/public/cpp/resource_response.h" #include "services/network/public/cpp/resource_response_info.h" #include "services/network/public/cpp/simple_url_loader.h" @@ -1490,7 +1492,8 @@ // Make sure the system URLRequestContext can handle fetching PAC scripts from // file URLs. class NetworkContextConfigurationFilePacBrowserTest - : public NetworkContextConfigurationBrowserTest { + : public NetworkContextConfigurationBrowserTest, + public network::NetworkConnectionTracker::NetworkConnectionObserver { public: NetworkContextConfigurationFilePacBrowserTest() {} @@ -1512,8 +1515,37 @@ switches::kProxyPacUrl, net::FilePathToFileURL(pac_file_path).spec()); } + void SetUpOnMainThread() override { + NetworkContextConfigurationBrowserTest::SetUpOnMainThread(); + + // The network service will have just been killed if network_service_state + // is kRestarted. Make sure it knows about the correct network state before + // continuing. + network::NetworkConnectionTracker* tracker = + content::GetNetworkConnectionTracker(); + auto connection_type = network::mojom::ConnectionType::CONNECTION_NONE; + run_loop_.reset(new base::RunLoop()); + tracker->AddNetworkConnectionObserver(this); + while (!tracker->GetConnectionType( + &connection_type, + base::BindOnce(&NetworkContextConfigurationFilePacBrowserTest:: + OnConnectionChanged, + base::Unretained(this))) || + connection_type == network::mojom::ConnectionType::CONNECTION_NONE) { + run_loop_->Run(); + run_loop_.reset(new base::RunLoop()); + } + tracker->RemoveNetworkConnectionObserver(this); + } + + // network::NetworkConnectionTracker::NetworkConnectionObserver + void OnConnectionChanged(network::mojom::ConnectionType type) override { + run_loop_->Quit(); + } + private: base::ScopedTempDir temp_dir_; + std::unique_ptr<base::RunLoop> run_loop_; DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationFilePacBrowserTest); };
diff --git a/chrome/browser/resource_coordinator/tab_ranker/example_preprocessor_config.pb b/chrome/browser/resource_coordinator/tab_ranker/example_preprocessor_config.pb index fb99da94..9b91af6 100644 --- a/chrome/browser/resource_coordinator/tab_ranker/example_preprocessor_config.pb +++ b/chrome/browser/resource_coordinator/tab_ranker/example_preprocessor_config.pb Binary files differ
diff --git a/chrome/browser/resource_coordinator/tab_ranker/native_inference.cc b/chrome/browser/resource_coordinator/tab_ranker/native_inference.cc index 78b79f4..2a899e6 100644 --- a/chrome/browser/resource_coordinator/tab_ranker/native_inference.cc +++ b/chrome/browser/resource_coordinator/tab_ranker/native_inference.cc
@@ -55,7 +55,6 @@ // ----------------------------------------------------------------------------- // Simple unary ops // ----------------------------------------------------------------------------- - template <typename T> void Relu(const int32_t rank, const int32_t* __restrict input_shape, @@ -69,2537 +68,3812 @@ } // ----------------------------------------------------------------------------- -// Dequantize ops -// ----------------------------------------------------------------------------- - -template <typename T> -void DequantizeMinFirst(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - const float* __restrict min_range, - const float* __restrict max_range, - float* __restrict output_values) { - const int32_t size = ShapeSize(rank, input_shape); - const float range_scale = (max_range[0] - min_range[0]) / - (static_cast<float>(std::numeric_limits<T>::max()) - - std::numeric_limits<T>::min()); - const float range_min_rounded = - (max_range[0] == min_range[0] - ? min_range[0] - : round(min_range[0] / range_scale) * range_scale); - for (int32_t i = 0; i < size; i++) { - output_values[i] = ((static_cast<int32_t>(input_values[i]) - - std::numeric_limits<T>::min()) * - range_scale) + - range_min_rounded; - } -} - -// ----------------------------------------------------------------------------- // CONSTANTS // Note that for now, endianness of the target machine needs to match that of // the one training was performed on. // ----------------------------------------------------------------------------- -const int32_t dnn_logits_biases__2__cf__2_shape[1] = {1}; -const union { - uint8_t bytes[4]; - float values[1]; -} dnn_logits_biases__2__cf__2 = {{ - 0x6d, 0x62, 0xe9, 0xbf, -}}; - -const int32_t dnn_hiddenlayer_0_weights__1__cf__1_quantized_const_shape[2] = { - FEATURES_SIZE, DNN_BIASES_SIZE}; -const union { - uint8_t bytes[DNN_WEIGHTS_SIZE]; - uint8_t values[DNN_WEIGHTS_SIZE]; -} dnn_hiddenlayer_0_weights__1__cf__1_quantized_const = {{ - 0x59, 0x57, 0x52, 0x5d, 0x12, 0x4e, 0x56, 0x55, 0x59, 0x56, 0x59, 0x58, - 0x5d, 0x49, 0x6a, 0x59, 0x5a, 0x58, 0x5c, 0x57, 0x59, 0x54, 0x5b, 0x58, - 0x5d, 0x59, 0x57, 0x57, 0x62, 0x5c, 0x51, 0x57, 0x5b, 0x54, 0x59, 0x5a, - 0x5c, 0x5d, 0x4a, 0x57, 0x59, 0x51, 0x57, 0x6b, 0x58, 0x50, 0x60, 0x59, - 0x58, 0x57, 0x59, 0x5d, 0x5a, 0x40, 0x60, 0x5b, 0x59, 0x5c, 0x60, 0x5a, - 0x5a, 0x4f, 0x4d, 0x4c, 0x58, 0x59, 0x57, 0x59, 0x5e, 0x55, 0x59, 0x59, - 0x59, 0x5c, 0x59, 0x5c, 0x5c, 0x59, 0x60, 0x5d, 0x58, 0x5f, 0x64, 0x5b, - 0x49, 0x60, 0x5b, 0x47, 0x4a, 0x5a, 0x59, 0x58, 0x5d, 0x5a, 0x73, 0x5b, - 0x59, 0x53, 0x65, 0x56, 0x5b, 0x4f, 0x3f, 0x2f, 0x58, 0x58, 0x55, 0x60, - 0x54, 0x6c, 0x5a, 0x5b, 0x54, 0x5d, 0x59, 0x57, 0x5f, 0x6a, 0x59, 0x56, - 0x57, 0x58, 0x58, 0x5a, 0x57, 0x58, 0x60, 0x66, 0x55, 0x56, 0x51, 0x5e, - 0x56, 0x5d, 0x53, 0x5a, 0x51, 0x55, 0x5d, 0x58, 0x56, 0x57, 0x55, 0x61, - 0x5d, 0x5d, 0x54, 0x5b, 0x56, 0x57, 0x61, 0x5a, 0x57, 0x5e, 0x56, 0x5a, - 0x59, 0x59, 0x5f, 0x57, 0x58, 0x5e, 0x57, 0x58, 0x5b, 0x56, 0x60, 0x68, - 0x51, 0x5c, 0x52, 0x60, 0x55, 0x5d, 0x56, 0x5f, 0x52, 0x59, 0x5c, 0x57, - 0x51, 0x57, 0x61, 0x5c, 0x5a, 0x60, 0x50, 0x62, 0x55, 0x58, 0x64, 0x5a, - 0x5b, 0x5f, 0x57, 0x5a, 0x53, 0x57, 0x59, 0x59, 0x58, 0x58, 0x57, 0x5d, - 0x58, 0x5a, 0x5e, 0x5c, 0x55, 0x5a, 0x51, 0x59, 0x58, 0x4f, 0x5d, 0x56, - 0x51, 0x54, 0x5b, 0x57, 0x59, 0x55, 0x5d, 0x4b, 0x5c, 0x5a, 0x59, 0x5b, - 0x56, 0x57, 0x5a, 0x58, 0x56, 0x59, 0x56, 0x58, 0x57, 0x58, 0x59, 0x59, - 0x57, 0x57, 0x58, 0x5d, 0x59, 0x59, 0x5d, 0x5d, 0x57, 0x5a, 0x50, 0x5a, - 0x56, 0x4b, 0x5d, 0x59, 0x50, 0x54, 0x5b, 0x57, 0x59, 0x55, 0x5b, 0x44, - 0x5a, 0x5b, 0x59, 0x5b, 0x56, 0x57, 0x59, 0x57, 0x56, 0x59, 0x56, 0x58, - 0x57, 0x58, 0x58, 0x58, 0x58, 0x56, 0x57, 0x5d, 0x58, 0x58, 0x5d, 0x5c, - 0x56, 0x5b, 0x51, 0x5b, 0x58, 0x4d, 0x5d, 0x57, 0x51, 0x55, 0x5b, 0x57, - 0x58, 0x54, 0x5a, 0x4d, 0x5d, 0x5b, 0x5b, 0x5b, 0x57, 0x57, 0x5b, 0x56, - 0x56, 0x59, 0x57, 0x59, 0x56, 0x59, 0x58, 0x57, 0x58, 0x56, 0x58, 0x5c, - 0x57, 0x59, 0x5c, 0x57, 0x55, 0x59, 0x52, 0x5c, 0x56, 0x4c, 0x5b, 0x57, - 0x51, 0x54, 0x5d, 0x57, 0x58, 0x54, 0x59, 0x4a, 0x5d, 0x5a, 0x5a, 0x5a, - 0x57, 0x57, 0x58, 0x56, 0x55, 0x59, 0x55, 0x58, 0x57, 0x58, 0x58, 0x58, - 0x58, 0x56, 0x5a, 0x5e, 0x58, 0x59, 0x5d, 0x57, 0x56, 0x59, 0x51, 0x5b, - 0x58, 0x4d, 0x5b, 0x57, 0x52, 0x54, 0x5e, 0x58, 0x58, 0x53, 0x5a, 0x4d, - 0x5d, 0x59, 0x59, 0x5a, 0x57, 0x57, 0x56, 0x56, 0x56, 0x5a, 0x56, 0x58, - 0x58, 0x59, 0x58, 0x58, 0x55, 0x55, 0x5a, 0x5b, 0x57, 0x58, 0x5c, 0x58, - 0x56, 0x59, 0x51, 0x5b, 0x56, 0x4f, 0x5b, 0x57, 0x51, 0x55, 0x5d, 0x57, - 0x58, 0x54, 0x58, 0x4d, 0x5c, 0x5a, 0x5a, 0x5b, 0x57, 0x55, 0x56, 0x58, - 0x56, 0x59, 0x56, 0x58, 0x57, 0x59, 0x58, 0x58, 0x57, 0x53, 0x5b, 0x5a, - 0x58, 0x59, 0x5c, 0x57, 0x55, 0x59, 0x52, 0x5a, 0x57, 0x4f, 0x5b, 0x56, - 0x52, 0x55, 0x5d, 0x57, 0x59, 0x53, 0x58, 0x4d, 0x5c, 0x5a, 0x5a, 0x59, - 0x58, 0x58, 0x55, 0x56, 0x56, 0x59, 0x55, 0x59, 0x57, 0x59, 0x56, 0x58, - 0x57, 0x58, 0x5a, 0x5b, 0x58, 0x58, 0x5b, 0x55, 0x56, 0x5b, 0x51, 0x5c, - 0x58, 0x4e, 0x5d, 0x57, 0x51, 0x54, 0x5b, 0x56, 0x59, 0x55, 0x57, 0x4e, - 0x5d, 0x59, 0x5a, 0x59, 0x58, 0x57, 0x53, 0x56, 0x55, 0x59, 0x57, 0x5a, - 0x58, 0x5a, 0x56, 0x58, 0x57, 0x55, 0x5b, 0x59, 0x58, 0x59, 0x5a, 0x54, - 0x55, 0x59, 0x52, 0x5b, 0x57, 0x4e, 0x59, 0x55, 0x51, 0x54, 0x5c, 0x57, - 0x58, 0x53, 0x55, 0x54, 0x5d, 0x59, 0x5b, 0x5b, 0x58, 0x57, 0x54, 0x59, - 0x57, 0x58, 0x56, 0x59, 0x57, 0x59, 0x55, 0x58, 0x58, 0x55, 0x5d, 0x57, - 0x57, 0x59, 0x59, 0x53, 0x55, 0x5a, 0x51, 0x5b, 0x55, 0x4f, 0x5c, 0x55, - 0x51, 0x55, 0x5d, 0x56, 0x5a, 0x54, 0x53, 0x4c, 0x5c, 0x58, 0x5a, 0x5a, - 0x59, 0x57, 0x52, 0x57, 0x55, 0x59, 0x56, 0x59, 0x58, 0x5a, 0x55, 0x58, - 0x58, 0x5a, 0x58, 0x5a, 0x53, 0x59, 0x5f, 0x62, 0x54, 0x5a, 0x51, 0x5e, - 0x55, 0x5e, 0x55, 0x58, 0x51, 0x55, 0x5a, 0x59, 0x55, 0x59, 0x5c, 0x58, - 0x5b, 0x5f, 0x53, 0x5c, 0x54, 0x59, 0x63, 0x5f, 0x59, 0x5f, 0x56, 0x5c, - 0x59, 0x56, 0x5d, 0x5b, 0x58, 0x54, 0x5c, 0x57, 0x57, 0x5a, 0x59, 0x53, - 0x55, 0x59, 0x51, 0x59, 0x59, 0x53, 0x5c, 0x57, 0x51, 0x54, 0x5c, 0x57, - 0x5a, 0x53, 0x51, 0x50, 0x5c, 0x59, 0x5a, 0x59, 0x59, 0x58, 0x52, 0x59, - 0x54, 0x59, 0x55, 0x59, 0x57, 0x5a, 0x53, 0x58, 0x57, 0x56, 0x5e, 0x56, - 0x57, 0x5a, 0x57, 0x51, 0x54, 0x57, 0x50, 0x5a, 0x59, 0x50, 0x5d, 0x56, - 0x51, 0x54, 0x5c, 0x57, 0x5b, 0x54, 0x51, 0x52, 0x5d, 0x59, 0x5b, 0x5a, - 0x5b, 0x59, 0x53, 0x5a, 0x56, 0x59, 0x57, 0x5a, 0x57, 0x5b, 0x4f, 0x58, - 0x58, 0x55, 0x5e, 0x56, 0x58, 0x5a, 0x56, 0x50, 0x55, 0x5a, 0x52, 0x5b, - 0x59, 0x50, 0x5b, 0x55, 0x52, 0x54, 0x5d, 0x58, 0x5b, 0x54, 0x50, 0x50, - 0x5e, 0x57, 0x5b, 0x5b, 0x59, 0x59, 0x52, 0x59, 0x55, 0x59, 0x58, 0x5b, - 0x57, 0x5b, 0x50, 0x58, 0x59, 0x54, 0x5f, 0x55, 0x5a, 0x5a, 0x56, 0x4f, - 0x55, 0x59, 0x51, 0x59, 0x5d, 0x4f, 0x5f, 0x55, 0x52, 0x54, 0x59, 0x57, - 0x5c, 0x57, 0x4f, 0x53, 0x5a, 0x56, 0x5b, 0x57, 0x5b, 0x5a, 0x51, 0x59, - 0x55, 0x58, 0x57, 0x5c, 0x58, 0x5c, 0x50, 0x59, 0x58, 0x55, 0x5f, 0x53, - 0x5b, 0x5c, 0x56, 0x54, 0x56, 0x5a, 0x52, 0x5a, 0x5b, 0x52, 0x5b, 0x58, - 0x51, 0x55, 0x5b, 0x57, 0x5d, 0x55, 0x4f, 0x50, 0x5c, 0x56, 0x5b, 0x5a, - 0x5e, 0x5a, 0x4f, 0x5a, 0x54, 0x58, 0x57, 0x5c, 0x58, 0x5c, 0x4f, 0x59, - 0x57, 0x51, 0x61, 0x53, 0x5c, 0x5c, 0x53, 0x51, 0x56, 0x59, 0x51, 0x57, - 0x59, 0x53, 0x5c, 0x55, 0x50, 0x55, 0x59, 0x57, 0x5d, 0x56, 0x4c, 0x54, - 0x5a, 0x55, 0x5a, 0x58, 0x5f, 0x5a, 0x52, 0x5a, 0x55, 0x58, 0x56, 0x5d, - 0x57, 0x5c, 0x50, 0x5a, 0x58, 0x54, 0x60, 0x52, 0x5f, 0x5c, 0x52, 0x51, - 0x56, 0x59, 0x50, 0x58, 0x59, 0x4f, 0x5e, 0x55, 0x51, 0x55, 0x5d, 0x57, - 0x5d, 0x55, 0x49, 0x51, 0x5a, 0x55, 0x5a, 0x58, 0x5e, 0x5d, 0x4f, 0x58, - 0x54, 0x57, 0x57, 0x5c, 0x58, 0x5b, 0x4f, 0x5a, 0x58, 0x4f, 0x62, 0x4e, - 0x5d, 0x5f, 0x52, 0x50, 0x56, 0x5b, 0x52, 0x58, 0x59, 0x53, 0x5d, 0x55, - 0x50, 0x53, 0x5a, 0x57, 0x5c, 0x56, 0x44, 0x4f, 0x59, 0x55, 0x5a, 0x5a, - 0x62, 0x63, 0x50, 0x5a, 0x54, 0x58, 0x56, 0x5e, 0x59, 0x59, 0x50, 0x5b, - 0x55, 0x4e, 0x60, 0x4d, 0x59, 0x67, 0x50, 0x52, 0x56, 0x58, 0x50, 0x5a, - 0x5a, 0x55, 0x5a, 0x54, 0x51, 0x54, 0x58, 0x56, 0x5a, 0x56, 0x4a, 0x53, - 0x58, 0x58, 0x55, 0x5d, 0x62, 0x6a, 0x4a, 0x5c, 0x51, 0x5b, 0x55, 0x5c, - 0x59, 0x56, 0x50, 0x5a, 0x53, 0x52, 0x5f, 0x4c, 0x57, 0x67, 0x50, 0x55, - 0x55, 0x57, 0x51, 0x5d, 0x5a, 0x56, 0x56, 0x56, 0x52, 0x55, 0x56, 0x57, - 0x59, 0x55, 0x54, 0x57, 0x54, 0x5e, 0x51, 0x5e, 0x61, 0x6b, 0x52, 0x60, - 0x50, 0x60, 0x54, 0x5d, 0x59, 0x54, 0x51, 0x59, 0x55, 0x5e, 0x53, 0x5e, - 0x58, 0x58, 0x5e, 0x61, 0x54, 0x5d, 0x51, 0x57, 0x56, 0x58, 0x5a, 0x58, - 0x51, 0x55, 0x5b, 0x56, 0x56, 0x5a, 0x5f, 0x55, 0x5d, 0x5e, 0x59, 0x5a, - 0x55, 0x55, 0x5f, 0x5f, 0x5b, 0x5c, 0x56, 0x58, 0x59, 0x57, 0x58, 0x58, - 0x4c, 0x55, 0x5e, 0x51, 0x58, 0x63, 0x50, 0x58, 0x50, 0x5f, 0x51, 0x5d, - 0x5c, 0x58, 0x5a, 0x53, 0x52, 0x55, 0x5b, 0x57, 0x57, 0x58, 0x56, 0x58, - 0x4f, 0x59, 0x53, 0x60, 0x5e, 0x62, 0x55, 0x58, 0x51, 0x5f, 0x53, 0x58, - 0x55, 0x55, 0x52, 0x5b, 0x5a, 0x5c, 0x5b, 0x60, 0x57, 0x59, 0x53, 0x5e, - 0x58, 0x5a, 0x50, 0x59, 0x54, 0x5e, 0x57, 0x57, 0x51, 0x54, 0x59, 0x56, - 0x56, 0x5b, 0x5c, 0x55, 0x60, 0x5c, 0x61, 0x5a, 0x58, 0x55, 0x67, 0x5a, - 0x57, 0x5b, 0x59, 0x54, 0x58, 0x55, 0x5d, 0x53, 0x57, 0x5b, 0x55, 0x60, - 0x5a, 0x58, 0x5e, 0x60, 0x56, 0x5d, 0x51, 0x56, 0x58, 0x56, 0x5b, 0x59, - 0x52, 0x54, 0x58, 0x57, 0x57, 0x5a, 0x60, 0x4d, 0x59, 0x5e, 0x5b, 0x5a, - 0x55, 0x57, 0x61, 0x5d, 0x5a, 0x5e, 0x56, 0x56, 0x5a, 0x56, 0x5b, 0x57, - 0x58, 0x57, 0x57, 0x61, 0x54, 0x55, 0x5d, 0x5e, 0x56, 0x5b, 0x51, 0x5b, - 0x56, 0x5a, 0x5c, 0x58, 0x52, 0x54, 0x56, 0x57, 0x57, 0x5a, 0x5d, 0x51, - 0x5a, 0x5d, 0x5c, 0x5b, 0x58, 0x56, 0x68, 0x5a, 0x58, 0x5d, 0x57, 0x55, - 0x5c, 0x57, 0x5e, 0x57, 0x58, 0x57, 0x55, 0x60, 0x56, 0x59, 0x5e, 0x5e, - 0x56, 0x5b, 0x51, 0x59, 0x57, 0x54, 0x5c, 0x58, 0x52, 0x53, 0x5a, 0x56, - 0x59, 0x56, 0x5f, 0x47, 0x5b, 0x5d, 0x5b, 0x5b, 0x55, 0x58, 0x61, 0x5b, - 0x59, 0x5c, 0x56, 0x57, 0x5a, 0x56, 0x5c, 0x57, 0x58, 0x56, 0x57, 0x5e, - 0x58, 0x58, 0x5d, 0x5d, 0x56, 0x5a, 0x51, 0x5a, 0x57, 0x4d, 0x5d, 0x57, - 0x51, 0x54, 0x5b, 0x57, 0x59, 0x56, 0x5e, 0x48, 0x5b, 0x5b, 0x59, 0x5b, - 0x56, 0x57, 0x5d, 0x58, 0x57, 0x5b, 0x57, 0x58, 0x59, 0x58, 0x5c, 0x58, - 0x58, 0x56, 0x56, 0x5e, 0x57, 0x57, 0x5e, 0x5c, 0x56, 0x5c, 0x51, 0x5b, - 0x57, 0x4f, 0x5d, 0x58, 0x52, 0x55, 0x5c, 0x56, 0x59, 0x54, 0x5d, 0x4f, - 0x5a, 0x5b, 0x59, 0x5b, 0x56, 0x57, 0x5b, 0x58, 0x56, 0x5b, 0x56, 0x57, - 0x59, 0x59, 0x59, 0x58, 0x66, 0x44, 0x54, 0x5f, 0x3c, 0x56, 0x31, 0x3e, - 0x53, 0x56, 0x49, 0x62, 0x60, 0x3c, 0x4c, 0x65, 0x51, 0x48, 0x55, 0x7b, - 0x6d, 0x4d, 0x39, 0x54, 0x3c, 0x43, 0x31, 0x47, 0x4e, 0x7f, 0x2a, 0x3c, - 0x81, 0x52, 0x5f, 0x89, 0x54, 0x9c, 0x44, 0x64, 0x48, 0x45, 0x56, 0x52, - 0x5a, 0x5e, 0x5c, 0x53, 0x66, 0x2b, 0x50, 0x56, 0x57, 0x56, 0x53, 0x33, - 0x56, 0x86, 0x5d, 0x39, 0x4e, 0x60, 0x4a, 0x5d, 0x21, 0x61, 0x73, 0x5b, - 0x56, 0x52, 0x59, 0x68, 0x2f, 0x61, 0x53, 0x66, 0x53, 0x6e, 0x5f, 0x59, - 0x57, 0x5e, 0x56, 0x57, 0x59, 0x56, 0x5e, 0x5c, 0x3e, 0x60, 0x50, 0x5c, - 0x55, 0x53, 0x64, 0x5c, 0x4f, 0x46, 0x60, 0x5a, 0x5f, 0x59, 0x5d, 0x4f, - 0x5e, 0x5e, 0x54, 0x65, 0x58, 0x5f, 0x62, 0x58, 0x53, 0x5b, 0x55, 0x4f, - 0x59, 0x40, 0x48, 0x5d, 0x60, 0x5f, 0x55, 0x5a, 0x5a, 0x55, 0x5e, 0x60, - 0x3e, 0x5a, 0x4f, 0x5e, 0x56, 0x52, 0x69, 0x5b, 0x4e, 0x44, 0x63, 0x5f, - 0x60, 0x58, 0x5e, 0x4d, 0x5c, 0x5c, 0x57, 0x62, 0x59, 0x5d, 0x64, 0x56, - 0x56, 0x5c, 0x50, 0x54, 0x58, 0x3f, 0x4b, 0x5d, 0x5b, 0x5f, 0x50, 0x55, - 0x59, 0x56, 0x5e, 0x61, 0x45, 0x5c, 0x50, 0x5c, 0x54, 0x51, 0x65, 0x5b, - 0x4f, 0x51, 0x63, 0x5d, 0x5f, 0x58, 0x5e, 0x4b, 0x5d, 0x5d, 0x52, 0x60, - 0x59, 0x5a, 0x63, 0x57, 0x56, 0x5f, 0x53, 0x58, 0x59, 0x3f, 0x4b, 0x5a, - 0x5d, 0x62, 0x48, 0x57, 0x57, 0x54, 0x62, 0x65, 0x43, 0x5f, 0x50, 0x62, - 0x56, 0x50, 0x64, 0x5b, 0x4f, 0x52, 0x66, 0x5f, 0x63, 0x53, 0x5f, 0x4b, - 0x5e, 0x5d, 0x59, 0x5f, 0x5a, 0x5b, 0x64, 0x50, 0x57, 0x5a, 0x53, 0x4d, - 0x58, 0x30, 0x4b, 0x61, 0x59, 0x60, 0x49, 0x59, 0x54, 0x52, 0x66, 0x65, - 0x4d, 0x58, 0x51, 0x64, 0x54, 0x4e, 0x64, 0x5a, 0x53, 0x4a, 0x61, 0x5f, - 0x60, 0x4d, 0x62, 0x4a, 0x5d, 0x5f, 0x56, 0x5f, 0x5a, 0x54, 0x65, 0x4f, - 0x59, 0x55, 0x56, 0x53, 0x59, 0x2c, 0x4d, 0x63, 0x59, 0x63, 0x45, 0x57, - 0x4c, 0x57, 0x67, 0x67, 0x54, 0x5a, 0x51, 0x63, 0x51, 0x43, 0x59, 0x59, - 0x53, 0x48, 0x64, 0x5c, 0x63, 0x4b, 0x5e, 0x4c, 0x64, 0x5d, 0x52, 0x64, - 0x5a, 0x51, 0x61, 0x4d, 0x5c, 0x4b, 0x59, 0x53, 0x5a, 0x28, 0x50, 0x65, - 0x5a, 0x63, 0x58, 0x56, 0x55, 0x59, 0x5b, 0x5b, 0x53, 0x5b, 0x53, 0x61, - 0x52, 0x4c, 0x54, 0x61, 0x55, 0x55, 0x6a, 0x62, 0x69, 0x4d, 0x6d, 0x4a, - 0x63, 0x5d, 0x5a, 0x56, 0x64, 0x55, 0x5a, 0x5d, 0x66, 0x49, 0x5a, 0x57, - 0x5d, 0x47, 0x58, 0x55, 0x59, 0x4e, 0x51, 0x51, 0x54, 0x59, 0x51, 0x57, - 0x4e, 0x4f, 0x52, 0x56, 0x4b, 0x41, 0x45, 0x5e, 0x55, 0x53, 0x5e, 0x68, - 0x54, 0x45, 0x57, 0x4b, 0x55, 0x56, 0x56, 0x69, 0x66, 0x54, 0x4e, 0x5f, - 0x64, 0x52, 0x56, 0x5c, 0x57, 0x3d, 0x5d, 0x63, 0x59, 0x57, 0x57, 0x57, - 0x61, 0x5d, 0x60, 0x59, 0x4f, 0x52, 0x4c, 0x56, 0x46, 0x47, 0x57, 0x56, - 0x56, 0x68, 0x5a, 0x55, 0x5a, 0x34, 0x58, 0x4a, 0x5c, 0x6a, 0x5b, 0x65, - 0x5f, 0x54, 0x59, 0x58, 0x59, 0x61, 0x59, 0x58, 0x61, 0x53, 0x57, 0x6b, - 0x5a, 0x57, 0x58, 0x5b, 0x5a, 0x59, 0x5a, 0x5b, 0x58, 0x59, 0x51, 0x5a, - 0x60, 0x5a, 0x59, 0x59, 0x54, 0x5b, 0x5a, 0x5a, 0x57, 0x56, 0x57, 0x55, - 0x5a, 0x5e, 0x5a, 0x58, 0x5c, 0x58, 0x59, 0x5b, 0x59, 0x59, 0x5b, 0x58, - 0x59, 0x5b, 0x59, 0x5a, 0x51, 0x4d, 0x65, 0x56, 0x5b, 0x5f, 0x5a, 0x59, - 0x5f, 0x75, 0x5f, 0x5e, 0x5a, 0x55, 0x54, 0x2d, 0x49, 0x49, 0x46, 0x43, - 0x52, 0x5e, 0x4e, 0x58, 0x64, 0x5c, 0x49, 0x48, 0x52, 0x53, 0x5a, 0x67, - 0x38, 0x5e, 0x54, 0x5c, 0x59, 0x68, 0x5a, 0x53, 0x5a, 0x59, 0x58, 0x57, - 0x59, 0x5f, 0x5b, 0x5a, 0x56, 0x5b, 0x50, 0x58, 0x56, 0x59, 0x5b, 0x5f, - 0x52, 0x57, 0x58, 0x5a, 0x5b, 0x55, 0x58, 0x6a, 0x5b, 0x5f, 0x59, 0x5e, - 0x5d, 0x57, 0x59, 0x58, 0x5a, 0x5a, 0x59, 0x59, 0x68, 0x56, 0x59, 0x53, - 0x50, 0x51, 0x66, 0x56, 0x5a, 0x62, 0x5a, 0x59, 0x59, 0x47, 0x40, 0x56, - 0x5b, 0x55, 0x58, 0x65, 0x5c, 0x5d, 0x53, 0x47, 0x53, 0x5d, 0x52, 0x55, - 0x66, 0x5e, 0x4c, 0x5a, 0x50, 0x55, 0x59, 0x62, 0x47, 0x5a, 0x54, 0x48, - 0x57, 0x62, 0x57, 0x52, 0x52, 0x54, 0x65, 0x59, 0x59, 0x62, 0x5a, 0x59, - 0x51, 0x56, 0x5a, 0x57, 0x58, 0x55, 0x5c, 0x5c, 0x49, 0x4c, 0x5c, 0x49, - 0x55, 0x5d, 0x54, 0x53, 0x60, 0x5e, 0x53, 0x57, 0x51, 0x56, 0x58, 0x61, - 0x4a, 0x5a, 0x54, 0x4e, 0x55, 0x5b, 0x53, 0x51, 0x55, 0x56, 0x62, 0x5b, - 0x59, 0x62, 0x58, 0x58, 0x4b, 0x5e, 0x55, 0x55, 0x57, 0x55, 0x5f, 0x54, - 0x52, 0x48, 0x5c, 0x4b, 0x56, 0x5c, 0x56, 0x52, 0x64, 0x5e, 0x54, 0x58, - 0x52, 0x54, 0x58, 0x5a, 0x4b, 0x59, 0x56, 0x4d, 0x56, 0x55, 0x50, 0x51, - 0x57, 0x57, 0x63, 0x5d, 0x58, 0x5f, 0x59, 0x5a, 0x43, 0x67, 0x53, 0x57, - 0x59, 0x56, 0x5e, 0x57, 0x52, 0x4b, 0x5a, 0x47, 0x57, 0x5d, 0x57, 0x52, - 0x67, 0x5d, 0x54, 0x6a, 0x53, 0x5d, 0x5a, 0x5d, 0x4d, 0x54, 0x56, 0x4d, - 0x52, 0x51, 0x4f, 0x56, 0x57, 0x5a, 0x61, 0x5d, 0x59, 0x5d, 0x5a, 0x59, - 0x3a, 0x66, 0x52, 0x58, 0x57, 0x54, 0x60, 0x58, 0x51, 0x49, 0x5b, 0x4a, - 0x5a, 0x5a, 0x58, 0x52, 0x63, 0x5f, 0x55, 0x6c, 0x55, 0x5e, 0x5b, 0x62, - 0x4e, 0x52, 0x55, 0x4c, 0x53, 0x49, 0x4d, 0x58, 0x55, 0x5c, 0x5d, 0x5b, - 0x59, 0x5a, 0x5b, 0x5d, 0x3a, 0x64, 0x50, 0x5b, 0x55, 0x54, 0x60, 0x5a, - 0x4d, 0x48, 0x61, 0x4d, 0x5b, 0x5b, 0x59, 0x51, 0x61, 0x5f, 0x57, 0x67, - 0x56, 0x5d, 0x5e, 0x57, 0x50, 0x57, 0x56, 0x4d, 0x55, 0x49, 0x49, 0x5a, - 0x58, 0x5e, 0x5a, 0x59, 0x5a, 0x57, 0x5b, 0x5a, 0x3e, 0x61, 0x51, 0x5c, - 0x54, 0x53, 0x65, 0x57, 0x4f, 0x47, 0x64, 0x55, 0x5e, 0x5a, 0x5a, 0x4f, - 0x5c, 0x60, 0x57, 0x65, 0x58, 0x5e, 0x60, 0x56, 0x51, 0x5a, 0x53, 0x54, - 0x56, 0x45, 0x4b, 0x5b, 0x5a, 0x5d, 0x2d, 0x52, 0x5d, 0x62, 0x62, 0x39, - 0x4d, 0x5f, 0x4f, 0x55, 0x5c, 0x61, 0x59, 0x5c, 0x4f, 0x56, 0x5c, 0x55, - 0x59, 0x5a, 0x55, 0x6b, 0x5c, 0x58, 0x38, 0x59, 0x6c, 0x5a, 0x5f, 0x54, - 0x55, 0x55, 0x57, 0x5a, 0x58, 0x5b, 0x50, 0x54, 0x57, 0x51, 0x5f, 0x55, - 0x4b, 0x62, 0x59, 0x60, 0x52, 0x54, 0x4e, 0x5c, 0x59, 0x53, 0x6b, 0x54, - 0x4f, 0x58, 0x60, 0x5a, 0x5b, 0x5d, 0x56, 0x5c, 0x5a, 0x58, 0x55, 0x59, - 0x55, 0x54, 0x61, 0x59, 0x52, 0x5a, 0x56, 0x60, 0x59, 0x64, 0x4f, 0x58, - 0x57, 0x56, 0x5c, 0x59, 0x59, 0x58, 0x5b, 0x5c, 0x56, 0x5a, 0x4f, 0x5b, - 0x55, 0x55, 0x56, 0x56, 0x4f, 0x51, 0x5b, 0x57, 0x59, 0x55, 0x5a, 0x4c, - 0x5c, 0x5e, 0x59, 0x5c, 0x59, 0x58, 0x5b, 0x5c, 0x54, 0x5d, 0x56, 0x58, - 0x5a, 0x56, 0x5a, 0x57, 0x57, 0x57, 0x5d, 0x5a, 0x58, 0x57, 0x5b, 0x5b, - 0x55, 0x5b, 0x50, 0x5b, 0x58, 0x56, 0x57, 0x56, 0x4f, 0x52, 0x5b, 0x58, - 0x5a, 0x54, 0x5b, 0x49, 0x5c, 0x5e, 0x5a, 0x5c, 0x59, 0x57, 0x5a, 0x5c, - 0x56, 0x5d, 0x56, 0x58, 0x5a, 0x57, 0x5a, 0x58, 0x58, 0x56, 0x5d, 0x5a, - 0x58, 0x57, 0x5a, 0x5a, 0x55, 0x59, 0x4f, 0x5b, 0x56, 0x53, 0x57, 0x56, - 0x50, 0x52, 0x5c, 0x59, 0x5a, 0x54, 0x5b, 0x48, 0x5b, 0x5d, 0x5a, 0x5c, - 0x58, 0x57, 0x5a, 0x5d, 0x56, 0x5d, 0x56, 0x58, 0x5b, 0x57, 0x5a, 0x59, - 0x58, 0x55, 0x5d, 0x5c, 0x58, 0x56, 0x5a, 0x59, 0x55, 0x5a, 0x4f, 0x5b, - 0x58, 0x53, 0x57, 0x56, 0x50, 0x52, 0x5e, 0x58, 0x5a, 0x53, 0x5b, 0x47, - 0x5c, 0x5d, 0x5b, 0x5d, 0x58, 0x58, 0x59, 0x5c, 0x56, 0x5d, 0x56, 0x59, - 0x5a, 0x57, 0x5a, 0x59, 0x57, 0x52, 0x5d, 0x5c, 0x58, 0x55, 0x59, 0x58, - 0x56, 0x5a, 0x50, 0x5b, 0x56, 0x51, 0x58, 0x57, 0x4f, 0x54, 0x5f, 0x58, - 0x5a, 0x53, 0x5b, 0x49, 0x5b, 0x5d, 0x5c, 0x5d, 0x57, 0x57, 0x58, 0x5c, - 0x57, 0x5d, 0x56, 0x5a, 0x5a, 0x58, 0x59, 0x5a, 0x56, 0x53, 0x5e, 0x5e, - 0x59, 0x54, 0x58, 0x57, 0x57, 0x5c, 0x4f, 0x5a, 0x58, 0x4a, 0x5a, 0x57, - 0x4f, 0x54, 0x5e, 0x58, 0x5a, 0x53, 0x5a, 0x4b, 0x5a, 0x5d, 0x5c, 0x5c, - 0x56, 0x59, 0x55, 0x5d, 0x57, 0x5e, 0x55, 0x5a, 0x5a, 0x59, 0x59, 0x5c, - 0x57, 0x52, 0x5e, 0x5f, 0x59, 0x54, 0x57, 0x54, 0x57, 0x5b, 0x4f, 0x5c, - 0x59, 0x4d, 0x5c, 0x57, 0x50, 0x54, 0x60, 0x59, 0x5a, 0x54, 0x56, 0x4b, - 0x5a, 0x5c, 0x5d, 0x5c, 0x56, 0x5a, 0x52, 0x5c, 0x57, 0x5d, 0x55, 0x5a, - 0x59, 0x58, 0x56, 0x5d, 0x55, 0x53, 0x5f, 0x60, 0x5b, 0x54, 0x56, 0x54, - 0x57, 0x5c, 0x50, 0x5c, 0x59, 0x4a, 0x60, 0x56, 0x50, 0x55, 0x5f, 0x59, - 0x59, 0x53, 0x52, 0x4e, 0x58, 0x5b, 0x5e, 0x5d, 0x54, 0x5b, 0x51, 0x5c, - 0x58, 0x5d, 0x56, 0x5c, 0x58, 0x58, 0x56, 0x5e, 0x54, 0x53, 0x60, 0x61, - 0x5b, 0x53, 0x55, 0x54, 0x57, 0x5a, 0x4f, 0x5d, 0x59, 0x48, 0x66, 0x57, - 0x4f, 0x55, 0x5f, 0x5a, 0x58, 0x55, 0x4c, 0x4b, 0x58, 0x59, 0x5d, 0x5d, - 0x51, 0x5e, 0x4d, 0x5b, 0x59, 0x5d, 0x55, 0x5d, 0x57, 0x58, 0x52, 0x61, - 0x53, 0x50, 0x61, 0x62, 0x58, 0x58, 0x53, 0x52, 0x57, 0x5c, 0x4f, 0x5e, - 0x57, 0x4d, 0x65, 0x56, 0x50, 0x55, 0x60, 0x5b, 0x57, 0x54, 0x41, 0x4e, - 0x55, 0x59, 0x5e, 0x5d, 0x4e, 0x60, 0x46, 0x5c, 0x57, 0x5e, 0x54, 0x60, - 0x56, 0x59, 0x53, 0x61, 0x59, 0x54, 0x5c, 0x55, 0x58, 0x65, 0x5d, 0x5a, - 0x53, 0x55, 0x4f, 0x61, 0x57, 0x5b, 0x61, 0x55, 0x4e, 0x58, 0x5d, 0x56, - 0x5b, 0x5d, 0x57, 0x60, 0x5c, 0x5a, 0x56, 0x5b, 0x57, 0x60, 0x60, 0x55, - 0x54, 0x5a, 0x57, 0x5b, 0x58, 0x5f, 0x52, 0x50, 0x51, 0x4d, 0x61, 0x60, - 0x51, 0x5e, 0x51, 0x4f, 0x57, 0x5e, 0x50, 0x61, 0x56, 0x53, 0x66, 0x55, - 0x4f, 0x57, 0x60, 0x5b, 0x55, 0x55, 0x47, 0x56, 0x55, 0x59, 0x5c, 0x5e, - 0x49, 0x62, 0x45, 0x5b, 0x57, 0x5d, 0x54, 0x62, 0x55, 0x5b, 0x55, 0x62, - 0x57, 0x58, 0x5c, 0x4f, 0x59, 0x65, 0x5b, 0x5b, 0x53, 0x56, 0x4f, 0x5c, - 0x56, 0x5d, 0x5d, 0x55, 0x4f, 0x57, 0x5a, 0x56, 0x5a, 0x5d, 0x5b, 0x5e, - 0x5d, 0x5a, 0x58, 0x5a, 0x57, 0x5e, 0x60, 0x58, 0x53, 0x59, 0x56, 0x59, - 0x57, 0x5c, 0x55, 0x4f, 0x59, 0x59, 0x5b, 0x4f, 0x5b, 0x60, 0x5c, 0x5d, - 0x54, 0x58, 0x4f, 0x5c, 0x56, 0x5a, 0x58, 0x56, 0x50, 0x53, 0x58, 0x56, - 0x58, 0x5a, 0x5b, 0x4d, 0x5e, 0x5c, 0x58, 0x5b, 0x59, 0x59, 0x5f, 0x58, - 0x54, 0x5a, 0x56, 0x58, 0x58, 0x59, 0x57, 0x50, 0x57, 0x59, 0x5b, 0x4f, - 0x59, 0x5c, 0x5c, 0x5e, 0x54, 0x59, 0x4f, 0x5c, 0x56, 0x58, 0x56, 0x56, - 0x4f, 0x52, 0x58, 0x57, 0x59, 0x57, 0x5b, 0x4e, 0x5e, 0x5c, 0x58, 0x5a, - 0x59, 0x59, 0x5d, 0x59, 0x55, 0x5b, 0x57, 0x57, 0x58, 0x58, 0x58, 0x51, - 0x58, 0x59, 0x5b, 0x51, 0x5a, 0x5a, 0x5c, 0x5e, 0x55, 0x5a, 0x4f, 0x5c, - 0x56, 0x57, 0x56, 0x56, 0x50, 0x52, 0x59, 0x57, 0x59, 0x56, 0x5b, 0x4a, - 0x5f, 0x5d, 0x59, 0x5c, 0x59, 0x58, 0x5e, 0x59, 0x54, 0x5b, 0x56, 0x57, - 0x5a, 0x58, 0x58, 0x52, 0x59, 0x59, 0x5c, 0x53, 0x58, 0x5a, 0x5c, 0x5e, - 0x55, 0x59, 0x4f, 0x5c, 0x55, 0x56, 0x56, 0x56, 0x4f, 0x51, 0x5a, 0x57, - 0x59, 0x56, 0x5b, 0x4b, 0x5e, 0x5d, 0x59, 0x5b, 0x5a, 0x57, 0x5c, 0x5a, - 0x55, 0x5c, 0x56, 0x57, 0x59, 0x58, 0x59, 0x54, 0x58, 0x58, 0x5c, 0x55, - 0x58, 0x58, 0x5c, 0x5d, 0x55, 0x5a, 0x4f, 0x5b, 0x57, 0x56, 0x55, 0x56, - 0x50, 0x51, 0x5a, 0x57, 0x59, 0x55, 0x5b, 0x4b, 0x5d, 0x5d, 0x58, 0x5c, - 0x59, 0x58, 0x5c, 0x5b, 0x55, 0x5d, 0x56, 0x58, 0x59, 0x57, 0x5a, 0x54, - 0x58, 0x58, 0x5c, 0x58, 0x59, 0x57, 0x5b, 0x5c, 0x55, 0x59, 0x50, 0x5b, - 0x56, 0x56, 0x56, 0x57, 0x50, 0x50, 0x5b, 0x57, 0x5a, 0x55, 0x5b, 0x4b, - 0x5e, 0x5e, 0x59, 0x5c, 0x59, 0x58, 0x5c, 0x5c, 0x55, 0x5d, 0x56, 0x57, - 0x5a, 0x56, 0x59, 0x56, 0x58, 0x61, 0x5b, 0x4f, 0x63, 0x67, 0x57, 0x54, - 0x69, 0x5a, 0x4e, 0x5d, 0x5a, 0x45, 0x4d, 0x5a, 0x4f, 0x50, 0x42, 0x54, - 0x59, 0x56, 0x66, 0x59, 0x5c, 0x5a, 0x5e, 0x57, 0x56, 0x56, 0x3b, 0x52, - 0x5c, 0x58, 0x56, 0x54, 0x57, 0x4b, 0x58, 0x55, 0x58, 0x69, 0x56, 0x56, - 0x57, 0x62, 0x5b, 0x59, 0x63, 0x5d, 0x4e, 0x59, 0x59, 0x6f, 0x55, 0x59, - 0x4f, 0x52, 0x4f, 0x55, 0x59, 0x56, 0x60, 0x56, 0x5d, 0x5b, 0x5e, 0x59, - 0x47, 0x53, 0x4c, 0x55, 0x5a, 0x59, 0x56, 0x55, 0x56, 0x50, 0x5b, 0x53, - 0x57, 0x51, 0x58, 0x59, 0x57, 0x59, 0x58, 0x5a, 0x49, 0x59, 0x4e, 0x5c, - 0x58, 0x55, 0x56, 0x56, 0x4f, 0x55, 0x6a, 0x57, 0x5b, 0x56, 0x4d, 0x4e, - 0x5b, 0x5b, 0x58, 0x5a, 0x56, 0x5a, 0x5b, 0x59, 0x53, 0x5d, 0x55, 0x5a, - 0x59, 0x5a, 0x59, 0x59, 0x58, 0x51, 0x59, 0x58, 0x58, 0x59, 0x59, 0x58, - 0x49, 0x5a, 0x4e, 0x5c, 0x56, 0x52, 0x5a, 0x56, 0x50, 0x53, 0x67, 0x58, - 0x5c, 0x57, 0x4f, 0x4e, 0x5b, 0x5d, 0x56, 0x59, 0x59, 0x5b, 0x5d, 0x5d, - 0x53, 0x5c, 0x55, 0x5a, 0x5a, 0x5d, 0x57, 0x59, 0x57, 0x50, 0x57, 0x5a, - 0x56, 0x57, 0x59, 0x56, 0x4a, 0x58, 0x4e, 0x5c, 0x54, 0x53, 0x5a, 0x55, - 0x4f, 0x54, 0x6a, 0x57, 0x5c, 0x57, 0x4a, 0x4e, 0x5e, 0x5b, 0x55, 0x59, - 0x5a, 0x5a, 0x5f, 0x5e, 0x53, 0x5c, 0x52, 0x5c, 0x5a, 0x5c, 0x58, 0x5a, - 0x57, 0x4f, 0x56, 0x5a, 0x57, 0x56, 0x59, 0x57, 0x4b, 0x59, 0x4f, 0x5c, - 0x58, 0x51, 0x5b, 0x56, 0x4f, 0x55, 0x6e, 0x59, 0x5b, 0x57, 0x4e, 0x4d, - 0x5d, 0x5c, 0x56, 0x5a, 0x5b, 0x5a, 0x5e, 0x5a, 0x51, 0x5e, 0x53, 0x5c, - 0x5a, 0x5e, 0x56, 0x5a, 0x55, 0x50, 0x57, 0x57, 0x58, 0x57, 0x58, 0x56, - 0x49, 0x59, 0x4e, 0x5a, 0x55, 0x52, 0x5c, 0x55, 0x50, 0x53, 0x6e, 0x58, - 0x5a, 0x56, 0x4e, 0x4e, 0x5e, 0x5c, 0x57, 0x57, 0x5c, 0x58, 0x5f, 0x62, - 0x53, 0x5c, 0x53, 0x5b, 0x5a, 0x61, 0x53, 0x5b, 0x54, 0x51, 0x57, 0x58, - 0x58, 0x56, 0x58, 0x55, 0x4a, 0x57, 0x50, 0x5a, 0x59, 0x53, 0x5f, 0x56, - 0x4f, 0x53, 0x69, 0x5a, 0x5b, 0x57, 0x4d, 0x4c, 0x5c, 0x5c, 0x54, 0x59, - 0x64, 0x5c, 0x60, 0x5f, 0x53, 0x5c, 0x52, 0x5c, 0x5b, 0x61, 0x48, 0x5a, - 0x54, 0x51, 0x57, 0x58, 0x58, 0x57, 0x58, 0x58, 0x4a, 0x58, 0x4e, 0x5a, - 0x59, 0x52, 0x5e, 0x57, 0x50, 0x53, 0x65, 0x59, 0x5c, 0x56, 0x4a, 0x4e, - 0x5b, 0x5d, 0x54, 0x57, 0x66, 0x5a, 0x63, 0x61, 0x53, 0x5d, 0x53, 0x5b, - 0x5a, 0x60, 0x44, 0x5a, 0x54, 0x54, 0x57, 0x57, 0x58, 0x55, 0x58, 0x51, - 0x4c, 0x58, 0x4f, 0x59, 0x58, 0x53, 0x5f, 0x54, 0x4f, 0x54, 0x68, 0x5b, - 0x5b, 0x56, 0x4c, 0x4d, 0x5b, 0x5c, 0x54, 0x56, 0x6a, 0x5c, 0x5f, 0x60, - 0x51, 0x5d, 0x51, 0x5b, 0x5b, 0x61, 0x47, 0x5b, 0x53, 0x51, 0x5b, 0x57, - 0x55, 0x58, 0x57, 0x55, 0x4e, 0x56, 0x4e, 0x57, 0x56, 0x51, 0x5c, 0x54, - 0x4f, 0x53, 0x63, 0x5b, 0x59, 0x56, 0x4d, 0x51, 0x5a, 0x5a, 0x54, 0x57, - 0x76, 0x5c, 0x63, 0x61, 0x52, 0x5e, 0x53, 0x59, 0x5c, 0x62, 0x42, 0x5a, - 0x53, 0x4f, 0x57, 0x5b, 0x54, 0x51, 0x57, 0x50, 0x4e, 0x56, 0x4e, 0x59, - 0x58, 0x4f, 0x5d, 0x53, 0x51, 0x54, 0x6b, 0x5b, 0x5a, 0x54, 0x4b, 0x55, - 0x59, 0x5d, 0x54, 0x55, 0x86, 0x5b, 0x61, 0x60, 0x53, 0x5e, 0x51, 0x59, - 0x5a, 0x69, 0x3a, 0x5c, 0x5a, 0x55, 0x5b, 0x5c, 0x60, 0x62, 0x5a, 0x5a, - 0x5a, 0x5c, 0x4e, 0x5b, 0x59, 0x51, 0x5c, 0x56, 0x50, 0x53, 0x54, 0x56, - 0x5a, 0x57, 0x60, 0x55, 0x5b, 0x5a, 0x59, 0x5c, 0x47, 0x59, 0x51, 0x54, - 0x57, 0x59, 0x57, 0x57, 0x56, 0x53, 0x5c, 0x53, 0x59, 0x58, 0x58, 0x5c, - 0x58, 0x55, 0x59, 0x59, 0x5c, 0x59, 0x5b, 0x59, 0x58, 0x58, 0x56, 0x59, - 0x56, 0x5c, 0x55, 0x5a, 0x5c, 0x56, 0x59, 0x5c, 0x58, 0x5a, 0x56, 0x54, - 0x55, 0x5d, 0x5a, 0x59, 0x5a, 0x58, 0x57, 0x56, 0x58, 0x5b, 0x5a, 0x5f, - 0x58, 0x51, 0x5c, 0x5d, 0x4e, 0x5e, 0x5a, 0x5c, 0x4d, 0x5c, 0x4e, 0x5b, - 0x58, 0x51, 0x5e, 0x57, 0x4f, 0x54, 0x57, 0x56, 0x5b, 0x58, 0x61, 0x54, - 0x5b, 0x5a, 0x58, 0x5c, 0x4a, 0x5b, 0x53, 0x55, 0x56, 0x5a, 0x56, 0x57, - 0x57, 0x52, 0x5d, 0x55, 0x59, 0x49, 0x5c, 0x5b, 0x56, 0x5e, 0x5a, 0x5c, - 0x46, 0x5c, 0x4e, 0x5c, 0x57, 0x4e, 0x5b, 0x57, 0x50, 0x54, 0x5b, 0x57, - 0x5a, 0x58, 0x5e, 0x52, 0x5c, 0x5b, 0x59, 0x5c, 0x4a, 0x5c, 0x57, 0x55, - 0x56, 0x5b, 0x56, 0x58, 0x56, 0x53, 0x5d, 0x56, 0x58, 0x4a, 0x5d, 0x56, - 0x59, 0x5b, 0x59, 0x5a, 0x49, 0x5e, 0x4e, 0x5a, 0x58, 0x50, 0x5a, 0x5a, - 0x50, 0x53, 0x5b, 0x55, 0x5b, 0x58, 0x5a, 0x4e, 0x5b, 0x5c, 0x5a, 0x5e, - 0x52, 0x5e, 0x5b, 0x54, 0x54, 0x5b, 0x56, 0x55, 0x57, 0x55, 0x5b, 0x55, - 0x58, 0x4a, 0x5b, 0x59, 0x58, 0x5a, 0x5a, 0x5a, 0x49, 0x5c, 0x4e, 0x5c, - 0x57, 0x53, 0x5a, 0x58, 0x50, 0x55, 0x5c, 0x57, 0x5c, 0x58, 0x57, 0x4d, - 0x5a, 0x5c, 0x58, 0x5d, 0x54, 0x5c, 0x5b, 0x57, 0x55, 0x5c, 0x55, 0x59, - 0x59, 0x57, 0x5c, 0x57, 0x57, 0x4f, 0x5a, 0x59, 0x58, 0x5a, 0x5a, 0x5a, - 0x48, 0x5b, 0x4e, 0x5c, 0x56, 0x53, 0x59, 0x57, 0x4f, 0x54, 0x61, 0x58, - 0x5b, 0x57, 0x53, 0x4e, 0x5b, 0x5c, 0x57, 0x5c, 0x53, 0x5b, 0x5b, 0x58, - 0x54, 0x5d, 0x55, 0x59, 0x57, 0x58, 0x5c, 0x57, 0x58, 0x52, 0x59, 0x5b, - 0x58, 0x58, 0x59, 0x5b, 0x4a, 0x5b, 0x4e, 0x5a, 0x58, 0x51, 0x58, 0x56, - 0x4f, 0x54, 0x65, 0x56, 0x5c, 0x57, 0x53, 0x4d, 0x5c, 0x5d, 0x57, 0x5b, - 0x56, 0x5a, 0x5b, 0x5a, 0x55, 0x5c, 0x55, 0x5a, 0x58, 0x59, 0x5b, 0x58, - 0x57, 0x4f, 0x5b, 0x59, 0x58, 0x58, 0x59, 0x59, 0x49, 0x59, 0x4e, 0x5c, - 0x57, 0x50, 0x57, 0x57, 0x4f, 0x54, 0x67, 0x58, 0x5b, 0x57, 0x4f, 0x4f, - 0x5c, 0x5d, 0x57, 0x5c, 0x55, 0x5b, 0x5b, 0x5a, 0x54, 0x5c, 0x55, 0x59, - 0x59, 0x59, 0x5b, 0x58, 0x42, 0x45, 0x55, 0x61, 0x5b, 0x5d, 0x5f, 0x3d, - 0x9a, 0x61, 0xff, 0x41, 0x58, 0x66, 0x5b, 0x8d, 0xfc, 0x95, 0x37, 0x53, - 0x4c, 0x5d, 0x53, 0x78, 0x50, 0x59, 0x46, 0x75, 0x61, 0x47, 0x48, 0x28, - 0x52, 0x67, 0x59, 0x59, 0x52, 0x83, 0x63, 0x5b, 0x55, 0x56, 0x5a, 0x41, - 0x50, 0x46, 0x45, 0x5e, 0x57, 0x61, 0x52, 0x36, 0x5e, 0x5d, 0x41, 0x5f, - 0x52, 0x5b, 0x50, 0x5c, 0x51, 0x5c, 0x56, 0x5d, 0x4c, 0x59, 0x48, 0x59, - 0x50, 0x42, 0x68, 0x63, 0x57, 0x5a, 0x54, 0x4f, 0x51, 0x4a, 0x5a, 0x5e, - 0x55, 0x58, 0x58, 0x46, 0x56, 0x49, 0x4b, 0x60, 0x55, 0x5e, 0x51, 0x47, - 0x54, 0x58, 0x49, 0x58, 0x52, 0x56, 0x52, 0x5b, 0x52, 0x58, 0x59, 0x43, - 0x51, 0x5d, 0x4c, 0x5a, 0x4c, 0x56, 0x63, 0x5e, 0x59, 0x5b, 0x54, 0x52, - 0x53, 0x4f, 0x59, 0x5b, 0x56, 0x57, 0x57, 0x5d, 0x5a, 0x5e, 0x56, 0x57, - 0x56, 0x59, 0x51, 0x62, 0x54, 0x4d, 0x5e, 0x56, 0x52, 0x52, 0x54, 0x58, - 0x59, 0x55, 0x5d, 0x54, 0x5c, 0x5d, 0x5a, 0x5b, 0x58, 0x5b, 0x54, 0x55, - 0x55, 0x58, 0x55, 0x5b, 0x56, 0x59, 0x55, 0x56, 0x58, 0x56, 0x57, 0x5f, - 0x5a, 0x5f, 0x56, 0x55, 0x56, 0x5a, 0x52, 0x61, 0x58, 0x4e, 0x5c, 0x55, - 0x53, 0x52, 0x58, 0x58, 0x58, 0x55, 0x5c, 0x54, 0x5e, 0x5d, 0x59, 0x5a, - 0x57, 0x5c, 0x52, 0x55, 0x55, 0x58, 0x55, 0x5c, 0x58, 0x59, 0x56, 0x56, - 0x57, 0x58, 0x57, 0x5d, 0x5b, 0x5f, 0x56, 0x54, 0x55, 0x57, 0x52, 0x62, - 0x56, 0x4f, 0x60, 0x56, 0x53, 0x52, 0x56, 0x58, 0x58, 0x54, 0x5a, 0x58, - 0x5d, 0x5e, 0x58, 0x5a, 0x57, 0x5b, 0x56, 0x56, 0x55, 0x57, 0x56, 0x5b, - 0x57, 0x5a, 0x56, 0x56, 0x57, 0x53, 0x57, 0x61, 0x5d, 0x5f, 0x57, 0x4f, - 0x55, 0x58, 0x52, 0x62, 0x55, 0x50, 0x60, 0x55, 0x52, 0x53, 0x56, 0x58, - 0x5a, 0x56, 0x5a, 0x57, 0x5e, 0x5c, 0x5a, 0x5b, 0x57, 0x5b, 0x57, 0x56, - 0x55, 0x58, 0x55, 0x5b, 0x58, 0x59, 0x57, 0x56, 0x56, 0x56, 0x57, 0x5e, - 0x5a, 0x5f, 0x59, 0x53, 0x57, 0x5a, 0x51, 0x61, 0x53, 0x52, 0x60, 0x56, - 0x52, 0x53, 0x5a, 0x57, 0x57, 0x58, 0x57, 0x56, 0x5e, 0x5a, 0x5b, 0x5a, - 0x59, 0x5c, 0x54, 0x55, 0x54, 0x58, 0x55, 0x59, 0x57, 0x58, 0x56, 0x56, - 0x57, 0x55, 0x57, 0x61, 0x5a, 0x60, 0x59, 0x51, 0x56, 0x57, 0x51, 0x64, - 0x57, 0x50, 0x5f, 0x55, 0x51, 0x51, 0x5c, 0x57, 0x59, 0x55, 0x55, 0x57, - 0x5e, 0x5c, 0x5a, 0x5a, 0x59, 0x5a, 0x51, 0x54, 0x54, 0x57, 0x55, 0x5a, - 0x57, 0x59, 0x55, 0x55, 0x57, 0x56, 0x57, 0x5f, 0x59, 0x5f, 0x59, 0x52, - 0x55, 0x56, 0x50, 0x62, 0x59, 0x51, 0x60, 0x55, 0x51, 0x53, 0x5e, 0x59, - 0x58, 0x56, 0x54, 0x58, 0x60, 0x5a, 0x5a, 0x5a, 0x59, 0x5b, 0x53, 0x54, - 0x55, 0x59, 0x55, 0x5c, 0x58, 0x5a, 0x56, 0x57, 0x57, 0x56, 0x57, 0x5f, - 0x5a, 0x60, 0x5a, 0x51, 0x54, 0x56, 0x51, 0x5f, 0x58, 0x51, 0x5e, 0x56, - 0x51, 0x51, 0x5e, 0x57, 0x5a, 0x56, 0x52, 0x59, 0x5f, 0x59, 0x5c, 0x58, - 0x5a, 0x5b, 0x52, 0x58, 0x55, 0x58, 0x56, 0x5b, 0x57, 0x59, 0x55, 0x56, - 0x58, 0x55, 0x57, 0x61, 0x5a, 0x60, 0x5c, 0x51, 0x56, 0x58, 0x51, 0x62, - 0x59, 0x53, 0x5f, 0x56, 0x51, 0x51, 0x5e, 0x57, 0x59, 0x55, 0x4d, 0x57, - 0x5f, 0x5c, 0x5d, 0x5b, 0x59, 0x5a, 0x53, 0x52, 0x55, 0x5a, 0x57, 0x5b, - 0x59, 0x5a, 0x56, 0x57, 0x59, 0x53, 0x57, 0x60, 0x5a, 0x61, 0x5b, 0x4c, - 0x56, 0x58, 0x51, 0x62, 0x56, 0x50, 0x63, 0x54, 0x52, 0x55, 0x5f, 0x57, - 0x57, 0x54, 0x4a, 0x57, 0x5e, 0x5a, 0x5c, 0x59, 0x58, 0x5a, 0x52, 0x54, - 0x56, 0x59, 0x57, 0x5a, 0x5a, 0x5b, 0x56, 0x56, 0x55, 0x5a, 0x57, 0x4c, - 0x59, 0x4c, 0x4d, 0x5f, 0x55, 0x5c, 0x51, 0x53, 0x56, 0x56, 0x4d, 0x57, - 0x52, 0x55, 0x51, 0x5b, 0x53, 0x57, 0x5c, 0x41, 0x53, 0x5e, 0x4f, 0x5b, - 0x50, 0x58, 0x5e, 0x5c, 0x58, 0x5a, 0x54, 0x58, 0x54, 0x52, 0x58, 0x59, - 0x59, 0x54, 0x57, 0x61, 0x57, 0x61, 0x5e, 0x51, 0x54, 0x59, 0x50, 0x61, - 0x58, 0x52, 0x61, 0x55, 0x51, 0x53, 0x61, 0x55, 0x57, 0x54, 0x49, 0x57, - 0x5f, 0x5d, 0x5c, 0x59, 0x58, 0x59, 0x57, 0x57, 0x54, 0x58, 0x55, 0x57, - 0x59, 0x5b, 0x57, 0x56, 0x59, 0x4e, 0x57, 0x5f, 0x5a, 0x61, 0x5d, 0x52, - 0x55, 0x57, 0x50, 0x63, 0x55, 0x51, 0x5f, 0x56, 0x52, 0x53, 0x62, 0x58, - 0x58, 0x55, 0x4d, 0x55, 0x60, 0x5a, 0x5d, 0x5a, 0x59, 0x59, 0x55, 0x54, - 0x53, 0x5b, 0x57, 0x5a, 0x5a, 0x5b, 0x56, 0x56, 0x58, 0x51, 0x58, 0x5f, - 0x55, 0x5f, 0x60, 0x51, 0x55, 0x56, 0x51, 0x64, 0x57, 0x53, 0x61, 0x56, - 0x52, 0x54, 0x5f, 0x56, 0x59, 0x54, 0x4a, 0x56, 0x60, 0x5c, 0x5e, 0x59, - 0x5a, 0x5b, 0x56, 0x55, 0x55, 0x5b, 0x57, 0x5b, 0x5b, 0x5c, 0x58, 0x55, - 0x57, 0x4f, 0x59, 0x5f, 0x55, 0x61, 0x62, 0x54, 0x55, 0x59, 0x50, 0x63, - 0x56, 0x54, 0x60, 0x56, 0x51, 0x53, 0x63, 0x56, 0x58, 0x55, 0x4f, 0x5a, - 0x61, 0x5a, 0x5f, 0x5a, 0x5c, 0x5a, 0x5c, 0x53, 0x55, 0x5a, 0x57, 0x57, - 0x5d, 0x5d, 0x59, 0x55, 0x57, 0x4f, 0x57, 0x60, 0x54, 0x60, 0x61, 0x56, - 0x56, 0x56, 0x50, 0x5f, 0x55, 0x52, 0x5f, 0x56, 0x51, 0x53, 0x66, 0x57, - 0x5a, 0x54, 0x4f, 0x55, 0x61, 0x5b, 0x5c, 0x58, 0x5c, 0x5a, 0x56, 0x57, - 0x57, 0x5c, 0x57, 0x59, 0x5b, 0x5b, 0x58, 0x55, 0x56, 0x4e, 0x56, 0x5d, - 0x55, 0x5e, 0x61, 0x51, 0x57, 0x58, 0x50, 0x62, 0x50, 0x52, 0x66, 0x55, - 0x52, 0x56, 0x69, 0x56, 0x58, 0x53, 0x4d, 0x5a, 0x5f, 0x5a, 0x5f, 0x58, - 0x5a, 0x5a, 0x56, 0x53, 0x54, 0x5c, 0x57, 0x58, 0x5c, 0x5c, 0x57, 0x56, - 0x57, 0x4e, 0x5a, 0x60, 0x53, 0x60, 0x66, 0x52, 0x56, 0x55, 0x50, 0x61, - 0x50, 0x55, 0x63, 0x54, 0x52, 0x55, 0x68, 0x57, 0x58, 0x56, 0x4e, 0x57, - 0x63, 0x5c, 0x60, 0x5c, 0x57, 0x59, 0x56, 0x59, 0x56, 0x5e, 0x57, 0x57, - 0x5d, 0x5d, 0x59, 0x54, 0x59, 0x50, 0x59, 0x61, 0x53, 0x5e, 0x6a, 0x55, - 0x56, 0x52, 0x51, 0x5f, 0x56, 0x53, 0x67, 0x53, 0x51, 0x53, 0x6b, 0x54, - 0x5c, 0x53, 0x52, 0x58, 0x66, 0x58, 0x62, 0x59, 0x5b, 0x5b, 0x55, 0x58, - 0x58, 0x59, 0x58, 0x57, 0x5c, 0x5d, 0x55, 0x54, 0x5a, 0x53, 0x5f, 0x5d, - 0x53, 0x60, 0x6e, 0x55, 0x54, 0x58, 0x51, 0x5e, 0x56, 0x54, 0x6a, 0x56, - 0x51, 0x54, 0x6c, 0x53, 0x5f, 0x54, 0x54, 0x5c, 0x67, 0x58, 0x66, 0x5a, - 0x58, 0x5f, 0x5a, 0x57, 0x58, 0x5b, 0x57, 0x5a, 0x60, 0x62, 0x56, 0x54, - 0x5f, 0x53, 0x63, 0x61, 0x56, 0x5d, 0x7b, 0x56, 0x51, 0x59, 0x50, 0x5f, - 0x54, 0x53, 0x68, 0x57, 0x51, 0x51, 0x6d, 0x58, 0x63, 0x53, 0x52, 0x61, - 0x6e, 0x58, 0x6f, 0x5a, 0x5a, 0x63, 0x5b, 0x5e, 0x5f, 0x5a, 0x5a, 0x5e, - 0x61, 0x5e, 0x53, 0x5a, 0x55, 0x5a, 0x56, 0x52, 0x59, 0x51, 0x4e, 0x5d, - 0x55, 0x5c, 0x51, 0x56, 0x55, 0x55, 0x54, 0x56, 0x52, 0x54, 0x50, 0x59, - 0x55, 0x55, 0x5e, 0x3f, 0x54, 0x5e, 0x51, 0x5b, 0x53, 0x5a, 0x5a, 0x5b, - 0x57, 0x5a, 0x54, 0x58, 0x55, 0x54, 0x57, 0x57, 0x55, 0x57, 0x68, 0x59, - 0x57, 0x66, 0x72, 0x56, 0x50, 0x61, 0x52, 0x67, 0x56, 0x58, 0x66, 0x70, - 0x53, 0x56, 0x6f, 0x59, 0x6e, 0x55, 0x50, 0x5c, 0x67, 0x5e, 0x75, 0x62, - 0x61, 0x58, 0x5e, 0x65, 0x58, 0x70, 0x58, 0x63, 0x5b, 0x5c, 0x57, 0x65, - 0x55, 0x5a, 0x55, 0x56, 0x5a, 0x52, 0x50, 0x5c, 0x56, 0x5c, 0x51, 0x59, - 0x56, 0x54, 0x58, 0x56, 0x52, 0x53, 0x51, 0x59, 0x57, 0x55, 0x5f, 0x42, - 0x57, 0x5e, 0x52, 0x5a, 0x54, 0x5a, 0x59, 0x5b, 0x57, 0x59, 0x54, 0x5b, - 0x55, 0x56, 0x56, 0x57, 0x56, 0x59, 0x55, 0x59, 0x59, 0x55, 0x51, 0x5b, - 0x56, 0x5b, 0x51, 0x5c, 0x55, 0x54, 0x5a, 0x55, 0x51, 0x53, 0x52, 0x59, - 0x57, 0x54, 0x5f, 0x44, 0x58, 0x5d, 0x53, 0x59, 0x55, 0x5c, 0x57, 0x5a, - 0x57, 0x58, 0x54, 0x5c, 0x56, 0x56, 0x55, 0x56, 0x56, 0x59, 0x56, 0x5a, - 0x5a, 0x58, 0x52, 0x5a, 0x55, 0x5a, 0x51, 0x5e, 0x54, 0x52, 0x5b, 0x56, - 0x52, 0x53, 0x52, 0x59, 0x58, 0x54, 0x5f, 0x49, 0x58, 0x5d, 0x54, 0x5a, - 0x55, 0x5c, 0x56, 0x59, 0x55, 0x58, 0x54, 0x5b, 0x56, 0x57, 0x56, 0x56, - 0x56, 0x58, 0x56, 0x5b, 0x5a, 0x59, 0x53, 0x5a, 0x55, 0x59, 0x52, 0x5f, - 0x55, 0x52, 0x5c, 0x54, 0x52, 0x52, 0x52, 0x58, 0x58, 0x55, 0x5f, 0x50, - 0x5a, 0x5d, 0x55, 0x5b, 0x56, 0x5c, 0x54, 0x5a, 0x56, 0x58, 0x55, 0x5c, - 0x56, 0x57, 0x56, 0x56, 0x56, 0x58, 0x55, 0x5d, 0x5a, 0x5a, 0x54, 0x59, - 0x55, 0x5a, 0x51, 0x61, 0x56, 0x51, 0x5f, 0x56, 0x52, 0x54, 0x54, 0x59, - 0x58, 0x51, 0x5d, 0x51, 0x5a, 0x5e, 0x56, 0x5a, 0x57, 0x5d, 0x55, 0x57, - 0x55, 0x58, 0x55, 0x5c, 0x56, 0x57, 0x56, 0x55, 0x56, 0x57, 0x57, 0x5c, - 0x59, 0x5b, 0x54, 0x56, 0x55, 0x59, 0x52, 0x63, 0x54, 0x4d, 0x5b, 0x56, - 0x52, 0x53, 0x54, 0x58, 0x58, 0x55, 0x5e, 0x54, 0x5c, 0x5d, 0x57, 0x5b, - 0x57, 0x5c, 0x52, 0x58, 0x55, 0x57, 0x55, 0x5e, 0x56, 0x58, 0x56, 0x56, - 0x5a, 0x76, 0x54, 0x63, 0x61, 0x52, 0x59, 0x4d, 0x6a, 0x55, 0x59, 0x4d, - 0x57, 0x6a, 0x6c, 0x5c, 0x59, 0x5b, 0x59, 0x51, 0x58, 0x4c, 0x64, 0x6c, - 0x5a, 0x55, 0x5e, 0x52, 0x4e, 0x4f, 0x5d, 0x4c, 0x5f, 0x51, 0x5b, 0x46, - 0x60, 0x4e, 0x53, 0x51, 0x59, 0x4b, 0x5a, 0x6a, 0x5d, 0x56, 0x5c, 0x61, - 0x55, 0x57, 0x59, 0x54, 0x5e, 0x48, 0x75, 0x5b, 0x5a, 0x5b, 0x5f, 0x58, - 0x5a, 0x52, 0x61, 0x6a, 0x57, 0x57, 0x55, 0x56, 0x45, 0x52, 0x35, 0x50, - 0x58, 0x56, 0x5b, 0x50, 0x61, 0x54, 0x51, 0x54, 0x5b, 0x6d, 0x5a, 0x4e, - 0x5e, 0x4f, 0x5d, 0x56, 0x6c, 0x4f, 0x59, 0x4c, 0x58, 0x58, 0x5e, 0x5b, - 0x58, 0x5a, 0x67, 0x50, 0x59, 0x4f, 0x64, 0x63, 0x59, 0x53, 0x5d, 0x50, - 0x54, 0x4e, 0x58, 0x4f, 0x5b, 0x4d, 0x5b, 0x49, 0x60, 0x52, 0x59, 0x4d, - 0x57, 0x4b, 0x60, 0x50, 0x44, 0x5f, 0x53, 0x30, 0x66, 0x50, 0x59, 0x5c, - 0x58, 0x43, 0x75, 0x5c, 0x59, 0x56, 0x4e, 0x50, 0x59, 0x5a, 0x64, 0x48, - 0x58, 0x5e, 0x5d, 0x5d, 0x50, 0x7b, 0x33, 0x55, 0x57, 0x58, 0x5a, 0x53, - 0x64, 0x53, 0x57, 0x50, 0x5a, 0x5a, 0x58, 0x6b, 0x5b, 0x55, 0x5f, 0x5e, - 0x58, 0x58, 0x59, 0x4c, 0x57, 0x50, 0x72, 0x5a, 0x59, 0x5c, 0x62, 0x55, - 0x5c, 0x50, 0x62, 0x6c, 0x58, 0x55, 0x58, 0x53, 0x44, 0x4f, 0x56, 0x51, - 0x5c, 0x53, 0x5a, 0x4a, 0x63, 0x53, 0x52, 0x54, 0x59, 0x3c, 0x56, 0x54, - 0x51, 0x56, 0x56, 0x4a, 0x54, 0x56, 0x59, 0x55, 0x54, 0x38, 0x52, 0x56, - 0x58, 0x5a, 0x69, 0x59, 0x56, 0x59, 0x69, 0x55, 0x5a, 0x54, 0x5a, 0x56, - 0x58, 0x5a, 0x4c, 0x5b, 0x57, 0x56, 0x59, 0x5d, 0x5a, 0x5b, 0x52, 0x57, - 0x59, 0x58, 0x5a, 0x5c, 0x49, 0x58, 0x5a, 0x59, 0x53, 0x5b, 0x4b, 0x5a, - 0x57, 0x50, 0x5c, 0x57, 0x4b, 0x4e, 0x5c, 0x55, 0x73, 0x57, 0x56, 0x4a, - 0x59, 0x59, 0x58, 0x5a, 0x4e, 0x59, 0x55, 0x53, 0x4d, 0x56, 0x54, 0x57, - 0x5b, 0x5d, 0x55, 0x58, 0x58, 0x57, 0x5f, 0x57, 0x58, 0x58, 0x5a, 0x58, - 0x53, 0x59, 0x4c, 0x5c, 0x57, 0x56, 0x59, 0x54, 0x4b, 0x4e, 0x5f, 0x55, - 0x5a, 0x56, 0x56, 0x51, 0x5c, 0x5d, 0x59, 0x5d, 0x56, 0x58, 0x58, 0x5c, - 0x53, 0x5c, 0x54, 0x58, 0x55, 0x5a, 0x56, 0x57, 0x52, 0x57, 0x5e, 0x5d, - 0x5e, 0x61, 0x59, 0x55, 0x52, 0x5f, 0x4a, 0x59, 0x54, 0x54, 0x63, 0x56, - 0x4b, 0x50, 0x55, 0x55, 0x4e, 0x51, 0x5c, 0x54, 0x5f, 0x63, 0x59, 0x5d, - 0x5f, 0x59, 0x5c, 0x60, 0x57, 0x64, 0x52, 0x57, 0x58, 0x52, 0x56, 0x57, - 0x57, 0x58, 0x5c, 0x58, 0x55, 0x59, 0x5b, 0x58, 0x51, 0x59, 0x4b, 0x5c, - 0x56, 0x58, 0x59, 0x54, 0x4b, 0x50, 0x60, 0x56, 0x56, 0x55, 0x54, 0x53, - 0x5d, 0x5d, 0x5a, 0x5c, 0x57, 0x5a, 0x5a, 0x5b, 0x53, 0x5d, 0x54, 0x5a, - 0x55, 0x59, 0x55, 0x59, 0x56, 0x57, 0x5d, 0x56, 0x57, 0x5a, 0x5c, 0x59, - 0x51, 0x5a, 0x4b, 0x5d, 0x56, 0x54, 0x58, 0x54, 0x4a, 0x50, 0x62, 0x55, - 0x54, 0x56, 0x54, 0x53, 0x5d, 0x5d, 0x5a, 0x5d, 0x58, 0x5b, 0x5a, 0x5c, - 0x54, 0x5d, 0x53, 0x5b, 0x54, 0x59, 0x55, 0x59, 0x54, 0x58, 0x5b, 0x59, - 0x5c, 0x58, 0x5c, 0x57, 0x51, 0x5b, 0x4b, 0x5d, 0x56, 0x55, 0x59, 0x54, - 0x4a, 0x51, 0x62, 0x55, 0x52, 0x55, 0x57, 0x54, 0x5f, 0x5e, 0x5a, 0x5d, - 0x5a, 0x5b, 0x59, 0x5c, 0x56, 0x5e, 0x53, 0x5b, 0x56, 0x58, 0x54, 0x59, - 0x55, 0x56, 0x5d, 0x5a, 0x5c, 0x5b, 0x5b, 0x58, 0x50, 0x5a, 0x4b, 0x5e, - 0x56, 0x51, 0x5a, 0x55, 0x4b, 0x51, 0x61, 0x56, 0x51, 0x56, 0x56, 0x53, - 0x5f, 0x5d, 0x59, 0x5c, 0x5a, 0x5a, 0x5a, 0x5d, 0x55, 0x5f, 0x53, 0x5c, - 0x54, 0x58, 0x55, 0x5a, 0x53, 0x57, 0x5c, 0x58, 0x5d, 0x5c, 0x5a, 0x56, - 0x50, 0x5a, 0x4b, 0x5e, 0x54, 0x52, 0x5c, 0x54, 0x4b, 0x52, 0x5f, 0x56, - 0x51, 0x55, 0x5a, 0x51, 0x5e, 0x5e, 0x59, 0x5c, 0x5b, 0x5a, 0x5a, 0x5e, - 0x55, 0x5d, 0x53, 0x5c, 0x55, 0x58, 0x55, 0x5a, 0x54, 0x56, 0x5e, 0x5a, - 0x5e, 0x5c, 0x5a, 0x57, 0x50, 0x5b, 0x4b, 0x5d, 0x58, 0x54, 0x5d, 0x55, - 0x4b, 0x53, 0x5e, 0x57, 0x51, 0x54, 0x58, 0x53, 0x5e, 0x5c, 0x59, 0x5c, - 0x5b, 0x5a, 0x5a, 0x5d, 0x55, 0x60, 0x52, 0x5c, 0x55, 0x57, 0x55, 0x59, - 0x54, 0x55, 0x5d, 0x59, 0x5c, 0x5f, 0x5a, 0x56, 0x51, 0x5b, 0x4b, 0x5c, - 0x55, 0x53, 0x5e, 0x55, 0x4b, 0x52, 0x5b, 0x55, 0x4e, 0x54, 0x56, 0x53, - 0x60, 0x5e, 0x59, 0x5c, 0x5b, 0x5a, 0x5b, 0x5f, 0x57, 0x5f, 0x52, 0x5c, - 0x56, 0x56, 0x54, 0x59, 0x53, 0x5a, 0x5c, 0x5c, 0x5f, 0x60, 0x5b, 0x55, - 0x50, 0x5c, 0x4b, 0x5c, 0x57, 0x55, 0x60, 0x56, 0x4b, 0x51, 0x5c, 0x57, - 0x4e, 0x54, 0x59, 0x55, 0x5f, 0x60, 0x58, 0x5d, 0x5d, 0x5b, 0x59, 0x5d, - 0x56, 0x61, 0x52, 0x5b, 0x56, 0x55, 0x54, 0x59, 0x2f, 0x61, 0x40, 0x59, - 0x59, 0x63, 0x49, 0x53, 0x4e, 0x64, 0x5c, 0x61, 0x3b, 0x53, 0x4b, 0x64, - 0x5b, 0x6e, 0x4c, 0x7e, 0x61, 0x37, 0x5f, 0x52, 0x73, 0x45, 0x29, 0x6d, - 0x5b, 0x6b, 0x4c, 0x2e, 0x55, 0x3f, 0x0d, 0x5e, 0x56, 0x4c, 0x61, 0x43, - 0x40, 0x58, 0x4c, 0x5e, 0x5c, 0x66, 0x4f, 0x57, 0x54, 0x41, 0x5b, 0x50, - 0x47, 0x62, 0x5a, 0x53, 0x59, 0x4c, 0x5e, 0x25, 0x69, 0x3f, 0x58, 0x5d, - 0x27, 0x51, 0x50, 0x71, 0x68, 0x67, 0x51, 0x5b, 0x71, 0x52, 0x30, 0x68, - 0x41, 0x45, 0x5f, 0x4a, 0x5e, 0x57, 0x7f, 0x55, 0x50, 0x56, 0x51, 0x6d, - 0x59, 0x58, 0x5b, 0x49, 0x91, 0x4f, 0x52, 0x68, 0x59, 0x62, 0x44, 0x70, - 0x3f, 0x8b, 0x4b, 0x48, 0x4d, 0x36, 0x4f, 0x7d, 0x55, 0x4a, 0x6b, 0x56, - 0x42, 0x7a, 0x5e, 0x52, 0x69, 0x5d, 0x61, 0x71, 0x5a, 0x6f, 0x52, 0x65, - 0x55, 0x52, 0x71, 0x67, 0x54, 0x49, 0x52, 0x6e, 0x97, 0x56, 0x61, 0x3f, - 0x59, 0x61, 0x3a, 0x74, 0x4b, 0x9b, 0x5e, 0x54, 0x53, 0x65, 0x64, 0x44, - 0x53, 0x52, 0x65, 0x52, 0x3e, 0x6d, 0x5f, 0x52, 0x63, 0x7f, 0x55, 0x6a, - 0x58, 0x61, 0x6b, 0x64, 0x5c, 0x57, 0x77, 0x5b, 0x66, 0x56, 0x52, 0x5f, - 0x99, 0x53, 0x5e, 0x52, 0x57, 0x51, 0x45, 0x70, 0x45, 0x9a, 0x59, 0x54, - 0x57, 0x64, 0x68, 0x4e, 0x52, 0x47, 0x51, 0x69, 0x56, 0x62, 0x5d, 0x58, - 0x62, 0x60, 0x54, 0x56, 0x5b, 0x66, 0x6a, 0x59, 0x56, 0x58, 0x64, 0x5f, - 0x5d, 0x56, 0x5f, 0x57, 0x66, 0x60, 0x5f, 0x5a, 0x58, 0x4d, 0x45, 0x50, - 0x45, 0xac, 0x56, 0x52, 0x4b, 0x61, 0x6d, 0x5e, 0x53, 0x53, 0x55, 0x5a, - 0x4b, 0x52, 0x5b, 0x57, 0x59, 0x59, 0x5a, 0x50, 0x57, 0x51, 0x5e, 0x5a, - 0x5a, 0x56, 0x53, 0x59, 0x58, 0x58, 0x54, 0x58, 0x61, 0x59, 0x5f, 0x56, - 0x55, 0x4d, 0x54, 0x49, 0x4f, 0xa6, 0x60, 0x40, 0x53, 0x54, 0x6b, 0x4c, - 0x59, 0x58, 0x5c, 0x59, 0x48, 0x46, 0x59, 0x57, 0x53, 0x5f, 0x59, 0x5f, - 0x58, 0x57, 0x54, 0x58, 0x5d, 0x4e, 0x4e, 0x56, 0x57, 0x48, 0x52, 0x51, - 0x67, 0x58, 0x51, 0x5c, 0x55, 0x56, 0x4f, 0x4b, 0x4a, 0x5a, 0x59, 0x5a, - 0x4a, 0x40, 0x61, 0x5b, 0x59, 0x57, 0x58, 0x44, 0x4f, 0x44, 0x5f, 0x5a, - 0x45, 0x56, 0x5d, 0x69, 0x57, 0x59, 0x59, 0x5a, 0x58, 0x56, 0x5a, 0x5c, - 0x57, 0x57, 0x58, 0x52, 0x59, 0x5b, 0x56, 0x57, 0x57, 0x59, 0x51, 0x48, - 0x54, 0x59, 0x59, 0x5a, 0x56, 0x52, 0x59, 0x54, 0x57, 0x5f, 0x59, 0x54, - 0x3e, 0x54, 0x5a, 0x51, 0x43, 0x67, 0x58, 0x6a, 0x31, 0x58, 0x4d, 0x5a, - 0x5c, 0x64, 0x4e, 0x58, 0x53, 0x67, 0x5b, 0x53, 0x48, 0x5c, 0x5e, 0x4d, - 0x59, 0x51, 0x71, 0x44, 0x69, 0x43, 0x5a, 0x5d, 0x3b, 0x5f, 0x53, 0x3b, - 0x66, 0x5e, 0x53, 0x5e, 0x6d, 0x5b, 0x52, 0x64, 0x3a, 0x46, 0x5a, 0x48, - 0x81, 0x56, 0x4d, 0x58, 0x5a, 0x5f, 0x4d, 0x5b, 0x55, 0x5d, 0x5b, 0x7e, - 0x43, 0x5b, 0x5b, 0x6d, 0x59, 0x52, 0x6a, 0x73, 0x6a, 0x45, 0x5a, 0x5e, - 0x4d, 0x45, 0x51, 0x18, 0x64, 0x5c, 0x58, 0x78, 0x4d, 0x47, 0x4f, 0x2f, - 0x40, 0x4c, 0x5b, 0x49, 0x6e, 0x56, 0x4c, 0x54, 0x57, 0x61, 0x4f, 0x5d, - 0x53, 0x4b, 0x5b, 0x58, 0x41, 0x59, 0x5c, 0x56, 0x59, 0x53, 0x6f, 0x73, - 0x6a, 0x44, 0x58, 0x5c, 0x5e, 0x55, 0x53, 0x33, 0x65, 0x58, 0x5a, 0x50, - 0x4f, 0x76, 0x75, 0x2d, 0x41, 0x4c, 0x5b, 0x49, 0x63, 0x53, 0x4d, 0x52, - 0x58, 0x60, 0x4c, 0x5a, 0x61, 0x44, 0x5b, 0x57, 0x3d, 0x5b, 0x61, 0x4f, - 0x58, 0x54, 0x5e, 0x3e, 0x6f, 0x46, 0x57, 0x5e, 0x61, 0x55, 0x52, 0x48, - 0x67, 0x56, 0x5a, 0x66, 0x71, 0x73, 0x78, 0x60, 0x43, 0x5a, 0x5e, 0x49, - 0x58, 0x54, 0x4b, 0x57, 0x55, 0x62, 0x4a, 0x58, 0x5e, 0x4b, 0x5b, 0x57, - 0x40, 0x58, 0x51, 0x48, 0x59, 0x56, 0x5b, 0x46, 0x50, 0x44, 0x5a, 0x5c, - 0x51, 0x3a, 0x50, 0x48, 0x5f, 0x56, 0x5b, 0x47, 0x73, 0x33, 0x92, 0x64, - 0x91, 0x5e, 0x5f, 0x47, 0x55, 0x55, 0x47, 0x58, 0x57, 0x5f, 0x50, 0x5a, - 0x5c, 0x4a, 0x5b, 0x57, 0x3a, 0x56, 0x55, 0x4f, 0x59, 0x53, 0x58, 0x52, - 0x34, 0x46, 0x59, 0x5a, 0x4b, 0x9d, 0x4f, 0x43, 0x5d, 0x55, 0x59, 0x41, - 0x72, 0x37, 0x8b, 0x6e, 0x63, 0x70, 0x63, 0x95, 0x56, 0x59, 0x48, 0x65, - 0x5b, 0x59, 0x4f, 0x58, 0x52, 0x4f, 0x5b, 0x59, 0x48, 0x54, 0x60, 0x51, - 0x59, 0x56, 0x60, 0x57, 0x42, 0x8b, 0x60, 0x56, 0x4e, 0x7d, 0x56, 0x44, - 0x59, 0x53, 0x59, 0x68, 0x73, 0x3c, 0x87, 0x67, 0x75, 0x87, 0x48, 0x97, - 0x59, 0x5e, 0x76, 0x6c, 0x55, 0x49, 0x4e, 0x68, 0x60, 0x58, 0x5b, 0x52, - 0x71, 0x47, 0x5d, 0x5f, 0x59, 0x60, 0x6b, 0x4a, 0x49, 0x8d, 0x53, 0x4d, - 0x51, 0x27, 0x55, 0x6a, 0x64, 0x65, 0x62, 0x75, 0x6f, 0x3f, 0x6e, 0x62, - 0x7d, 0x7d, 0x50, 0x80, 0x58, 0x5d, 0x73, 0x53, 0x58, 0x3f, 0x7d, 0x65, - 0x54, 0x5b, 0x52, 0x58, 0x57, 0x5e, 0x5f, 0x55, 0x52, 0x62, 0x5b, 0x57, - 0x5a, 0x5b, 0x61, 0x5e, 0x60, 0x5a, 0x78, 0x54, 0x59, 0x4b, 0x64, 0x59, - 0x5f, 0x5f, 0x56, 0x4e, 0x59, 0x46, 0x5b, 0x5f, 0x5d, 0x5a, 0x5d, 0x58, - 0x5b, 0x54, 0x5a, 0x5c, 0x55, 0x58, 0x52, 0x5f, 0x5a, 0x5a, 0x5d, 0x56, - 0x53, 0x55, 0x5f, 0x59, 0x5a, 0x57, 0x5e, 0x58, 0x5c, 0x5f, 0x53, 0x5a, - 0x55, 0x57, 0x5e, 0x5f, 0x58, 0x5e, 0x57, 0x5b, 0x59, 0x54, 0x56, 0x55, - 0x5a, 0x58, 0x5d, 0x59, 0x59, 0x59, 0x52, 0x5a, 0x56, 0x58, 0x52, 0x5e, - 0x57, 0x57, 0x5c, 0x57, 0x53, 0x54, 0x5d, 0x59, 0x59, 0x56, 0x58, 0x55, - 0x5e, 0x5e, 0x53, 0x5b, 0x57, 0x5a, 0x5d, 0x5d, 0x57, 0x5c, 0x57, 0x5a, - 0x58, 0x59, 0x57, 0x57, 0x5a, 0x59, 0x5d, 0x58, 0x58, 0x59, 0x55, 0x59, - 0x56, 0x59, 0x52, 0x60, 0x59, 0x57, 0x5c, 0x57, 0x52, 0x54, 0x5d, 0x5a, - 0x58, 0x56, 0x5a, 0x57, 0x5c, 0x5d, 0x54, 0x5c, 0x57, 0x5a, 0x5d, 0x5c, - 0x57, 0x5c, 0x57, 0x5b, 0x57, 0x59, 0x56, 0x58, 0x5b, 0x59, 0x5a, 0x59, - 0x59, 0x57, 0x54, 0x56, 0x55, 0x59, 0x52, 0x5d, 0x5b, 0x56, 0x5b, 0x57, - 0x52, 0x51, 0x5d, 0x59, 0x59, 0x56, 0x5a, 0x54, 0x5c, 0x5d, 0x53, 0x5a, - 0x58, 0x5c, 0x5a, 0x5d, 0x55, 0x5c, 0x57, 0x5b, 0x57, 0x59, 0x57, 0x57, - 0x5b, 0x59, 0x58, 0x58, 0x58, 0x59, 0x55, 0x55, 0x55, 0x59, 0x53, 0x5e, - 0x56, 0x56, 0x5a, 0x57, 0x52, 0x51, 0x5b, 0x5a, 0x59, 0x55, 0x58, 0x56, - 0x5d, 0x5c, 0x53, 0x5c, 0x59, 0x59, 0x5a, 0x5c, 0x56, 0x5b, 0x57, 0x5a, - 0x58, 0x59, 0x56, 0x58, 0x58, 0x56, 0x5a, 0x59, 0x58, 0x5c, 0x56, 0x56, - 0x56, 0x5b, 0x52, 0x5c, 0x58, 0x55, 0x59, 0x57, 0x53, 0x55, 0x5d, 0x58, - 0x59, 0x56, 0x56, 0x54, 0x5d, 0x5b, 0x52, 0x5a, 0x57, 0x58, 0x5a, 0x5b, - 0x56, 0x5b, 0x56, 0x5a, 0x57, 0x59, 0x57, 0x58, 0x5a, 0x57, 0x56, 0x59, - 0x58, 0x5a, 0x50, 0x5a, 0x55, 0x5a, 0x51, 0x5b, 0x57, 0x57, 0x59, 0x58, - 0x52, 0x54, 0x5c, 0x59, 0x58, 0x55, 0x56, 0x56, 0x5b, 0x5d, 0x51, 0x5c, - 0x57, 0x5a, 0x5a, 0x5c, 0x56, 0x5c, 0x57, 0x59, 0x5a, 0x5a, 0x57, 0x57, - 0x59, 0x57, 0x55, 0x5a, 0x58, 0x5a, 0x54, 0x57, 0x56, 0x5b, 0x51, 0x5d, - 0x59, 0x54, 0x5b, 0x58, 0x54, 0x51, 0x5c, 0x59, 0x59, 0x55, 0x54, 0x53, - 0x5b, 0x5d, 0x52, 0x5b, 0x56, 0x5a, 0x5a, 0x5c, 0x55, 0x5a, 0x57, 0x5b, - 0x58, 0x5a, 0x56, 0x57, 0x59, 0x55, 0x57, 0x5a, 0x57, 0x5c, 0x55, 0x54, - 0x54, 0x5a, 0x52, 0x5b, 0x55, 0x54, 0x5c, 0x59, 0x53, 0x4f, 0x5b, 0x5b, - 0x58, 0x56, 0x54, 0x54, 0x59, 0x5c, 0x56, 0x5c, 0x57, 0x5c, 0x59, 0x5c, - 0x56, 0x5b, 0x56, 0x58, 0x59, 0x5a, 0x58, 0x58, 0x59, 0x57, 0x5a, 0x59, - 0x58, 0x5c, 0x53, 0x56, 0x55, 0x5a, 0x52, 0x5c, 0x55, 0x53, 0x5b, 0x56, - 0x52, 0x52, 0x5d, 0x5a, 0x59, 0x53, 0x56, 0x57, 0x5a, 0x5b, 0x53, 0x5d, - 0x58, 0x5c, 0x57, 0x5c, 0x56, 0x5a, 0x58, 0x58, 0x59, 0x5b, 0x57, 0x58, - 0x59, 0x55, 0x59, 0x59, 0x59, 0x5b, 0x54, 0x57, 0x56, 0x5b, 0x52, 0x5a, - 0x57, 0x53, 0x5a, 0x57, 0x53, 0x52, 0x5b, 0x59, 0x59, 0x56, 0x53, 0x55, - 0x5a, 0x5c, 0x53, 0x5d, 0x59, 0x5c, 0x56, 0x5b, 0x55, 0x5b, 0x57, 0x59, - 0x58, 0x5a, 0x56, 0x56, 0x5b, 0x5c, 0x5c, 0x56, 0x5b, 0x56, 0x55, 0x5c, - 0x55, 0x59, 0x52, 0x5e, 0x56, 0x5a, 0x5c, 0x55, 0x53, 0x55, 0x61, 0x58, - 0x5b, 0x57, 0x5d, 0x58, 0x5f, 0x5f, 0x56, 0x5b, 0x55, 0x58, 0x5e, 0x5f, - 0x57, 0x5d, 0x57, 0x5b, 0x58, 0x57, 0x57, 0x55, 0x58, 0x56, 0x53, 0x59, - 0x58, 0x5b, 0x53, 0x58, 0x56, 0x5a, 0x52, 0x5c, 0x58, 0x52, 0x59, 0x57, - 0x52, 0x51, 0x5c, 0x59, 0x57, 0x56, 0x54, 0x55, 0x5b, 0x5e, 0x52, 0x5b, - 0x59, 0x5b, 0x5a, 0x5a, 0x55, 0x5b, 0x56, 0x5a, 0x59, 0x5a, 0x58, 0x57, - 0x5a, 0x56, 0x57, 0x5b, 0x56, 0x5c, 0x53, 0x55, 0x56, 0x5a, 0x51, 0x5b, - 0x58, 0x55, 0x5a, 0x57, 0x53, 0x52, 0x5c, 0x59, 0x59, 0x56, 0x55, 0x53, - 0x5a, 0x5a, 0x53, 0x5c, 0x58, 0x5b, 0x59, 0x5a, 0x56, 0x58, 0x57, 0x5a, - 0x58, 0x5c, 0x54, 0x57, 0x59, 0x55, 0x52, 0x5b, 0x56, 0x5c, 0x50, 0x55, - 0x56, 0x5b, 0x52, 0x59, 0x59, 0x54, 0x5c, 0x58, 0x52, 0x50, 0x5b, 0x58, - 0x59, 0x57, 0x55, 0x54, 0x5b, 0x5c, 0x54, 0x5c, 0x58, 0x5a, 0x58, 0x5b, - 0x55, 0x5c, 0x57, 0x5a, 0x58, 0x5b, 0x59, 0x56, 0x58, 0x54, 0x55, 0x59, - 0x57, 0x5d, 0x51, 0x58, 0x57, 0x5b, 0x52, 0x5a, 0x59, 0x53, 0x59, 0x58, - 0x53, 0x50, 0x5b, 0x59, 0x58, 0x54, 0x55, 0x56, 0x5b, 0x5a, 0x55, 0x5c, - 0x57, 0x5a, 0x58, 0x5b, 0x55, 0x5a, 0x58, 0x5a, 0x57, 0x5c, 0x55, 0x56, - 0x5a, 0x56, 0x56, 0x5a, 0x54, 0x5d, 0x51, 0x54, 0x55, 0x5c, 0x52, 0x58, - 0x58, 0x53, 0x5a, 0x58, 0x52, 0x51, 0x5c, 0x59, 0x5a, 0x55, 0x54, 0x53, - 0x5a, 0x5c, 0x53, 0x5d, 0x59, 0x5b, 0x59, 0x5a, 0x54, 0x5a, 0x57, 0x59, - 0x57, 0x5d, 0x56, 0x58, 0x58, 0x53, 0x56, 0x58, 0x56, 0x5d, 0x51, 0x55, - 0x56, 0x58, 0x52, 0x58, 0x58, 0x53, 0x59, 0x57, 0x52, 0x4f, 0x5c, 0x59, - 0x58, 0x56, 0x54, 0x53, 0x59, 0x5b, 0x53, 0x5c, 0x59, 0x5b, 0x59, 0x5b, - 0x54, 0x5a, 0x57, 0x59, 0x58, 0x5b, 0x56, 0x57, 0x56, 0x53, 0x4f, 0x5b, - 0x56, 0x61, 0x4b, 0x53, 0x56, 0x5a, 0x52, 0x59, 0x57, 0x52, 0x59, 0x58, - 0x53, 0x4d, 0x5b, 0x58, 0x57, 0x56, 0x4f, 0x52, 0x58, 0x5a, 0x4f, 0x5e, - 0x58, 0x5b, 0x57, 0x5b, 0x54, 0x57, 0x56, 0x5c, 0x57, 0x5d, 0x56, 0x57, - 0x4e, 0x50, 0x4c, 0x5d, 0x55, 0x66, 0x49, 0x52, 0x54, 0x58, 0x52, 0x55, - 0x5b, 0x51, 0x58, 0x58, 0x52, 0x4d, 0x58, 0x55, 0x58, 0x55, 0x4b, 0x4e, - 0x56, 0x5a, 0x4c, 0x5e, 0x56, 0x5c, 0x54, 0x5d, 0x51, 0x55, 0x53, 0x5f, - 0x54, 0x5c, 0x56, 0x56, 0x49, 0x48, 0x44, 0x61, 0x51, 0x69, 0x48, 0x53, - 0x52, 0x59, 0x51, 0x53, 0x59, 0x4c, 0x57, 0x59, 0x51, 0x4e, 0x59, 0x53, - 0x57, 0x53, 0x3e, 0x4a, 0x55, 0x5a, 0x3f, 0x60, 0x53, 0x5c, 0x4f, 0x5a, - 0x4e, 0x53, 0x50, 0x5d, 0x52, 0x5b, 0x54, 0x55, 0x42, 0x44, 0x47, 0x67, - 0x52, 0x6b, 0x50, 0x51, 0x4f, 0x58, 0x51, 0x4f, 0x5b, 0x45, 0x56, 0x5a, - 0x52, 0x4e, 0x59, 0x4f, 0x56, 0x55, 0x3d, 0x41, 0x51, 0x56, 0x47, 0x5f, - 0x50, 0x61, 0x47, 0x58, 0x4c, 0x52, 0x4f, 0x5e, 0x52, 0x58, 0x4d, 0x57, - 0x5a, 0x5b, 0x5b, 0x57, 0x5c, 0x55, 0x58, 0x5a, 0x55, 0x58, 0x52, 0x5f, - 0x56, 0x59, 0x5c, 0x56, 0x53, 0x56, 0x5f, 0x59, 0x59, 0x56, 0x5b, 0x58, - 0x5e, 0x5e, 0x53, 0x5a, 0x55, 0x58, 0x5c, 0x5e, 0x57, 0x5e, 0x57, 0x5c, - 0x59, 0x57, 0x57, 0x57, 0x45, 0x4c, 0x4f, 0x62, 0x53, 0x66, 0x56, 0x54, - 0x4d, 0x5c, 0x51, 0x50, 0x5c, 0x50, 0x56, 0x5d, 0x52, 0x52, 0x54, 0x4e, - 0x57, 0x54, 0x4a, 0x47, 0x54, 0x5a, 0x55, 0x61, 0x4c, 0x64, 0x52, 0x53, - 0x4d, 0x51, 0x4e, 0x60, 0x53, 0x55, 0x54, 0x58, 0x5a, 0x5b, 0x5c, 0x58, - 0x5b, 0x54, 0x58, 0x59, 0x54, 0x59, 0x52, 0x60, 0x55, 0x5a, 0x5c, 0x56, - 0x53, 0x55, 0x60, 0x5a, 0x5a, 0x56, 0x5c, 0x56, 0x5e, 0x5e, 0x58, 0x5c, - 0x54, 0x58, 0x5e, 0x5e, 0x56, 0x5e, 0x57, 0x5b, 0x59, 0x57, 0x57, 0x56, - 0x59, 0x59, 0x5e, 0x56, 0x5a, 0x57, 0x59, 0x5b, 0x54, 0x59, 0x52, 0x5e, - 0x5a, 0x58, 0x5b, 0x56, 0x52, 0x54, 0x5f, 0x58, 0x5a, 0x56, 0x5b, 0x55, - 0x5e, 0x5c, 0x54, 0x5a, 0x54, 0x59, 0x5d, 0x5c, 0x56, 0x5d, 0x58, 0x5c, - 0x59, 0x58, 0x56, 0x56, 0x59, 0x5a, 0x60, 0x57, 0x5b, 0x57, 0x54, 0x5b, - 0x56, 0x59, 0x52, 0x5f, 0x54, 0x56, 0x5a, 0x57, 0x53, 0x54, 0x5f, 0x58, - 0x59, 0x56, 0x5b, 0x56, 0x5d, 0x5d, 0x52, 0x5b, 0x55, 0x5a, 0x5c, 0x5d, - 0x58, 0x5e, 0x57, 0x5b, 0x58, 0x58, 0x56, 0x58, 0x5a, 0x5b, 0x5e, 0x58, - 0x5a, 0x56, 0x55, 0x57, 0x56, 0x58, 0x52, 0x5f, 0x56, 0x58, 0x5b, 0x58, - 0x53, 0x54, 0x5d, 0x58, 0x5a, 0x55, 0x5b, 0x57, 0x5e, 0x5d, 0x53, 0x5a, - 0x56, 0x59, 0x5b, 0x5e, 0x57, 0x5d, 0x57, 0x5b, 0x59, 0x58, 0x57, 0x57, - 0x59, 0x5b, 0x5c, 0x58, 0x5a, 0x57, 0x5a, 0x5b, 0x55, 0x5a, 0x52, 0x5f, - 0x55, 0x58, 0x5a, 0x56, 0x53, 0x52, 0x5e, 0x59, 0x58, 0x55, 0x5a, 0x56, - 0x5c, 0x5c, 0x54, 0x5a, 0x57, 0x59, 0x5d, 0x5e, 0x57, 0x5f, 0x57, 0x5e, - 0x59, 0x5a, 0x58, 0x56, 0x5b, 0x59, 0x5b, 0x5a, 0x5c, 0x59, 0x5a, 0x56, - 0x56, 0x59, 0x52, 0x5f, 0x57, 0x57, 0x5d, 0x56, 0x52, 0x56, 0x5e, 0x5a, - 0x59, 0x55, 0x59, 0x55, 0x5f, 0x5d, 0x54, 0x5c, 0x56, 0x59, 0x5c, 0x5c, - 0x56, 0x5c, 0x57, 0x59, 0x58, 0x59, 0x57, 0x56, 0x5a, 0x59, 0x53, 0x70, - 0x54, 0x4b, 0x5d, 0x51, 0x5c, 0x4e, 0x59, 0x61, 0x52, 0x41, 0x5e, 0x5d, - 0x59, 0x5c, 0x50, 0x59, 0x6c, 0x61, 0x43, 0x5d, 0x4f, 0x5a, 0x64, 0x5a, - 0x69, 0x5a, 0x5d, 0x49, 0x54, 0x56, 0x59, 0x55, 0x5d, 0x54, 0x63, 0x5c, - 0x59, 0x5c, 0x5d, 0x58, 0x59, 0x5c, 0x63, 0x55, 0x58, 0x5b, 0x58, 0x5a, - 0x5a, 0x5b, 0x61, 0x59, 0x58, 0x5c, 0x60, 0x5c, 0x5d, 0x58, 0x59, 0x58, - 0x59, 0x5e, 0x6a, 0x62, 0x60, 0x58, 0x61, 0x60, 0x57, 0x58, 0x59, 0x61, - 0x57, 0x56, 0x58, 0x5a, 0x56, 0x52, 0x5a, 0x51, 0x5b, 0x71, 0x55, 0x61, - 0x5d, 0x5a, 0x59, 0x5b, 0x56, 0x4e, 0x5f, 0x59, 0x58, 0x5e, 0x62, 0x59, - 0x56, 0x58, 0x54, 0x61, 0x4d, 0x58, 0x42, 0x61, 0x5b, 0x5e, 0x56, 0x5a, - 0x52, 0x4b, 0x58, 0x64, 0x4e, 0x59, 0x5e, 0x5a, 0x57, 0x4e, 0x5a, 0x5e, - 0x56, 0x5a, 0x58, 0x58, 0x60, 0x4b, 0x59, 0x3e, 0x58, 0x4d, 0x50, 0x47, - 0x59, 0x5c, 0x45, 0x54, 0x69, 0x5b, 0x69, 0x5e, 0x55, 0x5c, 0x5c, 0x54, - 0x54, 0x5f, 0x5b, 0x67, 0x5d, 0x5f, 0x58, 0x5c, 0x72, 0x55, 0x5b, 0x58, - 0x60, 0x4d, 0x5e, 0x5e, 0x5a, 0x51, 0x59, 0x5d, 0x55, 0x52, 0x59, 0x63, - 0x59, 0x53, 0x5c, 0x4c, 0x59, 0x66, 0x63, 0x5d, 0x6f, 0x5c, 0x52, 0x5f, - 0x58, 0x56, 0x5e, 0x46, 0x52, 0x59, 0x55, 0x58, 0x5b, 0x58, 0x5c, 0x4c, - 0x5d, 0x66, 0x5b, 0x5b, 0x56, 0x4d, 0x5f, 0x64, 0x57, 0x51, 0x53, 0x58, - 0x5a, 0x5c, 0x58, 0x52, 0x5a, 0x54, 0x5a, 0x57, 0x58, 0x58, 0x52, 0x56, - 0x54, 0x5c, 0x51, 0x60, 0x4e, 0x53, 0x5c, 0x4d, 0x61, 0x65, 0x47, 0x60, - 0x52, 0x64, 0x58, 0x4d, 0x59, 0x51, 0x73, 0x55, 0x5d, 0x5a, 0x5e, 0x4d, - 0x5a, 0x53, 0x63, 0x55, 0x58, 0x54, 0x58, 0x58, 0x58, 0x57, 0x5e, 0x59, - 0x59, 0x50, 0x5d, 0x59, 0x5e, 0x5d, 0x53, 0x62, 0x53, 0x58, 0x67, 0x5e, - 0x59, 0x5c, 0x66, 0x5c, 0x58, 0x58, 0x5d, 0x5c, 0x59, 0x63, 0x58, 0x58, - 0x5f, 0x4f, 0x58, 0x5c, 0x57, 0x5b, 0x57, 0x55, 0x5a, 0x57, 0x59, 0x5f, - 0x55, 0x50, 0x56, 0x5a, 0x59, 0x60, 0x56, 0x5b, 0x64, 0x5c, 0x4e, 0x66, - 0x5b, 0x5a, 0x5d, 0x58, 0x54, 0x5d, 0x52, 0x52, 0x59, 0x57, 0x5b, 0x55, - 0x5d, 0x5e, 0x58, 0x62, 0x58, 0x56, 0x63, 0x4f, 0x4f, 0x6c, 0x52, 0x6e, - 0x54, 0x5d, 0x58, 0x65, 0x5a, 0x53, 0x62, 0x5b, 0x59, 0x59, 0x64, 0x5a, - 0x5c, 0x57, 0x4b, 0x54, 0x5c, 0x60, 0x66, 0x5f, 0x4e, 0x56, 0x52, 0x5f, - 0x5a, 0x60, 0x57, 0x5f, 0x5a, 0x50, 0x58, 0x53, 0x57, 0x53, 0x58, 0x57, - 0x57, 0x61, 0x5f, 0x66, 0x5f, 0x55, 0x59, 0x52, 0x59, 0x51, 0x49, 0x59, - 0x59, 0x5a, 0x54, 0x59, 0x56, 0x5e, 0x56, 0x5f, 0x5b, 0x62, 0x52, 0x48, - 0x52, 0x55, 0x59, 0x4f, 0x63, 0x55, 0x5c, 0x4c, 0x5a, 0x56, 0x57, 0x5e, - 0x5a, 0x5c, 0x66, 0x60, 0x58, 0x52, 0x52, 0x68, 0x5a, 0x5d, 0x59, 0x62, - 0x5b, 0x58, 0x64, 0x59, 0x59, 0x59, 0x67, 0x56, 0x67, 0x5d, 0x4e, 0x60, - 0x5c, 0x58, 0x60, 0x51, 0x51, 0x63, 0x60, 0x5c, 0x59, 0x5a, 0x5d, 0x59, - 0x5a, 0x60, 0x66, 0x58, 0x59, 0x59, 0x57, 0x59, 0x58, 0x57, 0x5c, 0x5a, - 0x52, 0x5a, 0x59, 0x59, 0x57, 0x58, 0x5e, 0x56, 0x59, 0x5b, 0x5d, 0x5e, - 0x6b, 0x5f, 0x54, 0x5a, 0x5d, 0x5d, 0x66, 0x5c, 0x51, 0x64, 0x66, 0x58, - 0x58, 0x59, 0x5a, 0x5f, 0x57, 0x5e, 0x59, 0x63, 0x5b, 0x54, 0x56, 0x5b, - 0x58, 0x51, 0x60, 0x53, 0x55, 0x57, 0x57, 0x56, 0x57, 0x58, 0x5c, 0x58, - 0x5c, 0x61, 0x59, 0x5e, 0x66, 0x62, 0x56, 0x59, 0x58, 0x58, 0x5d, 0x5a, - 0x53, 0x5b, 0x5b, 0x56, 0x5c, 0x56, 0x5d, 0x5f, 0x56, 0x5b, 0x58, 0x63, - 0x59, 0x55, 0x5c, 0x5e, 0x59, 0x59, 0x58, 0x56, 0x5a, 0x58, 0x5a, 0x58, - 0x59, 0x55, 0x5c, 0x55, 0x58, 0x5d, 0x5d, 0x5c, 0x5c, 0x60, 0x53, 0x5e, - 0x58, 0x57, 0x5a, 0x57, 0x55, 0x59, 0x50, 0x5e, 0x5a, 0x58, 0x5b, 0x5d, - 0x58, 0x58, 0x58, 0x5c, 0x5a, 0x53, 0x59, 0x58, 0x57, 0x5d, 0x5e, 0x5c, - 0x56, 0x5e, 0x59, 0x5c, 0x59, 0x50, 0x5c, 0x5e, 0x59, 0x5a, 0x5b, 0x5b, - 0x51, 0x51, 0x54, 0x59, 0x61, 0x5f, 0x52, 0x53, 0x68, 0x52, 0x51, 0x56, - 0x56, 0x64, 0x59, 0x58, 0x5c, 0x64, 0x55, 0x5c, 0x5c, 0x5c, 0x5c, 0x5a, - 0x59, 0x51, 0x57, 0x53, 0x52, 0x5d, 0x5a, 0x5b, 0x5a, 0x5a, 0x63, 0x56, - 0x59, 0x59, 0x60, 0x57, 0x5d, 0x58, 0x56, 0x49, 0x5a, 0x5d, 0x56, 0x64, - 0x52, 0x5c, 0x5e, 0x5d, 0x57, 0x57, 0x5e, 0x5e, 0x58, 0x59, 0x59, 0x68, - 0x5b, 0x54, 0x55, 0x58, 0x57, 0x56, 0x52, 0x5f, 0x5a, 0x55, 0x59, 0x5d, - 0x5a, 0x55, 0x59, 0x5b, 0x58, 0x5c, 0x59, 0x5b, 0x62, 0x5d, 0x51, 0x5f, - 0x58, 0x59, 0x5b, 0x53, 0x55, 0x5e, 0x5f, 0x55, 0x5a, 0x5c, 0x59, 0x56, - 0x58, 0x62, 0x5a, 0x5c, 0x58, 0x59, 0x5f, 0x5a, 0x58, 0x5a, 0x61, 0x56, - 0x56, 0x5a, 0x58, 0x5b, 0x5a, 0x5a, 0x5f, 0x5a, 0x57, 0x5a, 0x62, 0x57, - 0x5d, 0x5e, 0x59, 0x57, 0x5a, 0x5b, 0x6a, 0x60, 0x5f, 0x59, 0x65, 0x5d, - 0x5a, 0x5d, 0x5d, 0x62, 0x56, 0x55, 0x57, 0x57, 0x5c, 0x57, 0x69, 0x54, - 0x5b, 0x48, 0x49, 0x59, 0x48, 0x52, 0x59, 0x62, 0x58, 0x5b, 0x63, 0x55, - 0x58, 0x5b, 0x65, 0x56, 0x75, 0x6d, 0x53, 0x54, 0x59, 0x5a, 0x5e, 0x45, - 0x74, 0x50, 0x52, 0x5e, 0x58, 0x54, 0x5e, 0x5a, 0x5d, 0x5e, 0x5a, 0x62, - 0x59, 0x57, 0x59, 0x5e, 0x58, 0x58, 0x56, 0x55, 0x58, 0x5b, 0x58, 0x58, - 0x59, 0x55, 0x5d, 0x5a, 0x59, 0x58, 0x5b, 0x5b, 0x63, 0x57, 0x56, 0x59, - 0x5b, 0x5b, 0x5d, 0x5b, 0x57, 0x5c, 0x62, 0x5e, 0x5d, 0x59, 0x5a, 0x5d, - 0x5c, 0x57, 0x5d, 0x5a, 0x62, 0x52, 0x57, 0x5e, 0x54, 0x5a, 0x61, 0x51, - 0x56, 0x55, 0x58, 0x59, 0x59, 0x4e, 0x44, 0x59, 0x58, 0x5a, 0x57, 0x53, - 0x74, 0x5a, 0x4f, 0x5b, 0x57, 0x56, 0x50, 0x55, 0x52, 0x56, 0x58, 0x58, - 0x5f, 0x54, 0x59, 0x58, 0x5d, 0x59, 0x64, 0x54, 0x55, 0x60, 0x56, 0x58, - 0x5b, 0x53, 0x50, 0x4f, 0x5c, 0x57, 0x59, 0x5f, 0x58, 0x54, 0x5f, 0x58, - 0x59, 0x57, 0x5d, 0x58, 0x4e, 0x5c, 0x56, 0x5a, 0x57, 0x5b, 0x54, 0x5a, - 0x56, 0x55, 0x5c, 0x5b, 0x58, 0x57, 0x58, 0x60, 0x53, 0x5a, 0x58, 0x5b, - 0x5c, 0x4e, 0x54, 0x5f, 0x5a, 0x58, 0x56, 0x5a, 0x62, 0x50, 0x58, 0x5b, - 0x58, 0x53, 0x59, 0x56, 0x5a, 0x5c, 0x60, 0x57, 0x62, 0x5e, 0x55, 0x64, - 0x54, 0x5d, 0x63, 0x54, 0x4d, 0x5d, 0x61, 0x59, 0x5f, 0x59, 0x5d, 0x55, - 0x59, 0x5e, 0x59, 0x5a, 0x5b, 0x5a, 0x5a, 0x6d, 0x59, 0x5a, 0x53, 0x58, - 0x52, 0x6a, 0x5a, 0x53, 0x58, 0x5a, 0x55, 0x6d, 0x5a, 0x49, 0x53, 0x61, - 0x51, 0x51, 0x54, 0x6c, 0x52, 0x61, 0x5d, 0x69, 0x5f, 0x6d, 0x5a, 0x5d, - 0x52, 0x53, 0x56, 0x6e, 0x57, 0x65, 0x5a, 0x57, 0x60, 0x42, 0x5c, 0x6c, - 0x56, 0x33, 0x4d, 0x69, 0x5d, 0x56, 0x59, 0x64, 0x57, 0x43, 0x63, 0x59, - 0x59, 0x5f, 0x82, 0x56, 0x72, 0x5e, 0x39, 0x54, 0x57, 0x5d, 0x58, 0x5f, - 0x47, 0x69, 0x4f, 0x53, 0x4c, 0x57, 0x5b, 0x5b, 0x5d, 0x5e, 0x7d, 0x60, - 0x5b, 0x63, 0x5c, 0x57, 0x52, 0x45, 0x69, 0x52, 0x60, 0x5a, 0x58, 0x54, - 0x58, 0x55, 0x5b, 0x59, 0x5d, 0x58, 0x56, 0x5b, 0x61, 0x56, 0x79, 0x65, - 0x58, 0x5f, 0x5e, 0x5b, 0x61, 0x55, 0x69, 0x60, 0x63, 0x52, 0x5b, 0x56, - 0x78, 0x50, 0x5b, 0x5a, 0x5b, 0x51, 0x58, 0x59, 0x5a, 0x5a, 0x58, 0x59, - 0x55, 0x56, 0x59, 0x55, 0x56, 0x55, 0x54, 0x5a, 0x5a, 0x5d, 0x54, 0x56, - 0x5d, 0x5e, 0x4d, 0x65, 0x58, 0x56, 0x52, 0x54, 0x55, 0x5b, 0x54, 0x53, - 0x5d, 0x5b, 0x5b, 0x51, 0x5f, 0x5a, 0x5b, 0x5c, 0x5c, 0x50, 0x56, 0x5a, - 0x58, 0x57, 0x5a, 0x59, 0x5a, 0x56, 0x59, 0x57, 0x58, 0x4d, 0x5b, 0x55, - 0x59, 0x5d, 0x5a, 0x5a, 0x5d, 0x5d, 0x56, 0x5d, 0x59, 0x56, 0x50, 0x56, - 0x57, 0x5a, 0x5b, 0x57, 0x59, 0x58, 0x58, 0x5a, 0x5d, 0x58, 0x59, 0x58, - 0x58, 0x50, 0x54, 0x55, 0x5b, 0x5e, 0x5c, 0x56, 0x59, 0x5d, 0x59, 0x55, - 0x54, 0x52, 0x55, 0x61, 0x59, 0x5b, 0x4e, 0x5c, 0x58, 0x58, 0x4f, 0x5d, - 0x64, 0x55, 0x4d, 0x5f, 0x5c, 0x56, 0x5e, 0x55, 0x5d, 0x51, 0x59, 0x57, - 0x53, 0x55, 0x57, 0x5b, 0x4f, 0x54, 0x59, 0x57, 0x58, 0x67, 0x54, 0x5b, - 0x58, 0x61, 0x58, 0x56, 0x56, 0x55, 0x5b, 0x5b, 0x58, 0x5d, 0x5d, 0x59, - 0x59, 0x56, 0x52, 0x62, 0x62, 0x55, 0x4d, 0x5b, 0x59, 0x55, 0x51, 0x59, - 0x5b, 0x57, 0x5b, 0x5a, 0x56, 0x53, 0x58, 0x63, 0x5d, 0x56, 0x5d, 0x5a, - 0x59, 0x58, 0x5a, 0x56, 0x55, 0x59, 0x58, 0x5e, 0x5a, 0x58, 0x5c, 0x5d, - 0x58, 0x59, 0x5f, 0x57, 0x59, 0x5f, 0x54, 0x59, 0x60, 0x58, 0x5a, 0x5a, - 0x5c, 0x5d, 0x57, 0x5b, 0x57, 0x5f, 0x5a, 0x58, 0x56, 0x5a, 0x5a, 0x61, - 0x5e, 0x52, 0x5a, 0x60, 0x52, 0x5c, 0x62, 0x52, 0x4f, 0x54, 0x59, 0x5a, - 0x59, 0x52, 0x45, 0x56, 0x59, 0x5a, 0x5a, 0x58, 0x69, 0x5a, 0x50, 0x5c, - 0x5b, 0x5a, 0x51, 0x55, 0x56, 0x59, 0x61, 0x59, 0x59, 0x58, 0x5a, 0x57, - 0x5b, 0x55, 0x5b, 0x58, 0x5c, 0x59, 0x61, 0x4a, 0x58, 0x55, 0x62, 0x5e, - 0x60, 0x5d, 0x5a, 0x62, 0x5a, 0x54, 0x5b, 0x50, 0x5a, 0x65, 0x61, 0x53, - 0x6b, 0x5c, 0x57, 0x5e, 0x55, 0x59, 0x69, 0x5a, 0x4d, 0x60, 0x43, 0x5f, - 0x53, 0x54, 0x5a, 0x5d, 0x5b, 0x56, 0x57, 0x4e, 0x5a, 0x54, 0x5e, 0x5c, - 0x59, 0x58, 0x59, 0x5c, 0x56, 0x5b, 0x59, 0x59, 0x57, 0x55, 0x5d, 0x59, - 0x59, 0x5b, 0x5d, 0x58, 0x52, 0x59, 0x4d, 0x60, 0x5b, 0x5b, 0x56, 0x59, - 0x59, 0x5d, 0x59, 0x5c, 0x59, 0x5b, 0x59, 0x58, 0x5a, 0x5c, 0x5a, 0x58, - 0x55, 0x4e, 0x5a, 0x5b, 0x4e, 0x5f, 0x56, 0x5a, 0x5f, 0x5c, 0x58, 0x64, - 0x58, 0x4d, 0x5a, 0x5d, 0x5a, 0x48, 0x5f, 0x55, 0x5e, 0x57, 0x4d, 0x4c, - 0x57, 0x64, 0x56, 0x62, 0x5c, 0x5c, 0x65, 0x5e, 0x54, 0x53, 0x5b, 0x64, - 0x55, 0x57, 0x54, 0x59, 0x5e, 0x5d, 0x4b, 0x6f, 0x58, 0x66, 0x56, 0x4f, - 0x4f, 0x5e, 0x59, 0x5e, 0x59, 0x55, 0x67, 0x5c, 0x59, 0x55, 0x61, 0x52, - 0x61, 0x5a, 0x4f, 0x56, 0x52, 0x60, 0x3e, 0x62, 0x53, 0x5e, 0x61, 0x58, - 0x58, 0x55, 0x5b, 0x5e, 0x57, 0x64, 0x75, 0x5c, 0x59, 0x56, 0x65, 0x55, - 0x58, 0x58, 0x57, 0x5a, 0x51, 0x5b, 0x5a, 0x66, 0x58, 0x58, 0x67, 0x5b, - 0x5a, 0x5b, 0x6d, 0x4b, 0x60, 0x67, 0x55, 0x57, 0x62, 0x5d, 0x68, 0x5a, - 0x62, 0x61, 0x59, 0x64, 0x57, 0x5e, 0x5d, 0x5c, 0x5b, 0x60, 0x59, 0x59, - 0x5f, 0x55, 0x64, 0x61, 0x59, 0x55, 0x55, 0x56, 0x55, 0x58, 0x5a, 0x5f, - 0x57, 0x58, 0x60, 0x5a, 0x5a, 0x5d, 0x5f, 0x58, 0x63, 0x5f, 0x51, 0x64, - 0x5a, 0x5b, 0x63, 0x52, 0x50, 0x5e, 0x56, 0x57, 0x5a, 0x5a, 0x5c, 0x5a, - 0x59, 0x60, 0x5b, 0x5c, 0x57, 0x58, 0x56, 0x50, 0x5a, 0x58, 0x5f, 0x51, - 0x5b, 0x55, 0x59, 0x5b, 0x5a, 0x53, 0x57, 0x57, 0x59, 0x5f, 0x56, 0x5a, - 0x55, 0x5c, 0x5d, 0x61, 0x5c, 0x53, 0x4f, 0x5d, 0x59, 0x58, 0x60, 0x53, - 0x5c, 0x55, 0x56, 0x59, 0x5b, 0x59, 0x5a, 0x58, 0x60, 0x66, 0x54, 0x60, - 0x55, 0x5d, 0x65, 0x4a, 0x54, 0x5a, 0x59, 0x5c, 0x59, 0x52, 0x5e, 0x56, - 0x59, 0x52, 0x5d, 0x58, 0x5c, 0x59, 0x56, 0x60, 0x52, 0x60, 0x61, 0x60, - 0x5b, 0x5d, 0x5f, 0x5e, 0x5e, 0x59, 0x5b, 0x5d, 0x57, 0x65, 0x59, 0x60, - 0x55, 0x5c, 0x57, 0x5d, 0x5a, 0x57, 0x5a, 0x4e, 0x56, 0x5a, 0x59, 0x59, - 0x5b, 0x5d, 0x50, 0x58, 0x58, 0x5a, 0x57, 0x5d, 0x6f, 0x59, 0x59, 0x53, - 0x55, 0x58, 0x51, 0x58, 0x56, 0x57, 0x55, 0x55, 0x5d, 0x55, 0x5a, 0x5a, - 0x57, 0x59, 0x59, 0x57, 0x5a, 0x54, 0x5c, 0x56, 0x59, 0x63, 0x57, 0x53, - 0x56, 0x58, 0x58, 0x5a, 0x57, 0x53, 0x61, 0x58, 0x5b, 0x5e, 0x67, 0x55, - 0x57, 0x57, 0x58, 0x5f, 0x61, 0x5a, 0x56, 0x62, 0x5b, 0x5c, 0x57, 0x5e, - 0x54, 0x56, 0x5c, 0x61, 0x5e, 0x5e, 0x58, 0x5a, 0x5b, 0x5a, 0x5b, 0x58, - 0x59, 0x52, 0x61, 0x59, 0x59, 0x58, 0x59, 0x59, 0x58, 0x59, 0x5b, 0x55, - 0x58, 0x5c, 0x5a, 0x5b, 0x63, 0x5e, 0x57, 0x54, 0x56, 0x55, 0x64, 0x5d, - 0x52, 0x5f, 0x65, 0x5b, 0x5a, 0x56, 0x5b, 0x59, 0x5c, 0x5d, 0x5a, 0x63, - 0x5c, 0x57, 0x5e, 0x58, 0x57, 0x4f, 0x52, 0x60, 0x5a, 0x5c, 0x58, 0x5c, - 0x58, 0x55, 0x5e, 0x59, 0x59, 0x5a, 0x5e, 0x57, 0x63, 0x5f, 0x54, 0x57, - 0x5b, 0x58, 0x54, 0x5b, 0x55, 0x59, 0x59, 0x58, 0x58, 0x59, 0x5d, 0x5b, - 0x57, 0x60, 0x5c, 0x51, 0x58, 0x5a, 0x5e, 0x58, 0x5a, 0x57, 0x65, 0x56, - 0x58, 0x58, 0x59, 0x5a, 0x59, 0x5a, 0x62, 0x59, 0x59, 0x5b, 0x65, 0x5c, - 0x5e, 0x5c, 0x57, 0x5b, 0x58, 0x5f, 0x69, 0x5f, 0x5d, 0x59, 0x63, 0x60, - 0x58, 0x5a, 0x5b, 0x61, 0x5b, 0x57, 0x56, 0x56, 0x5d, 0x55, 0x5e, 0x5a, - 0x5a, 0x57, 0x5f, 0x51, 0x59, 0x58, 0x58, 0x5c, 0x5c, 0x54, 0x58, 0x56, - 0x59, 0x5e, 0x5f, 0x53, 0x67, 0x5d, 0x56, 0x56, 0x5a, 0x55, 0x65, 0x5a, - 0x51, 0x5d, 0x60, 0x5d, 0x5a, 0x59, 0x5a, 0x58, 0x5a, 0x64, 0x56, 0x58, - 0x56, 0x4f, 0x3d, 0x54, 0xa5, 0x2d, 0x4d, 0x64, 0x54, 0x60, 0x5a, 0x63, - 0x55, 0x4c, 0x7a, 0x55, 0x5a, 0x56, 0x7b, 0x4f, 0x4f, 0x58, 0x50, 0x58, - 0x5e, 0x55, 0x42, 0x55, 0x87, 0x67, 0x74, 0x59, 0x4e, 0x54, 0x5a, 0x61, - 0x4b, 0x6b, 0x64, 0x64, 0x5a, 0x52, 0x58, 0x57, 0x58, 0x60, 0x5d, 0x51, - 0x65, 0x5b, 0x59, 0x52, 0x58, 0x58, 0x57, 0x58, 0x59, 0x58, 0x52, 0x58, - 0x52, 0x58, 0x51, 0x59, 0x5e, 0x57, 0x4a, 0x5d, 0x55, 0x57, 0x5a, 0x57, - 0x5f, 0x57, 0x59, 0x5a, 0x53, 0x56, 0x58, 0x5a, 0x5b, 0x50, 0x5b, 0x5c, - 0x54, 0x53, 0x56, 0x5c, 0x57, 0x5d, 0x58, 0x5d, 0x5a, 0x51, 0x60, 0x55, - 0x59, 0x60, 0x5c, 0x5c, 0x5b, 0x56, 0x53, 0x5f, 0x5e, 0x57, 0x5c, 0x58, - 0x5a, 0x5e, 0x50, 0x5b, 0x55, 0x58, 0x5a, 0x5d, 0x58, 0x5a, 0x6a, 0x5e, - 0x59, 0x55, 0x5b, 0x5a, 0x5a, 0x54, 0x5b, 0x59, 0x5b, 0x57, 0x59, 0x5e, - 0x58, 0x59, 0x59, 0x56, 0x58, 0x58, 0x5b, 0x58, 0x61, 0x5d, 0x53, 0x5b, - 0x5a, 0x58, 0x62, 0x5a, 0x55, 0x5f, 0x5e, 0x56, 0x5b, 0x59, 0x5d, 0x55, - 0x5c, 0x60, 0x5a, 0x5b, 0x60, 0x57, 0x58, 0x49, 0x4b, 0x47, 0x43, 0x78, - 0x7e, 0x52, 0x58, 0x5d, 0x58, 0x41, 0x69, 0x65, 0x59, 0x4f, 0x65, 0x4b, - 0x78, 0x52, 0x59, 0x4d, 0x4f, 0x4e, 0x45, 0x52, 0x7b, 0x5f, 0x74, 0x5b, - 0x59, 0x63, 0x5c, 0x5e, 0x5a, 0x55, 0x62, 0x49, 0x59, 0x55, 0x5e, 0x59, - 0x57, 0x5e, 0x54, 0x57, 0x5a, 0x58, 0x59, 0x5e, 0x57, 0x5b, 0x5b, 0x5c, - 0x59, 0x5a, 0x59, 0x5c, 0x57, 0x5a, 0x5b, 0x5f, 0x58, 0x58, 0x4d, 0x56, - 0x54, 0x53, 0x57, 0x5b, 0x5f, 0x58, 0x5a, 0x57, 0x56, 0x5d, 0x59, 0x5d, - 0x5e, 0x4c, 0x59, 0x6a, 0x56, 0x69, 0x51, 0x62, 0x65, 0x56, 0x59, 0x5c, - 0x56, 0x4c, 0x69, 0x5c, 0x59, 0x5d, 0x56, 0x5b, 0x64, 0x62, 0x4d, 0x55, - 0x56, 0x57, 0x60, 0x58, 0x4d, 0x56, 0x69, 0x55, 0x59, 0x5a, 0x5c, 0x5b, - 0x55, 0x69, 0x63, 0x5e, 0x59, 0x54, 0x5b, 0x59, 0x5a, 0x58, 0x5b, 0x5a, - 0x5a, 0x59, 0x59, 0x5b, 0x57, 0x57, 0x5b, 0x58, 0x59, 0x57, 0x5d, 0x5a, - 0x5d, 0x5d, 0x51, 0x5e, 0x5c, 0x58, 0x56, 0x51, 0x57, 0x61, 0x57, 0x57, - 0x57, 0x54, 0x59, 0x50, 0x61, 0x57, 0x5c, 0x60, 0x5a, 0x65, 0x53, 0x58, - 0x4e, 0x58, 0x63, 0x4e, 0x51, 0x51, 0x58, 0x5b, 0x52, 0x52, 0x3e, 0x5c, - 0x59, 0x5a, 0x52, 0x5b, 0x74, 0x58, 0x60, 0x5c, 0x56, 0x5f, 0x4e, 0x58, - 0x4e, 0x58, 0x5f, 0x57, 0x5b, 0x52, 0x58, 0x56, 0x60, 0x5a, 0x5e, 0x55, - 0x5a, 0x52, 0x4f, 0x5c, 0x52, 0x59, 0x53, 0x5b, 0x5c, 0x4c, 0x59, 0x5b, - 0x5b, 0x58, 0x51, 0x5a, 0x59, 0x51, 0x5f, 0x57, 0x5b, 0x5a, 0x54, 0x56, - 0x5a, 0x5f, 0x4a, 0x55, 0x4f, 0x5c, 0x6c, 0x50, 0x56, 0x58, 0x5c, 0x5a, - 0x56, 0x56, 0x54, 0x5c, 0x5f, 0x57, 0x5a, 0x59, 0x58, 0x57, 0x60, 0x5b, - 0x5b, 0x57, 0x59, 0x5d, 0x58, 0x58, 0x5d, 0x5d, 0x58, 0x5f, 0x5b, 0x5c, - 0x5d, 0x5b, 0x56, 0x5b, 0x5c, 0x59, 0x53, 0x5a, 0x58, 0x61, 0x4a, 0x58, - 0x58, 0x50, 0x5b, 0x5e, 0x58, 0x57, 0x5d, 0x58, 0x5d, 0x4b, 0x59, 0x63, - 0x50, 0x4b, 0x56, 0x57, 0x5e, 0x5b, 0x59, 0x5a, 0x57, 0x48, 0x65, 0x5a, - 0x59, 0x5f, 0x62, 0x5b, 0x69, 0x5b, 0x4a, 0x56, 0x5f, 0x56, 0x58, 0x5a, - 0x5b, 0x62, 0x4f, 0x5d, 0x50, 0x52, 0x5a, 0x66, 0x58, 0x59, 0x68, 0x5a, - 0x50, 0x4d, 0x5b, 0x58, 0x4b, 0x5f, 0x54, 0x71, 0x54, 0x57, 0x5a, 0x63, - 0x5d, 0x4f, 0x5c, 0x5b, 0x58, 0x52, 0x61, 0x56, 0x5f, 0x54, 0x4b, 0x59, - 0x5d, 0x50, 0x56, 0x55, 0x5f, 0x6a, 0x69, 0x4a, 0x58, 0x53, 0x57, 0x5e, - 0x5b, 0x57, 0x60, 0x5a, 0x5b, 0x57, 0x61, 0x66, 0x56, 0x4f, 0x5b, 0x57, - 0x5b, 0x55, 0x5a, 0x57, 0x5d, 0x55, 0x52, 0x56, 0x5b, 0x53, 0x5a, 0x53, - 0x79, 0x5b, 0x4e, 0x52, 0x50, 0x60, 0x58, 0x65, 0x59, 0x67, 0x55, 0x4e, - 0x54, 0x51, 0x5b, 0x52, 0x56, 0x67, 0x58, 0x5c, 0x60, 0x5b, 0x53, 0x53, - 0x58, 0x55, 0x68, 0x53, 0x5d, 0x67, 0x59, 0x52, 0x58, 0x54, 0x53, 0x5e, - 0x58, 0x62, 0x50, 0x5a, 0x7a, 0x62, 0x50, 0x56, 0x5a, 0x48, 0x5e, 0x61, - 0x27, 0x5c, 0x42, 0x4b, 0x58, 0x46, 0x5d, 0x64, 0x55, 0x63, 0x60, 0x5a, - 0x59, 0x53, 0x4b, 0x6b, 0x51, 0x50, 0x50, 0x57, 0x5d, 0x54, 0x58, 0x35, - 0x58, 0x49, 0x46, 0x49, 0x59, 0x5d, 0x4d, 0x5b, 0x64, 0x54, 0x47, 0x5f, - 0x4f, 0x59, 0x5d, 0x50, 0x54, 0x5c, 0x5b, 0x68, 0x50, 0x64, 0x54, 0x56, - 0x6b, 0x57, 0x5b, 0x57, 0x5e, 0x45, 0x5d, 0x55, 0x52, 0x75, 0x73, 0x59, - 0x58, 0x55, 0x59, 0x57, 0x57, 0x44, 0x37, 0x55, 0x59, 0x5d, 0x5b, 0x56, - 0x6c, 0x55, 0x49, 0x5b, 0x58, 0x58, 0x4b, 0x60, 0x55, 0x5a, 0x58, 0x55, - 0x59, 0x54, 0x5b, 0x57, 0x4f, 0x61, 0x54, 0x63, 0x56, 0x5c, 0x5b, 0x58, - 0x5a, 0x58, 0x57, 0x56, 0x55, 0x36, 0x59, 0x61, 0x55, 0x4f, 0x6f, 0x42, - 0x5a, 0x71, 0x4a, 0x3e, 0x5d, 0x5e, 0x4d, 0x56, 0x37, 0x56, 0x47, 0x4f, - 0x5e, 0x5e, 0x4a, 0x49, 0x44, 0x54, 0x5a, 0x51, 0x57, 0x36, 0x59, 0x4d, - 0x59, 0x5a, 0x5d, 0x59, 0x59, 0x5e, 0x5b, 0x57, 0x59, 0x5e, 0x59, 0x5a, - 0x57, 0x58, 0x62, 0x5d, 0x59, 0x56, 0x66, 0x5b, 0x5a, 0x59, 0x56, 0x5a, - 0x5d, 0x5e, 0x63, 0x64, 0x5f, 0x58, 0x5a, 0x5e, 0x57, 0x5b, 0x58, 0x63, - 0x56, 0x54, 0x57, 0x58, 0x5b, 0x52, 0x55, 0x55, 0x57, 0x62, 0x5c, 0x5a, - 0x5d, 0x5a, 0x57, 0x57, 0x59, 0x4f, 0x53, 0x5c, 0x57, 0x54, 0x4f, 0x5b, - 0x5a, 0x5b, 0x54, 0x63, 0x5d, 0x63, 0x4f, 0x58, 0x5c, 0x59, 0x56, 0x4f, - 0x5e, 0x54, 0x59, 0x57, 0x59, 0x61, 0x57, 0x5f, 0x5c, 0x53, 0x5b, 0x5c, - 0x58, 0x50, 0x55, 0x56, 0x5a, 0x54, 0x59, 0x59, 0x57, 0x51, 0x5b, 0x59, - 0x59, 0x5a, 0x5c, 0x57, 0x5d, 0x5b, 0x51, 0x5d, 0x59, 0x59, 0x5e, 0x59, - 0x5d, 0x5b, 0x61, 0x5b, 0x57, 0x5c, 0x5b, 0x57, 0x60, 0x60, 0x5a, 0x58, - 0x5d, 0x59, 0x56, 0x5d, 0x5a, 0x57, 0x54, 0x5a, 0x5a, 0x4e, 0x59, 0x5c, - 0x58, 0x55, 0x59, 0x53, 0x59, 0x5d, 0x5a, 0x58, 0x5d, 0x5c, 0x52, 0x5f, - 0x5b, 0x56, 0x5a, 0x54, 0x5a, 0x59, 0x60, 0x56, 0x59, 0x5c, 0x59, 0x53, - 0x5b, 0x5c, 0x5b, 0x5b, 0x5f, 0x59, 0x5a, 0x5b, 0x59, 0x62, 0x59, 0x57, - 0x58, 0x5c, 0x58, 0x5a, 0x57, 0x55, 0x5b, 0x5a, 0x58, 0x5b, 0x5e, 0x5a, - 0x5c, 0x57, 0x56, 0x61, 0x5e, 0x59, 0x57, 0x5e, 0x58, 0x5d, 0x56, 0x58, - 0x5a, 0x5b, 0x5a, 0x5b, 0x57, 0x55, 0x5a, 0x60, 0x5a, 0x53, 0x5a, 0x5b, - 0x53, 0x59, 0x56, 0x5a, 0x5b, 0x5c, 0x59, 0x5b, 0x5a, 0x53, 0x5e, 0x5c, - 0x59, 0x58, 0x5e, 0x53, 0x57, 0x5b, 0x4d, 0x58, 0x61, 0x59, 0x5a, 0x61, - 0x5f, 0x5b, 0x5c, 0x5f, 0x51, 0x5a, 0x5a, 0x5f, 0x58, 0x5b, 0x5c, 0x5a, - 0x5c, 0x55, 0x57, 0x5b, 0x5a, 0x58, 0x4f, 0x5f, 0x5a, 0x64, 0x59, 0x5a, - 0x5b, 0x5c, 0x64, 0x59, 0x59, 0x5a, 0x65, 0x56, 0x54, 0x59, 0x4b, 0x5b, - 0x54, 0x5f, 0x54, 0x65, 0x62, 0x5b, 0x45, 0x5c, 0x51, 0x5a, 0x59, 0x5f, - 0x4f, 0x5d, 0x65, 0x61, 0x58, 0x51, 0x5b, 0x5a, 0x5c, 0x5b, 0x52, 0x62, - 0x5f, 0x5a, 0x59, 0x57, 0x57, 0x4b, 0x59, 0x54, 0x5a, 0x5c, 0x5a, 0x5a, - 0x50, 0x5a, 0x4f, 0x5b, 0x5e, 0x59, 0x58, 0x5b, 0x5a, 0x57, 0x64, 0x5c, - 0x5e, 0x5a, 0x5b, 0x5a, 0x58, 0x51, 0x5e, 0x52, 0x5d, 0x55, 0x5d, 0x6a, - 0x54, 0x4c, 0x4d, 0x5d, 0x47, 0x53, 0x59, 0x5c, 0x5a, 0x4d, 0x52, 0x57, - 0x59, 0x61, 0x5b, 0x5e, 0x5a, 0x57, 0x54, 0x57, 0x55, 0x5d, 0x63, 0x66, - 0x51, 0x60, 0x5d, 0x5a, 0x59, 0x55, 0x5c, 0x5c, 0x56, 0x53, 0x5c, 0x5c, - 0x60, 0x53, 0x5e, 0x53, 0x59, 0x55, 0x56, 0x5d, 0x67, 0x5a, 0x59, 0x5d, - 0x58, 0x55, 0x53, 0x59, 0x59, 0x57, 0x50, 0x59, 0x6c, 0x5e, 0x5c, 0x5e, - 0x5b, 0x55, 0x59, 0x5f, 0x5b, 0x59, 0x53, 0x52, 0x58, 0x51, 0x5c, 0x5e, - 0x53, 0x63, 0x5b, 0x58, 0x56, 0x54, 0x54, 0x55, 0x5a, 0x5f, 0x59, 0x57, - 0x56, 0x55, 0x58, 0x59, 0x58, 0x56, 0x5a, 0x54, 0x58, 0x57, 0x56, 0x54, - 0x5d, 0x58, 0x4f, 0x65, 0x5b, 0x5b, 0x50, 0x5b, 0x54, 0x5d, 0x63, 0x5a, - 0x53, 0x5a, 0x53, 0x56, 0x5c, 0x58, 0x5a, 0x58, 0x57, 0x4b, 0x5a, 0x53, - 0x57, 0x62, 0x60, 0x7b, 0x69, 0x58, 0x58, 0x47, 0x5b, 0x4f, 0x49, 0x5b, - 0x5a, 0x5b, 0x3d, 0x5f, 0x5b, 0x5d, 0x4f, 0x4f, 0x5a, 0x58, 0x53, 0x61, - 0x54, 0x55, 0x4a, 0x52, 0x58, 0x4c, 0x5b, 0x4e, 0x4e, 0x4c, 0x57, 0x57, - 0x59, 0x54, 0x51, 0x62, 0x45, 0x71, 0x5e, 0x46, 0x5a, 0x59, 0x59, 0x59, - 0x57, 0x50, 0x4f, 0x59, 0x5a, 0x59, 0x5b, 0x59, 0x5e, 0x5a, 0x40, 0x5c, - 0x56, 0x5a, 0x47, 0x61, 0x4e, 0x61, 0x4d, 0x5b, 0x55, 0x55, 0x59, 0x5f, - 0x59, 0x58, 0x5e, 0x5b, 0x61, 0x4d, 0x59, 0x56, 0x57, 0x4a, 0x5a, 0x4e, - 0x56, 0x54, 0x58, 0x52, 0x55, 0x4c, 0x59, 0x55, 0x59, 0x62, 0x62, 0x5a, - 0x73, 0x5d, 0x51, 0x50, 0x54, 0x54, 0x56, 0x60, 0x54, 0x59, 0x5b, 0x5d, - 0x47, 0x4c, 0x5c, 0x63, 0x4e, 0x5f, 0x71, 0x5d, 0x56, 0x54, 0x5c, 0x57, - 0x58, 0x63, 0x55, 0x61, 0x5d, 0x61, 0x59, 0x5a, 0x64, 0x55, 0x46, 0x64, - 0x5a, 0x5b, 0x4c, 0x5e, 0x54, 0x5a, 0x53, 0x57, 0x59, 0x5d, 0x5f, 0x5d, - 0x50, 0x57, 0x62, 0x57, 0x57, 0x57, 0x5a, 0x5c, 0x4e, 0x61, 0x57, 0x51, - 0x56, 0x53, 0x56, 0x5a, 0x5a, 0x5a, 0x5e, 0x6b, 0x59, 0x5e, 0x5a, 0x58, - 0x5a, 0x5c, 0x46, 0x58, 0x59, 0x63, 0x5a, 0x5a, 0x54, 0x59, 0x51, 0x6a, - 0x69, 0x55, 0x51, 0x54, 0x54, 0x5f, 0x4e, 0x4d, 0x5d, 0x55, 0x5a, 0x57, - 0x53, 0x55, 0x56, 0x57, 0x55, 0x5d, 0x55, 0x55, 0x5a, 0x4f, 0x65, 0x56, - 0x62, 0x60, 0x57, 0x5b, 0x59, 0x58, 0x6b, 0x5b, 0x58, 0x5a, 0x61, 0x57, - 0x64, 0x6b, 0x56, 0x57, 0x5b, 0x5e, 0x60, 0x63, 0x59, 0x4e, 0x5a, 0x5f, - 0x56, 0x62, 0x53, 0x69, 0x57, 0x4b, 0x5a, 0x54, 0x63, 0x57, 0x4f, 0x50, - 0x5a, 0x4d, 0x68, 0x55, 0x5f, 0x52, 0x59, 0x56, 0x56, 0x55, 0x5b, 0x58, - 0x59, 0x5d, 0x55, 0x5b, 0x61, 0x60, 0x52, 0x4f, 0x54, 0x52, 0x59, 0x5e, - 0x4c, 0x5b, 0x56, 0x57, 0x57, 0x58, 0x5f, 0x62, 0x50, 0x54, 0x69, 0x63, - 0x5e, 0x61, 0x56, 0x64, 0x59, 0x56, 0x5d, 0x4c, 0x5f, 0x53, 0x5a, 0x5e, - 0x57, 0x55, 0x5d, 0x54, 0x59, 0x5b, 0x5f, 0x5a, 0x4f, 0x60, 0x48, 0x5f, - 0x5d, 0x58, 0x5e, 0x54, 0x55, 0x5c, 0x5d, 0x57, 0x63, 0x56, 0x5c, 0x5a, - 0x56, 0x5c, 0x58, 0x5e, 0x5f, 0x62, 0x55, 0x60, 0x5a, 0x53, 0x5c, 0x55, - 0x57, 0x5b, 0x59, 0x5f, 0x59, 0x59, 0x61, 0x55, 0x59, 0x5f, 0x5f, 0x5c, - 0x61, 0x60, 0x55, 0x5a, 0x51, 0x5a, 0x5a, 0x5e, 0x49, 0x5b, 0x58, 0x59, - 0x54, 0x55, 0x5a, 0x5e, 0x4a, 0x58, 0x5f, 0x68, 0x55, 0x52, 0x55, 0x5a, - 0x58, 0x56, 0x53, 0x58, 0x5a, 0x57, 0x5a, 0x5d, 0x56, 0x56, 0x5e, 0x58, - 0x59, 0x5b, 0x59, 0x5d, 0x61, 0x5a, 0x4d, 0x63, 0x5a, 0x56, 0x57, 0x57, - 0x57, 0x5b, 0x55, 0x59, 0x58, 0x5b, 0x5a, 0x56, 0x62, 0x5f, 0x5a, 0x5a, - 0x5e, 0x52, 0x5c, 0x52, 0x5b, 0x57, 0x5e, 0x69, 0x5e, 0x53, 0x59, 0x52, - 0x56, 0x54, 0x3b, 0x5a, 0x58, 0x4a, 0x56, 0x5f, 0x5a, 0x5c, 0x55, 0x5a, - 0x54, 0x5b, 0x4f, 0x5c, 0x4e, 0x45, 0x64, 0x4d, 0x5c, 0x59, 0x5c, 0x49, - 0x58, 0x4d, 0x51, 0x59, 0x58, 0x5b, 0x57, 0x5b, 0x58, 0x4f, 0x66, 0x5b, - 0x62, 0x5c, 0x59, 0x54, 0x5a, 0x58, 0x5d, 0x5b, 0x59, 0x57, 0x63, 0x5f, - 0x6f, 0x62, 0x52, 0x56, 0x52, 0x58, 0x5a, 0x5b, 0x4d, 0x6a, 0x69, 0x5a, - 0x58, 0x53, 0x5b, 0x64, 0x53, 0x5e, 0x5c, 0x64, 0x5c, 0x5b, 0x5f, 0x56, - 0x59, 0x56, 0x61, 0x56, 0x5a, 0x5e, 0x5c, 0x5d, 0x57, 0x57, 0x62, 0x5b, - 0x5d, 0x56, 0x62, 0x59, 0x5a, 0x61, 0x57, 0x5c, 0x5b, 0x5c, 0x5e, 0x5d, - 0x56, 0x5f, 0x5d, 0x5d, 0x59, 0x54, 0x5b, 0x5d, 0x5c, 0x61, 0x5b, 0x59, - 0x5a, 0x58, 0x58, 0x64, 0x5a, 0x52, 0x51, 0x4d, 0x58, 0x61, 0x58, 0x51, - 0x58, 0x58, 0x69, 0x5e, 0x58, 0x5f, 0x70, 0x5b, 0x66, 0x54, 0x4b, 0x64, - 0x4f, 0x57, 0x59, 0x57, 0x41, 0x69, 0x5f, 0x62, 0x64, 0x63, 0x5c, 0x58, - 0x57, 0x5c, 0x59, 0x58, 0x58, 0x4b, 0x5b, 0x54, 0x58, 0x57, 0x59, 0x5d, - 0x47, 0x51, 0x59, 0x51, 0x59, 0x59, 0x5b, 0x54, 0x58, 0x53, 0x42, 0x60, - 0x55, 0x59, 0x4c, 0x44, 0x5e, 0x57, 0x5d, 0x43, 0x52, 0x51, 0x57, 0x4e, - 0x55, 0x55, 0x5a, 0x4d, 0x51, 0x4f, 0x5a, 0x59, 0x5d, 0x55, 0x54, 0x5c, - 0x57, 0x54, 0x5b, 0x55, 0x56, 0x59, 0x58, 0x5e, 0x5b, 0x50, 0x66, 0x55, - 0x5b, 0x5e, 0x61, 0x59, 0x6a, 0x5e, 0x52, 0x57, 0x58, 0x58, 0x60, 0x58, - 0x3f, 0x5a, 0x5a, 0x5d, 0x5a, 0x53, 0x5d, 0x62, 0x5b, 0x66, 0x5a, 0x65, - 0x5d, 0x56, 0x5c, 0x4e, 0x59, 0x4e, 0x5e, 0x70, 0x5c, 0x58, 0x59, 0x5a, - 0x54, 0x57, 0x5d, 0x56, 0x58, 0x58, 0x5c, 0x5a, 0x6a, 0x61, 0x4f, 0x50, - 0x57, 0x58, 0x63, 0x58, 0x4c, 0x5f, 0x4a, 0x58, 0x53, 0x50, 0x5c, 0x62, - 0x55, 0x59, 0x5c, 0x5e, 0x5b, 0x4f, 0x56, 0x60, 0x54, 0x59, 0x58, 0x56, - 0x5a, 0x59, 0x5a, 0x57, 0x59, 0x56, 0x5e, 0x58, 0x59, 0x5a, 0x58, 0x5a, - 0x65, 0x5a, 0x54, 0x62, 0x5c, 0x56, 0x57, 0x54, 0x5a, 0x5e, 0x56, 0x52, - 0x5c, 0x5d, 0x5b, 0x58, 0x61, 0x5f, 0x5a, 0x5b, 0x5a, 0x56, 0x5a, 0x55, - 0x58, 0x5a, 0x53, 0x59, 0x5b, 0x5a, 0x5a, 0x57, 0x59, 0x58, 0x58, 0x5a, - 0x5c, 0x60, 0x5c, 0x56, 0x61, 0x5a, 0x58, 0x56, 0x5a, 0x59, 0x55, 0x5a, - 0x52, 0x59, 0x5a, 0x55, 0x58, 0x59, 0x5a, 0x5c, 0x57, 0x59, 0x59, 0x56, - 0x5a, 0x52, 0x5c, 0x50, 0x58, 0x73, 0x54, 0x4c, 0x48, 0x59, 0x59, 0x5c, - 0x52, 0x51, 0x5c, 0x5d, 0x59, 0x5f, 0x54, 0x55, 0x53, 0x5e, 0x4a, 0x57, - 0x59, 0x59, 0x57, 0x58, 0x6d, 0x61, 0x4c, 0x52, 0x5e, 0x59, 0x5b, 0x52, - 0x56, 0x61, 0x5c, 0x60, 0x5f, 0x4e, 0x57, 0x59, 0x50, 0x5b, 0x62, 0x4b, - 0x4f, 0x54, 0x59, 0x59, 0x59, 0x4c, 0x37, 0x57, 0x59, 0x5b, 0x59, 0x57, - 0x73, 0x5a, 0x4b, 0x56, 0x55, 0x5a, 0x55, 0x56, 0x50, 0x53, 0x60, 0x54, - 0x56, 0x56, 0x5c, 0x51, 0x5c, 0x58, 0x6a, 0x55, 0x5a, 0x50, 0x55, 0x56, - 0x59, 0x56, 0x5e, 0x58, 0x5a, 0x5c, 0x5a, 0x59, 0x56, 0x51, 0x54, 0x59, - 0x59, 0x5c, 0x54, 0x58, 0x5f, 0x5d, 0x54, 0x5c, 0x5e, 0x57, 0x53, 0x57, - 0x56, 0x58, 0x51, 0x57, 0x5a, 0x5a, 0x59, 0x55, 0x5d, 0x5c, 0x59, 0x5d, - 0x59, 0x58, 0x58, 0x5d, 0x56, 0x5c, 0x57, 0x59, 0x57, 0x5d, 0x58, 0x57, - 0x58, 0x56, 0x5b, 0x5e, 0x59, 0x5f, 0x5e, 0x5e, 0x5f, 0x57, 0x5a, 0x5d, - 0x5c, 0x58, 0x4e, 0x56, 0x59, 0x57, 0x5b, 0x5a, 0x63, 0x58, 0x58, 0x5d, - 0x5c, 0x53, 0x59, 0x57, 0x60, 0x4d, 0x84, 0x4b, 0x4b, 0x67, 0x59, 0x5b, - 0x53, 0x6a, 0x59, 0x55, 0x58, 0x44, 0x5d, 0x6a, 0x5a, 0x5a, 0x50, 0x53, - 0x4e, 0x52, 0x4a, 0x57, 0x74, 0x59, 0x54, 0x60, 0x56, 0x56, 0x5e, 0x59, - 0x68, 0x4e, 0x5b, 0x61, 0x52, 0x73, 0x56, 0x51, 0x5a, 0x53, 0x54, 0x5d, - 0x57, 0x61, 0x56, 0x5c, 0x59, 0x5b, 0x59, 0x5d, 0x59, 0x57, 0x5f, 0x58, - 0x59, 0x55, 0x65, 0x52, 0x5f, 0x5b, 0x4e, 0x57, 0x5f, 0x5e, 0x4e, 0x55, - 0x60, 0x60, 0x55, 0x60, 0x59, 0x5e, 0x5a, 0x5c, 0x5b, 0x61, 0x5f, 0x5e, - 0x57, 0x57, 0x54, 0x5b, 0x56, 0x59, 0x5d, 0x53, 0x5b, 0x55, 0x59, 0x5f, - 0x59, 0x50, 0x55, 0x58, 0x59, 0x5f, 0x58, 0x58, 0x64, 0x5b, 0x50, 0x59, - 0x5e, 0x58, 0x49, 0x5a, 0x58, 0x5e, 0x5a, 0x57, 0x5b, 0x58, 0x5a, 0x5d, - 0x5c, 0x5b, 0x59, 0x54, 0x5a, 0x51, 0x4f, 0x5d, 0x5a, 0x4f, 0x5b, 0x5d, - 0x5d, 0x5d, 0x5a, 0x59, 0x57, 0x49, 0x50, 0x58, 0x58, 0x5e, 0x5b, 0x59, - 0x68, 0x59, 0x54, 0x5c, 0x5b, 0x54, 0x50, 0x4f, 0x5c, 0x58, 0x3e, 0x59, - 0x5a, 0x5f, 0x5b, 0x56, 0x54, 0x5c, 0x5d, 0x5a, 0x58, 0x50, 0x4b, 0x5f, - 0x54, 0x6b, 0x51, 0x4a, 0x57, 0x4a, 0x59, 0x61, 0x57, 0x4a, 0x56, 0x51, - 0x59, 0x5d, 0x5e, 0x52, 0x46, 0x5c, 0x4d, 0x62, 0x58, 0x5c, 0x4d, 0x5a, - 0x49, 0x38, 0x54, 0x4a, 0x54, 0x53, 0x57, 0x4d, 0x4f, 0x62, 0x60, 0x60, - 0x5b, 0x73, 0x5b, 0x4d, 0x58, 0x55, 0x5a, 0x68, 0x58, 0x5e, 0x59, 0x5b, - 0x57, 0x58, 0x60, 0x5f, 0x59, 0x61, 0x65, 0x5b, 0x5b, 0x56, 0x52, 0x57, - 0x5e, 0x60, 0x56, 0x64, 0x5d, 0x57, 0x5d, 0x60, 0x54, 0x64, 0x57, 0x57, - 0x48, 0x69, 0x5a, 0x5f, 0x5d, 0x4f, 0x50, 0x45, 0x4d, 0x52, 0x6a, 0x5a, - 0x60, 0x4f, 0x58, 0x59, 0x57, 0x4b, 0x58, 0x58, 0x59, 0x60, 0x60, 0x5c, - 0x71, 0x5c, 0x46, 0x4b, 0x55, 0x50, 0x5d, 0x59, 0x48, 0x5e, 0x66, 0x54, - 0x53, 0x4f, 0x5b, 0x66, 0x54, 0x5d, 0x59, 0x5e, 0x5f, 0x5b, 0x5c, 0x65, - 0x57, 0x54, 0x5a, 0x53, 0x5f, 0x5f, 0x58, 0x5d, 0x58, 0x57, 0x5f, 0x60, - 0x59, 0x5d, 0x66, 0x5d, 0x6f, 0x59, 0x50, 0x4d, 0x59, 0x5b, 0x55, 0x61, - 0x51, 0x5c, 0x55, 0x5c, 0x54, 0x53, 0x5e, 0x69, 0x56, 0x58, 0x58, 0x5a, - 0x5c, 0x58, 0x5a, 0x58, 0x5b, 0x55, 0x5e, 0x54, 0x57, 0x57, 0x59, 0x5d, - 0x58, 0x52, 0x4c, 0x59, 0x5b, 0x57, 0x55, 0x5f, 0x71, 0x5b, 0x56, 0x54, - 0x57, 0x5c, 0x4d, 0x53, 0x59, 0x5e, 0x5d, 0x52, 0x5c, 0x53, 0x5d, 0x57, - 0x5d, 0x60, 0x56, 0x58, 0x59, 0x51, 0x57, 0x5e, 0x54, 0x63, 0x5f, 0x55, - 0x60, 0x50, 0x59, 0x5c, 0x59, 0x52, 0x4e, 0x5c, 0x58, 0x5a, 0x5d, 0x5c, - 0x64, 0x55, 0x54, 0x5c, 0x53, 0x56, 0x5e, 0x53, 0x55, 0x61, 0x59, 0x52, - 0x5d, 0x56, 0x5a, 0x59, 0x55, 0x5b, 0x58, 0x5f, 0x5b, 0x49, 0x57, 0x62, - 0x4e, 0x5b, 0x53, 0x4c, 0x64, 0x51, 0x58, 0x59, 0x56, 0x57, 0x57, 0x58, - 0x59, 0x5e, 0x2b, 0x55, 0x6d, 0x58, 0x72, 0x5b, 0x48, 0x5b, 0x65, 0x4e, - 0x5d, 0x40, 0x67, 0x5f, 0x58, 0x5c, 0x5c, 0x4b, 0x6a, 0x45, 0x5a, 0x59, - 0x57, 0x51, 0x4d, 0x4e, 0x55, 0x61, 0x6c, 0x49, 0x5b, 0x5b, 0x59, 0x53, - 0x5a, 0x4f, 0x55, 0x5c, 0x5a, 0x58, 0x52, 0x5b, 0x67, 0x59, 0x59, 0x52, - 0x58, 0x53, 0x54, 0x5e, 0x44, 0x60, 0x57, 0x50, 0x61, 0x4e, 0x5c, 0x63, - 0x55, 0x69, 0x55, 0x64, 0x5b, 0x51, 0x60, 0x66, 0x50, 0x58, 0x51, 0x61, - 0x5c, 0x5c, 0x59, 0x5a, 0x59, 0x53, 0x5d, 0x5c, 0x59, 0x5c, 0x6a, 0x5c, - 0x68, 0x59, 0x4a, 0x58, 0x5f, 0x59, 0x5b, 0x57, 0x56, 0x6a, 0x5b, 0x5d, - 0x58, 0x56, 0x5a, 0x63, 0x55, 0x64, 0x64, 0x5c, 0x59, 0x58, 0x54, 0x62, - 0x59, 0x5b, 0x6a, 0x4f, 0x51, 0x5a, 0x5a, 0x5b, 0x58, 0x59, 0x5f, 0x58, - 0x58, 0x60, 0x5a, 0x5e, 0x5e, 0x59, 0x57, 0x55, 0x59, 0x5e, 0x4c, 0x5f, - 0x57, 0x59, 0x59, 0x5c, 0x59, 0x56, 0x5d, 0x5f, 0x54, 0x55, 0x5a, 0x66, - 0x5b, 0x52, 0x61, 0x52, 0x57, 0x4c, 0x5c, 0x4f, 0x46, 0x4e, 0x59, 0x5e, - 0x59, 0x4c, 0x4b, 0x52, 0x57, 0x4a, 0x54, 0x53, 0x78, 0x5b, 0x57, 0x59, - 0x55, 0x5f, 0x56, 0x44, 0x60, 0x58, 0x40, 0x56, 0x5b, 0x54, 0x5a, 0x4b, - 0x5a, 0x58, 0x59, 0x56, 0x59, 0x50, 0x4d, 0x5b, 0x53, 0x5b, 0x62, 0x61, - 0x5c, 0x54, 0x59, 0x5f, 0x59, 0x50, 0x59, 0x5e, 0x59, 0x5c, 0x5f, 0x52, - 0x61, 0x59, 0x4d, 0x5a, 0x54, 0x61, 0x55, 0x55, 0x55, 0x60, 0x5f, 0x59, - 0x5c, 0x5d, 0x59, 0x54, 0x5e, 0x5e, 0x59, 0x57, 0x59, 0x59, 0x5a, 0x5f, - 0x59, 0x5c, 0x5b, 0x5c, 0x59, 0x59, 0x59, 0x5c, 0x58, 0x55, 0x5f, 0x56, - 0x59, 0x54, 0x65, 0x56, 0x61, 0x5b, 0x4f, 0x65, 0x59, 0x58, 0x5d, 0x59, - 0x4d, 0x5f, 0x64, 0x5e, 0x5d, 0x59, 0x5b, 0x5d, 0x5d, 0x63, 0x5c, 0x62, - 0x5b, 0x58, 0x57, 0x57, 0x58, 0x61, 0x5f, 0x54, 0x5c, 0x56, 0x57, 0x59, - 0x5c, 0x51, 0x55, 0x55, 0x59, 0x5d, 0x52, 0x5e, 0x60, 0x5c, 0x58, 0x55, - 0x53, 0x58, 0x5b, 0x5a, 0x51, 0x5b, 0x55, 0x57, 0x58, 0x55, 0x5b, 0x56, - 0x52, 0x5b, 0x5b, 0x60, 0x5a, 0x48, 0x57, 0x51, 0x4c, 0x76, 0x55, 0x61, - 0x55, 0x59, 0x59, 0x59, 0x52, 0x45, 0x62, 0x5b, 0x59, 0x5c, 0x4d, 0x58, - 0x5c, 0x5a, 0x45, 0x5d, 0x5d, 0x58, 0x4d, 0x57, 0x55, 0x57, 0x50, 0x4f, - 0x57, 0x54, 0x5a, 0x53, 0x56, 0x5d, 0x5b, 0x56, 0x57, 0x54, 0x58, 0x5a, - 0x58, 0x59, 0x59, 0x56, 0x5c, 0x58, 0x59, 0x59, 0x56, 0x57, 0x5d, 0x5a, - 0x59, 0x5f, 0x5e, 0x5a, 0x5c, 0x59, 0x54, 0x5b, 0x5e, 0x5a, 0x4c, 0x62, - 0x58, 0x5c, 0x5c, 0x58, 0x59, 0x58, 0x58, 0x59, 0x5f, 0x5d, 0x59, 0x5b, - 0x5a, 0x56, 0x5a, 0x53, 0x59, 0x53, 0x67, 0x5c, 0x5d, 0x5a, 0x59, 0x58, - 0x5a, 0x59, 0x59, 0x59, 0x58, 0x59, 0x5b, 0x5c, 0x65, 0x64, 0x54, 0x57, - 0x58, 0x54, 0x63, 0x5c, 0x53, 0x5a, 0x53, 0x56, 0x5a, 0x57, 0x5f, 0x5c, - 0x58, 0x61, 0x5a, 0x5d, 0x5b, 0x53, 0x57, 0x5c, 0x59, 0x56, 0x54, 0x5a, - 0x5a, 0x58, 0x59, 0x5a, 0x56, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x60, 0x58, - 0x60, 0x59, 0x50, 0x60, 0x59, 0x5a, 0x5b, 0x58, 0x51, 0x63, 0x5b, 0x57, - 0x5c, 0x5e, 0x5b, 0x56, 0x5e, 0x5e, 0x5a, 0x5e, 0x59, 0x5a, 0x58, 0x5c, - 0x56, 0x58, 0x5a, 0x56, 0x5d, 0x5a, 0x59, 0x54, 0x55, 0x4a, 0x53, 0x5d, - 0x59, 0x56, 0x52, 0x59, 0x57, 0x58, 0x5b, 0x65, 0x56, 0x59, 0x51, 0x58, - 0x57, 0x58, 0x60, 0x58, 0x57, 0x56, 0x57, 0x57, 0x60, 0x59, 0x5a, 0x56, - 0x5a, 0x4c, 0x51, 0x58, 0x54, 0x52, 0x5e, 0x5b, 0x58, 0x5b, 0x5b, 0x60, - 0x60, 0x50, 0x58, 0x64, 0x59, 0x5c, 0x56, 0x57, 0x59, 0x50, 0x4e, 0x58, - 0x68, 0x55, 0x4e, 0x5f, 0x66, 0x5b, 0x58, 0x51, 0x57, 0x5b, 0x5c, 0x58, - 0x58, 0x5b, 0x58, 0x5a, 0x5c, 0x56, 0x52, 0x57, 0x58, 0x52, 0x56, 0x53, - 0x56, 0x5b, 0x58, 0x5f, 0x59, 0x53, 0x5e, 0x54, 0x5b, 0x5d, 0x5f, 0x59, - 0x5c, 0x5a, 0x53, 0x57, 0x5a, 0x5d, 0x52, 0x61, 0x4f, 0x57, 0x68, 0x5e, - 0x5c, 0x52, 0x5c, 0x60, 0x4f, 0x5b, 0x60, 0x66, 0x5a, 0x58, 0x61, 0x59, - 0x56, 0x53, 0x63, 0x5a, 0x57, 0x5b, 0x59, 0x5a, 0x59, 0x57, 0x60, 0x5a, - 0x59, 0x5b, 0x60, 0x54, 0x5e, 0x60, 0x51, 0x5b, 0x57, 0x5b, 0x64, 0x5d, - 0x5c, 0x5e, 0x63, 0x5e, 0x54, 0x57, 0x5b, 0x61, 0x59, 0x5c, 0x62, 0x59, - 0x5d, 0x53, 0x61, 0x4d, 0x5b, 0x5d, 0x65, 0x4f, 0x56, 0x55, 0x59, 0x5b, - 0x59, 0x52, 0x61, 0x57, 0x58, 0x58, 0x5c, 0x57, 0x70, 0x5a, 0x5a, 0x60, - 0x57, 0x52, 0x48, 0x4c, 0x4f, 0x60, 0x53, 0x53, 0x5c, 0x5d, 0x5d, 0x4d, - 0x64, 0x6e, 0x63, 0x53, 0x5d, 0x48, 0x5c, 0x64, 0x53, 0x70, 0x50, 0x61, - 0x5e, 0x56, 0x59, 0x64, 0x53, 0x4a, 0x54, 0x5c, 0x59, 0x5b, 0x60, 0x5c, - 0x5f, 0x59, 0x46, 0x5d, 0x59, 0x59, 0x51, 0x5d, 0x59, 0x70, 0x4e, 0x53, - 0x55, 0x56, 0x5a, 0x5e, 0x58, 0x5b, 0x76, 0x53, 0x59, 0x55, 0x5a, 0x59, - 0x58, 0x56, 0x5b, 0x5a, 0x58, 0x5a, 0x59, 0x59, 0x58, 0x5a, 0x5d, 0x59, - 0x59, 0x58, 0x5c, 0x57, 0x5a, 0x57, 0x53, 0x5f, 0x5d, 0x58, 0x5e, 0x5d, - 0x5a, 0x59, 0x5b, 0x5d, 0x59, 0x5f, 0x5a, 0x58, 0x55, 0x57, 0x58, 0x56, - 0x5a, 0x50, 0x50, 0x59, 0x5a, 0x5e, 0x56, 0x54, 0x58, 0x59, 0x59, 0x5c, - 0x57, 0x60, 0x5c, 0x56, 0x59, 0x5b, 0x5f, 0x5a, 0x5d, 0x5b, 0x4d, 0x5e, - 0x5c, 0x57, 0x53, 0x59, 0x55, 0x5a, 0x56, 0x5a, 0x5a, 0x5a, 0x58, 0x5c, - 0x5d, 0x5d, 0x5a, 0x5a, 0x59, 0x4f, 0x57, 0x5f, 0x59, 0x60, 0x64, 0x57, - 0x59, 0x56, 0x59, 0x60, 0x58, 0x56, 0x5f, 0x5a, 0x5a, 0x5b, 0x62, 0x5a, - 0x61, 0x54, 0x57, 0x6b, 0x62, 0x56, 0x55, 0x55, 0x5e, 0x5a, 0x59, 0x5a, - 0x56, 0x60, 0x59, 0x55, 0x5a, 0x5d, 0x59, 0x5f, 0x5b, 0x5a, 0x5d, 0x5a, - 0x57, 0x57, 0x51, 0x5d, 0x60, 0x5c, 0x59, 0x5f, 0x57, 0x53, 0x5e, 0x56, - 0x5a, 0x5a, 0x61, 0x56, 0x59, 0x59, 0x52, 0x58, 0x5f, 0x5a, 0x57, 0x57, - 0x51, 0x62, 0x67, 0x5b, 0x57, 0x5c, 0x5b, 0x5d, 0x59, 0x5c, 0x58, 0x59, - 0x56, 0x56, 0x4f, 0x65, 0x58, 0x57, 0x62, 0x51, 0x53, 0x56, 0x59, 0x5d, - 0x56, 0x53, 0x56, 0x55, 0x59, 0x62, 0x58, 0x5a, 0x5d, 0x5d, 0x54, 0x65, - 0x56, 0x59, 0x4d, 0x5a, 0x59, 0x58, 0x5c, 0x55, 0x5c, 0x55, 0x5b, 0x5b, - 0x57, 0x59, 0x59, 0x60, 0x59, 0x4d, 0x53, 0x5d, 0x59, 0x57, 0x55, 0x55, - 0x56, 0x50, 0x59, 0x56, 0x5e, 0x57, 0x5a, 0x56, 0x59, 0x57, 0x56, 0x5b, - 0x57, 0x5b, 0x4c, 0x65, 0x59, 0x61, 0x51, 0x57, 0x5e, 0x5c, 0x56, 0x61, - 0x58, 0x5f, 0x58, 0x53, 0x64, 0x5e, 0x5b, 0x60, 0x60, 0x4e, 0x5b, 0x4f, - 0x4a, 0x4a, 0x56, 0x64, 0x5c, 0x55, 0x5a, 0x5d, 0x59, 0x46, 0x6a, 0x5c, - 0x5a, 0x57, 0x4c, 0x58, 0x62, 0x4c, 0x47, 0x5a, 0x5f, 0x5c, 0x57, 0x5a, - 0x53, 0x5f, 0x56, 0x53, 0x59, 0x58, 0x5c, 0x56, 0x5b, 0x5c, 0x5e, 0x5a, - 0x54, 0x55, 0x5e, 0x59, 0x5c, 0x54, 0x54, 0x5f, 0x58, 0x59, 0x59, 0x61, - 0x60, 0x5a, 0x5d, 0x5e, 0x58, 0x42, 0x6d, 0x5e, 0x55, 0x5c, 0x53, 0x51, - 0x57, 0x5e, 0x46, 0x66, 0x5a, 0x57, 0x55, 0x52, 0x4f, 0x55, 0x5a, 0x5e, - 0x57, 0x50, 0x54, 0x5d, 0x5c, 0x5e, 0x57, 0x61, 0x59, 0x57, 0x5e, 0x54, - 0x55, 0x56, 0x59, 0x5a, 0x59, 0x58, 0x5d, 0x59, 0x59, 0x54, 0x60, 0x56, - 0x5e, 0x5b, 0x54, 0x5c, 0x57, 0x5b, 0x4a, 0x62, 0x50, 0x5a, 0x5a, 0x59, - 0x5c, 0x54, 0x5d, 0x5f, 0x58, 0x62, 0x58, 0x5d, 0x5f, 0x51, 0x53, 0x5f, - 0x55, 0x52, 0x5b, 0x57, 0x5b, 0x55, 0x59, 0x5e, 0x56, 0x50, 0x5f, 0x5b, - 0x59, 0x5c, 0x63, 0x58, 0x5e, 0x58, 0x4d, 0x59, 0x5f, 0x57, 0x5c, 0x59, - 0x53, 0x63, 0x5d, 0x57, 0x5e, 0x5c, 0x5b, 0x5c, 0x5e, 0x66, 0x5a, 0x59, - 0x5b, 0x50, 0x57, 0x56, 0x59, 0x58, 0x56, 0x51, 0x54, 0x5a, 0x59, 0x5f, - 0x55, 0x57, 0x66, 0x61, 0x59, 0x58, 0x65, 0x5e, 0x5a, 0x5e, 0x50, 0x5c, - 0x5d, 0x5d, 0x57, 0x62, 0x56, 0x5d, 0x57, 0x5a, 0x5a, 0x5c, 0x5a, 0x54, - 0x5a, 0x66, 0x5a, 0x62, 0x5b, 0x56, 0x59, 0x57, 0x58, 0x51, 0x5e, 0x5a, - 0x57, 0x58, 0x5a, 0x57, 0x58, 0x57, 0x60, 0x58, 0x5b, 0x55, 0x5d, 0x58, - 0x60, 0x59, 0x5d, 0x5b, 0x59, 0x5c, 0x62, 0x62, 0x5f, 0x58, 0x68, 0x5b, - 0x58, 0x5c, 0x60, 0x60, 0x5c, 0x5d, 0x59, 0x56, 0x5a, 0x5a, 0x54, 0x5d, - 0x51, 0x5d, 0x57, 0x58, 0x55, 0x5a, 0x59, 0x5c, 0x57, 0x57, 0x5a, 0x5b, - 0x59, 0x53, 0x5a, 0x55, 0x5b, 0x5b, 0x56, 0x5f, 0x56, 0x55, 0x51, 0x5d, - 0x53, 0x59, 0x65, 0x58, 0x57, 0x57, 0x58, 0x56, 0x58, 0x59, 0x59, 0x61, - 0x59, 0x57, 0x54, 0x5b, 0x59, 0x54, 0x5e, 0x53, 0x50, 0x57, 0x58, 0x5b, - 0x59, 0x5a, 0x5a, 0x53, 0x59, 0x60, 0x59, 0x5d, 0x57, 0x5a, 0x54, 0x60, - 0x56, 0x5a, 0x4f, 0x60, 0x61, 0x5d, 0x5c, 0x59, 0x56, 0x57, 0x5b, 0x5d, - 0x59, 0x54, 0x5a, 0x66, 0x59, 0x56, 0x5b, 0x5f, 0x56, 0x5f, 0x5f, 0x51, - 0x53, 0x5b, 0x59, 0x5b, 0x5c, 0x52, 0x57, 0x5a, 0x5b, 0x5c, 0x58, 0x5c, - 0x5f, 0x57, 0x59, 0x5d, 0x5b, 0x5a, 0x53, 0x5d, 0x5c, 0x57, 0x5f, 0x5d, - 0x64, 0x58, 0x5b, 0x59, 0x58, 0x60, 0x56, 0x59, 0x5b, 0x53, 0x5f, 0x5c, - 0x5a, 0x57, 0x59, 0x5e, 0x59, 0x60, 0x58, 0x61, 0x5b, 0x5a, 0x5f, 0x58, - 0x59, 0x5b, 0x61, 0x5b, 0x68, 0x54, 0x55, 0x5f, 0x5b, 0x57, 0x62, 0x5c, - 0x50, 0x59, 0x5d, 0x5d, 0x52, 0x57, 0x5a, 0x5b, 0x54, 0x62, 0x5f, 0x5a, - 0x55, 0x53, 0x5a, 0x54, 0x59, 0x65, 0x60, 0x64, 0x58, 0x5d, 0x59, 0x5b, - 0x59, 0x57, 0x59, 0x5a, 0x59, 0x54, 0x58, 0x53, 0x54, 0x5a, 0x58, 0x62, - 0x59, 0x59, 0x4f, 0x5f, 0x64, 0x56, 0x50, 0x54, 0x51, 0x59, 0x59, 0x5d, - 0x56, 0x59, 0x5a, 0x5e, 0x56, 0x4e, 0x55, 0x50, 0x58, 0x5f, 0x5c, 0x66, - 0x66, 0x51, 0x59, 0x54, 0x56, 0x55, 0x59, 0x59, 0x59, 0x5e, 0x46, 0x56, - 0x54, 0x56, 0x57, 0x5b, 0x67, 0x5b, 0x47, 0x64, 0x54, 0x59, 0x57, 0x53, - 0x66, 0x54, 0x5a, 0x57, 0x4e, 0x55, 0x58, 0x54, 0x59, 0x54, 0x5a, 0x47, - 0x57, 0x40, 0x54, 0x5f, 0x67, 0x5e, 0x58, 0x5b, 0x58, 0x55, 0x5d, 0x58, - 0x57, 0x5d, 0x55, 0x58, 0x68, 0x5e, 0x4b, 0x5c, 0x5d, 0x57, 0x5b, 0x51, - 0x6b, 0x57, 0x41, 0x5d, 0x57, 0x4c, 0x5d, 0x64, 0x53, 0x56, 0x59, 0x55, - 0x5c, 0x55, 0x54, 0x59, 0x51, 0x55, 0x60, 0x49, 0x5a, 0x56, 0x58, 0x57, - 0x5a, 0x46, 0x51, 0x58, 0x59, 0x5f, 0x5c, 0x5a, 0x66, 0x5b, 0x59, 0x5c, - 0x58, 0x56, 0x54, 0x56, 0x5a, 0x54, 0x58, 0x54, 0x56, 0x54, 0x59, 0x59, - 0x5e, 0x5d, 0x57, 0x57, 0x59, 0x54, 0x5c, 0x51, 0x59, 0x58, 0x4d, 0x59, - 0x50, 0x59, 0x59, 0x5d, 0x59, 0x54, 0x5b, 0x59, 0x59, 0x58, 0x5d, 0x58, - 0x63, 0x5b, 0x53, 0x65, 0x5b, 0x5a, 0x55, 0x58, 0x66, 0x58, 0x4f, 0x58, - 0x57, 0x55, 0x5e, 0x58, 0x58, 0x5c, 0x68, 0x52, 0x5d, 0x52, 0x53, 0x54, - 0x54, 0x51, 0x66, 0x53, 0x5a, 0x4d, 0x5a, 0x61, 0x5e, 0x4d, 0x52, 0x53, - 0x5a, 0x58, 0x66, 0x5f, 0x73, 0x5e, 0x44, 0x50, 0x58, 0x5a, 0x5e, 0x52, - 0x4a, 0x5b, 0x47, 0x56, 0x59, 0x4c, 0x5d, 0x5f, 0x54, 0x61, 0x58, 0x61, - 0x5d, 0x59, 0x55, 0x61, 0x5a, 0x60, 0x59, 0x59, 0x53, 0x5e, 0x5a, 0x5e, - 0x58, 0x55, 0x61, 0x5b, 0x5a, 0x5d, 0x63, 0x59, 0x6e, 0x5d, 0x51, 0x54, - 0x56, 0x5d, 0x53, 0x59, 0x4a, 0x5b, 0x4f, 0x55, 0x59, 0x56, 0x5d, 0x5c, - 0x55, 0x68, 0x58, 0x66, 0x5b, 0x55, 0x56, 0x59, 0x57, 0x61, 0x5b, 0x54, - 0x59, 0x57, 0x59, 0x5a, 0x57, 0x53, 0x5b, 0x57, 0x59, 0x5e, 0x5c, 0x54, - 0x5e, 0x5d, 0x52, 0x60, 0x5e, 0x56, 0x52, 0x5b, 0x4f, 0x5d, 0x5a, 0x58, - 0x5c, 0x60, 0x59, 0x59, 0x60, 0x5b, 0x5a, 0x5d, 0x58, 0x57, 0x53, 0x59, - 0x4f, 0x60, 0x5b, 0x56, 0x57, 0x5e, 0x59, 0x5a, 0x59, 0x4d, 0x5c, 0x59, - 0x59, 0x5e, 0x5c, 0x5d, 0x57, 0x56, 0x5b, 0x67, 0x55, 0x59, 0x54, 0x57, - 0x58, 0x5b, 0x50, 0x5d, 0x5a, 0x51, 0x56, 0x60, 0x55, 0x5b, 0x57, 0x5d, - 0x5a, 0x52, 0x56, 0x57, 0x59, 0x57, 0x5f, 0x5b, 0x5c, 0x5a, 0x59, 0x58, - 0x57, 0x52, 0x51, 0x5a, 0x59, 0x5c, 0x52, 0x5a, 0x62, 0x59, 0x4f, 0x64, - 0x62, 0x50, 0x57, 0x59, 0x54, 0x5a, 0x5c, 0x54, 0x55, 0x57, 0x59, 0x53, - 0x5c, 0x59, 0x5b, 0x5e, 0x60, 0x50, 0x55, 0x50, 0x50, 0x60, 0x5b, 0x53, - 0x5f, 0x59, 0x58, 0x57, 0x58, 0x49, 0x5f, 0x55, 0x58, 0x5e, 0x59, 0x58, - 0x4f, 0x57, 0x52, 0x53, 0x59, 0x55, 0x4c, 0x5d, 0x4d, 0x4f, 0x58, 0x5e, - 0x4f, 0x51, 0x59, 0x62, 0x58, 0x5a, 0x53, 0x53, 0x6a, 0x4b, 0x5b, 0x5b, - 0x5a, 0x5b, 0x59, 0x57, 0x59, 0x4f, 0x59, 0x5c, 0x57, 0x53, 0x62, 0x5a, - 0x58, 0x58, 0x67, 0x50, 0x60, 0x56, 0x4f, 0x67, 0x66, 0x61, 0x53, 0x5a, - 0x4e, 0x67, 0x69, 0x5f, 0x65, 0x66, 0x54, 0x5b, 0x63, 0x5b, 0x59, 0x62, - 0x5b, 0x55, 0x55, 0x60, 0x5a, 0x5c, 0x54, 0x56, 0x58, 0x57, 0x59, 0x56, - 0x58, 0x53, 0x5b, 0x58, 0x58, 0x67, 0x59, 0x60, 0x5d, 0x55, 0x58, 0x5d, - 0x59, 0x57, 0x5f, 0x59, 0x54, 0x5b, 0x60, 0x5a, 0x62, 0x57, 0x58, 0x62, - 0x54, 0x57, 0x57, 0x5e, 0x52, 0x54, 0x48, 0x63, 0x59, 0x76, 0x62, 0x51, - 0x52, 0x5b, 0x59, 0x62, 0x52, 0x50, 0x60, 0x59, 0x59, 0x60, 0x58, 0x58, - 0x57, 0x5b, 0x4b, 0x43, 0x51, 0x5b, 0x43, 0x5d, 0x4e, 0x56, 0x65, 0x5f, - 0x4c, 0x59, 0x56, 0x68, 0x54, 0x5d, 0x7d, 0x5c, 0x54, 0x59, 0x62, 0x62, - 0x5a, 0x64, 0x5c, 0x58, 0x52, 0x62, 0x59, 0x62, 0x59, 0x58, 0x68, 0x5e, - 0x59, 0x5e, 0x61, 0x5b, 0x55, 0x5c, 0x40, 0x60, 0x5d, 0x66, 0x55, 0x6b, - 0x56, 0x62, 0x60, 0x5e, 0x56, 0x62, 0x55, 0x5f, 0x58, 0x5f, 0x59, 0x63, - 0x58, 0x63, 0x52, 0x64, 0x4e, 0x5b, 0x54, 0x4c, 0x5a, 0x56, 0x59, 0x4f, - 0x58, 0x47, 0x44, 0x51, 0x59, 0x60, 0x49, 0x59, 0x5c, 0x5a, 0x52, 0x64, - 0x5e, 0x5c, 0x58, 0x55, 0x4b, 0x57, 0x5e, 0x7f, 0x5d, 0x61, 0x5a, 0x5c, - 0x63, 0x47, 0x5a, 0x57, 0x5a, 0x59, 0x5b, 0x5c, 0x57, 0x4f, 0x57, 0x5b, - 0x64, 0x59, 0x59, 0x58, 0x5a, 0x52, 0x5a, 0x59, 0x59, 0x5e, 0x5e, 0x5e, - 0x5f, 0x5a, 0x51, 0x5c, 0x54, 0x58, 0x5b, 0x5d, 0x4f, 0x61, 0x50, 0x5a, - 0x59, 0x4f, 0x5c, 0x64, 0x59, 0x60, 0x5e, 0x64, 0x5d, 0x4d, 0x4d, 0x59, - 0x5a, 0x5a, 0x53, 0x5f, 0x5d, 0x4f, 0x5d, 0x58, 0x5d, 0x45, 0x4c, 0x57, - 0x58, 0x5f, 0x4f, 0x5c, 0x59, 0x5a, 0x51, 0x47, 0x5b, 0x4c, 0x4e, 0x4a, - 0x52, 0x55, 0x4f, 0x59, 0x5d, 0x62, 0x5b, 0x49, 0x58, 0x52, 0x59, 0x59, - 0x5c, 0x52, 0x58, 0x5c, 0x5b, 0x53, 0x56, 0x58, 0x5f, 0x4f, 0x5d, 0x5b, - 0x59, 0x54, 0x5c, 0x57, 0x59, 0x5a, 0x5b, 0x55, 0x61, 0x5c, 0x50, 0x60, - 0x5a, 0x5a, 0x5e, 0x57, 0x54, 0x5e, 0x58, 0x58, 0x5c, 0x5c, 0x5b, 0x56, - 0x5f, 0x60, 0x59, 0x5d, 0x5b, 0x55, 0x52, 0x5c, 0x58, 0x57, 0x51, 0x5c, - 0x58, 0x5b, 0x5a, 0x57, 0x58, 0x52, 0x5a, 0x59, 0x59, 0x5c, 0x5b, 0x50, - 0x5e, 0x57, 0x50, 0x5f, 0x5d, 0x59, 0x4f, 0x56, 0x5f, 0x5f, 0x57, 0x58, - 0x58, 0x57, 0x59, 0x57, 0x5b, 0x59, 0x62, 0x51, 0x58, 0x4f, 0x58, 0x66, - 0x58, 0x60, 0x58, 0x4c, 0x51, 0x55, 0x59, 0x5e, 0x57, 0x52, 0x5f, 0x5b, - 0x59, 0x5f, 0x5b, 0x57, 0x5c, 0x5e, 0x4f, 0x65, 0x58, 0x5a, 0x5b, 0x53, - 0x66, 0x5c, 0x62, 0x5a, 0x5c, 0x5d, 0x5b, 0x57, 0x5a, 0x5f, 0x5f, 0x63, - 0x65, 0x54, 0x55, 0x55, 0x58, 0x6b, 0x69, 0x4c, 0x5c, 0x54, 0x59, 0x56, - 0x5a, 0x50, 0x57, 0x5b, 0x59, 0x5b, 0x51, 0x5b, 0x66, 0x5f, 0x56, 0x58, - 0x57, 0x53, 0x5e, 0x5b, 0x4f, 0x5a, 0x57, 0x51, 0x5d, 0x4a, 0x58, 0x60, - 0x56, 0x64, 0x58, 0x6a, 0x57, 0x58, 0x58, 0x5b, 0x57, 0x53, 0x57, 0x50, - 0x5b, 0x51, 0x59, 0x58, 0x57, 0x53, 0x4f, 0x58, 0x59, 0x47, 0x59, 0x59, - 0x63, 0x5a, 0x4a, 0x59, 0x59, 0x57, 0x4e, 0x5d, 0x4c, 0x61, 0x66, 0x5e, - 0x5f, 0x5b, 0x5b, 0x58, 0x5a, 0x66, 0x56, 0x55, 0x5a, 0x4a, 0x57, 0x55, - 0x51, 0x62, 0x5c, 0x4c, 0x52, 0x56, 0x58, 0x55, 0x5a, 0x4a, 0x3d, 0x58, - 0x58, 0x5f, 0x56, 0x50, 0x76, 0x58, 0x5f, 0x61, 0x42, 0x5a, 0x48, 0x56, - 0x4f, 0x4d, 0x5b, 0x5d, 0x5c, 0x5d, 0x58, 0x61, 0x66, 0x58, 0x5a, 0x5a, - 0x54, 0x59, 0x59, 0x5d, 0x58, 0x6a, 0x5d, 0x54, 0x55, 0x5d, 0x59, 0x57, - 0x5f, 0x57, 0x60, 0x5e, 0x58, 0x53, 0x60, 0x5b, 0x56, 0x5c, 0x53, 0x5a, - 0x62, 0x5b, 0x4b, 0x66, 0x62, 0x53, 0x5d, 0x58, 0x5b, 0x64, 0x59, 0x62, - 0x3f, 0x56, 0x59, 0x5e, 0x58, 0x53, 0x53, 0x5a, 0x56, 0x55, 0x67, 0x51, - 0x5c, 0x5e, 0x59, 0x57, 0x5a, 0x52, 0x54, 0x5a, 0x59, 0x5e, 0x5f, 0x62, - 0x72, 0x5d, 0x4f, 0x60, 0x54, 0x5e, 0x62, 0x5c, 0x47, 0x60, 0x69, 0x5d, - 0x56, 0x56, 0x5c, 0x6b, 0x56, 0x5f, 0x55, 0x5f, 0x58, 0x50, 0x56, 0x5b, - 0x59, 0x56, 0x55, 0x55, 0x57, 0x59, 0x59, 0x57, 0x57, 0x52, 0x59, 0x59, - 0x59, 0x5a, 0x5a, 0x5c, 0x61, 0x5b, 0x54, 0x66, 0x58, 0x55, 0x55, 0x57, - 0x52, 0x5f, 0x5e, 0x5a, 0x5c, 0x5c, 0x5a, 0x58, 0x5c, 0x5c, 0x5a, 0x59, - 0x5a, 0x58, 0x58, 0x5b, 0x57, 0x5a, 0x57, 0x5b, 0x4b, 0x5e, 0x58, 0x56, - 0x5a, 0x5a, 0x5c, 0x5d, 0x5c, 0x51, 0x5c, 0x5f, 0x51, 0x66, 0x56, 0x71, - 0x58, 0x5a, 0x64, 0x6e, 0x5d, 0x5d, 0x57, 0x5d, 0x54, 0x55, 0x5d, 0x6a, - 0x57, 0x53, 0x5a, 0x59, 0x5a, 0x57, 0x58, 0x5d, 0x5c, 0x59, 0x4f, 0x5e, - 0x52, 0x62, 0x59, 0x5f, 0x59, 0x53, 0x63, 0x59, 0x59, 0x59, 0x61, 0x51, - 0x61, 0x58, 0x54, 0x58, 0x5b, 0x62, 0x51, 0x5d, 0x57, 0x53, 0x59, 0x5f, - 0x56, 0x56, 0x5a, 0x5f, 0x58, 0x5a, 0x5b, 0x57, 0x5c, 0x53, 0x5f, 0x56, - 0x57, 0x5c, 0x58, 0x56, 0x5b, 0x5c, 0x57, 0x5c, 0x58, 0x57, 0x5b, 0x5d, - 0x5c, 0x5a, 0x5e, 0x59, 0x57, 0x5d, 0x53, 0x5e, 0x60, 0x59, 0x57, 0x59, - 0x55, 0x59, 0x5d, 0x5b, 0x54, 0x58, 0x5c, 0x5e, 0x59, 0x5a, 0x5a, 0x56, - 0x57, 0x53, 0x56, 0x57, 0x63, 0x61, 0x54, 0x58, 0x53, 0x54, 0x59, 0x5c, - 0x56, 0x4f, 0x53, 0x5a, 0x58, 0x59, 0x5d, 0x57, 0x51, 0x55, 0x53, 0x5b, - 0x45, 0x63, 0x52, 0x46, 0x68, 0x58, 0x54, 0x4c, 0x52, 0x67, 0x57, 0x46, - 0x4f, 0x58, 0x59, 0x52, 0x58, 0x53, 0x57, 0x53, 0x57, 0x53, 0x59, 0x50, - 0x5e, 0x4e, 0x58, 0x56, 0x5b, 0x4a, 0x49, 0x57, 0x59, 0x56, 0x48, 0x5c, - 0x71, 0x5b, 0x4d, 0x5d, 0x50, 0x53, 0x4d, 0x56, 0x50, 0x52, 0x64, 0x4e, - 0x58, 0x57, 0x5a, 0x4c, 0x5f, 0x5e, 0x5f, 0x5b, 0x58, 0x53, 0x59, 0x5a, - 0x57, 0x53, 0x60, 0x59, 0x63, 0x5a, 0x5b, 0x5a, 0x5c, 0x52, 0x57, 0x5b, - 0x5a, 0x52, 0x5a, 0x54, 0x60, 0x5b, 0x4a, 0x58, 0x54, 0x64, 0x58, 0x5f, - 0x53, 0x5c, 0x5d, 0x5a, 0x5c, 0x5a, 0x5e, 0x52, 0x59, 0x66, 0x59, 0x5f, - 0x5a, 0x66, 0x65, 0x52, 0x5b, 0x56, 0x63, 0x5b, 0x5d, 0x5c, 0x58, 0x63, - 0x58, 0x5a, 0x64, 0x59, 0x57, 0x5c, 0x66, 0x5c, 0x5f, 0x65, 0x56, 0x50, - 0x57, 0x59, 0x71, 0x5f, 0x60, 0x5a, 0x64, 0x63, 0x55, 0x59, 0x5e, 0x60, - 0x54, 0x54, 0x5a, 0x56, 0x5c, 0x54, 0x51, 0x55, 0x58, 0x82, 0x6b, 0x58, - 0x58, 0x56, 0x57, 0x64, 0x5b, 0x57, 0x59, 0x5a, 0x58, 0x58, 0x56, 0x5d, - 0x64, 0x61, 0x54, 0x5e, 0x56, 0x58, 0x64, 0x49, 0x3a, 0x5a, 0x3a, 0x4a, - 0x64, 0x53, 0x5e, 0x54, 0x53, 0x76, 0x59, 0x6b, 0x5a, 0x52, 0x56, 0x56, - 0x57, 0x58, 0x5b, 0x52, 0x5a, 0x5c, 0x59, 0x58, 0x5d, 0x54, 0x56, 0x5c, - 0x5a, 0x5c, 0x4c, 0x54, 0x5e, 0x5d, 0x55, 0x5a, 0x5a, 0x59, 0x4c, 0x5b, - 0x57, 0x58, 0x5e, 0x55, 0x5e, 0x5e, 0x59, 0x51, 0x5e, 0x5b, 0x5a, 0x5f, - 0x55, 0x59, 0x53, 0x5a, 0x56, 0x5f, 0x56, 0x5c, 0x55, 0x58, 0x5a, 0x56, - 0x5a, 0x51, 0x56, 0x5b, 0x59, 0x5b, 0x5d, 0x61, 0x62, 0x59, 0x5b, 0x5d, - 0x53, 0x58, 0x50, 0x5b, 0x64, 0x59, 0x69, 0x5a, 0x67, 0x57, 0x57, 0x60, - 0x4f, 0x59, 0x5b, 0x60, 0x5d, 0x4b, 0x59, 0x58, 0x54, 0x5f, 0x50, 0x5d, - 0x5b, 0x59, 0x5b, 0x57, 0x5e, 0x65, 0x63, 0x5e, 0x5c, 0x5e, 0x55, 0x58, - 0x60, 0x58, 0x56, 0x5c, 0x5b, 0x57, 0x55, 0x5e, 0x5e, 0x58, 0x57, 0x58, - 0x65, 0x62, 0x5a, 0x5a, 0x5f, 0x58, 0x5a, 0x56, 0x59, 0x55, 0x5f, 0x5a, - 0x58, 0x5e, 0x51, 0x54, 0x53, 0x5d, 0x59, 0x5e, 0x5b, 0x53, 0x5a, 0x58, - 0x58, 0x65, 0x5d, 0x55, 0x61, 0x5a, 0x54, 0x62, 0x5b, 0x5c, 0x58, 0x58, - 0x56, 0x5f, 0x59, 0x57, 0x5b, 0x55, 0x5d, 0x5a, 0x5a, 0x5c, 0x59, 0x55, - 0x53, 0x4f, 0x58, 0x52, 0x5a, 0x67, 0x55, 0x5c, 0x5a, 0x62, 0x59, 0x5d, - 0x59, 0x57, 0x5d, 0x5e, 0x59, 0x5f, 0x61, 0x59, 0x55, 0x59, 0x53, 0x5c, - 0x5f, 0x58, 0x54, 0x5c, 0x57, 0x5e, 0x4f, 0x5a, 0x56, 0x5c, 0x57, 0x61, - 0x50, 0x5c, 0x58, 0x5a, 0x5e, 0x54, 0x58, 0x56, 0x5a, 0x50, 0x64, 0x5e, - 0x51, 0x52, 0x59, 0x59, 0x59, 0x53, 0x5c, 0x56, 0x59, 0x5c, 0x58, 0x5b, - 0x5d, 0x5f, 0x55, 0x57, 0x53, 0x56, 0x65, 0x59, 0x5c, 0x5c, 0x5a, 0x57, - 0x5d, 0x53, 0x5c, 0x5a, 0x5c, 0x58, 0x5d, 0x61, 0x5b, 0x53, 0x59, 0x61, - 0x56, 0x58, 0x5d, 0x56, 0x55, 0x59, 0x5a, 0x55, 0x57, 0x53, 0x4f, 0x59, - 0x5a, 0x5f, 0x5a, 0x58, 0x65, 0x59, 0x5c, 0x5a, 0x59, 0x5b, 0x51, 0x54, - 0x56, 0x5a, 0x5d, 0x59, 0x5b, 0x59, 0x5e, 0x59, 0x5f, 0x59, 0x5a, 0x58, - 0x5a, 0x56, 0x58, 0x5c, 0x58, 0x57, 0x55, 0x55, 0x59, 0x5b, 0x59, 0x59, - 0x59, 0x57, 0x5e, 0x5b, 0x5a, 0x62, 0x5b, 0x63, 0x5e, 0x58, 0x58, 0x60, - 0x5b, 0x56, 0x52, 0x55, 0x55, 0x5b, 0x5e, 0x5c, 0x62, 0x5b, 0x5a, 0x5c, - 0x58, 0x57, 0x58, 0x59, 0x57, 0x50, 0x5f, 0x4b, 0x59, 0x4b, 0x70, 0x7e, - 0x69, 0x65, 0x5b, 0x56, 0x59, 0x52, 0x5c, 0x5d, 0x57, 0x51, 0x46, 0x58, - 0x5a, 0x54, 0x4e, 0x44, 0x56, 0x58, 0x64, 0x5a, 0x5a, 0x49, 0x4b, 0x45, - 0x5d, 0x4f, 0x5f, 0x54, 0x53, 0x59, 0x5b, 0x56, 0x53, 0x4b, 0x57, 0x50, - 0x4f, 0x5b, 0x5e, 0x4d, 0x5b, 0x63, 0x59, 0x54, 0x58, 0x53, 0x56, 0x5f, - 0x5a, 0x5a, 0x53, 0x5d, 0x54, 0x57, 0x55, 0x66, 0x63, 0x55, 0x48, 0x59, - 0x53, 0x4c, 0x5e, 0x57, 0x5d, 0x55, 0x56, 0x5a, 0x54, 0x56, 0x59, 0x58, - 0x5d, 0x53, 0x60, 0x5d, 0x57, 0x52, 0x66, 0x5a, 0x55, 0x5b, 0x58, 0x5b, - 0x5a, 0x51, 0x5a, 0x5a, 0x5b, 0x5d, 0x5f, 0x5b, 0x66, 0x5c, 0x4f, 0x55, - 0x59, 0x5b, 0x67, 0x5a, 0x4b, 0x5c, 0x63, 0x59, 0x5a, 0x53, 0x5c, 0x61, - 0x5b, 0x5f, 0x5a, 0x65, 0x59, 0x57, 0x53, 0x5b, 0x58, 0x63, 0x5f, 0x4d, - 0x53, 0x59, 0x59, 0x5b, 0x5a, 0x54, 0x5a, 0x55, 0x58, 0x5f, 0x55, 0x5b, - 0x4f, 0x59, 0x59, 0x4f, 0x59, 0x59, 0x4c, 0x60, 0x54, 0x62, 0x65, 0x58, - 0x5a, 0x5b, 0x53, 0x61, 0x57, 0x53, 0x59, 0x63, 0x59, 0x5a, 0x60, 0x55, - 0x59, 0x56, 0x60, 0x56, 0x5e, 0x58, 0x5a, 0x5d, 0x5a, 0x58, 0x5b, 0x58, - 0x58, 0x56, 0x5d, 0x54, 0x5b, 0x62, 0x59, 0x5c, 0x58, 0x5c, 0x61, 0x57, - 0x5c, 0x5f, 0x5e, 0x5b, 0x54, 0x59, 0x58, 0x5a, 0x5a, 0x5e, 0x59, 0x5a, - 0x61, 0x66, 0x53, 0x64, 0x4f, 0x6b, 0x51, 0x4c, 0x5b, 0x5b, 0x59, 0x64, - 0x53, 0x58, 0x5c, 0x5b, 0x58, 0x60, 0x5b, 0x53, 0x5b, 0x5d, 0x54, 0x5e, - 0x58, 0x5a, 0x5a, 0x59, 0x52, 0x66, 0x5c, 0x4f, 0x59, 0x54, 0x5c, 0x56, - 0x51, 0x5a, 0x5a, 0x5c, 0x59, 0x56, 0x53, 0x58, 0x58, 0x4d, 0x58, 0x54, - 0x62, 0x49, 0x59, 0x55, 0x59, 0x54, 0x55, 0x58, 0x58, 0x5d, 0x4c, 0x5d, - 0x5e, 0x5c, 0x44, 0x5c, 0x60, 0x5b, 0x4d, 0x5a, 0x6b, 0x45, 0x60, 0x51, - 0x5c, 0x4f, 0x5b, 0x4a, 0x4d, 0x51, 0x5e, 0x60, 0x5a, 0x4e, 0x4b, 0x6c, - 0x50, 0x6f, 0x42, 0x48, 0x5d, 0x5e, 0x58, 0x3c, 0x57, 0x48, 0x10, 0x55, - 0x59, 0x5b, 0x44, 0x59, 0x76, 0x56, 0x67, 0x55, 0x49, 0x55, 0x6c, 0x45, - 0x4a, 0x53, 0x48, 0x79, 0x51, 0x64, 0x56, 0x5a, 0x69, 0x49, 0x57, 0x58, - 0x58, 0x54, 0x48, 0x68, 0x4f, 0x5b, 0x59, 0x54, 0x51, 0x57, 0x59, 0x4c, - 0x61, 0x45, 0x58, 0x5d, 0x59, 0x50, 0x68, 0x61, 0x5c, 0x5a, 0x45, 0x53, - 0x55, 0x59, 0x5e, 0x63, 0x60, 0x58, 0x7c, 0x5a, 0x5f, 0x6c, 0x58, 0x61, - 0x52, 0x5b, 0x58, 0x53, 0x5f, 0x54, 0x59, 0x57, 0x5b, 0x51, 0x61, 0x63, - 0x5a, 0x54, 0x58, 0x64, 0x58, 0x52, 0x57, 0x53, 0x5a, 0x5c, 0x5b, 0x5c, - 0x73, 0x5d, 0x48, 0x54, 0x57, 0x5d, 0x64, 0x52, 0x46, 0x60, 0x3f, 0x5a, - 0x4f, 0x51, 0x57, 0x60, 0x52, 0x5d, 0x59, 0x55, 0x64, 0x59, 0x5f, 0x5e, - 0x59, 0x4e, 0x51, 0x52, 0x5a, 0x55, 0x59, 0x5c, 0x58, 0x56, 0x5d, 0x54, - 0x59, 0x60, 0x64, 0x59, 0x69, 0x5b, 0x52, 0x5e, 0x59, 0x5c, 0x5b, 0x54, - 0x53, 0x65, 0x64, 0x5d, 0x5d, 0x56, 0x5c, 0x59, 0x57, 0x61, 0x5f, 0x5a, - 0x62, 0x50, 0x54, 0x50, 0x59, 0x4b, 0x60, 0x6c, 0x7c, 0x54, 0x58, 0x5e, - 0x5a, 0x42, 0x39, 0x81, 0x5b, 0x4c, 0x4c, 0x4c, 0x6d, 0x52, 0x76, 0x53, - 0x55, 0x56, 0x80, 0x5b, 0x77, 0x6a, 0x65, 0x57, 0x5c, 0x53, 0x5a, 0x65, - 0x57, 0x4d, 0x67, 0x5b, 0x65, 0x4d, 0x4f, 0x4d, 0x55, 0x54, 0x66, 0x5c, - 0x60, 0x5e, 0x59, 0x54, 0x5a, 0x4f, 0x5c, 0x61, 0x58, 0x62, 0x54, 0x5b, - 0x78, 0x5d, 0x48, 0x48, 0x57, 0x4f, 0x59, 0x5e, 0x4c, 0x5d, 0x69, 0x4f, - 0x54, 0x4e, 0x5b, 0x66, 0x4e, 0x64, 0x6c, 0x5d, 0x5b, 0x56, 0x62, 0x60, - 0x58, 0x61, 0x5e, 0x50, 0x57, 0x5a, 0x58, 0x54, 0x59, 0x55, 0x5a, 0x5f, - 0x59, 0x4e, 0x5b, 0x53, 0x62, 0x59, 0x57, 0x56, 0x53, 0x65, 0x54, 0x6b, - 0x55, 0x56, 0x5c, 0x58, 0x53, 0x54, 0x60, 0x5f, 0x57, 0x5d, 0x51, 0x5f, - 0x59, 0x55, 0x5b, 0x56, 0x5b, 0x56, 0x58, 0x58, 0x59, 0x5c, 0x59, 0x5c, - 0x59, 0x58, 0x5e, 0x5c, 0x58, 0x5a, 0x61, 0x5b, 0x5b, 0x57, 0x4e, 0x5c, - 0x60, 0x5d, 0x54, 0x5a, 0x5b, 0x5c, 0x58, 0x5c, 0x5e, 0x61, 0x5c, 0x5a, - 0x59, 0x60, 0x59, 0x61, 0x59, 0x5b, 0x58, 0x5b, 0x5a, 0x4f, 0x65, 0x60, - 0x59, 0x5a, 0x59, 0x59, 0x58, 0x5c, 0x5f, 0x5b, 0x58, 0x59, 0x5f, 0x5a, - 0x58, 0x61, 0x4d, 0x41, 0x54, 0x56, 0x64, 0x58, 0x50, 0x58, 0x5a, 0x53, - 0x5b, 0x51, 0x60, 0x69, 0x4c, 0x5c, 0x5b, 0x62, 0x5a, 0x4b, 0x54, 0x56, - 0x58, 0x65, 0x52, 0x5e, 0x52, 0x5b, 0x59, 0x59, 0x50, 0x4a, 0x59, 0x53, - 0x59, 0x58, 0x62, 0x58, 0x4c, 0x56, 0x4f, 0x5b, 0x64, 0x5c, 0x4a, 0x5c, - 0x63, 0x5a, 0x61, 0x5a, 0x5b, 0x52, 0x57, 0x59, 0x51, 0x5d, 0x58, 0x56, - 0x5e, 0x5a, 0x55, 0x63, 0x5a, 0x42, 0x53, 0x51, 0x48, 0x55, 0x59, 0x5c, - 0x58, 0x56, 0x59, 0x55, 0x5c, 0x5a, 0x60, 0x5a, 0x5d, 0x5a, 0x54, 0x5b, - 0x53, 0x5b, 0x61, 0x68, 0x5c, 0x61, 0x57, 0x52, 0x57, 0x54, 0x5b, 0x5a, - 0x51, 0x53, 0x6d, 0x5f, 0x5c, 0x4f, 0x62, 0x62, 0x59, 0x56, 0x55, 0x56, - 0x58, 0x5a, 0x59, 0x5b, 0x58, 0x4e, 0x61, 0x59, 0x59, 0x57, 0x61, 0x57, - 0x5b, 0x59, 0x50, 0x61, 0x5f, 0x5b, 0x5c, 0x5b, 0x5a, 0x5d, 0x59, 0x5b, - 0x5b, 0x5e, 0x5d, 0x5b, 0x60, 0x6b, 0x5a, 0x59, 0x5a, 0x59, 0x57, 0x5c, - 0x58, 0x56, 0x51, 0x59, 0x58, 0x5a, 0x59, 0x59, 0x57, 0x58, 0x5b, 0x5d, - 0x58, 0x62, 0x59, 0x61, 0x5c, 0x56, 0x58, 0x5f, 0x5a, 0x56, 0x4f, 0x59, - 0x57, 0x59, 0x5e, 0x59, 0x61, 0x54, 0x57, 0x5c, 0x5a, 0x50, 0x58, 0x5a, - 0x5a, 0x4f, 0x4c, 0x52, 0x55, 0x64, 0x52, 0x5a, 0x55, 0x4d, 0x58, 0x52, - 0x5e, 0x52, 0x43, 0x57, 0x57, 0x51, 0x53, 0x67, 0x61, 0x50, 0x52, 0x5c, - 0x54, 0x5b, 0x4c, 0x5f, 0x4b, 0x5a, 0x56, 0x52, 0x56, 0x57, 0x58, 0x5a, - 0x51, 0x54, 0x59, 0x6a, 0x55, 0x54, 0x57, 0x5b, 0x4f, 0x5a, 0x61, 0x54, - 0x62, 0x54, 0x59, 0x59, 0x5d, 0x55, 0x5e, 0x59, 0x59, 0x54, 0x50, 0x63, - 0x66, 0x59, 0x4f, 0x5e, 0x57, 0x54, 0x50, 0x53, 0x55, 0x55, 0x5d, 0x51, - 0x5e, 0x57, 0x5b, 0x58, 0x57, 0x5a, 0x59, 0x5d, 0x5e, 0x4e, 0x68, 0x61, - 0x58, 0x51, 0x5c, 0x5a, 0x4c, 0x5b, 0x5a, 0x64, 0x58, 0x5a, 0x66, 0x59, - 0x58, 0x5b, 0x66, 0x5d, 0x6a, 0x66, 0x55, 0x60, 0x5c, 0x63, 0x62, 0x4b, - 0x55, 0x69, 0x61, 0x58, 0x62, 0x55, 0x5c, 0x58, 0x57, 0x65, 0x59, 0x65, - 0x55, 0x5c, 0x58, 0x49, 0x5d, 0x61, 0x63, 0x54, 0x58, 0x5a, 0x59, 0x65, - 0x56, 0x47, 0x51, 0x5d, 0x59, 0x61, 0x56, 0x5a, 0x57, 0x5c, 0x60, 0x4b, - 0x50, 0x59, 0x45, 0x5f, 0x5b, 0x57, 0x5f, 0x53, 0x54, 0x5e, 0x53, 0x57, - 0x5c, 0x5c, 0x59, 0x55, 0x57, 0x55, 0x57, 0x65, 0x5a, 0x4a, 0x46, 0x4e, - 0x55, 0x56, 0x5a, 0x59, 0x57, 0x59, 0x5c, 0x5b, 0x58, 0x58, 0x5c, 0x6a, - 0x4d, 0x56, 0x58, 0x56, 0x53, 0x58, 0x5d, 0x56, 0x5b, 0x55, 0x69, 0x5d, - 0x66, 0x5a, 0x58, 0x5c, 0x55, 0x56, 0x57, 0x57, 0x5c, 0x53, 0x63, 0x59, - 0x53, 0x5d, 0x5d, 0x5b, 0x53, 0x56, 0x59, 0x62, 0x58, 0x54, 0x5d, 0x58, - 0x5a, 0x5c, 0x5e, 0x53, 0x62, 0x61, 0x4f, 0x57, 0x58, 0x5c, 0x64, 0x50, - 0x57, 0x64, 0x53, 0x5c, 0x5a, 0x58, 0x5b, 0x59, 0x52, 0x62, 0x59, 0x5d, - 0x51, 0x54, 0x59, 0x5b, 0x56, 0x54, 0x58, 0x52, 0x55, 0x5b, 0x5a, 0x56, - 0x57, 0x54, 0x5e, 0x52, 0x58, 0x5b, 0x5c, 0x59, 0x6a, 0x5c, 0x53, 0x5b, - 0x57, 0x55, 0x5e, 0x5d, 0x4b, 0x5d, 0x59, 0x58, 0x53, 0x51, 0x57, 0x66, - 0x54, 0x5e, 0x5a, 0x58, 0x5f, 0x5b, 0x5b, 0x54, 0x5a, 0x5b, 0x5e, 0x56, - 0x59, 0x53, 0x59, 0x5c, 0x57, 0x4e, 0x5f, 0x54, 0x59, 0x5f, 0x58, 0x58, - 0x59, 0x5d, 0x5a, 0x58, 0x55, 0x52, 0x4e, 0x56, 0x52, 0x57, 0x5d, 0x56, - 0x59, 0x59, 0x56, 0x5b, 0x57, 0x5f, 0x58, 0x5d, 0x59, 0x54, 0x5a, 0x5d, - 0x52, 0x5c, 0x61, 0x50, 0x58, 0x55, 0x5a, 0x5e, 0x5a, 0x52, 0x5d, 0x59, - 0x59, 0x63, 0x5a, 0x5b, 0x69, 0x5b, 0x55, 0x58, 0x58, 0x59, 0x61, 0x54, - 0x5c, 0x60, 0x50, 0x5a, 0x5d, 0x53, 0x5a, 0x5b, 0x59, 0x61, 0x5b, 0x60, - 0x59, 0x58, 0x5e, 0x52, 0x57, 0x58, 0x57, 0x5a, 0x56, 0x5e, 0x58, 0x60, - 0x58, 0x5a, 0x5b, 0x59, 0x58, 0x5d, 0x60, 0x58, 0x5c, 0x63, 0x59, 0x52, - 0x5b, 0x59, 0x5f, 0x59, 0x57, 0x57, 0x56, 0x5b, 0x55, 0x56, 0x56, 0x5c, - 0x5c, 0x58, 0x5b, 0x4f, 0x5c, 0x4e, 0x5a, 0x57, 0x4d, 0x59, 0x62, 0x4e, - 0x4d, 0x55, 0x58, 0x57, 0x58, 0x4c, 0x3d, 0x58, 0x59, 0x5c, 0x55, 0x53, - 0x72, 0x5b, 0x4a, 0x56, 0x54, 0x5a, 0x50, 0x57, 0x4f, 0x55, 0x5d, 0x56, - 0x56, 0x56, 0x5b, 0x51, 0x5c, 0x57, 0x67, 0x57, 0x5b, 0x51, 0x5c, 0x64, - 0x63, 0x53, 0x57, 0x56, 0x51, 0x57, 0x59, 0x5f, 0x59, 0x4d, 0x5e, 0x56, - 0x59, 0x54, 0x5d, 0x54, 0x61, 0x5a, 0x44, 0x52, 0x5b, 0x59, 0x57, 0x59, - 0x63, 0x59, 0x53, 0x56, 0x51, 0x59, 0x59, 0x58, 0x5d, 0x58, 0x59, 0x62, - 0x59, 0x53, 0x5f, 0x56, 0x53, 0x5b, 0x5e, 0x5a, 0x5b, 0x5b, 0x58, 0x5c, - 0x59, 0x54, 0x5e, 0x59, 0x57, 0x5c, 0x61, 0x55, 0x5e, 0x5e, 0x53, 0x5b, - 0x5c, 0x5a, 0x5f, 0x5c, 0x5b, 0x5c, 0x5c, 0x5b, 0x58, 0x5b, 0x57, 0x5c, - 0x55, 0x59, 0x59, 0x55, 0x54, 0x55, 0x4c, 0x53, 0x58, 0x5c, 0x5b, 0x4d, - 0x59, 0x57, 0x59, 0x61, 0x59, 0x4c, 0x5b, 0x55, 0x5a, 0x5d, 0x51, 0x57, - 0x4f, 0x5b, 0x5d, 0x5d, 0x5c, 0x5a, 0x51, 0x5b, 0x4d, 0x58, 0x5a, 0x58, - 0x60, 0x5a, 0x58, 0x5a, 0x5a, 0x5a, 0x6b, 0x59, 0x57, 0x45, 0x4e, 0x66, - 0x58, 0x5b, 0x4e, 0x68, 0x5a, 0x58, 0x59, 0x40, 0x58, 0x4b, 0x55, 0x53, - 0x58, 0x55, 0x54, 0x5e, 0x64, 0x5e, 0x49, 0x4d, 0x51, 0x5d, 0x4c, 0x5c, - 0x53, 0x50, 0x4d, 0x59, 0x52, 0x57, 0x56, 0x58, 0x63, 0x58, 0x57, 0x4d, - 0x63, 0x4e, 0x56, 0x4b, 0x62, 0x3e, 0x50, 0x58, 0x50, 0x58, 0x59, 0x61, - 0x55, 0x4e, 0x5f, 0x55, 0x59, 0x5a, 0x67, 0x57, 0x62, 0x5a, 0x4c, 0x57, - 0x51, 0x5b, 0x54, 0x64, 0x46, 0x58, 0x5c, 0x57, 0x50, 0x58, 0x5b, 0x5f, - 0x4e, 0x5a, 0x71, 0x67, 0x5b, 0x53, 0x58, 0x5c, 0x56, 0x56, 0x5f, 0x54, - 0x5b, 0x52, 0x59, 0x5b, 0x5f, 0x51, 0x5b, 0x57, 0x59, 0x5e, 0x5d, 0x54, - 0x61, 0x5a, 0x56, 0x5f, 0x5a, 0x56, 0x51, 0x5b, 0x5a, 0x5b, 0x5c, 0x56, - 0x5b, 0x56, 0x59, 0x5a, 0x55, 0x62, 0x59, 0x56, 0x5e, 0x51, 0x5e, 0x5a, - 0x58, 0x5d, 0x60, 0x53, 0x59, 0x58, 0x59, 0x5c, 0x57, 0x4f, 0x59, 0x56, - 0x59, 0x5c, 0x52, 0x5a, 0x5d, 0x59, 0x4b, 0x5a, 0x56, 0x5a, 0x56, 0x5b, - 0x5d, 0x53, 0x52, 0x5c, 0x59, 0x5b, 0x56, 0x5a, 0x5b, 0x4f, 0x5b, 0x63, - 0x5e, 0x54, 0x58, 0x5c, 0x58, 0x53, 0x57, 0x5c, 0x59, 0x57, 0x58, 0x55, - 0x5a, 0x50, 0x5b, 0x57, 0x59, 0x54, 0x5c, 0x57, 0x51, 0x5c, 0x57, 0x5d, - 0x54, 0x5b, 0x67, 0x65, 0x5c, 0x5e, 0x64, 0x5f, 0x56, 0x57, 0x5d, 0x65, - 0x59, 0x5d, 0x57, 0x59, 0x5d, 0x4f, 0x58, 0x5b, 0x5a, 0x53, 0x58, 0x5d, - 0x47, 0x4e, 0x59, 0x59, 0x58, 0x54, 0x5c, 0x58, 0x59, 0x62, 0x61, 0x5c, - 0x58, 0x63, 0x63, 0x47, 0x56, 0x5e, 0x4f, 0x44, 0x4b, 0x4a, 0x59, 0x5c, - 0x5e, 0x56, 0x5b, 0x53, 0x44, 0x56, 0x59, 0x6a, 0x5b, 0x51, 0x5b, 0x5b, - 0x57, 0x57, 0x59, 0x5a, 0x5b, 0x57, 0x59, 0x5c, 0x58, 0x52, 0x5d, 0x54, - 0x57, 0x5e, 0x5f, 0x56, 0x5f, 0x5b, 0x51, 0x5a, 0x57, 0x59, 0x5c, 0x58, - 0x59, 0x60, 0x59, 0x5a, 0x5a, 0x5c, 0x5b, 0x59, 0x58, 0x61, 0x59, 0x5c, - 0x57, 0x57, 0x63, 0x54, 0x58, 0x5b, 0x5f, 0x58, 0x57, 0x5b, 0x59, 0x5e, - 0x59, 0x59, 0x5f, 0x57, 0x59, 0x59, 0x65, 0x5a, 0x5c, 0x58, 0x55, 0x5c, - 0x5d, 0x5f, 0x63, 0x55, 0x61, 0x59, 0x5c, 0x5b, 0x59, 0x59, 0x5b, 0x5b, - 0x5b, 0x55, 0x5a, 0x58, 0x5c, 0x53, 0x59, 0x56, 0x58, 0x53, 0x68, 0x5e, - 0x54, 0x57, 0x5a, 0x58, 0x5a, 0x4d, 0x5e, 0x58, 0x59, 0x5c, 0x58, 0x55, - 0x65, 0x64, 0x53, 0x5a, 0x58, 0x57, 0x68, 0x60, 0x51, 0x59, 0x54, 0x5d, - 0x59, 0x56, 0x5b, 0x5e, 0x59, 0x57, 0x5c, 0x63, 0x56, 0x5c, 0x52, 0x62, - 0x56, 0x74, 0x58, 0x54, 0x54, 0x54, 0x58, 0x56, 0x5b, 0x4c, 0x58, 0x5d, - 0x59, 0x5e, 0x57, 0x57, 0x5b, 0x5b, 0x5e, 0x53, 0x5c, 0x57, 0x50, 0x58, - 0x57, 0x5c, 0x5b, 0x56, 0x5f, 0x5d, 0x56, 0x62, 0x5c, 0x5c, 0x59, 0x5f, - 0x5a, 0x58, 0x5a, 0x5b, 0x56, 0x59, 0x59, 0x5b, 0x58, 0x5b, 0x58, 0x58, - 0x57, 0x5a, 0x5a, 0x5a, 0x59, 0x64, 0x5d, 0x60, 0x5d, 0x54, 0x58, 0x5b, - 0x5c, 0x58, 0x56, 0x57, 0x5a, 0x59, 0x5d, 0x5d, 0x61, 0x5a, 0x56, 0x5d, - 0x5a, 0x57, 0x56, 0x5d, 0x5c, 0x58, 0x59, 0x60, 0x58, 0x4c, 0x59, 0x58, - 0x5c, 0x5a, 0x57, 0x58, 0x5a, 0x57, 0x5b, 0x59, 0x59, 0x5c, 0x5b, 0x5d, - 0x65, 0x5d, 0x53, 0x57, 0x58, 0x56, 0x61, 0x5a, 0x56, 0x64, 0x62, 0x58, - 0x5d, 0x50, 0x5d, 0x5f, 0x56, 0x5e, 0x59, 0x5c, 0x56, 0x51, 0x57, 0x5b, - 0x5a, 0x69, 0x4f, 0x5b, 0x56, 0x57, 0x5a, 0x62, 0x56, 0x55, 0x5e, 0x5b, - 0x5a, 0x58, 0x66, 0x54, 0x5a, 0x58, 0x4a, 0x5a, 0x5c, 0x5d, 0x45, 0x56, - 0x65, 0x63, 0x57, 0x57, 0x54, 0x5c, 0x59, 0x59, 0x5c, 0x61, 0x5f, 0x5a, - 0x61, 0x4b, 0x5a, 0x4b, 0x4e, 0x5c, 0x62, 0x48, 0x4c, 0x53, 0x59, 0x5a, - 0x57, 0x47, 0x2c, 0x56, 0x59, 0x5d, 0x59, 0x58, 0x74, 0x59, 0x4a, 0x56, - 0x55, 0x5a, 0x53, 0x59, 0x52, 0x4e, 0x60, 0x4f, 0x55, 0x54, 0x5a, 0x4f, - 0x5a, 0x58, 0x6b, 0x55, 0x5a, 0x54, 0x59, 0x5f, 0x5a, 0x5b, 0x52, 0x58, - 0x5a, 0x59, 0x58, 0x58, 0x57, 0x5a, 0x48, 0x5c, 0x58, 0x68, 0x52, 0x54, - 0x62, 0x5c, 0x4a, 0x6a, 0x58, 0x60, 0x55, 0x61, 0x63, 0x5e, 0x5f, 0x50, - 0x5b, 0x58, 0x59, 0x4e, 0x56, 0x58, 0x55, 0x67, 0x5d, 0x58, 0x60, 0x47, - 0x5d, 0x41, 0x59, 0x5a, 0x55, 0x5a, 0x5a, 0x5c, 0x56, 0x54, 0x66, 0x55, - 0x5a, 0x54, 0x6b, 0x4e, 0x66, 0x61, 0x57, 0x51, 0x59, 0x5c, 0x62, 0x5a, - 0x61, 0x69, 0x66, 0x65, 0x55, 0x56, 0x5a, 0x63, 0x56, 0x55, 0x6f, 0x5b, - 0x5b, 0x56, 0x5b, 0x57, 0x5a, 0x59, 0x61, 0x56, 0x58, 0x5d, 0x5b, 0x59, - 0x58, 0x53, 0x5c, 0x56, 0x59, 0x5a, 0x5f, 0x56, 0x63, 0x61, 0x56, 0x5e, - 0x54, 0x5d, 0x61, 0x5e, 0x5d, 0x5a, 0x5c, 0x63, 0x55, 0x60, 0x59, 0x58, - 0x5c, 0x59, 0x5a, 0x58, 0x57, 0x54, 0x57, 0x5c, 0x59, 0x5c, 0x52, 0x5f, - 0x58, 0x5b, 0x58, 0x59, 0x5a, 0x55, 0x59, 0x5a, 0x5a, 0x5c, 0x5b, 0x5c, - 0x5e, 0x54, 0x5a, 0x5a, 0x5e, 0x59, 0x55, 0x5d, 0x5d, 0x55, 0x60, 0x59, - 0x62, 0x5a, 0x5a, 0x5b, 0x5c, 0x54, 0x58, 0x5d, 0x5c, 0x57, 0x5f, 0x65, - 0x48, 0x5a, 0x62, 0x5d, 0x60, 0x4e, 0x59, 0x59, 0x59, 0x49, 0x58, 0x59, - 0x59, 0x5e, 0x57, 0x5e, 0x70, 0x5c, 0x49, 0x5d, 0x59, 0x54, 0x5c, 0x58, - 0x55, 0x5c, 0x4a, 0x55, 0x54, 0x4f, 0x5b, 0x61, 0x5a, 0x5e, 0x5e, 0x5a, - 0x56, 0x54, 0x4e, 0x51, 0x5b, 0x6c, 0x57, 0x5a, 0x54, 0x5a, 0x59, 0x5b, - 0x5a, 0x4f, 0x59, 0x5c, 0x58, 0x49, 0x68, 0x5c, 0x5e, 0x55, 0x4c, 0x5d, - 0x5a, 0x58, 0x4c, 0x56, 0x55, 0x5e, 0x5b, 0x58, 0x57, 0x55, 0x5a, 0x5b, - 0x51, 0x5d, 0x59, 0x5d, 0x5a, 0x5f, 0x5d, 0x5a, 0x5d, 0x58, 0x61, 0x54, - 0x58, 0x5c, 0x5b, 0x5c, 0x58, 0x5b, 0x5f, 0x56, 0x5b, 0x5d, 0x60, 0x59, - 0x63, 0x58, 0x59, 0x52, 0x59, 0x5b, 0x68, 0x61, 0x5a, 0x59, 0x62, 0x5e, - 0x59, 0x55, 0x5d, 0x64, 0x59, 0x56, 0x57, 0x5f, 0x5a, 0x59, 0x56, 0x5d, - 0x59, 0x55, 0x57, 0x61, 0x5f, 0x57, 0x58, 0x5b, 0x58, 0x56, 0x5b, 0x54, - 0x59, 0x5d, 0x5e, 0x5a, 0x50, 0x5f, 0x4d, 0x5b, 0x5c, 0x58, 0x5b, 0x53, - 0x5d, 0x5d, 0x5a, 0x5a, 0x59, 0x59, 0x5b, 0x55, 0x59, 0x5c, 0x5a, 0x5e, - 0x57, 0x57, 0x5d, 0x51, 0x57, 0x5b, 0x5f, 0x5a, 0x59, 0x5d, 0x5d, 0x5f, - 0x58, 0x58, 0x63, 0x5c, 0x59, 0x54, 0x64, 0x56, 0x57, 0x58, 0x58, 0x5b, - 0x5c, 0x5c, 0x5c, 0x5a, 0x5d, 0x59, 0x51, 0x5e, 0x54, 0x58, 0x5b, 0x5d, - 0x56, 0x57, 0x59, 0x52, 0x5f, 0x51, 0x5c, 0x61, 0x5a, 0x50, 0x5c, 0x5a, - 0x5b, 0x54, 0x59, 0x60, 0x57, 0x53, 0x64, 0x56, 0x59, 0x5d, 0x65, 0x57, - 0x63, 0x5d, 0x44, 0x5a, 0x58, 0x58, 0x5d, 0x5a, 0x5d, 0x68, 0x58, 0x5a, - 0x58, 0x55, 0x5c, 0x5f, 0x57, 0x5d, 0x59, 0x61, 0x5c, 0x50, 0x5c, 0x5a, - 0x57, 0x51, 0x5e, 0x59, 0x58, 0x59, 0x5a, 0x5e, 0x55, 0x55, 0x5c, 0x57, - 0x5a, 0x5e, 0x5b, 0x5a, 0x67, 0x5d, 0x54, 0x56, 0x56, 0x58, 0x61, 0x55, - 0x52, 0x60, 0x5d, 0x58, 0x5b, 0x5b, 0x5d, 0x5b, 0x58, 0x63, 0x59, 0x63, - 0x60, 0x51, 0x59, 0x64, 0x57, 0x59, 0x54, 0x54, 0x5e, 0x4f, 0x59, 0x5d, - 0x56, 0x4f, 0x5b, 0x5a, 0x59, 0x57, 0x61, 0x56, 0x66, 0x5b, 0x4a, 0x5d, - 0x57, 0x59, 0x61, 0x56, 0x56, 0x58, 0x55, 0x59, 0x5d, 0x5c, 0x5b, 0x59, - 0x5d, 0x67, 0x59, 0x58, 0x5d, 0x55, 0x5a, 0x45, 0x57, 0x67, 0x4e, 0x51, - 0x76, 0x50, 0x58, 0x67, 0x5c, 0x55, 0x65, 0x5b, 0x58, 0x61, 0x62, 0x5b, - 0x66, 0x58, 0x5a, 0x5f, 0x65, 0x4d, 0x69, 0x70, 0x5a, 0x58, 0x5d, 0x55, - 0x4b, 0x4f, 0x58, 0x78, 0x43, 0x56, 0x5b, 0x66, 0x58, 0x59, 0x60, 0x57, - 0x5a, 0x59, 0x64, 0x56, 0x57, 0x5a, 0x5b, 0x59, 0x58, 0x5a, 0x62, 0x5b, - 0x59, 0x5a, 0x66, 0x58, 0x5c, 0x59, 0x5a, 0x5b, 0x5a, 0x5e, 0x6a, 0x61, - 0x64, 0x59, 0x62, 0x62, 0x56, 0x5e, 0x59, 0x63, 0x57, 0x54, 0x59, 0x57, - 0x5f, 0x4e, 0x5d, 0x45, 0x4f, 0x54, 0x3c, 0x55, 0x48, 0x53, 0x58, 0x5c, - 0x5c, 0x4c, 0x65, 0x55, 0x59, 0x5c, 0x63, 0x53, 0x5a, 0x58, 0x58, 0x5f, - 0x53, 0x56, 0x56, 0x60, 0x47, 0x53, 0x5b, 0x51, 0x55, 0x51, 0x5b, 0x5d, - 0x4f, 0x5b, 0x6c, 0x5d, 0x5a, 0x55, 0x52, 0x6c, 0x57, 0x60, 0x64, 0x54, - 0x5d, 0x51, 0x5a, 0x5f, 0x59, 0x57, 0x63, 0x57, 0x59, 0x54, 0x55, 0x5b, - 0x6c, 0x5f, 0x52, 0x58, 0x56, 0x5f, 0x61, 0x58, 0x54, 0x6c, 0x5b, 0x51, - 0x5e, 0x58, 0x5a, 0x58, 0x5a, 0x58, 0x59, 0x63, 0x57, 0x58, 0x65, 0x55, - 0x59, 0x65, 0x66, 0x59, 0x56, 0x5d, 0x59, 0x5e, 0x58, 0x5a, 0x66, 0x58, - 0x58, 0x55, 0x69, 0x58, 0x5b, 0x62, 0x57, 0x5a, 0x5a, 0x61, 0x6f, 0x67, - 0x5d, 0x54, 0x5a, 0x62, 0x59, 0x5e, 0x59, 0x64, 0x57, 0x58, 0x59, 0x53, - 0x5a, 0x5a, 0x4c, 0x56, 0x59, 0x60, 0x67, 0x4f, 0x5a, 0x55, 0x59, 0x55, - 0x5a, 0x59, 0x53, 0x59, 0x57, 0x68, 0x58, 0x5c, 0x63, 0x5b, 0x58, 0x5a, - 0x56, 0x54, 0x55, 0x61, 0x48, 0x5c, 0x6b, 0x53, 0x58, 0x55, 0x5d, 0x62, - 0x57, 0x5a, 0x57, 0x64, 0x54, 0x41, 0x5b, 0x50, 0x5b, 0x68, 0x58, 0x58, - 0x50, 0x63, 0x58, 0x4c, 0x5b, 0x44, 0x41, 0x5a, 0x58, 0x56, 0x31, 0x62, - 0x55, 0x55, 0x4f, 0x45, 0x66, 0x4f, 0x5e, 0x41, 0x56, 0x4b, 0x52, 0x49, - 0x55, 0x5a, 0x5a, 0x4b, 0x59, 0x4d, 0x5b, 0x5c, 0x59, 0x52, 0x59, 0x57, - 0x59, 0x58, 0x60, 0x50, 0x51, 0x58, 0x59, 0x57, 0x57, 0x50, 0x4f, 0x5c, - 0x5a, 0x59, 0x4a, 0x57, 0x62, 0x57, 0x5c, 0x60, 0x57, 0x5c, 0x58, 0x57, - 0x55, 0x60, 0x4e, 0x55, 0x5a, 0x58, 0x56, 0x58, 0x5a, 0x53, 0x59, 0x58, - 0x5c, 0x5b, 0x55, 0x56, 0x57, 0x63, 0x62, 0x52, 0x5b, 0x58, 0x58, 0x5e, - 0x57, 0x4c, 0x45, 0x5d, 0x59, 0x58, 0x4f, 0x5c, 0x63, 0x59, 0x4f, 0x50, - 0x57, 0x5a, 0x53, 0x60, 0x56, 0x4f, 0x60, 0x46, 0x53, 0x56, 0x58, 0x4d, - 0x53, 0x52, 0x58, 0x59, 0x60, 0x54, 0x51, 0x5b, 0x59, 0x40, 0x6f, 0x58, - 0x67, 0x5f, 0x59, 0x63, 0x5d, 0x50, 0x5f, 0x65, 0x59, 0x52, 0x60, 0x5a, - 0x7b, 0x5c, 0x47, 0x45, 0x57, 0x5d, 0x67, 0x65, 0x66, 0x6e, 0x4c, 0x5b, - 0x53, 0x4d, 0x5c, 0x68, 0x53, 0x54, 0x89, 0x60, 0x5a, 0x52, 0x5b, 0x5f, - 0x55, 0x54, 0x55, 0x5a, 0x57, 0x57, 0x59, 0x5a, 0x58, 0x55, 0x5c, 0x59, - 0x5a, 0x5a, 0x60, 0x56, 0x62, 0x5a, 0x4f, 0x61, 0x5c, 0x59, 0x5b, 0x5d, - 0x59, 0x61, 0x56, 0x56, 0x5d, 0x5d, 0x5b, 0x57, 0x5f, 0x63, 0x5b, 0x5b, - 0x58, 0x4c, 0x5f, 0x54, 0x57, 0x57, 0x6d, 0x57, 0x59, 0x59, 0x59, 0x62, - 0x54, 0x53, 0x61, 0x5a, 0x59, 0x61, 0x5d, 0x55, 0x63, 0x53, 0x49, 0x5d, - 0x57, 0x48, 0x4e, 0x60, 0x4a, 0x5b, 0x56, 0x4c, 0x53, 0x50, 0x5b, 0x64, - 0x4e, 0x5f, 0x58, 0x64, 0x5d, 0x54, 0x61, 0x5d, 0x59, 0x56, 0x67, 0x56, - 0x4d, 0x55, 0x59, 0x5e, 0x59, 0x4e, 0x5c, 0x64, 0x59, 0x58, 0x5e, 0x55, - 0x7b, 0x71, 0x4f, 0x4d, 0x50, 0x61, 0x6b, 0x5a, 0x6e, 0x5b, 0x4d, 0x5a, - 0x54, 0x52, 0x60, 0x68, 0x50, 0x5e, 0x63, 0x52, 0x54, 0x59, 0x54, 0x5a, - 0x5b, 0x5b, 0x5c, 0x51, 0x5c, 0x55, 0x5a, 0x5a, 0x58, 0x54, 0x5a, 0x56, - 0x59, 0x5b, 0x59, 0x5b, 0x61, 0x5b, 0x5c, 0x5b, 0x58, 0x5a, 0x52, 0x55, - 0x54, 0x57, 0x58, 0x5b, 0x5a, 0x58, 0x58, 0x5a, 0x57, 0x60, 0x59, 0x59, - 0x5b, 0x57, 0x5a, 0x55, 0x57, 0x52, 0x5c, 0x60, 0x5d, 0x5a, 0x5a, 0x5f, - 0x5a, 0x5a, 0x5e, 0x5c, 0x5a, 0x58, 0x61, 0x5b, 0x67, 0x5f, 0x51, 0x54, - 0x5b, 0x58, 0x66, 0x5a, 0x52, 0x5c, 0x4e, 0x5d, 0x5b, 0x54, 0x5e, 0x5d, - 0x57, 0x5d, 0x58, 0x5c, 0x5c, 0x58, 0x58, 0x59, 0x56, 0x5b, 0x57, 0x54, - 0x56, 0x58, 0x59, 0x5a, 0x58, 0x52, 0x5f, 0x56, 0x59, 0x5b, 0x5e, 0x56, - 0x5a, 0x5b, 0x50, 0x5f, 0x58, 0x59, 0x5c, 0x5a, 0x55, 0x5e, 0x51, 0x5e, - 0x58, 0x56, 0x58, 0x58, 0x58, 0x5c, 0x5a, 0x5d, 0x5d, 0x51, 0x5a, 0x4c, - 0x53, 0x5a, 0x63, 0x55, 0x60, 0x53, 0x59, 0x58, 0x5d, 0x50, 0x53, 0x58, - 0x57, 0x60, 0x55, 0x55, 0x67, 0x5c, 0x51, 0x57, 0x55, 0x52, 0x5b, 0x58, - 0x4a, 0x58, 0x62, 0x55, 0x5a, 0x50, 0x5d, 0x5c, 0x52, 0x5b, 0x56, 0x57, - 0x53, 0x54, 0x54, 0x5a, 0x5b, 0x62, 0x5e, 0x52, 0x5b, 0x58, 0x59, 0x56, - 0x56, 0x57, 0x53, 0x5c, 0x5a, 0x5c, 0x51, 0x5d, 0x5e, 0x58, 0x53, 0x63, - 0x63, 0x54, 0x4a, 0x5d, 0x52, 0x54, 0x5a, 0x51, 0x5c, 0x4d, 0x59, 0x5d, - 0x4e, 0x50, 0x58, 0x60, 0x60, 0x51, 0x57, 0x5d, 0x57, 0x4b, 0x5a, 0x5d, - 0x5a, 0x57, 0x5a, 0x5d, 0x59, 0x53, 0x62, 0x56, 0x5a, 0x59, 0x63, 0x59, - 0x63, 0x5b, 0x4f, 0x59, 0x5a, 0x59, 0x5d, 0x56, 0x4b, 0x5e, 0x60, 0x54, - 0x59, 0x5e, 0x59, 0x59, 0x5f, 0x5f, 0x5d, 0x5f, 0x5c, 0x58, 0x5b, 0x59, - 0x5b, 0x59, 0x65, 0x56, 0x59, 0x5c, 0x5c, 0x56, 0x58, 0x59, 0x5a, 0x57, - 0x57, 0x5f, 0x5e, 0x5d, 0x61, 0x5b, 0x54, 0x5f, 0x5a, 0x5c, 0x64, 0x61, - 0x54, 0x5f, 0x66, 0x5e, 0x54, 0x56, 0x5d, 0x63, 0x59, 0x5a, 0x56, 0x5f, - 0x5d, 0x57, 0x5d, 0x5a, 0x58, 0x61, 0x5b, 0x5b, 0x55, 0x5c, 0x58, 0x5b, - 0x5a, 0x56, 0x4e, 0x5c, 0x5a, 0x55, 0x5c, 0x4d, 0x5f, 0x5f, 0x59, 0x59, - 0x55, 0x61, 0x4f, 0x63, 0x54, 0x64, 0x64, 0x57, 0x57, 0x56, 0x5b, 0x55, - 0x58, 0x52, 0x52, 0x5c, 0x59, 0x57, 0x57, 0x5a, 0x59, 0x62, 0x61, 0x5c, - 0x59, 0x5b, 0x5a, 0x57, 0x58, 0x51, 0x51, 0x59, 0x5a, 0x65, 0x5c, 0x5a, - 0x65, 0x5b, 0x54, 0x50, 0x58, 0x55, 0x5d, 0x62, 0x4c, 0x5a, 0x50, 0x5a, - 0x59, 0x4f, 0x5f, 0x60, 0x55, 0x5c, 0x58, 0x64, 0x5b, 0x4b, 0x56, 0x5e, - 0x58, 0x55, 0x57, 0x59, 0x5b, 0x56, 0x59, 0x5a, 0x58, 0x51, 0x56, 0x57, - 0x59, 0x5d, 0x57, 0x5c, 0x66, 0x5c, 0x51, 0x5d, 0x5a, 0x56, 0x56, 0x57, - 0x5b, 0x5b, 0x5a, 0x53, 0x62, 0x59, 0x5a, 0x51, 0x5f, 0x5c, 0x5b, 0x5f, - 0x5f, 0x56, 0x57, 0x56, 0x59, 0x50, 0x5b, 0x5b, 0x54, 0x56, 0x59, 0x5d, - 0x58, 0x55, 0x5b, 0x57, 0x5a, 0x5f, 0x5c, 0x5b, 0x6e, 0x5e, 0x56, 0x59, - 0x58, 0x5e, 0x62, 0x53, 0x56, 0x5c, 0x67, 0x56, 0x56, 0x55, 0x5d, 0x5d, - 0x5a, 0x5d, 0x5b, 0x60, 0x55, 0x59, 0x57, 0x5e, 0x59, 0x62, 0x5d, 0x57, - 0x58, 0x5a, 0x58, 0x5a, 0x59, 0x58, 0x5d, 0x58, 0x59, 0x5c, 0x60, 0x5b, - 0x56, 0x57, 0x58, 0x60, 0x57, 0x59, 0x57, 0x5b, 0x54, 0x5b, 0x5d, 0x5c, - 0x54, 0x5a, 0x55, 0x61, 0x55, 0x55, 0x58, 0x5d, 0x5b, 0x56, 0x55, 0x68, - 0x59, 0x51, 0x65, 0x58, 0x5f, 0x57, 0x58, 0x63, 0x54, 0x59, 0x62, 0x54, - 0x58, 0x5c, 0x65, 0x5a, 0x66, 0x60, 0x45, 0x5d, 0x55, 0x57, 0x5e, 0x55, - 0x60, 0x71, 0x59, 0x55, 0x5b, 0x58, 0x59, 0x59, 0x5a, 0x59, 0x58, 0x66, - 0x52, 0x47, 0x47, 0x56, 0x54, 0x6d, 0x61, 0x48, 0x71, 0x56, 0x59, 0x54, - 0x4d, 0x50, 0x5b, 0x5e, 0x58, 0x60, 0x3f, 0x5c, 0x5c, 0x5a, 0x5b, 0x5b, - 0x62, 0x58, 0x4b, 0x5b, 0x52, 0x59, 0x5c, 0x5e, 0x55, 0x59, 0x57, 0x61, - 0x55, 0x56, 0x5a, 0x56, 0x5c, 0x5d, 0x51, 0x5f, 0x56, 0x5f, 0x5d, 0x53, - 0x55, 0x56, 0x58, 0x59, 0x57, 0x52, 0x55, 0x58, 0x59, 0x5f, 0x5a, 0x5a, - 0x5a, 0x58, 0x57, 0x5c, 0x56, 0x53, 0x4f, 0x5e, 0x57, 0x56, 0x68, 0x50, - 0x58, 0x58, 0x55, 0x59, 0x53, 0x55, 0x5b, 0x62, 0x5a, 0x5c, 0x56, 0x5c, - 0x58, 0x52, 0x5c, 0x4e, 0x58, 0x54, 0x5a, 0x59, 0x56, 0x56, 0x43, 0x58, - 0x5a, 0x59, 0x5b, 0x5a, 0x6e, 0x58, 0x60, 0x5d, 0x4f, 0x54, 0x4b, 0x55, - 0x57, 0x59, 0x59, 0x57, 0x5d, 0x59, 0x5c, 0x57, 0x61, 0x57, 0x57, 0x58, - 0x5b, 0x54, 0x52, 0x58, 0x5a, 0x5c, 0x5c, 0x50, 0x56, 0x56, 0x58, 0x5c, - 0x56, 0x57, 0x5a, 0x5b, 0x58, 0x63, 0x57, 0x59, 0x59, 0x59, 0x58, 0x62, - 0x5a, 0x5a, 0x53, 0x54, 0x5d, 0x52, 0x51, 0x54, 0x5c, 0x54, 0x59, 0x59, - 0x57, 0x59, 0x5c, 0x64, 0x63, 0x5c, 0x5d, 0x53, 0x52, 0x5b, 0x5f, 0x4f, - 0x5c, 0x52, 0x59, 0x5b, 0x57, 0x4c, 0x58, 0x5a, 0x58, 0x5e, 0x58, 0x5c, - 0x64, 0x5b, 0x52, 0x48, 0x57, 0x55, 0x5b, 0x61, 0x4d, 0x5e, 0x59, 0x57, - 0x57, 0x4e, 0x5c, 0x62, 0x49, 0x5f, 0x66, 0x62, 0x54, 0x55, 0x5d, 0x5f, - 0x57, 0x55, 0x5b, 0x61, 0x61, 0x57, 0x5a, 0x5b, 0x5a, 0x53, 0x5b, 0x58, - 0x59, 0x5a, 0x61, 0x55, 0x65, 0x5a, 0x4b, 0x5d, 0x5a, 0x58, 0x60, 0x57, - 0x51, 0x60, 0x68, 0x5e, 0x57, 0x5b, 0x5d, 0x59, 0x5a, 0x60, 0x5b, 0x59, - 0x5b, 0x5a, 0x5a, 0x57, 0x59, 0x58, 0x58, 0x58, 0x5b, 0x5c, 0x59, 0x58, - 0x59, 0x56, 0x5b, 0x59, 0x59, 0x59, 0x5c, 0x59, 0x58, 0x5a, 0x54, 0x5c, - 0x61, 0x5f, 0x50, 0x58, 0x5f, 0x57, 0x58, 0x5b, 0x5d, 0x62, 0x5d, 0x56, - 0x5b, 0x5e, 0x5a, 0x59, 0x56, 0x52, 0x5c, 0x5e, 0x4e, 0x5f, 0x56, 0x55, - 0x56, 0x60, 0x59, 0x5f, 0x59, 0x50, 0x5c, 0x5b, 0x58, 0x5a, 0x5f, 0x5a, - 0x5b, 0x53, 0x52, 0x64, 0x61, 0x5c, 0x47, 0x55, 0x5f, 0x58, 0x59, 0x5b, - 0x5b, 0x58, 0x59, 0x59, 0x59, 0x5c, 0x58, 0x57, 0x54, 0x4d, 0x53, 0x4f, - 0x4a, 0x55, 0x61, 0x65, 0x60, 0x59, 0x59, 0x5e, 0x5c, 0x4a, 0x5c, 0x53, - 0x58, 0x59, 0x6b, 0x57, 0x60, 0x57, 0x4b, 0x5e, 0x5f, 0x56, 0x43, 0x4e, - 0x5c, 0x60, 0x60, 0x5b, 0x54, 0x59, 0x56, 0x5e, 0x61, 0x59, 0x5f, 0x54, - 0x58, 0x55, 0x58, 0x5a, 0x5b, 0x54, 0x5d, 0x5a, 0x57, 0x59, 0x59, 0x5a, - 0x56, 0x58, 0x57, 0x59, 0x59, 0x5c, 0x5a, 0x59, 0x62, 0x5b, 0x54, 0x5f, - 0x57, 0x59, 0x5b, 0x55, 0x59, 0x5e, 0x5a, 0x58, 0x59, 0x59, 0x5b, 0x51, - 0x5f, 0x60, 0x57, 0x58, 0x5c, 0x59, 0x59, 0x4f, 0x59, 0x59, 0x67, 0x57, - 0x55, 0x59, 0x58, 0x52, 0x57, 0x55, 0x64, 0x56, 0x59, 0x67, 0x4c, 0x61, - 0x6a, 0x60, 0x53, 0x5a, 0x5a, 0x4e, 0x61, 0x5b, 0x47, 0x57, 0x62, 0x4b, - 0x5b, 0x55, 0x59, 0x67, 0x56, 0x59, 0x59, 0x68, 0x59, 0x53, 0x67, 0x50, - 0x58, 0x54, 0x63, 0x56, 0x4e, 0x63, 0x5b, 0x60, 0x57, 0x52, 0x65, 0x60, - 0x57, 0x55, 0x69, 0x55, 0x6f, 0x6d, 0x74, 0x42, 0x5a, 0x61, 0x6d, 0x5d, - 0x6d, 0x4d, 0x48, 0x62, 0x57, 0x5a, 0x62, 0x6a, 0x57, 0x5e, 0x62, 0x51, - 0x58, 0x4d, 0x59, 0x61, 0x54, 0x5f, 0x5d, 0x58, 0x5e, 0x55, 0x5a, 0x5b, - 0x5d, 0x4b, 0x5d, 0x57, 0x59, 0x5b, 0x5e, 0x5e, 0x5f, 0x5c, 0x4b, 0x5f, - 0x55, 0x56, 0x59, 0x58, 0x59, 0x58, 0x53, 0x54, 0x56, 0x54, 0x59, 0x55, - 0x57, 0x5b, 0x5a, 0x5e, 0x61, 0x5a, 0x57, 0x5b, 0x5a, 0x57, 0x54, 0x54, - 0x58, 0x5b, 0x5a, 0x58, 0x58, 0x59, 0x60, 0x59, 0x58, 0x5d, 0x60, 0x57, - 0x58, 0x5f, 0x58, 0x64, 0x5a, 0x5a, 0x55, 0x56, 0x51, 0x65, 0x5c, 0x55, - 0x5c, 0x5a, 0x5d, 0x55, 0x5a, 0x58, 0x5a, 0x5f, 0x57, 0x4f, 0x53, 0x47, - 0x58, 0x74, 0x5d, 0x5d, 0x59, 0x5f, 0x59, 0x5b, 0x58, 0x54, 0x55, 0x63, - 0x59, 0x53, 0x39, 0x5e, 0x52, 0x61, 0x51, 0x5e, 0x5c, 0x5e, 0x56, 0x57, - 0x4f, 0x55, 0x50, 0x52, 0x5c, 0x55, 0x56, 0x55, 0x52, 0x5e, 0x58, 0x56, - 0x5a, 0x56, 0x50, 0x57, 0x5a, 0x55, 0x63, 0x51, 0x4b, 0x56, 0x59, 0x5e, - 0x57, 0x58, 0x5e, 0x56, 0x5a, 0x60, 0x5b, 0x5e, 0x5c, 0x58, 0x55, 0x57, - 0x58, 0x5c, 0x4f, 0x5f, 0x52, 0x5a, 0x5c, 0x5f, 0x5e, 0x56, 0x5c, 0x5f, - 0x53, 0x56, 0x5e, 0x68, 0x56, 0x55, 0x5e, 0x5a, 0x58, 0x58, 0x5b, 0x57, - 0x51, 0x60, 0x59, 0x5d, 0x5a, 0x58, 0x60, 0x58, 0x59, 0x58, 0x60, 0x57, - 0x59, 0x5c, 0x52, 0x5b, 0x5a, 0x5e, 0x59, 0x5b, 0x63, 0x56, 0x59, 0x5e, - 0x57, 0x5b, 0x57, 0x5a, 0x58, 0x55, 0x58, 0x55, 0x60, 0x5c, 0x57, 0x54, - 0x54, 0x65, 0x5a, 0x5d, 0x57, 0x64, 0x5a, 0x5c, 0x5c, 0x4a, 0x53, 0x5c, - 0x59, 0x4b, 0x4e, 0x61, 0x5e, 0x59, 0x41, 0x5c, 0x5c, 0x58, 0x56, 0x5e, - 0x3c, 0x53, 0x54, 0x52, 0x55, 0x52, 0x5a, 0x58, 0x4a, 0x6e, 0x6a, 0x43, - 0x50, 0x52, 0x56, 0x5c, 0x57, 0x54, 0x58, 0x58, 0x58, 0x56, 0x59, 0x5b, - 0x56, 0x55, 0x5d, 0x5a, 0x59, 0x58, 0x59, 0x58, 0x62, 0x5c, 0x4c, 0x63, - 0x58, 0x5a, 0x59, 0x56, 0x57, 0x5d, 0x5d, 0x5a, 0x57, 0x59, 0x58, 0x56, - 0x5c, 0x5e, 0x59, 0x5e, 0x5e, 0x54, 0x5a, 0x60, 0x56, 0x54, 0x59, 0x55, - 0x56, 0x4f, 0x59, 0x5e, 0x58, 0x50, 0x5d, 0x55, 0x59, 0x57, 0x5c, 0x56, - 0x60, 0x5b, 0x50, 0x60, 0x5c, 0x57, 0x58, 0x55, 0x4f, 0x5a, 0x5c, 0x55, - 0x5b, 0x5c, 0x5b, 0x55, 0x5c, 0x5a, 0x5a, 0x59, 0x59, 0x54, 0x53, 0x59, - 0x58, 0x59, 0x5e, 0x58, 0x58, 0x58, 0x59, 0x5a, 0x58, 0x55, 0x58, 0x5b, - 0x58, 0x5e, 0x56, 0x58, 0x60, 0x5a, 0x53, 0x61, 0x5b, 0x58, 0x58, 0x54, - 0x56, 0x5d, 0x56, 0x56, 0x5a, 0x5a, 0x5c, 0x53, 0x5d, 0x5b, 0x58, 0x5b, - 0x59, 0x59, 0x5b, 0x5b, 0x5a, 0x51, 0x65, 0x56, 0x59, 0x58, 0x5b, 0x5a, - 0x5b, 0x5a, 0x59, 0x55, 0x58, 0x5e, 0x5b, 0x56, 0x53, 0x5c, 0x58, 0x5b, - 0x56, 0x5c, 0x60, 0x5a, 0x5d, 0x60, 0x5c, 0x5d, 0x56, 0x59, 0x5a, 0x5e, - 0x58, 0x61, 0x58, 0x54, 0x56, 0x62, 0x5a, 0x5a, 0x58, 0x68, 0x50, 0x5e, - 0x54, 0x61, 0x59, 0x5f, 0x57, 0x59, 0x68, 0x5b, 0x58, 0x5b, 0x6d, 0x52, - 0x5d, 0x5b, 0x4a, 0x60, 0x5b, 0x57, 0x52, 0x5d, 0x4b, 0x5c, 0x61, 0x56, - 0x4d, 0x58, 0x58, 0x62, 0x57, 0x64, 0x5a, 0x5b, 0x57, 0x4c, 0x60, 0x63, - 0x5e, 0x5b, 0x59, 0x67, 0x47, 0x5e, 0x59, 0x5d, 0x58, 0x54, 0x65, 0x56, - 0x59, 0x55, 0x69, 0x56, 0x57, 0x60, 0x4b, 0x50, 0x52, 0x5c, 0x49, 0x60, - 0x6c, 0x5d, 0x54, 0x62, 0x52, 0x56, 0x5a, 0x64, 0x54, 0x61, 0x5e, 0x5d, - 0x5b, 0x57, 0x5e, 0x5b, 0x5a, 0x58, 0x50, 0x64, 0x55, 0x59, 0x5a, 0x5e, - 0x58, 0x56, 0x59, 0x59, 0x5c, 0x5d, 0x5a, 0x55, 0x64, 0x5e, 0x53, 0x5b, - 0x5e, 0x5b, 0x59, 0x4f, 0x60, 0x61, 0x51, 0x57, 0x5a, 0x5c, 0x5e, 0x56, - 0x59, 0x63, 0x5a, 0x51, 0x59, 0x56, 0x54, 0x5a, 0x5a, 0x5c, 0x53, 0x58, - 0x56, 0x5e, 0x58, 0x5c, 0x57, 0x57, 0x5d, 0x58, 0x5a, 0x59, 0x5f, 0x5b, - 0x59, 0x5a, 0x57, 0x61, 0x57, 0x61, 0x50, 0x5e, 0x5a, 0x57, 0x57, 0x5e, - 0x56, 0x59, 0x59, 0x5f, 0x55, 0x5b, 0x5a, 0x5c, 0x4b, 0x56, 0x5a, 0x60, - 0x58, 0x56, 0x5e, 0x4f, 0x5d, 0x54, 0x59, 0x59, 0x57, 0x55, 0x5a, 0x56, - 0x58, 0x5d, 0x58, 0x5e, 0x5a, 0x5d, 0x50, 0x63, 0x53, 0x59, 0x59, 0x5d, - 0x50, 0x5e, 0x65, 0x59, 0x5a, 0x5b, 0x5b, 0x57, 0x5c, 0x60, 0x58, 0x5d, - 0x57, 0x5a, 0x51, 0x55, 0x60, 0x63, 0x5d, 0x5e, 0x59, 0x5a, 0x59, 0x58, - 0x58, 0x50, 0x5b, 0x5c, 0x59, 0x58, 0x62, 0x5c, 0x5a, 0x58, 0x4d, 0x4d, - 0x58, 0x55, 0x45, 0x57, 0x50, 0x5d, 0x53, 0x51, 0x53, 0x51, 0x59, 0x58, - 0x52, 0x4f, 0x5f, 0x5b, 0x59, 0x53, 0x49, 0x51, 0x55, 0x4d, 0x51, 0x55, - 0x54, 0x50, 0x58, 0x60, 0x53, 0x4a, 0x62, 0x5a, 0x59, 0x5b, 0x64, 0x5a, - 0x7a, 0x57, 0x66, 0x54, 0x50, 0x64, 0x3e, 0x4c, 0x4b, 0x83, 0x41, 0x6d, - 0x50, 0x5c, 0x5a, 0x5c, 0x71, 0x55, 0x70, 0x53, 0x5c, 0x52, 0x5b, 0x5b, - 0x5a, 0x55, 0x58, 0x5d, 0x5b, 0x54, 0x59, 0x61, 0x56, 0x56, 0x5a, 0x5a, - 0x5a, 0x58, 0x59, 0x57, 0x64, 0x5f, 0x4c, 0x55, 0x5c, 0x58, 0x61, 0x4d, - 0x53, 0x5b, 0x52, 0x57, 0x57, 0x5d, 0x5c, 0x4f, 0x5e, 0x61, 0x5b, 0x59, - 0x5b, 0x57, 0x57, 0x56, 0x59, 0x63, 0x5e, 0x55, 0x5a, 0x5a, 0x59, 0x56, - 0x59, 0x58, 0x5a, 0x54, 0x59, 0x5a, 0x58, 0x5a, 0x53, 0x59, 0x54, 0x5a, - 0x5a, 0x5b, 0x52, 0x62, 0x54, 0x58, 0x52, 0x59, 0x59, 0x56, 0x59, 0x5c, - 0x56, 0x56, 0x57, 0x64, 0x5a, 0x56, 0x5f, 0x5c, 0x5b, 0x5f, 0x5e, 0x56, - 0x55, 0x62, 0x58, 0x5e, 0x5a, 0x59, 0x64, 0x58, 0x58, 0x62, 0x67, 0x5a, - 0x57, 0x57, 0x56, 0x63, 0x60, 0x65, 0x60, 0x5d, 0x5b, 0x5a, 0x60, 0x63, - 0x4b, 0x58, 0x59, 0x5f, 0x59, 0x5e, 0x5b, 0x62, 0x5a, 0x59, 0x5f, 0x57, - 0x5a, 0x59, 0x65, 0x55, 0x56, 0x5c, 0x59, 0x59, 0x5a, 0x57, 0x64, 0x59, - 0x58, 0x58, 0x65, 0x5a, 0x5e, 0x59, 0x5a, 0x59, 0x58, 0x60, 0x6a, 0x65, - 0x64, 0x58, 0x64, 0x60, 0x58, 0x5d, 0x5b, 0x63, 0x5a, 0x51, 0x57, 0x57, - 0x58, 0x54, 0x5c, 0x57, 0x59, 0x5e, 0x5d, 0x54, 0x58, 0x58, 0x5a, 0x5e, - 0x59, 0x57, 0x5c, 0x57, 0x58, 0x5a, 0x60, 0x59, 0x5a, 0x56, 0x55, 0x63, - 0x5e, 0x5b, 0x5d, 0x5b, 0x59, 0x5d, 0x57, 0x5b, 0x57, 0x5b, 0x54, 0x5d, - 0x59, 0x5c, 0x5b, 0x5a, 0x5a, 0x51, 0x5d, 0x6b, 0x55, 0x54, 0x4a, 0x5c, - 0x58, 0x54, 0x59, 0x5f, 0x56, 0x48, 0x5d, 0x5a, 0x5a, 0x5b, 0x5f, 0x56, - 0x6c, 0x5b, 0x4b, 0x59, 0x5d, 0x58, 0x4d, 0x56, 0x61, 0x64, 0x45, 0x53, - 0x56, 0x59, 0x5b, 0x5d, 0x5b, 0x67, 0x69, 0x52, 0x56, 0x4a, 0x53, 0x5d, - 0x59, 0x61, 0x51, 0x5a, 0x56, 0x5b, 0x59, 0x59, 0x59, 0x56, 0x5b, 0x63, - 0x59, 0x52, 0x5f, 0x5a, 0x64, 0x58, 0x51, 0x52, 0x4c, 0x59, 0x5f, 0x67, - 0x59, 0x52, 0x54, 0x54, 0x5d, 0x59, 0x58, 0x5a, 0x59, 0x53, 0x57, 0x57, - 0x5c, 0x58, 0x5a, 0x60, 0x59, 0x57, 0x5c, 0x52, 0x55, 0x57, 0x59, 0x5b, - 0x57, 0x58, 0x5c, 0x58, 0x59, 0x54, 0x60, 0x57, 0x5e, 0x58, 0x58, 0x63, - 0x52, 0x5b, 0x5f, 0x5c, 0x59, 0x61, 0x69, 0x5b, 0x5a, 0x56, 0x5b, 0x5b, - 0x58, 0x61, 0x58, 0x60, 0x5d, 0x55, 0x60, 0x63, 0x57, 0x56, 0x5f, 0x4e, - 0x56, 0x56, 0x58, 0x5a, 0x5a, 0x5a, 0x5f, 0x55, 0x59, 0x62, 0x5d, 0x5f, - 0x5b, 0x5d, 0x58, 0x59, 0x52, 0x58, 0x4a, 0x59, 0x56, 0x61, 0x64, 0x5f, - 0x5f, 0x5b, 0x5b, 0x58, 0x56, 0x62, 0x5b, 0x5a, 0x5a, 0x54, 0x5c, 0x60, - 0x5b, 0x5b, 0x53, 0x59, 0x5d, 0x53, 0x5a, 0x5e, 0x55, 0x51, 0x5d, 0x56, - 0x5c, 0x5a, 0x5d, 0x57, 0x66, 0x5c, 0x4d, 0x5b, 0x5c, 0x58, 0x5e, 0x55, - 0x53, 0x5f, 0x5b, 0x55, 0x5a, 0x5f, 0x5c, 0x50, 0x62, 0x64, 0x59, 0x59, - 0x5c, 0x4f, 0x5a, 0x53, 0x59, 0x60, 0x61, 0x4f, 0x5d, 0x52, 0x5a, 0x56, - 0x56, 0x47, 0x53, 0x57, 0x58, 0x57, 0x54, 0x5a, 0x58, 0x5a, 0x57, 0x5a, - 0x54, 0x5b, 0x57, 0x58, 0x4f, 0x55, 0x56, 0x51, 0x5e, 0x53, 0x54, 0x58, - 0x5b, 0x63, 0x53, 0x5d, 0x5b, 0x58, 0x5c, 0x50, 0x58, 0x57, 0x64, 0x5a, - 0x5a, 0x59, 0x58, 0x59, 0x56, 0x59, 0x5b, 0x56, 0x59, 0x5d, 0x5c, 0x5d, - 0x6f, 0x60, 0x53, 0x57, 0x54, 0x57, 0x61, 0x58, 0x4f, 0x5b, 0x4b, 0x5c, - 0x54, 0x53, 0x58, 0x60, 0x52, 0x59, 0x5a, 0x60, 0x5b, 0x52, 0x55, 0x5d, - 0x57, 0x54, 0x5b, 0x56, 0x59, 0x50, 0x59, 0x5e, 0x57, 0x54, 0x5b, 0x5a, - 0x5a, 0x5a, 0x5c, 0x54, 0x59, 0x5a, 0x4f, 0x5d, 0x5c, 0x57, 0x5c, 0x56, - 0x5e, 0x5e, 0x61, 0x55, 0x5c, 0x5b, 0x5c, 0x58, 0x61, 0x5f, 0x5b, 0x5a, - 0x5a, 0x55, 0x5d, 0x69, 0x59, 0x55, 0x5e, 0x4a, 0x55, 0x50, 0x59, 0x61, - 0x5b, 0x52, 0x47, 0x55, 0x58, 0x59, 0x6b, 0x58, 0x62, 0x5a, 0x55, 0x5f, - 0x56, 0x5b, 0x55, 0x56, 0x4a, 0x5f, 0x5c, 0x5f, 0x5b, 0x5b, 0x5b, 0x58, - 0x5b, 0x5c, 0x59, 0x5b, 0x5a, 0x58, 0x58, 0x49, 0x58, 0x55, 0x5e, 0x50, - 0x5d, 0x57, 0x58, 0x56, 0x5b, 0x53, 0x5a, 0x57, 0x5a, 0x62, 0x55, 0x5d, - 0x66, 0x5f, 0x54, 0x4e, 0x54, 0x59, 0x5e, 0x62, 0x4e, 0x5d, 0x4d, 0x5b, - 0x55, 0x4a, 0x5e, 0x61, 0x53, 0x59, 0x5c, 0x57, 0x5b, 0x5a, 0x64, 0x54, - 0x59, 0x51, 0x55, 0x59, 0x59, 0x57, 0x59, 0x5f, 0x59, 0x59, 0x64, 0x58, - 0x57, 0x5a, 0x63, 0x5b, 0x58, 0x64, 0x55, 0x52, 0x5a, 0x5b, 0x6d, 0x5e, - 0x57, 0x56, 0x54, 0x5e, 0x5a, 0x57, 0x5b, 0x5e, 0x57, 0x5a, 0x5b, 0x58, - 0x5c, 0x5e, 0x64, 0x5d, 0x59, 0x5c, 0x51, 0x5d, 0x5b, 0x5c, 0x58, 0x50, - 0x58, 0x51, 0x5f, 0x5b, 0x59, 0x59, 0x5e, 0x57, 0x5c, 0x52, 0x4c, 0x58, - 0x60, 0x62, 0x54, 0x6c, 0x57, 0x4e, 0x56, 0x61, 0x50, 0x5d, 0x5b, 0x5a, - 0x58, 0x5e, 0x58, 0x5a, 0x5a, 0x4f, 0x58, 0x5e, 0x54, 0x4b, 0x5f, 0x54, - 0x5e, 0x5d, 0x5a, 0x58, 0x5a, 0x4c, 0x60, 0x5e, 0x5a, 0x58, 0x64, 0x5b, - 0x62, 0x56, 0x4e, 0x5a, 0x5c, 0x59, 0x5c, 0x5d, 0x59, 0x63, 0x4d, 0x5a, - 0x59, 0x53, 0x5a, 0x5f, 0x56, 0x62, 0x6a, 0x57, 0x5f, 0x54, 0x5b, 0x62, - 0x58, 0x68, 0x59, 0x53, 0x51, 0x66, 0x5c, 0x5e, 0x59, 0x5a, 0x6a, 0x58, - 0x57, 0x5d, 0x6a, 0x5c, 0x57, 0x5d, 0x55, 0x56, 0x61, 0x5e, 0x5a, 0x60, - 0x5d, 0x63, 0x56, 0x65, 0x57, 0x5a, 0x5e, 0x69, 0x57, 0x66, 0x59, 0x61, - 0x59, 0x51, 0x5b, 0x4f, 0x5a, 0x4a, 0x53, 0x5a, 0x59, 0x56, 0x59, 0x55, - 0x5a, 0x45, 0x4f, 0x5b, 0x58, 0x54, 0x5a, 0x53, 0x5e, 0x5c, 0x49, 0x51, - 0x56, 0x5e, 0x54, 0x5f, 0x5e, 0x59, 0x56, 0x59, 0x55, 0x61, 0x5a, 0x4d, - 0x5d, 0x59, 0x5e, 0x5a, 0x5a, 0x53, 0x67, 0x5e, 0x52, 0x61, 0x5e, 0x57, - 0x5e, 0x60, 0x57, 0x62, 0x5a, 0x59, 0x62, 0x58, 0x58, 0x57, 0x66, 0x5a, - 0x5c, 0x5d, 0x53, 0x56, 0x5a, 0x5f, 0x5c, 0x4e, 0x58, 0x5c, 0x57, 0x5e, - 0x59, 0x5f, 0x5c, 0x58, 0x5b, 0x66, 0x5b, 0x5a, 0x5a, 0x59, 0x57, 0x58, - 0x58, 0x5d, 0x55, 0x52, 0x55, 0x5c, 0x59, 0x5f, 0x57, 0x58, 0x60, 0x5b, - 0x59, 0x57, 0x61, 0x56, 0x58, 0x60, 0x53, 0x60, 0x59, 0x5a, 0x5b, 0x5c, - 0x56, 0x5c, 0x58, 0x5e, 0x5a, 0x5b, 0x59, 0x58, 0x5c, 0x59, 0x5a, 0x60, - 0x5c, 0x5a, 0x54, 0x5f, 0x59, 0x5d, 0x56, 0x53, 0x57, 0x57, 0x57, 0x55, - 0x59, 0x55, 0x5a, 0x59, 0x5a, 0x53, 0x59, 0x54, 0x5e, 0x5a, 0x5c, 0x59, - 0x59, 0x58, 0x4b, 0x62, 0x54, 0x5d, 0x66, 0x59, 0x54, 0x5a, 0x5d, 0x5f, - 0x57, 0x61, 0x59, 0x5c, 0x56, 0x41, 0x62, 0x3b, 0x57, 0x55, 0x67, 0x58, - 0x4a, 0x4c, 0x59, 0x65, 0x59, 0x4b, 0x37, 0x59, 0x5a, 0x61, 0x49, 0x5d, - 0x58, 0x5a, 0x61, 0x57, 0x4b, 0x65, 0x56, 0x5f, 0x5a, 0x43, 0x5a, 0x4c, - 0x58, 0x5c, 0x58, 0x4b, 0x55, 0x51, 0x61, 0x63, 0x5c, 0x55, 0x57, 0x58, - 0x58, 0x51, 0x5d, 0x58, 0x54, 0x5e, 0x58, 0x59, 0x56, 0x57, 0x5e, 0x58, - 0x58, 0x5e, 0x5e, 0x56, 0x5e, 0x59, 0x57, 0x58, 0x57, 0x5b, 0x57, 0x62, - 0x5f, 0x5a, 0x58, 0x5c, 0x58, 0x56, 0x5c, 0x5c, 0x57, 0x59, 0x59, 0x63, - 0x5c, 0x4c, 0x59, 0x63, 0x52, 0x73, 0x5b, 0x5c, 0x5c, 0x51, 0x59, 0x5c, - 0x59, 0x49, 0x52, 0x56, 0x5a, 0x5b, 0x64, 0x60, 0x6b, 0x5e, 0x4d, 0x58, - 0x58, 0x55, 0x60, 0x55, 0x4b, 0x5b, 0x5b, 0x51, 0x5b, 0x53, 0x5a, 0x61, - 0x5a, 0x6f, 0x5a, 0x60, 0x5a, 0x60, 0x5c, 0x55, 0x58, 0x51, 0x66, 0x59, - 0x5b, 0x53, 0x58, 0x5c, 0x5a, 0x5e, 0x58, 0x5f, 0x58, 0x5b, 0x5d, 0x58, - 0x5a, 0x57, 0x5f, 0x48, 0x5d, 0x5b, 0x5c, 0x57, 0x54, 0x59, 0x69, 0x57, - 0x58, 0x58, 0x5b, 0x5a, 0x63, 0x54, 0x5a, 0x5e, 0x5a, 0x5b, 0x60, 0x63, - 0x56, 0x51, 0x5b, 0x59, 0x5b, 0x58, 0x59, 0x5e, 0x57, 0x58, 0x61, 0x5f, - 0x5b, 0x53, 0x63, 0x5e, 0x5d, 0x5c, 0x58, 0x5b, 0x55, 0x5b, 0x63, 0x52, - 0x57, 0x59, 0x59, 0x5a, 0x5b, 0x52, 0x59, 0x5b, 0x58, 0x51, 0x59, 0x5f, - 0x57, 0x52, 0x58, 0x5c, 0x58, 0x60, 0x5b, 0x59, 0x56, 0x5d, 0x59, 0x5f, - 0x58, 0x57, 0x62, 0x63, 0x59, 0x59, 0x62, 0x5a, 0x5c, 0x57, 0x48, 0x67, - 0x5f, 0x53, 0x49, 0x5d, 0x5c, 0x56, 0x5a, 0x5c, 0x5b, 0x63, 0x5b, 0x59, - 0x5a, 0x5a, 0x57, 0x62, 0x56, 0x56, 0x5b, 0x56, 0x57, 0x5a, 0x60, 0x5e, - 0x63, 0x58, 0x58, 0x5b, 0x59, 0x55, 0x5b, 0x56, 0x5a, 0x5f, 0x60, 0x58, - 0x55, 0x5d, 0x58, 0x52, 0x56, 0x60, 0x64, 0x55, 0x5d, 0x5e, 0x5f, 0x5b, - 0x57, 0x56, 0x5d, 0x5d, 0x55, 0x5c, 0x58, 0x56, 0x5c, 0x51, 0x59, 0x5c, - 0x52, 0x4e, 0x56, 0x62, 0x5b, 0x5c, 0x58, 0x58, 0x5a, 0x50, 0x5e, 0x58, - 0x59, 0x64, 0x5f, 0x55, 0x61, 0x56, 0x53, 0x57, 0x5e, 0x5a, 0x56, 0x59, - 0x54, 0x64, 0x5e, 0x5b, 0x55, 0x53, 0x5d, 0x62, 0x55, 0x5a, 0x62, 0x5a, - 0x5a, 0x63, 0x50, 0x62, 0x56, 0x5f, 0x61, 0x5c, 0x58, 0x5c, 0x59, 0x5b, - 0x51, 0x4d, 0x61, 0x5a, 0x59, 0x61, 0x56, 0x54, 0x59, 0x58, 0x52, 0x63, - 0x61, 0x5f, 0x4c, 0x5c, 0x53, 0x53, 0x49, 0x51, 0x62, 0x51, 0x5a, 0x57, - 0x54, 0x51, 0x66, 0x60, 0x59, 0x55, 0x55, 0x5b, 0x52, 0x58, 0x63, 0x4e, - 0x53, 0x57, 0x58, 0x5c, 0x5c, 0x56, 0x49, 0x5a, 0x58, 0x5b, 0x51, 0x57, - 0x6d, 0x5b, 0x55, 0x5b, 0x51, 0x5b, 0x52, 0x55, 0x55, 0x61, 0x5c, 0x55, - 0x5d, 0x59, 0x5a, 0x56, 0x60, 0x5a, 0x5c, 0x56, 0x5e, 0x51, 0x52, 0x65, - 0x59, 0x5a, 0x50, 0x67, 0x53, 0x62, 0x59, 0x5b, 0x56, 0x59, 0x5e, 0x5c, - 0x59, 0x59, 0x59, 0x5d, 0x51, 0x5e, 0x50, 0x5c, 0x65, 0x56, 0x4d, 0x5c, - 0x5f, 0x5a, 0x44, 0x56, 0x57, 0x58, 0x5a, 0x5d, 0x50, 0x58, 0x69, 0x5e, - 0x51, 0x56, 0x56, 0x56, 0x5a, 0x5c, 0x5d, 0x5c, 0x56, 0x59, 0x59, 0x59, - 0x5c, 0x57, 0x5c, 0x5a, 0x59, 0x5c, 0x5f, 0x56, 0x52, 0x58, 0x59, 0x58, - 0x5d, 0x5c, 0x52, 0x5b, 0x5c, 0x5a, 0x62, 0x58, 0x5d, 0x5e, 0x56, 0x5e, - 0x58, 0x53, 0x5b, 0x5f, 0x5a, 0x57, 0x5c, 0x61, 0x5a, 0x53, 0x5a, 0x59, - 0x5c, 0x53, 0x59, 0x5f, 0x59, 0x58, 0x5e, 0x5d, 0x58, 0x5c, 0x5e, 0x5b, - 0x65, 0x61, 0x53, 0x60, 0x56, 0x57, 0x64, 0x57, 0x52, 0x5c, 0x56, 0x59, - 0x5d, 0x59, 0x5b, 0x56, 0x56, 0x6a, 0x5c, 0x60, 0x5a, 0x54, 0x57, 0x5a, - 0x56, 0x67, 0x53, 0x61, 0x5b, 0x56, 0x59, 0x60, 0x58, 0x51, 0x5e, 0x5b, - 0x58, 0x59, 0x5f, 0x5b, 0x5d, 0x53, 0x58, 0x5f, 0x61, 0x58, 0x53, 0x5a, - 0x64, 0x56, 0x58, 0x5a, 0x5a, 0x5f, 0x5a, 0x55, 0x5f, 0x59, 0x5b, 0x62, - 0x57, 0x5b, 0x5d, 0x56, 0x57, 0x5d, 0x5d, 0x59, 0x5c, 0x5b, 0x59, 0x60, - 0x5b, 0x53, 0x5d, 0x57, 0x5a, 0x5b, 0x5d, 0x58, 0x5d, 0x5d, 0x54, 0x5f, - 0x5d, 0x5b, 0x55, 0x58, 0x5c, 0x5c, 0x64, 0x5a, 0x59, 0x59, 0x55, 0x5b, - 0x58, 0x55, 0x58, 0x5f, 0x5a, 0x4f, 0x4a, 0x49, 0x4e, 0x57, 0x57, 0x58, - 0x68, 0x53, 0x59, 0x61, 0x59, 0x49, 0x60, 0x5c, 0x59, 0x51, 0x40, 0x63, - 0x60, 0x4f, 0x45, 0x66, 0x4e, 0x66, 0x50, 0x60, 0x58, 0x46, 0x3d, 0x4e, - 0x5f, 0x57, 0x59, 0x55, 0x52, 0x4c, 0x57, 0x58, 0x59, 0x61, 0x50, 0x5d, - 0x66, 0x54, 0x5b, 0x53, 0x5c, 0x4e, 0x5a, 0x4d, 0x57, 0x50, 0x5d, 0x5e, - 0x5c, 0x5e, 0x4d, 0x5c, 0x60, 0x56, 0x55, 0x56, 0x51, 0x55, 0x5b, 0x5b, - 0x5c, 0x55, 0x58, 0x60, 0x51, 0x55, 0x58, 0x5f, 0x66, 0x4f, 0x5a, 0x5a, - 0x5a, 0x4f, 0x56, 0x56, 0x58, 0x57, 0x5c, 0x57, 0x5a, 0x57, 0x59, 0x5d, - 0x55, 0x55, 0x53, 0x59, 0x59, 0x5e, 0x50, 0x5a, 0x5f, 0x5c, 0x4b, 0x5f, - 0x5d, 0x58, 0x4f, 0x57, 0x5a, 0x5a, 0x58, 0x4b, 0x5e, 0x5a, 0x5a, 0x53, - 0x5a, 0x59, 0x57, 0x58, 0x5e, 0x4f, 0x54, 0x55, 0x4f, 0x5a, 0x63, 0x4a, - 0x50, 0x55, 0x59, 0x58, 0x56, 0x4d, 0x39, 0x59, 0x59, 0x5d, 0x59, 0x53, - 0x73, 0x5a, 0x4c, 0x57, 0x56, 0x5b, 0x54, 0x58, 0x52, 0x54, 0x5e, 0x53, - 0x54, 0x56, 0x5a, 0x50, 0x5d, 0x58, 0x69, 0x57, 0x58, 0x55, 0x58, 0x63, - 0x55, 0x51, 0x52, 0x57, 0x56, 0x5d, 0x59, 0x59, 0x58, 0x53, 0x5f, 0x56, - 0x58, 0x5a, 0x5b, 0x5f, 0x67, 0x5b, 0x56, 0x63, 0x5c, 0x59, 0x62, 0x5e, - 0x50, 0x64, 0x69, 0x5a, 0x5b, 0x54, 0x58, 0x67, 0x58, 0x69, 0x59, 0x60, - 0x60, 0x53, 0x5d, 0x58, 0x5b, 0x5a, 0x57, 0x66, 0x5a, 0x5b, 0x59, 0x5a, - 0x56, 0x53, 0x58, 0x59, 0x59, 0x5f, 0x58, 0x5d, 0x57, 0x5d, 0x54, 0x58, - 0x59, 0x57, 0x56, 0x5c, 0x5b, 0x57, 0x5d, 0x5d, 0x4c, 0x53, 0x59, 0x65, - 0x56, 0x57, 0x5b, 0x58, 0x5a, 0x52, 0x5e, 0x5f, 0x58, 0x59, 0x52, 0x56, - 0x5a, 0x57, 0x59, 0x5d, 0x57, 0x51, 0x5a, 0x56, 0x59, 0x59, 0x5f, 0x55, - 0x63, 0x5c, 0x53, 0x60, 0x5a, 0x5b, 0x5d, 0x56, 0x56, 0x5e, 0x5b, 0x5e, - 0x57, 0x5a, 0x5a, 0x55, 0x5c, 0x62, 0x5b, 0x5f, 0x57, 0x4b, 0x57, 0x52, - 0x58, 0x5d, 0x59, 0x56, 0x59, 0x4f, 0x58, 0x53, 0x51, 0x51, 0x50, 0x5a, - 0x57, 0x70, 0x3e, 0x5b, 0x50, 0x5c, 0x49, 0x41, 0x55, 0x50, 0x54, 0x52, - 0x54, 0x50, 0x4b, 0x48, 0x56, 0x47, 0x58, 0x4c, 0x49, 0x52, 0x58, 0x52, - 0x5c, 0x55, 0x5e, 0x4e, 0x5a, 0x53, 0x61, 0x62, 0x5c, 0x58, 0x5e, 0x5c, - 0x5b, 0x58, 0x5c, 0x52, 0x5b, 0x68, 0x5c, 0x54, 0x61, 0x63, 0x54, 0x55, - 0x56, 0x5b, 0x67, 0x5f, 0x5d, 0x5c, 0x58, 0x5d, 0x5a, 0x58, 0x5e, 0x62, - 0x59, 0x57, 0x5b, 0x50, 0x59, 0x57, 0x62, 0x58, 0x57, 0x5e, 0x5e, 0x58, - 0x56, 0x5a, 0x59, 0x5f, 0x57, 0x55, 0x63, 0x5b, 0x59, 0x4f, 0x66, 0x57, - 0x5f, 0x59, 0x4e, 0x59, 0x59, 0x60, 0x5e, 0x5d, 0x5e, 0x58, 0x59, 0x60, - 0x58, 0x61, 0x59, 0x5e, 0x4f, 0x5b, 0x58, 0x56, 0x5c, 0x58, 0x59, 0x58, - 0x55, 0x5a, 0x5b, 0x57, 0x5e, 0x56, 0x59, 0x58, 0x5a, 0x51, 0x59, 0x55, - 0x59, 0x5a, 0x5c, 0x5a, 0x63, 0x5c, 0x53, 0x56, 0x55, 0x54, 0x5a, 0x5a, - 0x4b, 0x5c, 0x56, 0x54, 0x5f, 0x53, 0x5d, 0x5f, 0x55, 0x5f, 0x5a, 0x61, - 0x5c, 0x61, 0x4b, 0x78, 0x59, 0x5a, 0x54, 0x48, 0x4e, 0x62, 0x59, 0x5c, - 0x52, 0x51, 0x71, 0x5e, 0x58, 0x58, 0x67, 0x55, 0x65, 0x5a, 0x40, 0x5d, - 0x51, 0x5c, 0x40, 0x63, 0x42, 0x59, 0x65, 0x56, 0x53, 0x56, 0x59, 0x5c, - 0x55, 0x61, 0x77, 0x5c, 0x5b, 0x58, 0x56, 0x5b, 0x59, 0x58, 0x5c, 0x53, - 0x57, 0x5c, 0x5a, 0x55, 0x5b, 0x52, 0x58, 0x59, 0x5c, 0x5a, 0x59, 0x5c, - 0x61, 0x5a, 0x54, 0x59, 0x57, 0x56, 0x5a, 0x56, 0x53, 0x65, 0x60, 0x55, - 0x5f, 0x56, 0x5c, 0x5f, 0x57, 0x5c, 0x5d, 0x58, 0x58, 0x4f, 0x52, 0x51, - 0x4f, 0x5e, 0x5f, 0x59, 0x59, 0x5a, 0x59, 0x5f, 0x56, 0x48, 0x57, 0x61, - 0x59, 0x5e, 0x53, 0x56, 0x57, 0x57, 0x61, 0x5f, 0x5c, 0x5d, 0x4d, 0x57, - 0x56, 0x55, 0x5f, 0x56, 0x59, 0x5c, 0x56, 0x55, 0x5d, 0x5b, 0x58, 0x53, - 0x5a, 0x59, 0x5d, 0x58, 0x5a, 0x58, 0x61, 0x56, 0x5d, 0x57, 0x59, 0x5e, - 0x5b, 0x58, 0x60, 0x59, 0x59, 0x5b, 0x63, 0x57, 0x5b, 0x5d, 0x59, 0x56, - 0x5a, 0x5c, 0x67, 0x5e, 0x5e, 0x5a, 0x62, 0x5d, 0x5a, 0x5a, 0x57, 0x5c, - 0x59, 0x55, 0x56, 0x55, 0x56, 0x51, 0x63, 0x7b, 0x48, 0x48, 0x44, 0x4e, - 0x58, 0x52, 0x59, 0x67, 0x5e, 0x3b, 0x4c, 0x5f, 0x5a, 0x6d, 0x69, 0x59, - 0x7b, 0x52, 0x6e, 0x5e, 0x6c, 0x5e, 0x65, 0x44, 0x60, 0x86, 0x5d, 0x66, - 0x62, 0x5b, 0x57, 0x53, 0x56, 0x4e, 0x7e, 0x52, 0x59, 0x55, 0x57, 0x5e, - 0x5a, 0x64, 0x5c, 0x5e, 0x50, 0x58, 0x59, 0x58, 0x57, 0x51, 0x47, 0x59, - 0x59, 0x60, 0x58, 0x5a, 0x61, 0x59, 0x52, 0x5c, 0x55, 0x5c, 0x4e, 0x5a, - 0x52, 0x57, 0x52, 0x59, 0x5a, 0x59, 0x55, 0x5b, 0x56, 0x61, 0x59, 0x5d, - 0x51, 0x57, 0x51, 0x5d, 0x57, 0x59, 0x54, 0x54, 0x5d, 0x55, 0x58, 0x59, - 0x54, 0x63, 0x53, 0x54, 0x58, 0x55, 0x51, 0x5e, 0x57, 0x58, 0x52, 0x5b, - 0x54, 0x59, 0x58, 0x51, 0x54, 0x51, 0x57, 0x5a, 0x5c, 0x57, 0x5a, 0x5a, - 0x5b, 0x56, 0x58, 0x59, 0x59, 0x5f, 0x55, 0x4c, 0x65, 0x57, 0x56, 0x51, - 0x5c, 0x5a, 0x58, 0x57, 0x56, 0x50, 0x5a, 0x59, 0x59, 0x5f, 0x4c, 0x5a, - 0x4c, 0x57, 0x5a, 0x60, 0x5b, 0x61, 0x4e, 0x55, 0x50, 0x4d, 0x5a, 0x5c, - 0x5a, 0x5c, 0x58, 0x57, 0x57, 0x51, 0x58, 0x62, 0x5d, 0x50, 0x5e, 0x57, - 0x55, 0x4a, 0x4e, 0x63, 0x59, 0x46, 0x59, 0x56, 0x55, 0x4f, 0x64, 0x54, - 0x59, 0x4d, 0x60, 0x54, 0x67, 0x60, 0x55, 0x55, 0x53, 0x59, 0x55, 0x56, - 0x4d, 0x5b, 0x44, 0x56, 0x55, 0x4c, 0x5f, 0x52, 0x4e, 0x5c, 0x62, 0x5a, - 0x59, 0x59, 0x58, 0x55, 0x58, 0x55, 0x4f, 0x62, 0x5a, 0x5a, 0x59, 0x65, - 0x59, 0x4d, 0x51, 0x56, 0x58, 0x68, 0x4e, 0x55, 0x62, 0x58, 0x44, 0x62, - 0x55, 0x5e, 0x5a, 0x61, 0x54, 0x6e, 0x40, 0x56, 0x55, 0x5d, 0x59, 0x5c, - 0x56, 0x4f, 0x58, 0x64, 0x57, 0x5a, 0x5f, 0x56, 0x5b, 0x52, 0x64, 0x57, - 0x55, 0x5e, 0x5a, 0x5b, 0x59, 0x5a, 0x62, 0x58, 0x5b, 0x59, 0x65, 0x5b, - 0x59, 0x5a, 0x58, 0x5d, 0x5c, 0x60, 0x6b, 0x5f, 0x60, 0x5e, 0x58, 0x5f, - 0x5a, 0x59, 0x59, 0x62, 0x5b, 0x58, 0x5e, 0x59, 0x56, 0x5a, 0x4f, 0x56, - 0x59, 0x53, 0x5b, 0x58, 0x66, 0x49, 0x58, 0x5b, 0x58, 0x51, 0x57, 0x59, - 0x58, 0x57, 0x56, 0x59, 0x59, 0x5c, 0x50, 0x5e, 0x53, 0x57, 0x67, 0x5e, - 0x58, 0x59, 0x63, 0x5b, 0x5b, 0x5c, 0x5b, 0x5c, 0x5d, 0x56, 0x59, 0x58, - 0x5c, 0x53, 0x56, 0x57, 0x58, 0x65, 0x5f, 0x64, 0x5d, 0x4c, 0x59, 0x53, - 0x53, 0x58, 0x44, 0x59, 0x59, 0x59, 0x56, 0x56, 0x55, 0x5e, 0x4b, 0x57, - 0x55, 0x5d, 0x52, 0x45, 0x53, 0x50, 0x54, 0x4d, 0x64, 0x55, 0x5c, 0x4c, - 0x56, 0x59, 0x57, 0x5e, 0x5b, 0x53, 0x5b, 0x55, 0x59, 0x57, 0x61, 0x56, - 0x5a, 0x59, 0x59, 0x5c, 0x58, 0x58, 0x5b, 0x59, 0x5a, 0x59, 0x5a, 0x52, - 0x5b, 0x62, 0x52, 0x4e, 0x61, 0x5a, 0x56, 0x59, 0x57, 0x59, 0x5d, 0x58, - 0x5b, 0x5f, 0x5b, 0x56, 0x5b, 0x5d, 0x5a, 0x5a, 0x5a, 0x56, 0x59, 0x5e, - 0x53, 0x62, 0x54, 0x57, 0x53, 0x5c, 0x59, 0x55, 0x5a, 0x4f, 0x58, 0x56, - 0x5a, 0x5a, 0x5a, 0x57, 0x5f, 0x56, 0x58, 0x58, 0x56, 0x56, 0x5a, 0x61, - 0x52, 0x60, 0x5d, 0x59, 0x55, 0x52, 0x5a, 0x61, 0x55, 0x5a, 0x63, 0x5e, - 0x5a, 0x5a, 0x55, 0x57, 0x55, 0x50, 0x55, 0x5a, 0x59, 0x4e, 0x59, 0x55, - 0x5b, 0x4d, 0x5a, 0x56, 0x59, 0x57, 0x4f, 0x59, 0x54, 0x53, 0x41, 0x61, - 0x54, 0x4f, 0x58, 0x5b, 0x5e, 0x56, 0x61, 0x58, 0x5c, 0x5d, 0x58, 0x56, - 0x61, 0x56, 0x58, 0x59, 0x5a, 0x53, 0x51, 0x56, 0x54, 0x5d, 0x69, 0x59, - 0x56, 0x53, 0x57, 0x5a, 0x5a, 0x54, 0x53, 0x55, 0x59, 0x5e, 0x58, 0x5b, - 0x6b, 0x5b, 0x54, 0x5a, 0x57, 0x57, 0x63, 0x59, 0x51, 0x62, 0x55, 0x53, - 0x60, 0x52, 0x59, 0x5f, 0x56, 0x59, 0x61, 0x61, 0x5b, 0x56, 0x5c, 0x5c, - 0x5b, 0x5a, 0x5d, 0x54, 0x59, 0x59, 0x5a, 0x5b, 0x59, 0x56, 0x5f, 0x57, - 0x5a, 0x5a, 0x5b, 0x56, 0x5d, 0x5c, 0x56, 0x5b, 0x58, 0x5d, 0x50, 0x5b, - 0x5c, 0x5b, 0x60, 0x5c, 0x57, 0x5b, 0x5b, 0x5d, 0x5a, 0x5e, 0x5b, 0x60, - 0x5d, 0x56, 0x57, 0x59, 0x55, 0x68, 0x62, 0x58, 0x59, 0x56, 0x59, 0x5d, - 0x5a, 0x54, 0x58, 0x5a, 0x59, 0x60, 0x5c, 0x5b, 0x5f, 0x5c, 0x56, 0x5b, - 0x57, 0x56, 0x5d, 0x5e, 0x4e, 0x62, 0x58, 0x55, 0x5e, 0x52, 0x5b, 0x5d, - 0x58, 0x5e, 0x57, 0x5c, 0x61, 0x56, 0x55, 0x56, 0x57, 0x49, 0x5a, 0x65, - 0x60, 0x51, 0x5b, 0x58, 0x5b, 0x4d, 0x5b, 0x5b, 0x5a, 0x5f, 0x3a, 0x59, - 0x76, 0x60, 0x49, 0x62, 0x56, 0x56, 0x61, 0x4c, 0x6f, 0x5d, 0x4b, 0x51, - 0x53, 0x4b, 0x5a, 0x56, 0x58, 0x58, 0x61, 0x5e, 0x5b, 0x58, 0x5b, 0x53, - 0x5a, 0x5f, 0x61, 0x56, 0x53, 0x59, 0x5a, 0x5c, 0x58, 0x59, 0x61, 0x59, - 0x59, 0x5c, 0x60, 0x59, 0x55, 0x5d, 0x59, 0x5a, 0x59, 0x5d, 0x6a, 0x5f, - 0x60, 0x57, 0x58, 0x5d, 0x57, 0x58, 0x5c, 0x61, 0x59, 0x55, 0x5b, 0x53, - 0x59, 0x51, 0x56, 0x5a, 0x61, 0x5c, 0x56, 0x64, 0x5b, 0x5d, 0x59, 0x58, - 0x58, 0x51, 0x5b, 0x5d, 0x59, 0x4b, 0x61, 0x54, 0x63, 0x54, 0x54, 0x5e, - 0x5b, 0x5e, 0x4b, 0x62, 0x5f, 0x5a, 0x51, 0x59, 0x56, 0x55, 0x59, 0x58, - 0x5a, 0x5e, 0x57, 0x57, 0x5b, 0x54, 0x56, 0x59, 0x59, 0x58, 0x5f, 0x57, - 0x58, 0x55, 0x59, 0x5c, 0x59, 0x56, 0x58, 0x55, 0x5a, 0x5c, 0x56, 0x58, - 0x61, 0x5a, 0x53, 0x5f, 0x58, 0x58, 0x5a, 0x56, 0x54, 0x5c, 0x5e, 0x56, - 0x5d, 0x58, 0x5b, 0x55, 0x5c, 0x5b, 0x57, 0x5b, 0x5b, 0x56, 0x64, 0x53, - 0x60, 0x52, 0x57, 0x59, 0x57, 0x60, 0x59, 0x65, 0x58, 0x58, 0x67, 0x57, - 0x58, 0x54, 0x6a, 0x51, 0x5d, 0x60, 0x57, 0x52, 0x60, 0x60, 0x64, 0x5d, - 0x60, 0x5a, 0x53, 0x61, 0x54, 0x5c, 0x5c, 0x61, 0x58, 0x5d, 0x5f, 0x54, - 0x59, 0x60, 0x66, 0x56, 0x59, 0x5a, 0x60, 0x55, 0x5b, 0x5d, 0x58, 0x5f, - 0x5b, 0x5a, 0x61, 0x57, 0x59, 0x5b, 0x60, 0x59, 0x51, 0x59, 0x53, 0x54, - 0x5a, 0x5e, 0x66, 0x59, 0x5e, 0x54, 0x53, 0x5e, 0x58, 0x59, 0x62, 0x5d, - 0x56, 0x56, 0x58, 0x58, 0x5a, 0x55, 0x5d, 0x53, 0x56, 0x60, 0x5e, 0x59, - 0x5b, 0x5c, 0x59, 0x5b, 0x59, 0x56, 0x5a, 0x57, 0x5a, 0x57, 0x5b, 0x5b, - 0x56, 0x5a, 0x55, 0x5b, 0x59, 0x57, 0x57, 0x5b, 0x5e, 0x58, 0x5f, 0x5e, - 0x5c, 0x54, 0x5a, 0x5e, 0x54, 0x59, 0x59, 0x62, 0x5b, 0x58, 0x5c, 0x56, - 0x5b, 0x5e, 0x57, 0x56, 0x5d, 0x55, 0x57, 0x5b, 0x57, 0x5a, 0x55, 0x57, - 0x59, 0x56, 0x53, 0x5c, 0x5c, 0x5a, 0x58, 0x55, 0x57, 0x60, 0x50, 0x53, - 0x59, 0x51, 0x52, 0x53, 0x60, 0x58, 0x5d, 0x5a, 0x51, 0x4e, 0x58, 0x5b, - 0x5b, 0x52, 0x57, 0x5a, 0x57, 0x56, 0x56, 0x55, 0x55, 0x57, 0x59, 0x5a, - 0x54, 0x55, 0x5a, 0x52, 0x59, 0x5a, 0x58, 0x5b, 0x58, 0x5a, 0x54, 0x5b, - 0x59, 0x5a, 0x55, 0x5c, 0x57, 0x5c, 0x61, 0x5a, 0x5b, 0x5a, 0x5a, 0x57, - 0x5d, 0x5f, 0x5b, 0x5b, 0x5a, 0x57, 0x59, 0x5c, 0x59, 0x5a, 0x5b, 0x5a, - 0x59, 0x5c, 0x58, 0x58, 0x59, 0x56, 0x5a, 0x5b, 0x59, 0x5d, 0x59, 0x5c, - 0x5b, 0x55, 0x57, 0x52, 0x5c, 0x57, 0x57, 0x60, 0x5a, 0x56, 0x5b, 0x5e, - 0x54, 0x55, 0x5c, 0x5f, 0x58, 0x58, 0x5a, 0x5b, 0x57, 0x5a, 0x55, 0x5a, - 0x58, 0x5b, 0x61, 0x57, 0x55, 0x5a, 0x59, 0x56, 0x59, 0x54, 0x5a, 0x57, - 0x5a, 0x60, 0x59, 0x5b, 0x54, 0x58, 0x59, 0x5a, 0x56, 0x59, 0x55, 0x5f, - 0x54, 0x57, 0x58, 0x59, 0x5a, 0x53, 0x57, 0x5f, 0x53, 0x59, 0x5a, 0x63, - 0x58, 0x55, 0x5e, 0x53, 0x57, 0x50, 0x65, 0x56, 0x51, 0x55, 0x58, 0x60, - 0x59, 0x54, 0x62, 0x5b, 0x5a, 0x57, 0x61, 0x59, 0x69, 0x5d, 0x52, 0x4e, - 0x5a, 0x61, 0x65, 0x51, 0x5a, 0x60, 0x4f, 0x58, 0x55, 0x53, 0x5c, 0x5b, - 0x59, 0x57, 0x78, 0x61, 0x60, 0x4e, 0x58, 0x53, 0x4e, 0x59, 0x60, 0x4b, - 0x4f, 0x53, 0x59, 0x58, 0x58, 0x4c, 0x30, 0x59, 0x5b, 0x5e, 0x55, 0x57, - 0x76, 0x59, 0x49, 0x56, 0x53, 0x59, 0x56, 0x59, 0x4f, 0x54, 0x60, 0x4e, - 0x54, 0x4f, 0x5b, 0x50, 0x58, 0x56, 0x6c, 0x56, 0x5d, 0x4d, 0x5d, 0x5d, - 0x53, 0x67, 0x5c, 0x59, 0x58, 0x57, 0x59, 0x5c, 0x56, 0x48, 0x58, 0x57, - 0x59, 0x62, 0x5a, 0x56, 0x5d, 0x59, 0x4d, 0x62, 0x5a, 0x55, 0x57, 0x5b, - 0x62, 0x60, 0x54, 0x54, 0x5c, 0x5b, 0x5c, 0x61, 0x54, 0x64, 0x57, 0x61, - 0x5b, 0x57, 0x5d, 0x60, 0x57, 0x56, 0x53, 0x58, 0x59, 0x58, 0x58, 0x5b, - 0x5a, 0x57, 0x63, 0x5a, 0x5b, 0x5e, 0x5c, 0x5b, 0x56, 0x5c, 0x4e, 0x45, - 0x5e, 0x5a, 0x54, 0x59, 0x58, 0x59, 0x61, 0x5d, 0x5a, 0x5b, 0x5d, 0x58, - 0x58, 0x58, 0x58, 0x58, 0x59, 0x5b, 0x59, 0x5a, 0x57, 0x5e, 0x5a, 0x57, - 0x5c, 0x58, 0x58, 0x53, 0x58, 0x55, 0x59, 0x5e, 0x59, 0x60, 0x55, 0x59, - 0x56, 0x5e, 0x54, 0x5e, 0x54, 0x58, 0x5a, 0x5f, 0x49, 0x5a, 0x57, 0x57, - 0x5c, 0x50, 0x5a, 0x5f, 0x51, 0x5e, 0x5b, 0x63, 0x5c, 0x51, 0x59, 0x61, - 0x55, 0x54, 0x57, 0x5b, 0x58, 0x55, 0x59, 0x5d, 0x52, 0x51, 0x5d, 0x5a, - 0x59, 0x5e, 0x5c, 0x5a, 0x61, 0x5b, 0x4c, 0x61, 0x5a, 0x57, 0x5d, 0x59, - 0x56, 0x62, 0x56, 0x58, 0x5a, 0x5b, 0x5a, 0x54, 0x5f, 0x5d, 0x5c, 0x59, - 0x58, 0x57, 0x5b, 0x57, 0x59, 0x55, 0x63, 0x55, 0x59, 0x59, 0x58, 0x57, - 0x5b, 0x55, 0x59, 0x59, 0x5b, 0x5a, 0x5b, 0x59, 0x62, 0x5d, 0x55, 0x58, - 0x56, 0x5a, 0x64, 0x5c, 0x58, 0x5b, 0x56, 0x5a, 0x59, 0x54, 0x59, 0x5e, - 0x5a, 0x59, 0x59, 0x5f, 0x59, 0x56, 0x54, 0x62, 0x57, 0x4f, 0x64, 0x5d, - 0x59, 0x5c, 0x58, 0x58, 0x58, 0x56, 0x5a, 0x58, 0x58, 0x5f, 0x5c, 0x5f, - 0x65, 0x5b, 0x4d, 0x52, 0x59, 0x5a, 0x5b, 0x60, 0x52, 0x65, 0x72, 0x5b, - 0x5d, 0x52, 0x5b, 0x66, 0x57, 0x5e, 0x5f, 0x62, 0x5c, 0x53, 0x4d, 0x52, - 0x5d, 0x4b, 0x60, 0x51, 0x4d, 0x59, 0x5a, 0x5a, 0x5a, 0x59, 0x5e, 0x55, - 0x59, 0x5c, 0x5f, 0x58, 0x5e, 0x5a, 0x50, 0x53, 0x55, 0x5a, 0x51, 0x64, - 0x5e, 0x5b, 0x62, 0x57, 0x58, 0x57, 0x5a, 0x60, 0x52, 0x57, 0x73, 0x66, - 0x5a, 0x56, 0x59, 0x55, 0x5a, 0x55, 0x54, 0x5c, 0x58, 0x5f, 0x58, 0x5d, - 0x58, 0x54, 0x62, 0x5a, 0x60, 0x5b, 0x64, 0x5c, 0x59, 0x5a, 0x61, 0x68, - 0x5f, 0x5e, 0x59, 0x64, 0x56, 0x5a, 0x69, 0x60, 0x64, 0x59, 0x59, 0x64, - 0x55, 0x62, 0x62, 0x55, 0x5d, 0x52, 0x62, 0x5d, 0x52, 0x57, 0x52, 0x61, - 0x59, 0x5a, 0x58, 0x5d, 0x5a, 0x4f, 0x59, 0x5c, 0x58, 0x56, 0x62, 0x55, - 0x5c, 0x5e, 0x56, 0x57, 0x59, 0x5d, 0x5b, 0x52, 0x57, 0x62, 0x62, 0x57, - 0x5a, 0x53, 0x5e, 0x5a, 0x51, 0x62, 0x5a, 0x59, 0x5b, 0x57, 0x55, 0x55, - 0x58, 0x54, 0x55, 0x58, 0x5b, 0x52, 0x59, 0x5c, 0x5b, 0x55, 0x58, 0x57, - 0x59, 0x5e, 0x5a, 0x59, 0x69, 0x5e, 0x54, 0x5c, 0x58, 0x55, 0x5f, 0x53, - 0x51, 0x5d, 0x5a, 0x51, 0x59, 0x5a, 0x5b, 0x55, 0x5c, 0x63, 0x5b, 0x60, - 0x56, 0x50, 0x54, 0x54, 0x59, 0x58, 0x61, 0x52, 0x58, 0x56, 0x58, 0x58, - 0x56, 0x55, 0x53, 0x57, 0x58, 0x60, 0x52, 0x59, 0x58, 0x59, 0x51, 0x62, - 0x56, 0x54, 0x53, 0x54, 0x59, 0x51, 0x57, 0x58, 0x5b, 0x59, 0x58, 0x56, - 0x5b, 0x54, 0x59, 0x5c, 0x59, 0x57, 0x57, 0x5c, 0x57, 0x59, 0x55, 0x58, - 0x55, 0x5b, 0x5a, 0x57, 0x58, 0x56, 0x5f, 0x5b, 0x59, 0x62, 0x5d, 0x5e, - 0x5c, 0x56, 0x54, 0x57, 0x5b, 0x5a, 0x58, 0x5a, 0x5b, 0x58, 0x62, 0x60, - 0x5e, 0x5c, 0x58, 0x60, 0x5a, 0x57, 0x5b, 0x5c, 0x5f, 0x54, 0x6d, 0x48, - 0x59, 0x6b, 0x59, 0x53, 0x56, 0x5c, 0x5b, 0x67, 0x58, 0x56, 0x63, 0x5d, - 0x58, 0x59, 0x63, 0x4c, 0x6c, 0x59, 0x53, 0x5a, 0x61, 0x62, 0x5d, 0x6b, - 0x57, 0x53, 0x45, 0x5c, 0x4f, 0x67, 0x5f, 0x5e, 0x59, 0x60, 0x5a, 0x56, - 0x60, 0x55, 0x55, 0x51, 0x5a, 0x4f, 0x60, 0x5b, 0x5d, 0x5b, 0x59, 0x5a, - 0x63, 0x56, 0x5c, 0x5b, 0x58, 0x66, 0x5b, 0x5d, 0x70, 0x5d, 0x53, 0x55, - 0x59, 0x57, 0x61, 0x5f, 0x42, 0x59, 0x5f, 0x58, 0x54, 0x53, 0x5e, 0x62, - 0x52, 0x5b, 0x65, 0x58, 0x5c, 0x58, 0x53, 0x62, 0x54, 0x55, 0x61, 0x4f, - 0x56, 0x57, 0x59, 0x56, 0x52, 0x49, 0x4a, 0x5c, 0x5a, 0x56, 0x57, 0x56, - 0x71, 0x5a, 0x4e, 0x5a, 0x54, 0x58, 0x4f, 0x57, 0x55, 0x57, 0x5a, 0x56, - 0x58, 0x55, 0x5c, 0x57, 0x63, 0x59, 0x62, 0x54, 0x5e, 0x56, 0x5c, 0x5b, - 0x59, 0x66, 0x5a, 0x4d, 0x5b, 0x54, 0x59, 0x5c, 0x56, 0x55, 0x5a, 0x57, - 0x59, 0x4d, 0x55, 0x59, 0x5a, 0x5b, 0x50, 0x5d, 0x54, 0x59, 0x55, 0x5c, - 0x54, 0x59, 0x57, 0x58, 0x5b, 0x58, 0x5a, 0x5a, 0x58, 0x5c, 0x59, 0x60, - 0x5d, 0x54, 0x53, 0x54, 0x57, 0x59, 0x65, 0x55, 0x59, 0x58, 0x58, 0x58, - 0x5e, 0x51, 0x5e, 0x56, 0x58, 0x5c, 0x57, 0x5e, 0x6b, 0x5d, 0x53, 0x4d, - 0x58, 0x52, 0x5b, 0x58, 0x4a, 0x5f, 0x5d, 0x58, 0x59, 0x4f, 0x59, 0x60, - 0x58, 0x60, 0x57, 0x60, 0x5a, 0x55, 0x5b, 0x52, 0x58, 0x51, 0x54, 0x5f, - 0x59, 0x5d, 0x59, 0x5a, 0x59, 0x57, 0x5a, 0x55, 0x58, 0x5c, 0x5c, 0x59, - 0x5b, 0x59, 0x59, 0x57, 0x5a, 0x5b, 0x65, 0x5c, 0x5e, 0x5c, 0x61, 0x5b, - 0x5c, 0x58, 0x5a, 0x5d, 0x5a, 0x64, 0x57, 0x59, 0x59, 0x58, 0x5b, 0x58, - 0x59, 0x59, 0x61, 0x59, 0x57, 0x5c, 0x59, 0x5b, 0x5b, 0x57, 0x5f, 0x59, - 0x59, 0x5d, 0x63, 0x5b, 0x5c, 0x59, 0x59, 0x5a, 0x59, 0x5a, 0x67, 0x63, - 0x61, 0x5a, 0x62, 0x61, 0x57, 0x5a, 0x56, 0x64, 0x59, 0x52, 0x57, 0x56, - 0x5d, 0x52, 0x5a, 0x61, 0x57, 0x5b, 0x52, 0x5b, 0x5b, 0x59, 0x5a, 0x5c, - 0x58, 0x54, 0x5f, 0x56, 0x59, 0x5c, 0x62, 0x59, 0x62, 0x5a, 0x51, 0x5c, - 0x5b, 0x58, 0x5a, 0x5b, 0x55, 0x5e, 0x59, 0x5e, 0x59, 0x5c, 0x57, 0x5a, - 0x59, 0x5e, 0x58, 0x5f, 0x56, 0x57, 0x58, 0x58, 0x58, 0x62, 0x55, 0x58, - 0x55, 0x5d, 0x59, 0x5c, 0x57, 0x55, 0x60, 0x60, 0x58, 0x54, 0x5e, 0x54, - 0x56, 0x53, 0x58, 0x5b, 0x5b, 0x5d, 0x50, 0x61, 0x5f, 0x5c, 0x5c, 0x5c, - 0x54, 0x57, 0x55, 0x5e, 0x55, 0x54, 0x5c, 0x58, 0x5a, 0x58, 0x55, 0x63, - 0x59, 0x4b, 0x55, 0x53, 0x4c, 0x5d, 0x5b, 0x61, 0x5c, 0x5c, 0x68, 0x56, - 0x5a, 0x5b, 0x68, 0x60, 0x60, 0x59, 0x50, 0x4e, 0x58, 0x5e, 0x58, 0x63, - 0x62, 0x67, 0x64, 0x62, 0x57, 0x5b, 0x5a, 0x68, 0x58, 0x5a, 0x71, 0x68, - 0x59, 0x55, 0x59, 0x57, 0x59, 0x60, 0x5f, 0x57, 0x58, 0x60, 0x59, 0x5b, - 0x59, 0x55, 0x5e, 0x55, 0x58, 0x5d, 0x60, 0x56, 0x51, 0x58, 0x55, 0x5b, - 0x5d, 0x5d, 0x52, 0x5e, 0x5f, 0x58, 0x54, 0x5d, 0x5c, 0x55, 0x57, 0x5e, - 0x59, 0x5a, 0x58, 0x5b, 0x5b, 0x56, 0x53, 0x5d, 0x59, 0x5c, 0x59, 0x56, - 0x56, 0x55, 0x59, 0x59, 0x58, 0x4e, 0x5b, 0x59, 0x59, 0x5b, 0x5a, 0x58, - 0x5c, 0x5d, 0x55, 0x62, 0x58, 0x58, 0x54, 0x60, 0x54, 0x59, 0x5b, 0x57, - 0x58, 0x59, 0x5a, 0x5a, 0x59, 0x5d, 0x59, 0x62, 0x5b, 0x57, 0x55, 0x52, - 0x59, 0x5d, 0x64, 0x5a, 0x63, 0x55, 0x58, 0x57, 0x5c, 0x54, 0x58, 0x55, - 0x59, 0x5f, 0x59, 0x5b, 0x59, 0x5e, 0x53, 0x66, 0x5a, 0x58, 0x5b, 0x57, - 0x60, 0x5a, 0x54, 0x5a, 0x5b, 0x59, 0x59, 0x5b, 0x5b, 0x5b, 0x5c, 0x5f, - 0x57, 0x52, 0x54, 0x56, 0x5a, 0x59, 0x61, 0x56, 0x59, 0x5b, 0x59, 0x5b, - 0x57, 0x57, 0x56, 0x55, 0x59, 0x5e, 0x52, 0x5c, 0x5a, 0x59, 0x5b, 0x63, - 0x5f, 0x58, 0x50, 0x57, 0x59, 0x58, 0x5c, 0x50, 0x60, 0x58, 0x5a, 0x55, - 0x5c, 0x58, 0x58, 0x63, 0x57, 0x5a, 0x4f, 0x57, 0x59, 0x5d, 0x5d, 0x55, - 0x58, 0x59, 0x59, 0x55, 0x5c, 0x54, 0x5d, 0x5a, 0x5a, 0x5d, 0x55, 0x5b, - 0x57, 0x5c, 0x57, 0x5f, 0x56, 0x56, 0x50, 0x5a, 0x4f, 0x53, 0x5f, 0x57, - 0x5c, 0x5f, 0x59, 0x57, 0x5e, 0x5e, 0x5a, 0x5a, 0x53, 0x4f, 0x4e, 0x55, - 0x5a, 0x57, 0x5e, 0x5d, 0x59, 0x5a, 0x58, 0x5b, 0x55, 0x4f, 0x5e, 0x5b, - 0x59, 0x64, 0x60, 0x57, 0x5c, 0x59, 0x52, 0x64, 0x58, 0x57, 0x44, 0x5d, - 0x50, 0x5c, 0x5e, 0x51, 0x5f, 0x55, 0x55, 0x5f, 0x59, 0x5c, 0x5a, 0x65, - 0x5c, 0x53, 0x5c, 0x59, 0x55, 0x54, 0x5f, 0x54, 0x5a, 0x54, 0x59, 0x59, - 0x58, 0x51, 0x5b, 0x52, 0x59, 0x55, 0x5d, 0x50, 0x60, 0x59, 0x53, 0x5a, - 0x59, 0x59, 0x5b, 0x59, 0x58, 0x5e, 0x5e, 0x58, 0x58, 0x58, 0x5b, 0x58, - 0x61, 0x63, 0x59, 0x5a, 0x55, 0x4d, 0x66, 0x55, 0x5b, 0x4e, 0x55, 0x58, - 0x58, 0x42, 0x58, 0x66, 0x5f, 0x70, 0x5b, 0x57, 0x58, 0x53, 0x5e, 0x62, - 0x66, 0x5f, 0x56, 0x58, 0x61, 0x60, 0x63, 0x4a, 0x58, 0x5b, 0x57, 0x51, - 0x69, 0x5e, 0x67, 0x3f, 0x58, 0x4d, 0x58, 0x43, 0x5a, 0x5e, 0x53, 0x68, - 0x56, 0x5c, 0x57, 0x53, 0x5e, 0x4f, 0x59, 0x57, 0x55, 0x53, 0x52, 0x57, - 0x58, 0x53, 0x5a, 0x5d, 0x65, 0x5f, 0x4e, 0x6c, 0x4e, 0x58, 0x48, 0x5e, - 0x61, 0x56, 0x4f, 0x50, 0x5c, 0x58, 0x58, 0x57, 0x5d, 0x55, 0x58, 0x61, - 0x5f, 0x56, 0x52, 0x5a, 0x54, 0x57, 0x61, 0x51, 0x53, 0x59, 0x58, 0x5c, - 0x59, 0x50, 0x44, 0x54, 0x5a, 0x5e, 0x57, 0x56, 0x71, 0x5c, 0x4f, 0x55, - 0x56, 0x53, 0x51, 0x52, 0x55, 0x57, 0x5a, 0x50, 0x5b, 0x55, 0x5b, 0x56, - 0x5d, 0x57, 0x5f, 0x57, 0x5d, 0x58, 0x54, 0x5a, 0x56, 0x4d, 0x5d, 0x57, - 0x5c, 0x4f, 0x5a, 0x5e, 0x58, 0x54, 0x5c, 0x58, 0x5a, 0x58, 0x56, 0x5a, - 0x65, 0x5c, 0x50, 0x56, 0x5a, 0x59, 0x64, 0x55, 0x58, 0x5b, 0x60, 0x58, - 0x5d, 0x54, 0x5b, 0x57, 0x54, 0x5d, 0x62, 0x5f, 0x5f, 0x52, 0x5f, 0x5f, - 0x54, 0x57, 0x55, 0x5c, 0x5c, 0x56, 0x5a, 0x5e, 0x58, 0x4c, 0x60, 0x5a, - 0x5a, 0x5d, 0x61, 0x5c, 0x70, 0x5e, 0x54, 0x5d, 0x57, 0x5a, 0x62, 0x59, - 0x59, 0x63, 0x58, 0x59, 0x59, 0x50, 0x5e, 0x60, 0x5d, 0x69, 0x60, 0x5e, - 0x64, 0x55, 0x5c, 0x53, 0x58, 0x5a, 0x64, 0x5f, 0x53, 0x54, 0x59, 0x5b, - 0x59, 0x4d, 0x5d, 0x5a, 0x59, 0x60, 0x5d, 0x56, 0x6c, 0x5a, 0x56, 0x55, - 0x5a, 0x59, 0x60, 0x53, 0x48, 0x5f, 0x5b, 0x58, 0x57, 0x54, 0x5c, 0x5a, - 0x59, 0x5d, 0x5a, 0x57, 0x62, 0x5d, 0x58, 0x47, 0x43, 0x5b, 0x61, 0x44, - 0x4d, 0x50, 0x59, 0x59, 0x58, 0x36, 0x2c, 0x57, 0x59, 0x5d, 0x57, 0x55, - 0x74, 0x5a, 0x49, 0x52, 0x53, 0x5a, 0x57, 0x58, 0x54, 0x49, 0x62, 0x4d, - 0x54, 0x54, 0x5b, 0x4e, 0x59, 0x55, 0x6a, 0x57, 0x5d, 0x57, 0x58, 0x4f, - 0x4f, 0x59, 0x62, 0x48, 0x4b, 0x51, 0x59, 0x5a, 0x5a, 0x48, 0x31, 0x59, - 0x5a, 0x59, 0x58, 0x57, 0x73, 0x59, 0x55, 0x59, 0x52, 0x5a, 0x56, 0x58, - 0x53, 0x4c, 0x60, 0x50, 0x53, 0x55, 0x59, 0x53, 0x5c, 0x56, 0x6a, 0x56, - 0x59, 0x59, 0x54, 0x56, 0x5a, 0x4a, 0x67, 0x59, 0x52, 0x5b, 0x59, 0x5a, - 0x5a, 0x5d, 0x5d, 0x54, 0x59, 0x5d, 0x5f, 0x59, 0x59, 0x57, 0x53, 0x56, - 0x59, 0x5d, 0x4d, 0x64, 0x4b, 0x56, 0x57, 0x61, 0x58, 0x58, 0x5a, 0x5d, - 0x50, 0x56, 0x70, 0x67, 0x58, 0x67, 0x58, 0x66, 0x64, 0x62, 0x55, 0x56, - 0x5d, 0x5b, 0x59, 0x55, 0x58, 0x43, 0x6c, 0x58, 0x59, 0x5d, 0x5e, 0x58, - 0x46, 0x58, 0x57, 0x5a, 0x5a, 0x5d, 0x59, 0x64, 0x52, 0x5d, 0x4b, 0x58, - 0x5a, 0x50, 0x58, 0x59, 0x57, 0x4f, 0x63, 0x5b, 0x59, 0x56, 0x57, 0x5f, - 0x59, 0x5d, 0x52, 0x53, 0x59, 0x5b, 0x59, 0x54, 0x5b, 0x55, 0x5c, 0x5d, - 0x5b, 0x66, 0x58, 0x64, 0x5b, 0x59, 0x57, 0x5d, 0x57, 0x58, 0x4c, 0x55, - 0x50, 0x61, 0x62, 0x5a, 0x65, 0x57, 0x59, 0x65, 0x59, 0x58, 0x58, 0x5a, - 0x5a, 0x5c, 0x61, 0x57, 0x59, 0x5a, 0x63, 0x55, 0x5a, 0x5b, 0x59, 0x5d, - 0x57, 0x59, 0x5f, 0x58, 0x5b, 0x58, 0x62, 0x5a, 0x62, 0x59, 0x5a, 0x58, - 0x58, 0x5f, 0x67, 0x5d, 0x5b, 0x56, 0x60, 0x5e, 0x56, 0x58, 0x5b, 0x61, - 0x5a, 0x57, 0x58, 0x59, 0x59, 0x4d, 0x64, 0x53, 0x5b, 0x54, 0x63, 0x52, - 0x54, 0x5b, 0x58, 0x5e, 0x5d, 0x55, 0x60, 0x5d, 0x59, 0x5e, 0x65, 0x57, - 0x68, 0x52, 0x4d, 0x5d, 0x54, 0x46, 0x53, 0x60, 0x4b, 0x5b, 0x5f, 0x4d, - 0x4a, 0x52, 0x5f, 0x6a, 0x49, 0x5d, 0x58, 0x69, 0x58, 0x59, 0x62, 0x61, - 0x55, 0x5a, 0x50, 0x5e, 0x58, 0x58, 0x59, 0x60, 0x5b, 0x48, 0x5c, 0x5a, - 0x59, 0x52, 0x5c, 0x5a, 0x5d, 0x52, 0x56, 0x55, 0x5c, 0x4e, 0x5b, 0x62, - 0x57, 0x55, 0x4f, 0x5b, 0x5f, 0x69, 0x5a, 0x5e, 0x54, 0x52, 0x57, 0x56, - 0x5e, 0x59, 0x5e, 0x54, 0x58, 0x5f, 0x53, 0x56, 0x56, 0x5e, 0x59, 0x5a, - 0x5a, 0x57, 0x5f, 0x5b, 0x5a, 0x51, 0x63, 0x4d, 0x53, 0x58, 0x57, 0x56, - 0x56, 0x5f, 0x59, 0x64, 0x58, 0x5f, 0x5e, 0x5c, 0x53, 0x57, 0x58, 0x5e, - 0x59, 0x5a, 0x56, 0x55, 0x5c, 0x5c, 0x58, 0x5d, 0x57, 0x56, 0x5b, 0x51, - 0x5c, 0x56, 0x5a, 0x5d, 0x56, 0x53, 0x5c, 0x57, 0x59, 0x59, 0x56, 0x58, - 0x64, 0x5e, 0x52, 0x60, 0x59, 0x56, 0x50, 0x5b, 0x50, 0x58, 0x55, 0x56, - 0x5b, 0x56, 0x5c, 0x59, 0x5c, 0x5e, 0x58, 0x5b, 0x5d, 0x65, 0x5e, 0x56, - 0x58, 0x5b, 0x51, 0x58, 0x5a, 0x5e, 0x5a, 0x5e, 0x5f, 0x55, 0x60, 0x5a, - 0x58, 0x5f, 0x64, 0x59, 0x5b, 0x5f, 0x53, 0x5b, 0x5b, 0x5b, 0x56, 0x5a, - 0x4b, 0x5e, 0x50, 0x5e, 0x54, 0x56, 0x5c, 0x5d, 0x56, 0x62, 0x5d, 0x58, - 0x5b, 0x58, 0x5e, 0x53, 0x59, 0x55, 0x60, 0x5a, 0x59, 0x5c, 0x59, 0x5c, - 0x58, 0x59, 0x5d, 0x59, 0x59, 0x61, 0x60, 0x5c, 0x6a, 0x60, 0x59, 0x4f, - 0x5c, 0x5e, 0x67, 0x5c, 0x55, 0x56, 0x57, 0x5b, 0x5a, 0x56, 0x5e, 0x5f, - 0x58, 0x58, 0x5b, 0x54, 0x5a, 0x5d, 0x4f, 0x59, 0x59, 0x57, 0x55, 0x5c, - 0x63, 0x49, 0x59, 0x57, 0x58, 0x4f, 0x4d, 0x55, 0x58, 0x5d, 0x4b, 0x5d, - 0x5e, 0x57, 0x54, 0x62, 0x54, 0x53, 0x66, 0x59, 0x60, 0x59, 0x61, 0x5a, - 0x5b, 0x55, 0x5b, 0x57, 0x57, 0x57, 0x58, 0x5b, 0x5c, 0x56, 0x4e, 0x52, - 0x55, 0x65, 0x65, 0x56, 0x5c, 0x4c, 0x59, 0x59, 0x5a, 0x57, 0x47, 0x55, - 0x58, 0x48, 0x5f, 0x59, 0x6b, 0x5b, 0x4d, 0x45, 0x58, 0x64, 0x5c, 0x59, - 0x5a, 0x5f, 0x4d, 0x56, 0x5e, 0x52, 0x5b, 0x5a, 0x50, 0x69, 0x52, 0x5d, - 0x5a, 0x59, 0x57, 0x5f, 0x5b, 0x5a, 0x57, 0x55, 0x58, 0x5a, 0x59, 0x58, - 0x59, 0x59, 0x5a, 0x5d, 0x5a, 0x63, 0x59, 0x64, 0x5d, 0x58, 0x5e, 0x64, - 0x5b, 0x5a, 0x4c, 0x5a, 0x54, 0x56, 0x5c, 0x56, 0x63, 0x58, 0x58, 0x5f, - 0x5b, 0x53, 0x5a, 0x5c, 0x57, 0x56, 0x53, 0x61, 0x59, 0x5f, 0x59, 0x54, - 0x58, 0x5a, 0x58, 0x55, 0x65, 0x56, 0x5a, 0x5a, 0x59, 0x60, 0x5c, 0x5f, - 0x5a, 0x56, 0x57, 0x60, 0x5a, 0x56, 0x45, 0x56, 0x57, 0x5b, 0x62, 0x56, - 0x61, 0x5c, 0x58, 0x5e, 0x50, 0x55, 0x58, 0x59, 0x54, 0x57, 0x5c, 0x5b, - 0x5a, 0x59, 0x59, 0x57, 0x57, 0x63, 0x59, 0x5a, 0x58, 0x58, 0x65, 0x5c, - 0x59, 0x56, 0x67, 0x5b, 0x5a, 0x5c, 0x57, 0x61, 0x5f, 0x5e, 0x56, 0x60, - 0x56, 0x59, 0x5c, 0x5f, 0x5a, 0x5f, 0x5e, 0x62, 0x5c, 0x63, 0x56, 0x56, - 0x58, 0x57, 0x56, 0x57, 0x5e, 0x5a, 0x5c, 0x59, 0x59, 0x5b, 0x59, 0x58, - 0x5a, 0x55, 0x5a, 0x57, 0x5a, 0x5c, 0x5c, 0x5b, 0x5a, 0x59, 0x59, 0x60, - 0x5c, 0x5a, 0x52, 0x59, 0x5d, 0x57, 0x5d, 0x5b, 0x62, 0x56, 0x5a, 0x5d, - 0x57, 0x55, 0x57, 0x56, 0x59, 0x58, 0x55, 0x65, 0x51, 0x55, 0x64, 0x4e, - 0x52, 0x56, 0x59, 0x55, 0x59, 0x56, 0x5d, 0x5b, 0x59, 0x64, 0x62, 0x5d, - 0x70, 0x61, 0x54, 0x56, 0x59, 0x51, 0x5e, 0x59, 0x5b, 0x65, 0x5f, 0x5c, - 0x55, 0x54, 0x5b, 0x61, 0x57, 0x5c, 0x5b, 0x61, 0x58, 0x45, 0x4c, 0x52, - 0x58, 0x5b, 0x58, 0x63, 0x5a, 0x51, 0x58, 0x4e, 0x55, 0x40, 0x4b, 0x55, - 0x58, 0x70, 0x43, 0x5c, 0x50, 0x57, 0x4f, 0x4d, 0x5e, 0x55, 0x53, 0x52, - 0x57, 0x57, 0x51, 0x4b, 0x5e, 0x49, 0x5a, 0x51, 0x4d, 0x52, 0x59, 0x58, - 0x5a, 0x58, 0x5c, 0x59, 0x59, 0x55, 0x59, 0x58, 0x5b, 0x57, 0x59, 0x5c, - 0x5c, 0x57, 0x57, 0x5a, 0x59, 0x5a, 0x5a, 0x5a, 0x59, 0x5d, 0x59, 0x5a, - 0x56, 0x58, 0x53, 0x57, 0x56, 0x5c, 0x60, 0x58, 0x5a, 0x5a, 0x59, 0x5c, - 0x57, 0x5d, 0x5a, 0x57, 0x57, 0x51, 0x58, 0x5b, 0x53, 0x5e, 0x5c, 0x5c, - 0x5b, 0x5c, 0x59, 0x57, 0x59, 0x47, 0x5b, 0x5b, 0x5a, 0x56, 0x5c, 0x52, - 0x60, 0x55, 0x5b, 0x5b, 0x5d, 0x5d, 0x53, 0x5f, 0x5b, 0x59, 0x5c, 0x56, - 0x58, 0x57, 0x53, 0x5c, 0x56, 0x5b, 0x5a, 0x60, 0x5c, 0x55, 0x58, 0x51, - 0x57, 0x5c, 0x61, 0x55, 0x5d, 0x50, 0x59, 0x5c, 0x5d, 0x4e, 0x55, 0x58, - 0x59, 0x56, 0x5b, 0x5a, 0x76, 0x5f, 0x57, 0x50, 0x53, 0x57, 0x60, 0x59, - 0x4b, 0x5b, 0x56, 0x57, 0x56, 0x4e, 0x5c, 0x60, 0x53, 0x61, 0x5a, 0x55, - 0x5b, 0x5b, 0x58, 0x5d, 0x56, 0x4c, 0x51, 0x51, 0x58, 0x62, 0x59, 0x5a, - 0x58, 0x51, 0x66, 0x63, 0x58, 0x5c, 0x6b, 0x5e, 0x64, 0x58, 0x51, 0x4b, - 0x5e, 0x5a, 0x5b, 0x5f, 0x4f, 0x68, 0x64, 0x5e, 0x53, 0x51, 0x5a, 0x69, - 0x52, 0x5d, 0x5b, 0x56, 0x5a, 0x5c, 0x53, 0x5e, 0x55, 0x5d, 0x5f, 0x4f, - 0x5e, 0x50, 0x5a, 0x5a, 0x59, 0x50, 0x4c, 0x55, 0x59, 0x58, 0x54, 0x5b, - 0x6c, 0x58, 0x5c, 0x55, 0x55, 0x57, 0x52, 0x54, 0x55, 0x5d, 0x5f, 0x52, - 0x56, 0x5a, 0x5a, 0x58, 0x65, 0x57, 0x5b, 0x57, 0x5e, 0x54, 0x65, 0x5e, - 0x59, 0x4e, 0x5a, 0x5a, 0x53, 0x5e, 0x5a, 0x60, 0x57, 0x59, 0x64, 0x56, - 0x58, 0x5b, 0x60, 0x59, 0x5c, 0x5f, 0x47, 0x54, 0x5d, 0x5d, 0x63, 0x61, - 0x60, 0x68, 0x57, 0x62, 0x5b, 0x57, 0x5c, 0x5b, 0x55, 0x65, 0x5a, 0x64, - 0x5c, 0x50, 0x59, 0x58, 0x5e, 0x47, 0x56, 0x5d, 0x58, 0x55, 0x5b, 0x57, - 0x56, 0x4d, 0x5d, 0x52, 0x58, 0x61, 0x62, 0x58, 0x63, 0x5b, 0x75, 0x52, - 0x5b, 0x59, 0x6b, 0x5c, 0x6f, 0x5a, 0x55, 0x62, 0x59, 0x54, 0x5e, 0x5f, - 0x58, 0x60, 0x64, 0x59, 0x53, 0x50, 0x51, 0x5f, 0x59, 0x71, 0x59, 0x59, - 0x46, 0x59, 0x5a, 0x5c, 0x56, 0x51, 0x58, 0x54, 0x59, 0x5d, 0x57, 0x5e, - 0x5d, 0x5e, 0x4f, 0x60, 0x53, 0x58, 0x49, 0x58, 0x60, 0x55, 0x44, 0x59, - 0x57, 0x52, 0x54, 0x5e, 0x56, 0x5e, 0x5b, 0x5c, 0x63, 0x5c, 0x4d, 0x4f, - 0x5b, 0x58, 0x6a, 0x4b, 0x5d, 0x58, 0x5a, 0x5d, 0x56, 0x56, 0x5d, 0x54, - 0x5b, 0x5b, 0x5f, 0x58, 0x66, 0x5e, 0x50, 0x76, 0x55, 0x53, 0x45, 0x49, - 0x4a, 0x56, 0x4f, 0x50, 0x5d, 0x5b, 0x5d, 0x48, 0x60, 0x64, 0x5f, 0x54, - 0x59, 0x55, 0x55, 0x5e, 0x57, 0x5a, 0x5c, 0x4f, 0x58, 0x57, 0x59, 0x5b, - 0x54, 0x57, 0x59, 0x57, 0x59, 0x60, 0x59, 0x5a, 0x54, 0x5b, 0x53, 0x60, - 0x56, 0x59, 0x4e, 0x5a, 0x52, 0x5b, 0x5c, 0x5b, 0x5d, 0x59, 0x57, 0x57, - 0x59, 0x58, 0x5c, 0x5e, 0x5a, 0x53, 0x5e, 0x5f, 0x59, 0x59, 0x56, 0x58, - 0x5a, 0x52, 0x58, 0x5c, 0x58, 0x54, 0x5a, 0x5a, 0x58, 0x59, 0x5b, 0x58, - 0x5f, 0x5d, 0x53, 0x62, 0x5a, 0x58, 0x5e, 0x54, 0x54, 0x5b, 0x5e, 0x57, - 0x5b, 0x5c, 0x58, 0x56, 0x5e, 0x5c, 0x58, 0x5e, 0x52, 0x51, 0x52, 0x4f, - 0x59, 0x5b, 0x60, 0x58, 0x5f, 0x55, 0x59, 0x59, 0x56, 0x51, 0x58, 0x5c, - 0x59, 0x5b, 0x4b, 0x52, 0x60, 0x5a, 0x51, 0x50, 0x5b, 0x5b, 0x4f, 0x5c, - 0x52, 0x53, 0x5b, 0x50, 0x58, 0x5b, 0x4f, 0x53, 0x5c, 0x53, 0x59, 0x54, - 0x5c, 0x52, 0x57, 0x5c, 0x57, 0x55, 0x65, 0x54, 0x61, 0x4e, 0x59, 0x5c, - 0x5f, 0x4f, 0x60, 0x5a, 0x59, 0x5e, 0x5d, 0x58, 0x67, 0x5e, 0x56, 0x57, - 0x5a, 0x5b, 0x65, 0x54, 0x57, 0x5d, 0x3f, 0x52, 0x5c, 0x57, 0x5c, 0x57, - 0x5a, 0x5c, 0x67, 0x62, 0x5a, 0x5a, 0x56, 0x55, 0x5a, 0x52, 0x59, 0x58, - 0x5d, 0x56, 0x59, 0x54, 0x59, 0x51, 0x57, 0x57, 0x5d, 0x5e, 0x5f, 0x59, - 0x64, 0x59, 0x57, 0x51, 0x59, 0x56, 0x60, 0x68, 0x51, 0x60, 0x5b, 0x5a, - 0x53, 0x51, 0x5d, 0x64, 0x56, 0x58, 0x58, 0x5f, 0x5b, 0x58, 0x5f, 0x59, - 0x5a, 0x59, 0x59, 0x59, 0x5a, 0x60, 0x58, 0x5c, 0x5a, 0x54, 0x5d, 0x5a, - 0x59, 0x61, 0x5f, 0x55, 0x5a, 0x59, 0x5a, 0x5c, 0x5c, 0x57, 0x58, 0x5c, - 0x4e, 0x5e, 0x5d, 0x5d, 0x57, 0x57, 0x5b, 0x5b, 0x55, 0x5a, 0x58, 0x59, - 0x58, 0x52, 0x5e, 0x61, 0x58, 0x53, 0x59, 0x5a, 0x4e, 0x68, 0x58, 0x56, - 0x58, 0x53, 0x62, 0x5d, 0x59, 0x56, 0x55, 0x5a, 0x5c, 0x58, 0x52, 0x5c, - 0x62, 0x5a, 0x6b, 0x68, 0x53, 0x61, 0x54, 0x5d, 0x56, 0x54, 0x59, 0x67, - 0x57, 0x64, 0x5a, 0x5b, 0x56, 0x55, 0x56, 0x54, 0x5a, 0x5d, 0x63, 0x5c, - 0x58, 0x5e, 0x5c, 0x59, 0x58, 0x57, 0x5b, 0x55, 0x5c, 0x60, 0x5e, 0x5d, - 0x5c, 0x57, 0x52, 0x5a, 0x5d, 0x5c, 0x54, 0x59, 0x55, 0x58, 0x59, 0x57, - 0x58, 0x5d, 0x52, 0x5f, 0x5b, 0x57, 0x5b, 0x61, 0x55, 0x58, 0x50, 0x5d, - 0x59, 0x6a, 0x63, 0x56, 0x5d, 0x5a, 0x59, 0x5d, 0x56, 0x56, 0x5a, 0x59, - 0x59, 0x60, 0x58, 0x5b, 0x50, 0x5d, 0x54, 0x56, 0x59, 0x54, 0x50, 0x5a, - 0x57, 0x51, 0x5a, 0x5c, 0x59, 0x57, 0x56, 0x64, 0x56, 0x59, 0x64, 0x5a, - 0x5d, 0x55, 0x54, 0x79, 0x59, 0x56, 0x61, 0x54, 0x62, 0x58, 0x59, 0x61, - 0x5b, 0x52, 0x60, 0x58, 0x59, 0x57, 0x54, 0x61, 0x6b, 0x61, 0x45, 0x5a, - 0x54, 0x57, 0x5f, 0x56, 0x62, 0x58, 0x50, 0x59, 0x5c, 0x59, 0x5c, 0x5d, - 0x56, 0x65, 0x5e, 0x65, 0x59, 0x58, 0x5b, 0x5c, 0x59, 0x5e, 0x5d, 0x56, - 0x53, 0x59, 0x59, 0x5a, 0x59, 0x5a, 0x5f, 0x64, 0x59, 0x5a, 0x5d, 0x5a, - 0x5c, 0x54, 0x53, 0x5b, 0x58, 0x58, 0x5e, 0x5e, 0x61, 0x54, 0x57, 0x5e, - 0x58, 0x63, 0x59, 0x5f, 0x56, 0x58, 0x58, 0x59, 0x5b, 0x55, 0x5f, 0x51, - 0x5b, 0x4e, 0x52, 0x61, 0x57, 0x5f, 0x5b, 0x58, 0x5b, 0x57, 0x58, 0x58, - 0x5b, 0x5f, 0x5e, 0x5a, 0x5d, 0x5b, 0x57, 0x52, 0x57, 0x58, 0x6b, 0x5b, - 0x60, 0x5e, 0x61, 0x5b, 0x5b, 0x58, 0x5c, 0x5c, 0x58, 0x63, 0x56, 0x59, - 0x59, 0x51, 0x53, 0x55, 0x5c, 0x57, 0x59, 0x4d, 0x5a, 0x51, 0x59, 0x5c, - 0x5b, 0x57, 0x5a, 0x61, 0x59, 0x5a, 0x59, 0x5a, 0x69, 0x5d, 0x49, 0x5e, - 0x55, 0x61, 0x4a, 0x59, 0x44, 0x5b, 0x63, 0x5a, 0x5d, 0x62, 0x5a, 0x56, - 0x5a, 0x68, 0x58, 0x54, 0x58, 0x53, 0x62, 0x53, 0x58, 0x4d, 0x5c, 0x59, - 0x5d, 0x56, 0x58, 0x5d, 0x59, 0x56, 0x60, 0x57, 0x5a, 0x5d, 0x64, 0x5d, - 0x63, 0x56, 0x4e, 0x5d, 0x62, 0x53, 0x4b, 0x5c, 0x59, 0x66, 0x58, 0x5d, - 0x59, 0x68, 0x55, 0x50, 0x63, 0x5c, 0x5a, 0x5f, 0x5b, 0x58, 0x63, 0x59, - 0x58, 0x56, 0x64, 0x54, 0x59, 0x59, 0x5a, 0x62, 0x59, 0x58, 0x62, 0x59, - 0x59, 0x5c, 0x67, 0x59, 0x59, 0x61, 0x56, 0x59, 0x59, 0x5d, 0x6e, 0x5b, - 0x62, 0x5c, 0x69, 0x64, 0x58, 0x5b, 0x5b, 0x59, 0x5a, 0x58, 0x5a, 0x57, - 0x5d, 0x54, 0x5e, 0x5a, 0x51, 0x6b, 0x55, 0x61, 0x57, 0x56, 0x58, 0x5d, - 0x58, 0x54, 0x58, 0x57, 0x5b, 0x5a, 0x64, 0x5a, 0x6a, 0x5e, 0x53, 0x53, - 0x5b, 0x57, 0x57, 0x53, 0x55, 0x62, 0x4c, 0x58, 0x5a, 0x52, 0x5b, 0x59, - 0x5a, 0x6e, 0x57, 0x5a, 0x55, 0x61, 0x5d, 0x57, 0x51, 0x5f, 0x5f, 0x81, - 0x57, 0x59, 0x59, 0x5c, 0x5b, 0x49, 0x5e, 0x56, 0x59, 0x62, 0x54, 0x56, - 0x54, 0x58, 0x51, 0x5d, 0x60, 0x52, 0x51, 0x55, 0x49, 0x4e, 0x78, 0x58, - 0x5f, 0x59, 0x5b, 0x65, 0x59, 0x4f, 0x57, 0x60, 0x5f, 0x59, 0x49, 0x5d, - 0x5b, 0x55, 0x59, 0x4b, 0x58, 0x52, 0x59, 0x5d, 0x55, 0x53, 0x5b, 0x52, - 0x59, 0x60, 0x62, 0x5d, 0x50, 0x5b, 0x48, 0x5e, 0x5a, 0x5e, 0x4e, 0x55, - 0x4e, 0x64, 0x54, 0x5b, 0x5f, 0x59, 0x5c, 0x54, 0x52, 0x5b, 0x57, 0x5c, - 0x52, 0x5a, 0x5a, 0x54, 0x5b, 0x59, 0x60, 0x54, 0x59, 0x5c, 0x59, 0x58, - 0x5a, 0x56, 0x57, 0x58, 0x57, 0x5d, 0x5a, 0x53, 0x52, 0x52, 0x59, 0x54, - 0x59, 0x5a, 0x59, 0x5e, 0x60, 0x59, 0x60, 0x5c, 0x57, 0x57, 0x58, 0x5d, - 0x58, 0x58, 0x58, 0x54, 0x62, 0x50, 0x5e, 0x63, 0x57, 0x57, 0x5b, 0x53, - 0x5a, 0x54, 0x59, 0x5d, 0x58, 0x52, 0x5d, 0x58, 0x59, 0x5d, 0x5b, 0x57, - 0x63, 0x5d, 0x4b, 0x5c, 0x58, 0x58, 0x61, 0x58, 0x52, 0x5f, 0x57, 0x55, - 0x59, 0x57, 0x5b, 0x54, 0x5b, 0x61, 0x5a, 0x57, 0x5a, 0x53, 0x50, 0x65, - 0x5b, 0x5a, 0x54, 0x4f, 0x57, 0x5e, 0x58, 0x5f, 0x56, 0x56, 0x5c, 0x5c, - 0x5b, 0x58, 0x58, 0x64, 0x5e, 0x57, 0x4a, 0x58, 0x61, 0x57, 0x45, 0x5f, - 0x5a, 0x5c, 0x5c, 0x58, 0x62, 0x56, 0x59, 0x55, 0x5a, 0x5c, 0x5a, 0x63, - 0x5e, 0x4e, 0x5b, 0x54, 0x55, 0x5c, 0x67, 0x54, 0x5e, 0x56, 0x5a, 0x5b, - 0x59, 0x51, 0x40, 0x55, 0x58, 0x65, 0x56, 0x5d, 0x60, 0x5a, 0x52, 0x5e, - 0x5b, 0x4d, 0x5a, 0x59, 0x5e, 0x56, 0x4d, 0x56, 0x59, 0x4e, 0x5a, 0x58, - 0x4d, 0x56, 0x52, 0x5b, 0x5e, 0x57, 0x59, 0x57, 0x50, 0x66, 0x5b, 0x5e, - 0x60, 0x5e, 0x5b, 0x55, 0x59, 0x4d, 0x61, 0x55, 0x57, 0x61, 0x56, 0x58, - 0x4f, 0x55, 0x50, 0x52, 0x5f, 0x59, 0x59, 0x5f, 0x51, 0x4d, 0x65, 0x61, - 0x51, 0x52, 0x57, 0x63, 0x53, 0x5e, 0x55, 0x5b, 0x5a, 0x58, 0x5a, 0x55, - 0x58, 0x54, 0x64, 0x4e, 0x58, 0x59, 0x58, 0x58, 0x5b, 0x56, 0x56, 0x57, - 0x59, 0x67, 0x59, 0x59, 0x69, 0x5c, 0x5a, 0x55, 0x56, 0x56, 0x5f, 0x5d, - 0x54, 0x59, 0x4a, 0x5b, 0x55, 0x54, 0x58, 0x61, 0x56, 0x5b, 0x53, 0x53, - 0x5f, 0x4e, 0x5b, 0x59, 0x52, 0x62, 0x66, 0x57, 0x67, 0x52, 0x59, 0x59, - 0x56, 0x46, 0x5f, 0x61, 0x59, 0x5d, 0x5b, 0x5b, 0x54, 0x53, 0x51, 0x56, - 0x60, 0x58, 0x64, 0x56, 0x4c, 0x4c, 0x53, 0x47, 0x5b, 0x55, 0x56, 0x52, - 0x53, 0x62, 0x5b, 0x60, 0x5e, 0x5c, 0x57, 0x57, 0x59, 0x53, 0x5a, 0x5d, - 0x5a, 0x59, 0x59, 0x5e, 0x58, 0x54, 0x64, 0x5a, 0x5a, 0x4c, 0x5e, 0x58, - 0x5f, 0x5e, 0x52, 0x54, 0x58, 0x5b, 0x5d, 0x5f, 0x58, 0x5d, 0x5b, 0x58, - 0x58, 0x56, 0x5d, 0x5e, 0x54, 0x61, 0x57, 0x5e, 0x54, 0x54, 0x52, 0x58, - 0x4f, 0x50, 0x5c, 0x55, 0x60, 0x53, 0x59, 0x57, 0x58, 0x54, 0x60, 0x5c, - 0x59, 0x5e, 0x57, 0x58, 0x60, 0x5b, 0x50, 0x68, 0x50, 0x5c, 0x58, 0x55, - 0x54, 0x5c, 0x6a, 0x52, 0x5f, 0x54, 0x55, 0x5d, 0x50, 0x5f, 0x57, 0x61, - 0x5a, 0x5a, 0x65, 0x4e, 0x59, 0x65, 0x63, 0x54, 0x5a, 0x5b, 0x5a, 0x66, - 0x5a, 0x58, 0x65, 0x5b, 0x5b, 0x59, 0x66, 0x56, 0x64, 0x56, 0x55, 0x5b, - 0x5e, 0x62, 0x62, 0x62, 0x5d, 0x54, 0x50, 0x5e, 0x54, 0x6a, 0x61, 0x5b, - 0x5b, 0x52, 0x59, 0x56, 0x5b, 0x51, 0x4d, 0x5e, 0x57, 0x53, 0x57, 0x52, - 0x5c, 0x53, 0x59, 0x5a, 0x5b, 0x3f, 0x5b, 0x58, 0x58, 0x54, 0x51, 0x5d, - 0x66, 0x5a, 0x51, 0x60, 0x56, 0x55, 0x4c, 0x55, 0x4e, 0x56, 0x56, 0x50, - 0x5f, 0x58, 0x5b, 0x53, 0x5f, 0x62, 0x58, 0x5a, 0x59, 0x63, 0x55, 0x59, - 0x5a, 0x5e, 0x5b, 0x54, 0x59, 0x5b, 0x58, 0x5a, 0x59, 0x58, 0x5b, 0x5a, - 0x5a, 0x5d, 0x5c, 0x5a, 0x5b, 0x5b, 0x51, 0x5f, 0x5a, 0x56, 0x4f, 0x57, - 0x59, 0x54, 0x60, 0x5a, 0x55, 0x50, 0x5c, 0x60, 0x5b, 0x58, 0x5a, 0x5d, - 0x59, 0x55, 0x57, 0x52, 0x59, 0x4f, 0x66, 0x59, 0x5c, 0x53, 0x58, 0x58, - 0x55, 0x57, 0x5b, 0x58, 0x59, 0x5d, 0x52, 0x5b, 0x5f, 0x61, 0x54, 0x46, - 0x5c, 0x4e, 0x5d, 0x65, 0x4a, 0x56, 0x54, 0x57, 0x52, 0x52, 0x5a, 0x63, - 0x56, 0x60, 0x5e, 0x59, 0x5e, 0x54, 0x59, 0x5b, 0x5b, 0x55, 0x52, 0x5f, - 0x5c, 0x58, 0x59, 0x5e, 0x59, 0x53, 0x63, 0x57, 0x58, 0x5a, 0x5f, 0x5c, - 0x6c, 0x5d, 0x54, 0x58, 0x53, 0x58, 0x5f, 0x55, 0x4c, 0x5a, 0x4d, 0x5f, - 0x58, 0x52, 0x5d, 0x5f, 0x55, 0x5f, 0x68, 0x53, 0x5c, 0x52, 0x56, 0x50, - 0x57, 0x56, 0x61, 0x57, 0x5a, 0x58, 0x58, 0x59, 0x5c, 0x4a, 0x57, 0x5d, - 0x58, 0x5b, 0x52, 0x5d, 0x64, 0x5d, 0x57, 0x47, 0x53, 0x58, 0x5f, 0x63, - 0x46, 0x5a, 0x5b, 0x4f, 0x57, 0x52, 0x5b, 0x5f, 0x4c, 0x62, 0x57, 0x62, - 0x5f, 0x51, 0x5b, 0x5b, 0x50, 0x4e, 0x58, 0x68, 0x5a, 0x5b, 0x59, 0x64, - 0x58, 0x4c, 0x4e, 0x58, 0x59, 0x59, 0x6b, 0x5c, 0x70, 0x5c, 0x49, 0x52, - 0x59, 0x57, 0x5b, 0x59, 0x5e, 0x68, 0x53, 0x5a, 0x58, 0x51, 0x5a, 0x5f, - 0x58, 0x68, 0x5f, 0x5d, 0x67, 0x54, 0x56, 0x5c, 0x58, 0x5f, 0x5d, 0x67, - 0x62, 0x50, 0x59, 0x55, 0x56, 0x51, 0x52, 0x58, 0x58, 0x5a, 0x52, 0x5e, - 0x6b, 0x59, 0x51, 0x63, 0x53, 0x4f, 0x56, 0x60, 0x4c, 0x5c, 0x47, 0x4e, - 0x5c, 0x52, 0x5c, 0x56, 0x53, 0x5b, 0x64, 0x64, 0x5e, 0x47, 0x5a, 0x61, - 0x4c, 0x67, 0x56, 0x5a, 0x64, 0x5a, 0x59, 0x5e, 0x57, 0x46, 0x71, 0x5c, - 0x5a, 0x60, 0x49, 0x5d, 0x65, 0x59, 0x45, 0x59, 0x5d, 0x56, 0x56, 0x5a, - 0x52, 0x73, 0x3d, 0x59, 0x53, 0x54, 0x5b, 0x67, 0x56, 0x5f, 0x69, 0x54, - 0x5e, 0x53, 0x59, 0x5c, 0x50, 0x5b, 0x64, 0x4c, 0x4e, 0x53, 0x59, 0x5b, - 0x5c, 0x4e, 0x44, 0x57, 0x58, 0x5d, 0x5c, 0x55, 0x68, 0x5a, 0x51, 0x5b, - 0x57, 0x5a, 0x51, 0x57, 0x57, 0x55, 0x64, 0x55, 0x5b, 0x58, 0x5e, 0x57, - 0x57, 0x52, 0x5d, 0x58, 0x5a, 0x59, 0x5d, 0x59, 0x58, 0x5b, 0x62, 0x56, - 0x58, 0x5c, 0x59, 0x5b, 0x5b, 0x5b, 0x62, 0x58, 0x58, 0x58, 0x64, 0x5b, - 0x5a, 0x5d, 0x59, 0x59, 0x5c, 0x5f, 0x69, 0x63, 0x62, 0x57, 0x63, 0x61, - 0x59, 0x5c, 0x59, 0x64, 0x59, 0x54, 0x59, 0x56, 0x5b, 0x53, 0x5b, 0x5a, - 0x58, 0x51, 0x5b, 0x53, 0x5c, 0x5c, 0x58, 0x58, 0x58, 0x56, 0x5a, 0x5b, - 0x58, 0x61, 0x5f, 0x57, 0x5a, 0x5a, 0x56, 0x56, 0x5c, 0x56, 0x5d, 0x59, - 0x52, 0x59, 0x54, 0x5e, 0x52, 0x54, 0x5c, 0x61, 0x52, 0x56, 0x5a, 0x58, - 0x5c, 0x58, 0x4f, 0x6a, 0x58, 0x52, 0x51, 0x52, 0x56, 0x5f, 0x5a, 0x58, - 0x57, 0x57, 0x62, 0x63, 0x5a, 0x5a, 0x63, 0x52, 0x63, 0x5e, 0x51, 0x5e, - 0x54, 0x5c, 0x46, 0x66, 0x45, 0x5f, 0x5b, 0x54, 0x57, 0x52, 0x5b, 0x5d, - 0x50, 0x59, 0x5a, 0x5b, 0x58, 0x5b, 0x5d, 0x57, 0x5a, 0x5c, 0x60, 0x57, - 0x57, 0x5a, 0x5a, 0x5c, 0x5a, 0x5b, 0x60, 0x57, 0x59, 0x5b, 0x64, 0x57, - 0x5d, 0x5a, 0x58, 0x59, 0x5a, 0x5d, 0x66, 0x60, 0x5d, 0x58, 0x65, 0x5e, - 0x58, 0x5b, 0x57, 0x61, 0x59, 0x56, 0x58, 0x5c, 0x58, 0x60, 0x63, 0x52, - 0x58, 0x52, 0x65, 0x56, 0x57, 0x5a, 0x59, 0x4b, 0x54, 0x58, 0x58, 0x5f, - 0x59, 0x56, 0x5a, 0x59, 0x5b, 0x56, 0x53, 0x57, 0x55, 0x56, 0x59, 0x57, - 0x4a, 0x5b, 0x58, 0x55, 0x57, 0x58, 0x59, 0x5a, 0x59, 0x5c, 0x59, 0x57, - 0x5b, 0x56, 0x5c, 0x5a, 0x58, 0x59, 0x59, 0x55, 0x58, 0x5e, 0x5a, 0x5a, - 0x58, 0x53, 0x60, 0x5a, 0x5a, 0x5f, 0x63, 0x56, 0x5f, 0x5c, 0x54, 0x5a, - 0x5d, 0x5c, 0x5c, 0x5a, 0x56, 0x5d, 0x64, 0x5d, 0x54, 0x58, 0x5b, 0x62, - 0x59, 0x5f, 0x5a, 0x59, 0x5d, 0x50, 0x5f, 0x4e, 0x54, 0x63, 0x49, 0x5d, - 0x58, 0x52, 0x5a, 0x5b, 0x57, 0x4d, 0x59, 0x59, 0x59, 0x57, 0x60, 0x54, - 0x6b, 0x59, 0x4e, 0x58, 0x5d, 0x58, 0x58, 0x50, 0x60, 0x63, 0x56, 0x55, - 0x54, 0x55, 0x5b, 0x55, 0x61, 0x68, 0x5c, 0x50, 0x5c, 0x62, 0x47, 0x6f, - 0x51, 0x87, 0x73, 0x5b, 0x55, 0x56, 0x5a, 0x58, 0x54, 0x48, 0x66, 0x59, - 0x59, 0x56, 0x6e, 0x53, 0x5a, 0x59, 0x4f, 0x59, 0x47, 0x55, 0x3b, 0x5d, - 0x37, 0x61, 0x62, 0x53, 0x56, 0x54, 0x5a, 0x5c, 0x59, 0x56, 0x9a, 0x5b, - 0x5e, 0x53, 0x4e, 0x51, 0x58, 0x5d, 0x61, 0x55, 0x4e, 0x6a, 0x59, 0x56, - 0x58, 0x5a, 0x46, 0x68, 0x5a, 0x55, 0x54, 0x60, 0x5a, 0x5a, 0x50, 0x47, - 0x58, 0x58, 0x54, 0x61, 0x48, 0x51, 0x6d, 0x4a, 0x53, 0x52, 0x58, 0x5e, - 0x50, 0x68, 0x56, 0x45, 0x60, 0x4c, 0x64, 0x63, 0x5a, 0x50, 0x59, 0x53, - 0x57, 0x53, 0x58, 0x60, 0x59, 0x52, 0x5c, 0x5d, 0x59, 0x54, 0x5f, 0x54, - 0x78, 0x55, 0x41, 0x55, 0x57, 0x4e, 0x5f, 0x5f, 0x4a, 0x59, 0x51, 0x53, - 0x48, 0x5b, 0x56, 0x56, 0x5d, 0x5e, 0x5b, 0x58, 0x5a, 0x53, 0x5a, 0x59, - 0x59, 0x5d, 0x52, 0x58, 0x58, 0x56, 0x59, 0x5a, 0x57, 0x54, 0x57, 0x5a, - 0x59, 0x5e, 0x56, 0x57, 0x62, 0x5b, 0x57, 0x64, 0x5a, 0x56, 0x59, 0x56, - 0x59, 0x5b, 0x54, 0x51, 0x61, 0x5c, 0x5c, 0x55, 0x5b, 0x5e, 0x5c, 0x61, - 0x5c, 0x50, 0x59, 0x4b, 0x4c, 0x5b, 0x60, 0x56, 0x61, 0x58, 0x58, 0x5a, - 0x58, 0x49, 0x62, 0x57, 0x58, 0x61, 0x4d, 0x56, 0x4c, 0x56, 0x51, 0x51, - 0x5e, 0x54, 0x54, 0x57, 0x53, 0x4b, 0x60, 0x5d, 0x54, 0x4d, 0x56, 0x62, - 0x55, 0x52, 0x53, 0x52, 0x5b, 0x4e, 0x56, 0x5a, 0x5a, 0x55, 0x5a, 0x57, - 0x59, 0x52, 0x59, 0x56, 0x54, 0x51, 0x5b, 0x58, 0x59, 0x5d, 0x5b, 0x57, - 0x61, 0x5b, 0x4d, 0x5e, 0x5d, 0x57, 0x54, 0x57, 0x52, 0x5f, 0x5c, 0x56, - 0x59, 0x5b, 0x57, 0x56, 0x5e, 0x61, 0x58, 0x58, 0x5b, 0x5a, 0x5e, 0x56, - 0x59, 0x5a, 0x66, 0x58, 0x5b, 0x5a, 0x59, 0x5f, 0x59, 0x59, 0x60, 0x59, - 0x5a, 0x5d, 0x64, 0x58, 0x61, 0x68, 0x54, 0x4f, 0x58, 0x5f, 0x67, 0x5c, - 0x60, 0x5b, 0x61, 0x5f, 0x55, 0x58, 0x5d, 0x60, 0x55, 0x56, 0x5c, 0x59, - 0x5e, 0x52, 0x58, 0x62, 0x5b, 0x4d, 0x54, 0x5d, 0x60, 0x53, 0x59, 0x5d, - 0x5e, 0x57, 0x5e, 0x58, 0x59, 0x59, 0x5a, 0x57, 0x63, 0x5e, 0x4b, 0x5c, - 0x58, 0x5c, 0x62, 0x52, 0x61, 0x60, 0x4e, 0x5b, 0x58, 0x56, 0x5c, 0x5d, - 0x5c, 0x5d, 0x5c, 0x5a, 0x5c, 0x51, 0x55, 0x5d, 0x56, 0x4f, 0x51, 0x56, - 0x5f, 0x50, 0x59, 0x5a, 0x58, 0x4d, 0x5f, 0x58, 0x59, 0x59, 0x5c, 0x5a, - 0x62, 0x5b, 0x57, 0x5d, 0x5b, 0x5a, 0x61, 0x58, 0x5a, 0x5a, 0x5a, 0x5b, - 0x5a, 0x5a, 0x5b, 0x57, 0x5e, 0x61, 0x5b, 0x58, 0x5e, 0x4f, 0x64, 0x4e, - 0x55, 0x60, 0x56, 0x6a, 0x61, 0x59, 0x5a, 0x64, 0x58, 0x55, 0x62, 0x58, - 0x59, 0x54, 0x4a, 0x5c, 0x62, 0x61, 0x53, 0x61, 0x5d, 0x5d, 0x59, 0x59, - 0x63, 0x5b, 0x5c, 0x56, 0x58, 0x4d, 0x59, 0x59, 0x53, 0x62, 0x5f, 0x56, - 0x5b, 0x5d, 0x55, 0x5e, 0x58, 0x58, 0x59, 0x55, 0x64, 0x4c, 0x58, 0x5c, - 0x56, 0x4b, 0x57, 0x56, 0x58, 0x59, 0x55, 0x55, 0x64, 0x5d, 0x4e, 0x62, - 0x57, 0x53, 0x66, 0x5e, 0x5f, 0x57, 0x5d, 0x54, 0x5a, 0x58, 0x5e, 0x54, - 0x5b, 0x5d, 0x5a, 0x58, 0x66, 0x58, 0x49, 0x59, 0x57, 0x55, 0x4f, 0x57, - 0x58, 0x4d, 0x59, 0x54, 0x81, 0x59, 0x3e, 0x36, 0x58, 0x57, 0x34, 0x3b, - 0x51, 0x68, 0x59, 0x54, 0x49, 0x51, 0x4a, 0x4f, 0x46, 0x5a, 0x52, 0x50, - 0x3b, 0x55, 0xd4, 0x4f, 0x52, 0x6d, 0x5c, 0x5c, 0x61, 0x5b, 0x3f, 0x50, - 0x55, 0x48, 0x47, 0x4e, 0x5f, 0x72, 0x70, 0x20, 0x54, 0x57, 0x50, 0x6c, - 0x67, 0x66, 0x21, 0x7b, 0x3a, 0x4e, 0x55, 0x61, 0x76, 0x6a, 0x47, 0x42, - 0x59, 0x6c, 0x4f, 0x46, 0x20, 0x6a, 0x9a, 0x5c, 0x48, 0x66, 0x49, 0x73, - 0x4a, 0x57, 0x64, 0x5f, 0x58, 0x5b, 0x57, 0x59, 0x4f, 0x58, 0x4b, 0x63, - 0x75, 0x57, 0x5c, 0x58, 0x4d, 0x57, 0x58, 0x54, 0x58, 0x6c, 0x5a, 0x56, - 0x5c, 0x71, 0x52, 0x5a, 0x5c, 0x5d, 0x55, 0x5e, 0x58, 0x53, 0x33, 0x50, - 0x5d, 0x56, 0x57, 0x27, 0x4a, 0x59, 0x60, 0x5d, 0x57, 0x5b, 0x57, 0x58, - 0x46, 0x59, 0x48, 0x60, 0x77, 0x59, 0x5e, 0x58, 0x4a, 0x5c, 0x5c, 0x51, - 0x57, 0x2e, 0x59, 0x57, 0x5b, 0x71, 0x58, 0x5a, 0x57, 0x5e, 0x56, 0x57, - 0x57, 0x51, 0x34, 0x4d, 0x5a, 0x4c, 0x57, 0x22, 0x4f, 0x55, 0x5c, 0x61, - 0x5b, 0x59, 0x54, 0x59, 0x48, 0x5c, 0x48, 0x62, 0x58, 0x59, 0x5d, 0x56, - 0x49, 0x5a, 0x5b, 0x52, 0x57, 0x2d, 0x5a, 0x57, 0x5d, 0x73, 0x56, 0x5a, - 0x5a, 0x60, 0x56, 0x5f, 0x57, 0x4d, 0x36, 0x44, 0x5c, 0x3a, 0x58, 0x19, - 0x50, 0x55, 0x60, 0x60, 0x5b, 0x50, 0x58, 0x57, 0x47, 0x5a, 0x47, 0x64, - 0x50, 0x5c, 0x5c, 0x5a, 0x49, 0x55, 0x62, 0x51, 0x55, 0x30, 0x5c, 0x56, - 0x5c, 0x69, 0x53, 0x5a, 0x5c, 0x5d, 0x53, 0x60, 0x57, 0x4d, 0x38, 0x50, - 0x5a, 0x41, 0x59, 0x2e, 0x50, 0x55, 0x60, 0x63, 0x5f, 0x52, 0x5a, 0x56, - 0x44, 0x59, 0x47, 0x66, 0x4f, 0x5b, 0x5c, 0x5b, 0x49, 0x57, 0x66, 0x4e, - 0x56, 0x31, 0x5b, 0x58, 0x5c, 0x63, 0x56, 0x5b, 0x5b, 0x5a, 0x53, 0x61, - 0x55, 0x4c, 0x38, 0x4f, 0x5b, 0x41, 0x5a, 0x2f, 0x52, 0x53, 0x64, 0x63, - 0x60, 0x53, 0x59, 0x57, 0x45, 0x57, 0x47, 0x66, 0x4f, 0x5a, 0x5c, 0x58, - 0x49, 0x54, 0x68, 0x51, 0x58, 0x31, 0x56, 0x58, 0x5c, 0x62, 0x55, 0x58, - 0x5c, 0x58, 0x52, 0x63, 0x53, 0x4d, 0x38, 0x4f, 0x5b, 0x42, 0x5a, 0x2f, - 0x53, 0x55, 0x63, 0x65, 0x5e, 0x55, 0x58, 0x55, 0x53, 0x54, 0x45, 0x5f, - 0x4f, 0x57, 0x5b, 0x5a, 0x47, 0x54, 0x65, 0x53, 0x56, 0x30, 0x57, 0x5a, - 0x5b, 0x64, 0x53, 0x58, 0x5c, 0x57, 0x53, 0x65, 0x54, 0x48, 0x38, 0x52, - 0x5c, 0x44, 0x5a, 0x2e, 0x56, 0x54, 0x65, 0x65, 0x58, 0x58, 0x31, 0x55, - 0x60, 0x51, 0x45, 0x5f, 0x34, 0x5a, 0x67, 0x57, 0x46, 0x56, 0x62, 0x56, - 0x57, 0x31, 0x53, 0x5e, 0x53, 0x5d, 0x51, 0x5d, 0x58, 0x60, 0x53, 0x5f, - 0x56, 0x58, 0x39, 0x44, 0x5b, 0x47, 0x4f, 0x22, 0x58, 0x52, 0x66, 0x5b, - 0x57, 0x5d, 0x4f, 0x55, 0x60, 0x55, 0x45, 0x56, 0x34, 0x5c, 0x67, 0x58, - 0x46, 0x55, 0x5e, 0x55, 0x52, 0x31, 0x56, 0x64, 0x59, 0x55, 0x53, 0x5d, - 0x52, 0x4d, 0x57, 0x5c, 0x55, 0x62, 0x3a, 0x5a, 0x60, 0x46, 0x53, 0x31, - 0x59, 0x41, 0x57, 0x57, 0x54, 0x4d, 0x58, 0x52, 0x5e, 0x4a, 0x44, 0x62, - 0x32, 0x55, 0x6e, 0x43, 0x46, 0x56, 0x50, 0x5e, 0x4a, 0x2b, 0x51, 0x62, - 0x4f, 0x67, 0x49, 0x50, 0x52, 0x4d, 0x53, 0x4f, 0x4c, 0x72, 0x38, 0x43, - 0x5f, 0x3f, 0x55, 0x2f, 0x7e, 0x52, 0x46, 0x4d, 0x51, 0x61, 0x5c, 0x5b, - 0x64, 0x4a, 0x74, 0x2c, 0x4f, 0x40, 0x5a, 0x82, 0x5d, 0x48, 0x42, 0x4b, - 0x60, 0x70, 0x52, 0x47, 0x4d, 0x43, 0x64, 0x81, 0x52, 0x5d, 0x61, 0x5b, - 0x5f, 0x4e, 0x8f, 0x7c, 0x4f, 0x65, 0x4f, 0x75, 0x5b, 0x3c, 0x71, 0x5c, - 0x60, 0x56, 0x64, 0x69, 0x4b, 0x50, 0x44, 0x63, 0x33, 0x54, 0x71, 0x60, - 0x44, 0x5a, 0x50, 0x59, 0x43, 0x25, 0x46, 0x5c, 0x59, 0x72, 0x7d, 0x53, - 0x51, 0x46, 0x51, 0x59, 0x64, 0x4c, 0x40, 0x5a, 0x77, 0x47, 0x64, 0x5e, - 0x8d, 0x59, 0x5d, 0x51, 0x52, 0x60, 0x5d, 0x5a, 0x5b, 0x6a, 0x47, 0x25, - 0x51, 0x49, 0x5b, 0x4a, 0x68, 0x4d, 0x56, 0x52, 0x5e, 0x6e, 0x50, 0x49, - 0x63, 0x6f, 0x5d, 0x4b, 0x57, 0x5d, 0x5f, 0x33, 0x61, 0x48, 0x6f, 0x8a, - 0x53, 0x69, 0x56, 0x76, 0x3d, 0x59, 0x5b, 0x52, 0x55, 0x63, 0x5f, 0x54, - 0x5a, 0x6c, 0x70, 0x67, 0x59, 0x4f, 0x5e, 0x57, 0x4e, 0x4e, 0x70, 0x59, - 0x5d, 0x6c, 0x56, 0x4b, 0x53, 0x55, 0x5b, 0x53, 0x57, 0x56, 0x5c, 0x64, - 0x5c, 0x48, 0x70, 0x40, 0x53, 0x67, 0x58, 0x76, 0x40, 0x59, 0x5d, 0x52, - 0x57, 0x63, 0x60, 0x54, 0x5c, 0x63, 0x53, 0x6a, 0x4b, 0x53, 0x5c, 0x58, - 0x60, 0x52, 0x6f, 0x5e, 0x5e, 0x6c, 0x59, 0x4d, 0x58, 0x53, 0x59, 0x55, - 0x5a, 0x55, 0x5d, 0x5f, 0x59, 0x4b, 0x6c, 0x39, 0x56, 0x69, 0x59, 0x76, - 0x4b, 0x58, 0x5d, 0x56, 0x5b, 0x5f, 0x5e, 0x53, 0x60, 0x58, 0x4f, 0x67, - 0x69, 0x58, 0x5a, 0x55, 0x54, 0x55, 0x67, 0x5d, 0x5e, 0x6c, 0x58, 0x50, - 0x5c, 0x40, 0x57, 0x52, 0x5a, 0x55, 0x57, 0x50, 0x57, 0x79, 0x4c, 0x41, - 0x29, 0x68, 0x59, 0x77, 0x4a, 0x58, 0x60, 0x5a, 0x59, 0x5c, 0x5d, 0x54, - 0x5c, 0x58, 0x4d, 0x63, 0x6b, 0x59, 0x5c, 0x57, 0x50, 0x58, 0x62, 0x54, - 0x5b, 0x6b, 0x57, 0x53, 0x59, 0x00, 0x56, 0x56, 0x5d, 0x57, 0x56, 0x5a, - 0x58, 0x75, 0x34, 0x4c, 0x5e, 0x60, 0x58, 0x78, 0x4b, 0x57, 0x62, 0x5c, - 0x58, 0x5c, 0x5c, 0x55, 0x54, 0x5b, 0x4b, 0x61, 0x73, 0x59, 0x5e, 0x56, - 0x4f, 0x5b, 0x61, 0x54, 0x58, 0x6c, 0x57, 0x53, 0x5b, 0x62, 0x54, 0x59, - 0x5f, 0x5c, 0x57, 0x60, 0x58, 0x58, 0x2c, 0x44, 0x5d, 0x5e, 0x56, 0x28, - 0x4d, 0x58, 0x63, 0x5e, 0x58, 0x5a, 0x57, 0x59, 0x54, 0x58, 0x4c, 0x60, - 0x74, 0x59, 0x5c, 0x57, 0x4e, 0x59, 0x5a, 0x55, 0x58, 0x6c, 0x58, 0x55, - 0x5c, 0x6e, 0x54, 0x59, 0x5b, 0x5c, 0x57, 0x5e, 0x57, 0x54, 0x32, 0x4a, - 0x5e, 0x54, 0x55, 0x27, 0x52, 0x5c, 0x5e, 0x56, 0x5a, 0x5b, 0x58, 0x58, - 0x4f, 0x5c, 0x46, 0x5e, 0x54, 0x5a, 0x5c, 0x55, 0x47, 0x50, 0x5d, 0x56, - 0x57, 0x57, 0x5b, 0x5c, 0x5f, 0x5f, 0x58, 0x5f, 0x58, 0x5a, 0x5d, 0x59, - 0x54, 0x5d, 0x51, 0x57, 0x55, 0x54, 0x53, 0x56, 0x55, 0x51, 0x5b, 0x50, - 0x57, 0x5b, 0x58, 0x5a, 0x51, 0x5d, 0x46, 0x5f, 0x58, 0x4d, 0x53, 0x56, - 0x47, 0x4b, 0x5f, 0x57, 0x5a, 0x51, 0x52, 0x45, 0x5d, 0x5e, 0x5b, 0x5f, - 0x59, 0x5b, 0x5a, 0x5e, 0x4f, 0x60, 0x52, 0x5b, 0x59, 0x58, 0x5a, 0x57, - 0x51, 0x4f, 0x5d, 0x60, 0x59, 0x5d, 0x5b, 0x53, 0x50, 0x5b, 0x47, 0x5f, - 0x56, 0x49, 0x62, 0x53, 0x46, 0x4f, 0x6b, 0x55, 0x55, 0x52, 0x4b, 0x49, - 0x5a, 0x5d, 0x55, 0x5c, 0x50, 0x5a, 0x4e, 0x5b, 0x50, 0x5e, 0x52, 0x5d, - 0x57, 0x5a, 0x50, 0x58, 0x54, 0x4f, 0x5f, 0x56, 0x53, 0x59, 0x5a, 0x58, - 0x51, 0x5c, 0x45, 0x5f, 0x55, 0x4b, 0x54, 0x52, 0x48, 0x4c, 0x61, 0x57, - 0x58, 0x51, 0x50, 0x44, 0x5f, 0x5f, 0x59, 0x61, 0x59, 0x5d, 0x5b, 0x5d, - 0x4c, 0x5d, 0x51, 0x5b, 0x58, 0x57, 0x58, 0x55, 0x53, 0x50, 0x60, 0x54, - 0x53, 0x5a, 0x57, 0x58, 0x50, 0x5a, 0x46, 0x5f, 0x55, 0x48, 0x54, 0x52, - 0x47, 0x4d, 0x65, 0x54, 0x56, 0x53, 0x4d, 0x42, 0x61, 0x5e, 0x58, 0x61, - 0x58, 0x5b, 0x5c, 0x5f, 0x50, 0x5e, 0x51, 0x5b, 0x56, 0x5b, 0x5a, 0x56, - 0x53, 0x4b, 0x5d, 0x58, 0x54, 0x59, 0x58, 0x58, 0x50, 0x59, 0x46, 0x5f, - 0x56, 0x43, 0x5b, 0x52, 0x48, 0x4d, 0x64, 0x55, 0x56, 0x50, 0x55, 0x41, - 0x5e, 0x60, 0x58, 0x5e, 0x58, 0x5c, 0x5a, 0x5e, 0x52, 0x5d, 0x52, 0x5c, - 0x58, 0x5a, 0x54, 0x56, 0x53, 0x4c, 0x5c, 0x59, 0x53, 0x5b, 0x58, 0x56, - 0x50, 0x59, 0x45, 0x5e, 0x51, 0x43, 0x5e, 0x51, 0x48, 0x4d, 0x64, 0x55, - 0x58, 0x51, 0x50, 0x43, 0x60, 0x5e, 0x57, 0x5d, 0x56, 0x5b, 0x59, 0x5d, - 0x51, 0x5e, 0x52, 0x59, 0x58, 0x5a, 0x55, 0x58, 0x51, 0x4c, 0x5e, 0x5a, - 0x56, 0x59, 0x57, 0x57, 0x51, 0x5b, 0x45, 0x5f, 0x55, 0x44, 0x61, 0x53, - 0x47, 0x4f, 0x63, 0x56, 0x58, 0x50, 0x4d, 0x45, 0x5d, 0x5d, 0x58, 0x60, - 0x57, 0x5a, 0x56, 0x5d, 0x50, 0x5c, 0x52, 0x59, 0x59, 0x59, 0x54, 0x5a, - 0x52, 0x4b, 0x5d, 0x5b, 0x53, 0x5d, 0x59, 0x52, 0x50, 0x5a, 0x47, 0x5b, - 0x54, 0x44, 0x62, 0x51, 0x48, 0x4f, 0x63, 0x56, 0x58, 0x51, 0x4b, 0x48, - 0x5e, 0x5b, 0x58, 0x5b, 0x56, 0x59, 0x55, 0x5b, 0x51, 0x5d, 0x52, 0x5b, - 0x5a, 0x5a, 0x51, 0x58, 0x56, 0x4b, 0x5c, 0x5e, 0x55, 0x5c, 0x5b, 0x51, - 0x4f, 0x5d, 0x46, 0x5a, 0x56, 0x47, 0x62, 0x53, 0x47, 0x4e, 0x65, 0x57, - 0x57, 0x50, 0x4b, 0x43, 0x5d, 0x5d, 0x58, 0x5b, 0x58, 0x59, 0x56, 0x5b, - 0x52, 0x5e, 0x52, 0x59, 0x5a, 0x59, 0x51, 0x58, 0x56, 0x4c, 0x5d, 0x5e, - 0x55, 0x5d, 0x5b, 0x4e, 0x4e, 0x5b, 0x47, 0x5d, 0x55, 0x47, 0x61, 0x53, - 0x45, 0x4e, 0x67, 0x57, 0x58, 0x50, 0x4a, 0x44, 0x5d, 0x5d, 0x57, 0x5c, - 0x54, 0x5a, 0x55, 0x5a, 0x50, 0x5c, 0x52, 0x59, 0x5a, 0x5a, 0x50, 0x59, - 0x52, 0x58, 0x39, 0x63, 0x54, 0x56, 0x36, 0x5f, 0x58, 0x44, 0x58, 0x53, - 0x5c, 0x50, 0x52, 0x4d, 0x55, 0x5f, 0x64, 0x61, 0x4d, 0x69, 0x52, 0x4f, - 0x45, 0x3e, 0x3a, 0x3e, 0x68, 0x5e, 0x4c, 0x60, 0x6d, 0x3d, 0x75, 0x4f, - 0x61, 0x5b, 0x63, 0x57, 0x64, 0x38, 0x6a, 0x45, 0x4a, 0x61, 0x47, 0x54, - 0x4c, 0x2a, 0x57, 0x7d, 0x61, 0x45, 0x56, 0x37, 0x55, 0x3c, 0x4b, 0x44, - 0x59, 0x78, 0x64, 0x48, 0x10, 0x6a, 0x8f, 0x4f, 0x53, 0x58, 0x4a, 0x60, - 0x65, 0x6c, 0x8e, 0x44, 0x4d, 0x51, 0x58, 0x49, 0x56, 0x58, 0x51, 0x4e, - 0x51, 0x57, 0x6b, 0x51, 0x5b, 0x59, 0x59, 0x57, 0x56, 0x47, 0x60, 0x59, - 0x59, 0x5b, 0x56, 0x5b, 0x56, 0x59, 0x57, 0x46, 0x50, 0x57, 0x55, 0x5a, - 0x58, 0x50, 0x5e, 0x56, 0x5a, 0x5a, 0x58, 0x57, 0x59, 0x56, 0x2b, 0x5d, -}}; - -const union { - uint8_t bytes[4]; - float values[1]; -} dnn_hiddenlayer_0_weights__1__cf__1_quantized_min = {{ - 0xc0, 0xfa, 0x78, 0xc0, -}}; const int32_t dnn_logits_weights__3__cf__3_shape[2] = {DNN_BIASES_SIZE, 1}; const union { uint8_t bytes[2 * 2 * DNN_BIASES_SIZE]; float values[DNN_BIASES_SIZE]; } dnn_logits_weights__3__cf__3 = {{ - 0x51, 0xc5, 0x8b, 0xc0, 0x11, 0x4c, 0xa9, 0xbf, 0x72, 0x97, 0x02, 0x3f, - 0x37, 0x6a, 0xe7, 0xbe, 0x9e, 0xa8, 0xf0, 0xbf, 0x2e, 0x77, 0xe2, 0x3e, - 0xf3, 0xcc, 0x2a, 0x3f, 0x5c, 0x60, 0x38, 0xbf, 0x5a, 0x26, 0x9e, 0xbf, - 0x7e, 0xf0, 0xe0, 0x3e, 0xf6, 0xcb, 0xa4, 0xc1, 0xc8, 0xb6, 0xcd, 0x3e, - 0xe9, 0x5a, 0xa8, 0xc0, 0xbd, 0xbe, 0x3b, 0xc0, 0xed, 0xe4, 0xf3, 0x3e, - 0xe3, 0xf8, 0x42, 0x3f, 0xf5, 0xc6, 0xa2, 0xc1, 0x88, 0xd3, 0xe3, 0xbf, - 0xbb, 0xd9, 0x00, 0x3f, 0x11, 0x0a, 0x13, 0x40, 0x5e, 0xac, 0x2c, 0x3f, - 0x06, 0x4c, 0x2b, 0xc0, 0x8d, 0x3e, 0xbc, 0xbf, 0xe6, 0xbb, 0xbb, 0x3f, - 0x0c, 0xc2, 0x02, 0x3f, 0x36, 0xa4, 0x0b, 0x3f, 0xd4, 0xb6, 0x46, 0x3f, - 0x65, 0x69, 0x1a, 0x3f, 0xc9, 0x38, 0x07, 0x3f, 0x0f, 0x34, 0x0c, 0xbf, - 0x34, 0x90, 0x2b, 0x3f, 0x32, 0x86, 0xbe, 0x3e, 0xa8, 0x08, 0xf6, 0x3f, - 0xa6, 0xe5, 0x07, 0x3f, 0x07, 0xa2, 0xd5, 0xc0, 0xbe, 0x38, 0x0b, 0x3f, - 0x97, 0x9d, 0x7d, 0x3f, 0x26, 0xe1, 0x3f, 0xbf, 0x3b, 0x1c, 0x68, 0xbf, - 0x8d, 0x90, 0x96, 0xbf, + 0x69, 0x82, 0x30, 0x3f, 0x64, 0x09, 0x1b, 0x3f, 0xc0, 0x71, 0x85, 0xbf, + 0xdb, 0xba, 0x8b, 0xbe, 0xcf, 0x8c, 0x6f, 0xc0, 0x6b, 0xcb, 0x2b, 0x3f, + 0xa5, 0xb5, 0x3f, 0x40, 0x1f, 0x85, 0xb0, 0xbf, 0xe6, 0xa4, 0x5e, 0x3f, + 0x32, 0x13, 0x0f, 0x3f, 0x03, 0x4f, 0xdb, 0x3f, 0x63, 0x24, 0x21, 0x3f, + 0xdb, 0xaa, 0xb1, 0xc1, 0x81, 0x1f, 0xd0, 0x3f, 0x3f, 0x2f, 0x00, 0xc0, + 0x01, 0x70, 0x70, 0xbe, 0xdd, 0x4e, 0xe8, 0xbd, 0x67, 0x58, 0xe8, 0x3f, + 0x24, 0xb1, 0x76, 0xbf, 0xc2, 0x5e, 0x0a, 0x3f, 0x4f, 0x11, 0x24, 0xc0, + 0x14, 0x76, 0x38, 0xbe, 0x3d, 0xe9, 0xd5, 0xbf, 0xaf, 0x94, 0xac, 0x3f, + 0xef, 0xa5, 0x5c, 0xc0, 0xe8, 0xa2, 0x38, 0x3f, 0x2b, 0xfe, 0xeb, 0xbf, + 0x69, 0x1f, 0x87, 0x3f, 0x56, 0x94, 0xae, 0xbf, 0x2e, 0xce, 0x07, 0x3f, + 0xb0, 0x2b, 0x3a, 0x40, 0xa6, 0xe7, 0xba, 0xbf, 0x7b, 0x18, 0xde, 0x3f, + 0x0e, 0x9e, 0x0e, 0x3f, 0xf5, 0x5a, 0x89, 0xbf, 0x7a, 0x2f, 0x0e, 0xbe, + 0x79, 0x40, 0x0d, 0xc0, 0xa9, 0xb3, 0x86, 0xbe, 0x6d, 0x5a, 0x01, 0x40, + 0x4c, 0xbd, 0x0d, 0x3f, }}; +const int32_t dnn_hiddenlayer_0_weights__1__cf__1_shape[2] = {FEATURES_SIZE, + DNN_BIASES_SIZE}; +const union { + uint8_t bytes[4 * DNN_WEIGHTS_SIZE]; + float values[DNN_WEIGHTS_SIZE]; +} dnn_hiddenlayer_0_weights__1__cf__1 = {{ + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0x08, 0x07, 0x04, 0x3f, + 0x46, 0x96, 0x69, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x38, 0xbe, 0xf3, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x88, 0x1e, 0xcb, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0x6c, 0x46, 0x55, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, + 0x80, 0x1e, 0xcb, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x30, 0xbe, 0xf3, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, 0xa7, 0xce, 0xb6, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0xf8, 0x2e, 0x0e, 0x3f, 0xfd, 0x1a, 0x89, 0xbf, 0xc8, 0x7e, 0xa2, 0xbe, + 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0x30, 0xbe, 0xf3, 0xbe, 0xfd, 0x1a, 0x89, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xd0, 0x7e, 0x22, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, 0x98, 0xf6, 0x40, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x08, 0x07, 0x04, 0x3f, + 0x04, 0x07, 0x04, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, 0xf6, 0x2e, 0x8e, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1e, 0x4b, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0x22, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x5a, 0x6e, 0x5f, 0xbf, 0xe4, 0x56, 0x18, 0x3f, + 0xd0, 0x7e, 0x22, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, 0x38, 0xbe, 0xf3, 0x3e, + 0x9d, 0xe2, 0xbb, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0x08, 0x07, 0x84, 0x3f, + 0x51, 0x82, 0xe4, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0xfe, 0x1a, 0x89, 0x3f, + 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0x4b, 0xbf, 0x40, 0xbe, 0x73, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xf8, 0x2e, 0x0e, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0x8a, 0x0a, 0xc6, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0x34, 0xbe, 0x73, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xcd, 0x7e, 0xa2, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x06, 0x07, 0x84, 0xbf, 0xa6, 0xce, 0x36, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0x80, 0x1e, 0x4b, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0xc6, 0x92, 0xa7, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x34, 0xbe, 0x73, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xba, 0xa6, 0x2c, 0xbf, 0x30, 0xbe, 0x73, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, 0xcc, 0x7e, 0x22, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, + 0x08, 0x07, 0x04, 0x3f, 0x92, 0xf6, 0x40, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x04, 0x07, 0x04, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0xa6, 0xce, 0x36, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x88, 0x1e, 0xcb, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa6, 0xce, 0x36, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbf, 0xcc, 0x7e, 0x22, 0xbf, + 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0x92, 0xf6, 0x40, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0x92, 0xf6, 0x40, 0xbf, 0xd0, 0x7e, 0x22, 0x3f, 0xa6, 0xce, 0x36, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xf3, 0x2e, 0x8e, 0xbf, + 0xcc, 0x7e, 0x22, 0xbf, 0xa6, 0xce, 0x36, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0x36, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, + 0x5c, 0x6e, 0x5f, 0x3f, 0xec, 0x42, 0x93, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, + 0xf3, 0x2e, 0x8e, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf8, 0x2e, 0x8e, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0x30, 0xbe, 0xf3, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x46, 0xd5, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xe6, 0x7d, 0xbf, 0xbc, 0xa6, 0x2c, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x98, 0xf6, 0x40, 0x3f, 0xfd, 0x1a, 0x89, 0xbf, 0xf3, 0x2e, 0x8e, 0xbf, + 0x5a, 0x6e, 0x5f, 0xbf, 0xa6, 0xce, 0x36, 0xbf, 0xba, 0xa6, 0xac, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0xa2, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0xa8, 0xce, 0xb6, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x92, 0xf6, 0x40, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x96, 0x69, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x92, 0xf6, 0x40, 0xbf, 0xf3, 0x2e, 0x8e, 0xbf, 0x6c, 0x46, 0x55, 0xbf, + 0xe4, 0x56, 0x18, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0xd0, 0x7e, 0x22, 0x3f, 0xa6, 0xce, 0x36, 0xbf, + 0xa6, 0xce, 0x36, 0xbf, 0xa6, 0xce, 0x36, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xe6, 0x7d, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0x38, 0xbe, 0xf3, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3f, + 0xba, 0xa6, 0x2c, 0xbf, 0x40, 0xbe, 0x73, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0xe0, 0x56, 0x18, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x98, 0xf6, 0x40, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xa6, 0xce, 0x36, 0xbf, 0x08, 0x07, 0x04, 0x3f, + 0x60, 0x6e, 0xdf, 0x3e, 0xe0, 0x56, 0x18, 0xbf, 0x30, 0xbe, 0xf3, 0xbe, + 0xd0, 0x7e, 0x22, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, 0x48, 0x96, 0x69, 0x3f, + 0x08, 0x07, 0x04, 0x3f, 0xce, 0x7e, 0xa2, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0x22, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0x36, 0x3f, + 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x88, 0x1e, 0xcb, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0x98, 0xf6, 0x40, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0xa2, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x70, 0x46, 0x55, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xcc, 0x7e, 0x22, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x48, 0x96, 0x69, 0x3f, + 0x04, 0x07, 0x04, 0xbf, 0xd0, 0x7e, 0xa2, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0xbc, 0xa6, 0x2c, 0x3f, 0xe0, 0x56, 0x98, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, 0x84, 0x1e, 0x4b, 0x3f, + 0xec, 0x42, 0x93, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf8, 0x2e, 0x8e, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x84, 0x1e, 0x4b, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0x80, 0x1e, 0x4b, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbf, 0xc8, 0x7e, 0xa2, 0xbe, + 0xa6, 0xce, 0x36, 0xbf, 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, 0x6c, 0x46, 0x55, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x92, 0xf6, 0x40, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, + 0x88, 0x1e, 0xcb, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x38, 0xbe, 0xf3, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0x73, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, + 0xe0, 0x56, 0x18, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3f, + 0x06, 0x07, 0x84, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x80, 0x1e, 0x4b, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x5a, 0x6e, 0xdf, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x98, 0xf6, 0x40, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, + 0xd0, 0x7e, 0x22, 0x3f, 0xcd, 0x7e, 0xa2, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, + 0x70, 0x46, 0x55, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x56, 0x18, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, 0x70, 0x46, 0x55, 0x3f, + 0x84, 0x1e, 0x4b, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x5a, 0x6e, 0x5f, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x08, 0x07, 0x84, 0x3f, + 0x30, 0xbe, 0x73, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xbc, 0xa6, 0x2c, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x08, 0x07, 0x04, 0x3f, + 0x80, 0x1e, 0x4b, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0xfe, 0x1a, 0x89, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xcc, 0x7e, 0x22, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xec, 0x42, 0x93, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0xd0, 0x7e, 0x22, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0xf6, 0x2e, 0x8e, 0x3f, + 0x78, 0x32, 0xd0, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xcc, 0x7e, 0x22, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x24, 0xe6, 0x7d, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0x36, 0x3f, 0x30, 0xbe, 0xf3, 0xbe, + 0x84, 0x1e, 0x4b, 0x3f, 0x06, 0x07, 0x84, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x46, 0x96, 0x69, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x94, 0xf6, 0xc0, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x58, 0x6e, 0xdf, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0xce, 0x7e, 0xa2, 0x3f, + 0x94, 0xf6, 0xc0, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x5c, 0x6e, 0x5f, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0x70, 0x46, 0x55, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xba, 0xa6, 0x2c, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0xa8, 0xce, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, + 0x5a, 0x6e, 0x5f, 0xbf, 0x58, 0x6e, 0xdf, 0xbe, 0x38, 0xbe, 0x73, 0x3f, + 0xa6, 0xce, 0x36, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0xa6, 0xce, 0x36, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xf6, 0x2e, 0x8e, 0x3f, + 0x84, 0x1e, 0xcb, 0x3f, 0xd7, 0x6a, 0x9d, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, + 0xe2, 0x56, 0x98, 0x3f, 0x5a, 0x6e, 0x5f, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, + 0xd0, 0x7e, 0x22, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0x34, 0xbe, 0xf3, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, + 0xe4, 0x56, 0x18, 0x3f, 0x70, 0x46, 0x55, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x5c, 0x6e, 0x5f, 0x3f, + 0x46, 0x96, 0x69, 0xbf, 0xd0, 0x7e, 0x22, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x5a, 0x6e, 0x5f, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, + 0xbc, 0xa6, 0x2c, 0x3f, 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xcc, 0x7e, 0x22, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0x5c, 0x6e, 0x5f, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x38, 0xbe, 0x73, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0x88, 0x1e, 0xcb, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0xba, 0xa6, 0x2c, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xa6, 0xce, 0x36, 0xbf, + 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, + 0x92, 0xf6, 0x40, 0xbf, 0x30, 0xbe, 0xf3, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0x04, 0x07, 0x04, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xf4, 0x2e, 0x0e, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0xa8, 0xce, 0xb6, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x04, 0x07, 0x04, 0xbf, 0x30, 0xbe, 0xf3, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xf4, 0x2e, 0x0e, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xa6, 0xce, 0x36, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xc8, 0x7e, 0xa2, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, + 0x98, 0xf6, 0x40, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0x80, 0x1e, 0x4b, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x80, 0x1e, 0xcb, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0xa8, 0xce, 0xb6, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x58, 0x6e, 0xdf, 0xbe, + 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x7e, 0xa2, 0xbe, + 0xba, 0xa6, 0x2c, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x6e, 0xdf, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xf3, 0x3e, 0xd0, 0x7e, 0x22, 0x3f, + 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, + 0x04, 0x07, 0x04, 0xbf, 0x70, 0x46, 0x55, 0x3f, 0xbc, 0xa6, 0x2c, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x56, 0x18, 0xbf, 0x58, 0x6e, 0xdf, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0xe4, 0x56, 0x18, 0x3f, 0x08, 0x07, 0x04, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0xe0, 0x56, 0x18, 0xbf, 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0x98, 0xf6, 0x40, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, + 0xa8, 0xce, 0xb6, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xe4, 0x56, 0x18, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xe4, 0x56, 0x18, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xf8, 0x2e, 0x0e, 0x3f, 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x84, 0x1e, 0x4b, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x46, 0x96, 0x69, 0xbf, + 0x38, 0xbe, 0xf3, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0xba, 0xa6, 0x2c, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf8, 0x2e, 0x8e, 0x3e, 0xfd, 0x1a, 0x89, 0xbf, 0x04, 0x07, 0x04, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0x84, 0x1e, 0x4b, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xfd, 0x1a, 0x89, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf4, 0x2e, 0x0e, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0x04, 0x07, 0x04, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xcc, 0x7e, 0x22, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xba, 0xa6, 0x2c, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x04, 0x07, 0x04, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xc8, 0x7e, 0xa2, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x04, 0x07, 0x04, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x30, 0xbe, 0xf3, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa6, 0xce, 0x36, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x04, 0x07, 0x04, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0xd0, 0x7e, 0x22, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0xbe, 0xf3, 0x3e, 0xa8, 0xce, 0x36, 0x3f, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbf, + 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0xa2, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0x4b, 0xbf, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x04, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xa8, 0xce, 0xb6, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, + 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xcc, 0x7e, 0x22, 0xbf, + 0x30, 0xbe, 0xf3, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xf4, 0x2e, 0x0e, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x60, 0x6e, 0xdf, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xe6, 0x7d, 0xbf, 0x40, 0xbe, 0x73, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x04, 0x07, 0x04, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x2e, 0x8e, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0xe0, 0x56, 0x18, 0xbf, + 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x06, 0x07, 0x84, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xe0, 0x56, 0x18, 0xbf, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x92, 0xf6, 0x40, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xbe, 0xf3, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xc8, 0x7e, 0xa2, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xe4, 0x56, 0x18, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0x8c, 0x0a, 0xc6, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0xba, 0xa6, 0xac, 0xbf, 0xfd, 0x1a, 0x89, 0xbf, + 0x77, 0x32, 0xd0, 0xbf, 0x30, 0xbe, 0x73, 0xbe, 0x5a, 0x6e, 0x5f, 0xbf, + 0x30, 0xbe, 0x73, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, + 0x3c, 0xef, 0xef, 0x40, 0x58, 0x6e, 0xdf, 0xbe, 0x34, 0xbe, 0x73, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xe4, 0x56, 0x18, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0x06, 0x07, 0x84, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, + 0x51, 0x82, 0xe4, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x04, 0x07, 0x04, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, + 0xf3, 0x2e, 0x8e, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, 0xc4, 0x92, 0x27, 0xc0, + 0x30, 0xbe, 0xf3, 0xbe, 0xa6, 0xce, 0x36, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xec, 0x42, 0x13, 0x40, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe4, 0x56, 0x18, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xcc, 0x7e, 0x22, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x04, 0x07, 0x04, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x04, 0x07, 0x04, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xe6, 0x7d, 0xbf, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf4, 0x2e, 0x0e, 0xbf, 0x58, 0x6e, 0xdf, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1e, 0x4b, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x34, 0xbe, 0x73, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x6e, 0x5f, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x6e, 0xdf, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x8e, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x1e, 0x4b, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x96, 0x69, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0xa8, 0xce, 0xb6, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x56, 0x18, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0xcc, 0x7e, 0x22, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xe4, 0x56, 0x18, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, 0x40, 0xbe, 0x73, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, + 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x04, 0x07, 0x04, 0xbf, 0xd0, 0x7e, 0xa2, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x92, 0xf6, 0x40, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, + 0xa8, 0xce, 0xb6, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x08, 0x07, 0x04, 0x3f, 0xfd, 0x1a, 0x89, 0xbf, 0xbc, 0xa6, 0x2c, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x0e, 0x3f, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x98, 0xf6, 0x40, 0x3f, + 0xa6, 0xce, 0x36, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xa8, 0xce, 0x36, 0x3f, 0xcd, 0x7e, 0xa2, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0x6e, 0x46, 0xd5, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0x70, 0x46, 0x55, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0x60, 0x6e, 0xdf, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xa6, 0xce, 0x36, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0x04, 0x07, 0x04, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x92, 0xf6, 0x40, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0x22, 0x3e, 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xc8, 0x7e, 0xa2, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0x84, 0x1e, 0x4b, 0x3f, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0x60, 0x6e, 0xdf, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x7e, 0xa2, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0x36, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe2, 0x56, 0x98, 0x3f, 0x5a, 0x6e, 0x5f, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, + 0xba, 0xa6, 0x2c, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0x92, 0xf6, 0x40, 0xbf, 0xd0, 0x7e, 0xa2, 0x3e, 0x46, 0x96, 0x69, 0xbf, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0x5a, 0x6e, 0x5f, 0xbf, + 0x08, 0x07, 0x04, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, + 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xcd, 0x7e, 0xa2, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0x34, 0xbe, 0x73, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0x80, 0x1e, 0xcb, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x04, 0x07, 0x04, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xe4, 0x56, 0x18, 0x3f, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0xa6, 0xce, 0x36, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0x04, 0x07, 0x04, 0xbf, 0x40, 0xbe, 0x73, 0x3e, 0x92, 0xf6, 0x40, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, + 0x88, 0x1e, 0xcb, 0x3e, 0x6c, 0x46, 0x55, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xb0, 0xba, 0xb1, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x92, 0xf6, 0x40, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0x40, 0xbe, 0x73, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0x5c, 0x6e, 0x5f, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, + 0x06, 0x07, 0x84, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0x30, 0xbe, 0xf3, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x88, 0x1e, 0xcb, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x92, 0xf6, 0x40, 0xbf, 0xa8, 0xce, 0xb6, 0x3e, + 0xb0, 0xba, 0xb1, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xa8, 0xce, 0xb6, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x56, 0x18, 0xbf, 0xe0, 0x56, 0x18, 0xbf, + 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xe6, 0x7d, 0xbf, + 0xd0, 0x7e, 0x22, 0x3f, 0xc6, 0x92, 0xa7, 0x3f, 0x92, 0xf6, 0x40, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0x84, 0x1e, 0x4b, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0x06, 0x07, 0x84, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, 0xa6, 0xce, 0x36, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x92, 0xf6, 0x40, 0xbf, + 0xd0, 0x7e, 0x22, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x77, 0x32, 0xd0, 0xbf, + 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, + 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xbe, 0xf3, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x92, 0xf6, 0x40, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0x38, 0xbe, 0xf3, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, + 0xf8, 0x2e, 0x0e, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0x6c, 0x46, 0x55, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x92, 0xf6, 0x40, 0xbf, 0x30, 0xbe, 0x73, 0xbe, + 0x08, 0x07, 0x04, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0x58, 0x6e, 0xdf, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0x84, 0x1e, 0x4b, 0x3f, 0x30, 0xbe, 0x73, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x2e, 0x8e, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xc8, 0x7e, 0xa2, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0x38, 0xbe, 0xf3, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0xe4, 0x56, 0x18, 0x3f, + 0xf0, 0x2e, 0x8e, 0xbe, 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x5c, 0x6e, 0x5f, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x58, 0x6e, 0xdf, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xa6, 0xce, 0x36, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xa8, 0xce, 0xb6, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0x56, 0x18, 0x3f, 0x58, 0x6e, 0xdf, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0xf4, 0x2e, 0x0e, 0xbf, 0x98, 0xf6, 0x40, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x08, 0x07, 0x04, 0x3f, + 0xd0, 0x7e, 0xa2, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, + 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xa6, 0xce, 0x36, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x07, 0x04, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x56, 0x18, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, + 0x60, 0x6e, 0xdf, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0xd0, 0x7e, 0x22, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0x34, 0xbe, 0x73, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xa6, 0xce, 0x36, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0x88, 0x1e, 0xcb, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x38, 0xbe, 0xf3, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0x04, 0x07, 0x04, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, 0xd0, 0x7e, 0xa2, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x56, 0x18, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x94, 0xf6, 0xc0, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0x73, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, + 0xa8, 0xce, 0xb6, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x56, 0x18, 0xbf, 0xf8, 0x2e, 0x0e, 0x3f, + 0x88, 0x1e, 0xcb, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x04, 0x07, 0x04, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0xf6, 0x2e, 0x8e, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0xa8, 0xce, 0xb6, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x04, 0x07, 0x04, 0xbf, 0xd0, 0x7e, 0x22, 0x3f, + 0xf8, 0x2e, 0x0e, 0x3f, 0x20, 0xe6, 0x7d, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf3, 0x2e, 0x8e, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0x04, 0x07, 0x04, 0xbf, 0x48, 0x96, 0x69, 0x3f, + 0x80, 0x1e, 0xcb, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x38, 0xbe, 0xf3, 0x3e, 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x06, 0x07, 0x84, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xe6, 0x7d, 0xbf, + 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x84, 0x1e, 0x4b, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xa8, 0xce, 0x36, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe4, 0x56, 0x18, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xbc, 0xa6, 0x2c, 0x3f, + 0x08, 0x07, 0x84, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0xbc, 0xa6, 0x2c, 0x3f, 0x84, 0x1e, 0x4b, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, + 0xf4, 0x2e, 0x0e, 0xbf, 0x58, 0x6e, 0xdf, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xec, 0x42, 0x93, 0x3f, + 0xd0, 0x7e, 0x22, 0x3e, 0x48, 0x96, 0x69, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x94, 0xf6, 0xc0, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0x08, 0x07, 0x04, 0x3f, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x98, 0xf6, 0x40, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x84, 0x1e, 0x4b, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xcd, 0x7e, 0xa2, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xce, 0x7e, 0xa2, 0x3f, 0xd0, 0x7e, 0x22, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0x08, 0x07, 0x04, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x98, 0xf6, 0x40, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0x04, 0x07, 0x04, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0x22, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0x30, 0xbe, 0xf3, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0xf3, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x0e, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0x98, 0xf6, 0x40, 0x3f, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0x22, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xa7, 0xce, 0xb6, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xfe, 0x1a, 0x89, 0x3f, + 0xbc, 0xa6, 0x2c, 0x3f, 0xce, 0x7e, 0xa2, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xbc, 0xa6, 0x2c, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0xd7, 0x6a, 0x9d, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0x04, 0x07, 0x04, 0xbf, + 0x80, 0x1e, 0x4b, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0xe4, 0x56, 0x18, 0x3f, + 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x84, 0x1e, 0x4b, 0x3f, 0xba, 0xa6, 0x2c, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, + 0xc8, 0x7e, 0xa2, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x24, 0xe6, 0x7d, 0x3f, 0x08, 0x07, 0x04, 0x3f, 0xa8, 0xce, 0xb6, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x04, 0x07, 0x04, 0xbf, 0x6c, 0x46, 0x55, 0xbf, + 0xa8, 0xce, 0x36, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x34, 0xbe, 0x73, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, + 0x30, 0xbe, 0x73, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0x04, 0x07, 0x04, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xa8, 0xce, 0x36, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0x98, 0xf6, 0x40, 0x3f, 0x84, 0x1e, 0x4b, 0x3f, 0x04, 0x07, 0x04, 0xbf, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0x60, 0x6e, 0xdf, 0x3e, 0x30, 0xbe, 0x73, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3f, 0x40, 0xbe, 0x73, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0xbf, 0xe0, 0x56, 0x18, 0xbf, + 0xcc, 0x7e, 0x22, 0xbf, 0x08, 0x07, 0x04, 0x3f, 0xa8, 0xce, 0xb6, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x92, 0xf6, 0x40, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xbc, 0xa6, 0x2c, 0x3f, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0x36, 0x3f, + 0xfe, 0x1a, 0x89, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x38, 0xbe, 0xf3, 0x3e, 0xa6, 0xce, 0x36, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, + 0xbc, 0xa6, 0x2c, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x84, 0x1e, 0x4b, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x24, 0xe6, 0x7d, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0x70, 0x46, 0x55, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xcc, 0x7e, 0x22, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xcc, 0x7e, 0x22, 0xbf, 0xe0, 0x56, 0x18, 0xbf, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0x30, 0xbe, 0x73, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x2e, 0x8e, 0x3f, + 0x58, 0x6e, 0xdf, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xf3, 0x2e, 0x8e, 0xbf, + 0x58, 0x6e, 0xdf, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0xcc, 0x7e, 0x22, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, 0xe0, 0x56, 0x18, 0xbf, + 0xd0, 0x7e, 0xa2, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x84, 0x1e, 0x4b, 0x3f, + 0xd0, 0x7e, 0x22, 0x3e, 0xcd, 0x7e, 0xa2, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x6c, 0x46, 0x55, 0xbf, + 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x56, 0x18, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, + 0xa8, 0xce, 0x36, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x92, 0xf6, 0x40, 0xbf, + 0xf0, 0x2e, 0x8e, 0xbe, 0xa8, 0xce, 0x36, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, + 0x5a, 0x6e, 0x5f, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0x80, 0x1e, 0x4b, 0xbf, 0xe4, 0x56, 0x18, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xec, 0x42, 0x93, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xbc, 0xa6, 0x2c, 0x3f, 0x40, 0xbe, 0x73, 0x3e, + 0x30, 0xbe, 0xf3, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x30, 0xbe, 0xf3, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0x88, 0x1e, 0xcb, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0x08, 0x07, 0x04, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x7e, 0x22, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0x08, 0x07, 0x84, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0x36, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0x70, 0x46, 0x55, 0x3f, 0x5c, 0x6e, 0x5f, 0x3f, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x08, 0x07, 0x04, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, + 0xbc, 0xa6, 0x2c, 0x3f, 0xa8, 0xce, 0xb6, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0x04, 0x07, 0x04, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0x04, 0x07, 0x04, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe4, 0x56, 0x18, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xcc, 0x7e, 0x22, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x5c, 0x6e, 0x5f, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0xa8, 0xce, 0x36, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, + 0x60, 0x6e, 0xdf, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0x6c, 0x46, 0x55, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0x5a, 0x6e, 0x5f, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xbc, 0xa6, 0x2c, 0x3f, + 0x20, 0xe6, 0x7d, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0xba, 0xa6, 0x2c, 0xbf, 0xd0, 0x7e, 0x22, 0x3f, + 0xe0, 0x56, 0x18, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x5c, 0x6e, 0x5f, 0x3f, + 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, 0xe0, 0x56, 0x18, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x08, 0x07, 0x04, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xcc, 0x7e, 0x22, 0xbf, + 0x04, 0x07, 0x04, 0xbf, 0xc8, 0x7e, 0xa2, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x2e, 0x0e, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x58, 0x6e, 0xdf, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x5c, 0x6e, 0x5f, 0x3f, + 0xd0, 0x7e, 0x22, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3f, + 0x38, 0xbe, 0xf3, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x46, 0x96, 0x69, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x08, 0x07, 0x04, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0xd0, 0x7e, 0x22, 0x3f, 0x92, 0xf6, 0x40, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x08, 0x07, 0x84, 0x3f, + 0x38, 0xbe, 0xf3, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x98, 0xf6, 0x40, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc8, 0x7e, 0xa2, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xe4, 0x56, 0x18, 0x3f, + 0xf8, 0x2e, 0x8e, 0x3e, 0x08, 0x07, 0x04, 0x3f, 0x80, 0x1e, 0xcb, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0xa2, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0x48, 0x96, 0x69, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xcc, 0x7e, 0x22, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0xce, 0xb6, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0xa8, 0xce, 0x36, 0x3f, 0x08, 0x07, 0x04, 0x3f, + 0xec, 0x42, 0x93, 0x3f, 0xce, 0x7e, 0xa2, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xfd, 0x1a, 0x89, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0x5c, 0x6e, 0x5f, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x38, 0xbe, 0xf3, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0xf3, 0x2e, 0x8e, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xe4, 0x56, 0x18, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x56, 0x18, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, + 0xf8, 0x2e, 0x0e, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, 0x98, 0xf6, 0x40, 0x3f, + 0x80, 0x1e, 0xcb, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x46, 0x55, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0xcc, 0x7e, 0x22, 0xbf, 0x58, 0x6e, 0xdf, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0x36, 0x3f, + 0x30, 0xbe, 0x73, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x06, 0x07, 0x84, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0x80, 0x1e, 0x4b, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xc8, 0x7e, 0xa2, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0xa2, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0xce, 0x36, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xbc, 0xa6, 0x2c, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x98, 0xf6, 0x40, 0x3f, 0x40, 0xbe, 0x73, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xbc, 0xa6, 0x2c, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x92, 0xf6, 0x40, 0xbf, 0x58, 0x6e, 0xdf, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x58, 0x6e, 0xdf, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x5c, 0x6e, 0x5f, 0x3f, 0x38, 0xbe, 0x73, 0x3f, + 0xc8, 0x7e, 0xa2, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x0e, 0x3f, + 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1a, 0x89, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x6c, 0x46, 0x55, 0xbf, + 0x80, 0x1e, 0x4b, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0x48, 0x96, 0x69, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x24, 0xe6, 0x7d, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xbc, 0xa6, 0x2c, 0x3f, + 0xa8, 0xce, 0xb6, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xa8, 0xce, 0xb6, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe4, 0x56, 0x18, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x56, 0x18, 0xbf, + 0x80, 0x1e, 0x4b, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x56, 0x18, 0xbf, 0x34, 0xbe, 0x73, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x84, 0x1e, 0x4b, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, + 0xd0, 0x7e, 0x22, 0x3f, 0xa8, 0xce, 0xb6, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x08, 0x07, 0x04, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0xf4, 0x2e, 0x0e, 0xbf, 0xcc, 0x7e, 0x22, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x6e, 0xdf, 0x3e, 0xfd, 0x1a, 0x89, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0xd7, 0x6a, 0x9d, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x88, 0x1e, 0xcb, 0x3e, 0xbc, 0xa6, 0x2c, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xf4, 0x2e, 0x0e, 0xbf, 0xa8, 0xce, 0x36, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0x4b, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0xa6, 0xce, 0x36, 0xbf, + 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xba, 0xa6, 0x2c, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xe4, 0x56, 0x18, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x56, 0x18, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xf3, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x84, 0x1e, 0x4b, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, + 0x24, 0xe6, 0x7d, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0xe2, 0x56, 0x98, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0xcc, 0x7e, 0x22, 0xbf, 0x40, 0xbe, 0x73, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x5a, 0x6e, 0x5f, 0xbf, 0x30, 0xbe, 0x73, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xf3, 0x3e, + 0xe0, 0x56, 0x18, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x56, 0x18, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, + 0xbc, 0xa6, 0x2c, 0x3f, 0x46, 0x96, 0x69, 0xbf, 0x30, 0xbe, 0xf3, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0xa6, 0xce, 0x36, 0xbf, 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x08, 0x07, 0x84, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x38, 0xbe, 0x73, 0x3f, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xf3, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x70, 0x46, 0x55, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0x46, 0x96, 0x69, 0xbf, + 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x48, 0x96, 0x69, 0x3f, + 0x98, 0xf6, 0x40, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0xbc, 0xa6, 0x2c, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0xcb, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xd0, 0x7e, 0xa2, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x04, 0x07, 0x04, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x0e, 0x3f, + 0xa8, 0xce, 0x36, 0x3f, 0x98, 0xf6, 0x40, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x78, 0x32, 0xd0, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, + 0x04, 0x07, 0x04, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0x24, 0xe6, 0x7d, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1e, 0x4b, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x48, 0x96, 0x69, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xa6, 0x2c, 0x3f, + 0xd0, 0x7e, 0xa2, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0xa6, 0xce, 0x36, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xcc, 0x7e, 0x22, 0xbf, + 0xbc, 0xa6, 0x2c, 0x3f, 0xf3, 0x2e, 0x8e, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x92, 0xf6, 0x40, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xe4, 0x56, 0x18, 0x3f, + 0x40, 0xbe, 0x73, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0x84, 0x1e, 0x4b, 0x3f, + 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x56, 0x18, 0xbf, 0x40, 0xbe, 0x73, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0xf3, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x24, 0xe6, 0x7d, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x98, 0xf6, 0x40, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x5a, 0x6e, 0x5f, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xba, 0xa6, 0x2c, 0xbf, + 0x80, 0x1e, 0xcb, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xbc, 0xa6, 0x2c, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, + 0xa8, 0xce, 0xb6, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0x48, 0x96, 0x69, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0x04, 0x07, 0x04, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x84, 0x1e, 0x4b, 0x3f, + 0xa6, 0xce, 0x36, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x6e, 0x5f, 0x3f, + 0x5a, 0x6e, 0x5f, 0xbf, 0xa6, 0xce, 0x36, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0x80, 0x1e, 0x4b, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x5c, 0x6e, 0x5f, 0x3f, + 0x80, 0x1e, 0xcb, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x38, 0xbe, 0x73, 0x3f, 0xba, 0xa6, 0x2c, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xa8, 0xce, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1e, 0x4b, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x84, 0x1e, 0x4b, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x38, 0xbe, 0x73, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0x22, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x60, 0x6e, 0xdf, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xf6, 0x2e, 0x8e, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xa6, 0xce, 0x36, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0xd0, 0x7e, 0xa2, 0x3e, 0x38, 0xbe, 0x73, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, + 0x08, 0x07, 0x84, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, + 0xea, 0x42, 0x93, 0xbf, 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x70, 0x46, 0x55, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, + 0x5a, 0x6e, 0x5f, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0xa6, 0xce, 0x36, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0x34, 0xbe, 0x73, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xe4, 0x56, 0x18, 0x3f, 0x30, 0xbe, 0xf3, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, + 0xa8, 0xce, 0xb6, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x04, 0x07, 0x04, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0x92, 0xf6, 0x40, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xe4, 0x56, 0x18, 0x3f, + 0x90, 0x1e, 0x4b, 0x3e, 0x81, 0x1e, 0xcb, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, 0xba, 0xa6, 0x2c, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x56, 0x98, 0xbf, 0x70, 0x46, 0x55, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0xec, 0x42, 0x93, 0x3f, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x84, 0x1e, 0x4b, 0x3f, 0x48, 0x96, 0x69, 0x3f, 0x04, 0x07, 0x04, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0xbc, 0xa6, 0xac, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xbe, 0x73, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x96, 0xe9, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0x80, 0x1e, 0xcb, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0x80, 0x1e, 0xcb, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0xfd, 0x1a, 0x89, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x34, 0xbe, 0x73, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, + 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xea, 0x42, 0x93, 0xbf, + 0xd0, 0x7e, 0x22, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x84, 0x1e, 0x4b, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0x6c, 0x46, 0x55, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xf8, 0x2e, 0x0e, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0x84, 0x1e, 0x4b, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, + 0x84, 0x1e, 0x4b, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, + 0xd0, 0x7e, 0x22, 0x3f, 0xa8, 0xce, 0x36, 0x3f, 0x30, 0xbe, 0xf3, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0x5c, 0x6e, 0x5f, 0x3f, + 0xa6, 0xce, 0x36, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, 0xd7, 0x6a, 0x9d, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x60, 0x6e, 0xdf, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x6c, 0x46, 0x55, 0xbf, + 0xc8, 0x7e, 0xa2, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xf6, 0x2e, 0x8e, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0x06, 0x07, 0x84, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xa6, 0xce, 0x36, 0xbf, 0xe4, 0x56, 0x18, 0x3f, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf4, 0x2e, 0x0e, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0xa2, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0x22, 0x3f, 0xe0, 0x56, 0x18, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x92, 0xf6, 0x40, 0xbf, 0xc8, 0x7e, 0xa2, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x92, 0xf6, 0x40, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0x56, 0x18, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x08, 0x07, 0x04, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x38, 0xbe, 0xf3, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, + 0x58, 0x6e, 0xdf, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xf6, 0x2e, 0x8e, 0x3f, + 0x30, 0xbe, 0x73, 0xbe, 0xea, 0x42, 0x93, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x08, 0x07, 0x04, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0x46, 0x55, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0x04, 0x07, 0x04, 0xbf, 0x5a, 0x6e, 0x5f, 0xbf, + 0xba, 0xa6, 0x2c, 0xbf, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x7e, 0xa2, 0xbe, + 0xa8, 0xce, 0xb6, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, + 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xa6, 0xce, 0x36, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x38, 0xbe, 0xf3, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0xf3, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0xea, 0x42, 0x93, 0xbf, + 0xa8, 0xce, 0xb6, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x5a, 0x6e, 0x5f, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x38, 0xbe, 0xf3, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x60, 0x6e, 0xdf, 0x3e, 0xfe, 0x1a, 0x89, 0x3f, 0xf8, 0x2e, 0x0e, 0x3f, + 0x90, 0x1e, 0x4b, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0x40, 0xbe, 0x73, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0x5a, 0x6e, 0x5f, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x2e, 0x0e, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x0e, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x56, 0x18, 0xbf, 0xc8, 0x7e, 0xa2, 0xbe, + 0xe4, 0x56, 0x18, 0x3f, 0x30, 0xbe, 0x73, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0xe4, 0x56, 0x18, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0x80, 0x1e, 0xcb, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x98, 0xf6, 0x40, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x56, 0x18, 0x3f, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x6e, 0xdf, 0x3e, 0xe4, 0x56, 0x18, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xa8, 0xce, 0x36, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0x70, 0x46, 0x55, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xa8, 0xce, 0x36, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, + 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xfe, 0x1a, 0x89, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x84, 0x1e, 0x4b, 0x3f, 0xcc, 0x7e, 0x22, 0xbf, + 0xf8, 0x2e, 0x0e, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x70, 0x46, 0x55, 0x3f, 0x38, 0xbe, 0x73, 0x3f, + 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x8e, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x04, 0x07, 0x04, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x92, 0xf6, 0x40, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x46, 0x96, 0x69, 0xbf, + 0xc8, 0x7e, 0xa2, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x04, 0x07, 0x04, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0xf3, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0xe4, 0x56, 0x18, 0x3f, + 0xe4, 0x56, 0x18, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, + 0xf4, 0x2e, 0x0e, 0xbf, 0xbc, 0xa6, 0x2c, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x08, 0x07, 0x04, 0x3f, + 0x60, 0x6e, 0xdf, 0x3e, 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xfe, 0x1a, 0x89, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0x04, 0x07, 0x04, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xe4, 0x56, 0x18, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0xa2, 0x3e, 0x08, 0x07, 0x04, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xf8, 0x2e, 0x0e, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xe4, 0x56, 0x18, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xbe, 0x73, 0xbe, 0x70, 0x46, 0x55, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0xc6, 0x92, 0xa7, 0x3f, + 0xe0, 0x56, 0x98, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0xcd, 0x7e, 0xa2, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, 0xbc, 0xa6, 0x2c, 0x3f, + 0x24, 0xe6, 0x7d, 0x3f, 0xf0, 0x2e, 0x8e, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xe6, 0x7d, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0x73, 0x3e, 0x08, 0x07, 0x04, 0x3f, + 0xd0, 0x7e, 0xa2, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xba, 0xb1, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, 0x92, 0xf6, 0x40, 0xbf, + 0x04, 0x07, 0x04, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0x20, 0xe6, 0x7d, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x92, 0xf6, 0x40, 0xbf, + 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x98, 0xf6, 0x40, 0x3f, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0x4b, 0xbf, 0x40, 0xbe, 0x73, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, + 0xa8, 0xce, 0xb6, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, 0x80, 0x1e, 0x4b, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, 0x30, 0xbe, 0xf3, 0xbe, + 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x07, 0x04, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0x36, 0x3f, + 0xe4, 0x56, 0x18, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, + 0xd0, 0x7e, 0x22, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, 0x84, 0x1e, 0x4b, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x6c, 0x46, 0x55, 0xbf, 0xe0, 0x56, 0x98, 0xbf, + 0xcc, 0x7e, 0x22, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x56, 0x18, 0xbf, + 0x30, 0xbe, 0x73, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xcc, 0x7e, 0x22, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0xfd, 0x1a, 0x89, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x70, 0x46, 0x55, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, + 0x58, 0x6e, 0xdf, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x98, 0xf6, 0x40, 0x3f, + 0xa8, 0xce, 0x36, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x58, 0x6e, 0xdf, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x92, 0xf6, 0x40, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x20, 0xe6, 0x7d, 0xbf, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0x6c, 0x46, 0x55, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x58, 0x6e, 0xdf, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0x92, 0xf6, 0x40, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xe6, 0x7d, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, 0xcd, 0x7e, 0xa2, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x8c, 0x0a, 0xc6, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x6c, 0x46, 0x55, 0xbf, 0xba, 0xa6, 0xac, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0x5a, 0x6e, 0x5f, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0x36, 0x3f, 0x38, 0xbe, 0x73, 0x3f, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x0e, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x98, 0xf6, 0x40, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, 0x98, 0xf6, 0x40, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x04, 0x07, 0x04, 0xbf, + 0xba, 0xa6, 0x2c, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xa6, 0xce, 0x36, 0xbf, 0x08, 0x07, 0x04, 0x3f, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x80, 0x1e, 0xcb, 0xbe, 0x48, 0x96, 0x69, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xbc, 0xa6, 0x2c, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0xa8, 0xce, 0x36, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xf3, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x96, 0x69, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x80, 0x1e, 0xcb, 0xbe, 0xfd, 0x1a, 0x89, 0xbf, 0xe4, 0x56, 0x18, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0x88, 0x1e, 0xcb, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x2e, 0x0e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x08, 0x07, 0x84, 0x3f, + 0x60, 0x6e, 0xdf, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0xe4, 0x56, 0x18, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0x36, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0x22, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, + 0xe4, 0x56, 0x18, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0xd0, 0x7e, 0x22, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf6, 0x2e, 0x8e, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xfe, 0x1a, 0x89, 0x3f, 0xf8, 0x2e, 0x0e, 0x3f, + 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x5c, 0x6e, 0x5f, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0x5c, 0x6e, 0x5f, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xba, 0xa6, 0x2c, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xf3, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0x08, 0x07, 0x04, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x88, 0x1e, 0xcb, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, 0xd0, 0x7e, 0x22, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe4, 0x56, 0x18, 0x3f, 0xc4, 0x92, 0xa7, 0xbf, + 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0xf3, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x70, 0x46, 0x55, 0x3f, 0x34, 0xbe, 0x73, 0xbf, + 0xd0, 0x7e, 0xa2, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, 0xe0, 0x56, 0x18, 0xbf, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0xe4, 0x56, 0x18, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0x04, 0x07, 0x04, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, + 0x92, 0xf6, 0x40, 0xbf, 0xf8, 0x2e, 0x0e, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0xa8, 0xce, 0xb6, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0xea, 0x42, 0x93, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x08, 0x07, 0x04, 0x3f, 0xf0, 0x2e, 0x8e, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0x04, 0x07, 0x04, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x08, 0x07, 0x04, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xa6, 0xce, 0x36, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x04, 0x07, 0x04, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, + 0x80, 0x1e, 0xcb, 0xbe, 0x92, 0xf6, 0x40, 0xbf, 0x20, 0xe6, 0x7d, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, 0x92, 0xf6, 0x40, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x08, 0x07, 0x04, 0x3f, + 0x30, 0xbe, 0x73, 0xbe, 0xa6, 0xce, 0x36, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0xfe, 0x1a, 0x89, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x38, 0xbe, 0xf3, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0x38, 0xbe, 0xf3, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x30, 0xbe, 0xf3, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xe6, 0x7d, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x84, 0x3f, + 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x24, 0xe6, 0x7d, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x04, 0x07, 0x04, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xf4, 0x2e, 0x0e, 0xbf, 0xfe, 0x1a, 0x89, 0x3f, 0xfd, 0x1a, 0x89, 0xbf, + 0xe0, 0x56, 0x18, 0xbf, 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0xba, 0xa6, 0x2c, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0xf6, 0x2e, 0x8e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0xf3, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0x88, 0x1e, 0xcb, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x06, 0x07, 0x84, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc6, 0x92, 0xa7, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, + 0xa8, 0xce, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x58, 0x6e, 0xdf, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x84, 0x1e, 0x4b, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xcc, 0x7e, 0x22, 0xbf, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xe2, 0x56, 0x98, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x58, 0x6e, 0xdf, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0xce, 0xb6, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0x84, 0x1e, 0x4b, 0x3f, + 0x30, 0xbe, 0x73, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xf8, 0x2e, 0x8e, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, 0xa8, 0xce, 0x36, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0xa8, 0xce, 0x36, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, + 0xe4, 0x56, 0x18, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf4, 0x2e, 0x0e, 0xbf, 0xe4, 0x56, 0x18, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x08, 0x07, 0x04, 0x3f, 0x04, 0x07, 0x04, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x8e, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0xa8, 0xce, 0x36, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x08, 0x07, 0x04, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3f, + 0xc8, 0x7e, 0xa2, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0x4b, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbf, + 0x08, 0x07, 0x84, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xba, 0xa6, 0x2c, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x0e, 0x3f, 0x04, 0x07, 0x04, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0xa2, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xe2, 0x56, 0x98, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0x5c, 0x6e, 0xdf, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0x38, 0xbe, 0xf3, 0x3e, 0x92, 0xf6, 0x40, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x98, 0xf6, 0x40, 0x3f, 0x5a, 0x6e, 0x5f, 0xbf, + 0x80, 0x1e, 0x4b, 0xbe, 0x34, 0xbe, 0x73, 0xbf, 0x20, 0xe6, 0x7d, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xa8, 0xce, 0xb6, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xe2, 0x56, 0x98, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, + 0xbc, 0xa6, 0x2c, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0xe4, 0x56, 0x18, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, + 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x5c, 0x6e, 0x5f, 0x3f, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x38, 0xbe, 0x73, 0x3f, 0x84, 0x1e, 0x4b, 0x3f, 0x40, 0xbe, 0x73, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xa8, 0xce, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x88, 0x1e, 0xcb, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x56, 0x18, 0xbf, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0x8c, 0x0a, 0xc6, 0x3f, + 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0xa8, 0xce, 0x36, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, 0x34, 0xbe, 0x73, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, 0xcc, 0x7e, 0x22, 0xbf, + 0x5c, 0x6e, 0x5f, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xa8, 0xce, 0x36, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0xf8, 0x2e, 0x0e, 0x3f, 0x98, 0xf6, 0x40, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x08, 0x07, 0x04, 0x3f, 0xf0, 0x2e, 0x8e, 0xbe, + 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0x80, 0x1e, 0x4b, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0x84, 0x1e, 0x4b, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xce, 0x7e, 0xa2, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0xc8, 0x7e, 0xa2, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0xba, 0xa6, 0x2c, 0xbf, 0x92, 0xf6, 0x40, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0xbc, 0xa6, 0x2c, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x04, 0x07, 0x04, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, + 0xa8, 0xce, 0x36, 0x3f, 0x5c, 0x6e, 0x5f, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x04, 0x07, 0x04, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xa7, 0xce, 0xb6, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0xa8, 0xce, 0xb6, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0x22, 0x3f, 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x56, 0x18, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x80, 0x1e, 0xcb, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x98, 0xf6, 0x40, 0x3f, 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x08, 0x07, 0x04, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0x38, 0xbe, 0x73, 0x3f, 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x08, 0x07, 0x04, 0x3f, + 0xa8, 0xce, 0x36, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0x5c, 0x6e, 0x5f, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0xa8, 0xce, 0xb6, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0x36, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x70, 0x46, 0x55, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0xbc, 0xa6, 0x2c, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, + 0x88, 0x1e, 0xcb, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xa8, 0xce, 0x36, 0x3f, + 0x38, 0xbe, 0xf3, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, + 0x08, 0x07, 0x04, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xe2, 0x56, 0x98, 0x3f, 0xf4, 0x2e, 0x0e, 0xbf, 0xf8, 0x2e, 0x0e, 0x3f, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xa6, 0xce, 0x36, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x38, 0xbe, 0x73, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0xd8, 0x6a, 0x9d, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xba, 0xa6, 0xac, 0xbf, + 0x48, 0x96, 0x69, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, + 0xa6, 0xce, 0x36, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf8, 0x2e, 0x0e, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, 0x5a, 0x6e, 0x5f, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0x30, 0xbe, 0x73, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0xba, 0xa6, 0x2c, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x46, 0x55, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xe4, 0x56, 0x18, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x6c, 0x46, 0x55, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0xbc, 0xa6, 0x2c, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0xf3, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0xe4, 0x56, 0x18, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, 0xcc, 0x7e, 0x22, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xf4, 0x2e, 0x0e, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xbc, 0xa6, 0x2c, 0x3f, + 0xa8, 0xce, 0xb6, 0xbe, 0x98, 0xf6, 0x40, 0x3f, 0xe4, 0x56, 0x18, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbf, + 0xfe, 0x1a, 0x89, 0x3f, 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0x80, 0x1e, 0xcb, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0xe4, 0x56, 0x18, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0xf6, 0x2e, 0x8e, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x46, 0x96, 0x69, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0x4b, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xea, 0x42, 0x93, 0xbf, + 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0xf3, 0x2e, 0x8e, 0xbf, + 0x04, 0x07, 0x04, 0xbf, 0x98, 0xf6, 0x40, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, 0x48, 0x96, 0x69, 0x3f, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xcd, 0x7e, 0xa2, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, 0x58, 0x6e, 0xdf, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xd0, 0x7e, 0xa2, 0x3e, 0x08, 0x07, 0x04, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0xe2, 0x56, 0x98, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0xd0, 0x7e, 0x22, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xc8, 0x7e, 0xa2, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0xa8, 0xce, 0xb6, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0x38, 0xbe, 0xf3, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x6c, 0x46, 0x55, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, 0xe4, 0x56, 0x18, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xbc, 0xa6, 0x2c, 0x3f, + 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x56, 0x98, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, + 0x70, 0x46, 0x55, 0x3f, 0x08, 0x07, 0x04, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0x36, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0x58, 0x6e, 0xdf, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, + 0x08, 0x07, 0x04, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, + 0x80, 0x1e, 0xcb, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0x08, 0x07, 0x04, 0x3f, 0x04, 0x07, 0x04, 0xbf, 0x38, 0xbe, 0x73, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x38, 0xbe, 0xf3, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xfe, 0x1a, 0x89, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x80, 0x1e, 0xcb, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe4, 0x56, 0x18, 0x3f, 0xe0, 0x56, 0x18, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf8, 0x2e, 0x8e, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xa6, 0xce, 0x36, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0x34, 0xbe, 0x73, 0xbf, 0xe4, 0x56, 0x18, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x04, 0x07, 0x04, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x34, 0xbe, 0x73, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x08, 0x07, 0x04, 0x3f, + 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0x5a, 0x6e, 0x5f, 0xbf, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0x04, 0x07, 0x04, 0xbf, 0x40, 0xbe, 0x73, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x60, 0x6e, 0xdf, 0x3e, 0xce, 0x7e, 0xa2, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x04, 0x07, 0x04, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x58, 0x6e, 0xdf, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0xa6, 0xce, 0x36, 0xbf, + 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xb4, 0xba, 0xb1, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x92, 0xf6, 0x40, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x92, 0xf6, 0x40, 0xbf, 0xe4, 0x56, 0x18, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x5c, 0x6e, 0x5f, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x38, 0xbe, 0xf3, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xcc, 0x7e, 0x22, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xbc, 0xa6, 0x2c, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xe4, 0x56, 0x18, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x38, 0xbe, 0xf3, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xb4, 0xba, 0xb1, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0x38, 0xbe, 0x73, 0x3f, + 0x80, 0x1e, 0xcb, 0xbe, 0xf6, 0x2e, 0x8e, 0x3f, 0x58, 0x6e, 0xdf, 0xbe, + 0x80, 0x1e, 0x4b, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3f, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1e, 0x4b, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x84, 0x1e, 0x4b, 0x3f, + 0x30, 0xbe, 0x73, 0xbe, 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x84, 0x1e, 0x4b, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x8e, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xbc, 0xa6, 0x2c, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0x22, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xe4, 0x56, 0x18, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x48, 0x96, 0x69, 0x3f, + 0xd0, 0x7e, 0x22, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xe4, 0x56, 0x18, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xd8, 0x6a, 0x9d, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0xd0, 0x7e, 0x22, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x5c, 0x6e, 0x5f, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0x73, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0xf8, 0x2e, 0x0e, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xba, 0xa6, 0x2c, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, 0x84, 0x1e, 0x4b, 0x3f, + 0xf0, 0x2e, 0x8e, 0xbe, 0x98, 0xf6, 0x40, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0x08, 0x07, 0x04, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xbc, 0xa6, 0x2c, 0x3f, + 0x92, 0xf6, 0x40, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0xcb, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x88, 0x1e, 0xcb, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x04, 0x07, 0x04, 0xbf, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, + 0xd7, 0x6a, 0x9d, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xec, 0x42, 0x93, 0x3f, + 0x90, 0x1e, 0x4b, 0x3e, 0x70, 0x46, 0x55, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0x04, 0x07, 0x04, 0xbf, + 0x70, 0x46, 0x55, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf3, 0x2e, 0x8e, 0xbf, 0xc8, 0x7e, 0xa2, 0xbe, 0xa6, 0xce, 0x36, 0xbf, + 0x80, 0x1e, 0x4b, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0x6c, 0x46, 0x55, 0xbf, + 0xbc, 0xa6, 0x2c, 0x3f, 0x92, 0xf6, 0x40, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0xce, 0xb6, 0xbe, 0x98, 0xf6, 0x40, 0x3f, 0xf8, 0x2e, 0x0e, 0x3f, + 0x88, 0x1e, 0xcb, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xd7, 0x6a, 0x9d, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, 0xe4, 0x56, 0x18, 0x3f, + 0x30, 0xbe, 0xf3, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf4, 0x2e, 0x0e, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x88, 0x1e, 0xcb, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x8e, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x6c, 0x46, 0x55, 0xbf, 0x84, 0x1e, 0x4b, 0x3f, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xa8, 0xce, 0x36, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x08, 0x07, 0x04, 0x3f, 0x04, 0x07, 0x04, 0xbf, + 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0x36, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0xd0, 0x7e, 0x22, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x98, 0xf6, 0x40, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x08, 0x07, 0x04, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xba, 0xa6, 0x2c, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0xbf, + 0x70, 0x46, 0x55, 0x3f, 0xf8, 0x2e, 0x0e, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0xa8, 0xce, 0xb6, 0xbe, 0x5c, 0x6e, 0x5f, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0xfe, 0x1a, 0x89, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0x48, 0x96, 0x69, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xf3, 0x2e, 0x8e, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, 0xba, 0xa6, 0x2c, 0xbf, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0x46, 0x96, 0x69, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0x84, 0x1e, 0x4b, 0x3f, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0x36, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0x30, 0xbe, 0x73, 0xbe, 0x51, 0x82, 0xe4, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0x56, 0x18, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x5a, 0x6e, 0x5f, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, + 0x70, 0x46, 0x55, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x84, 0x1e, 0x4b, 0x3f, 0x84, 0x1e, 0x4b, 0x3f, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x5c, 0x6e, 0x5f, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0xbc, 0xa6, 0x2c, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x8e, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xec, 0x42, 0x93, 0x3f, + 0xe4, 0x56, 0x18, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, 0xa6, 0xce, 0x36, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0xcb, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, + 0x88, 0x1e, 0xcb, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0xe0, 0x56, 0x18, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0xe0, 0x56, 0x18, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x24, 0xe6, 0x7d, 0x3f, + 0x38, 0xbe, 0xf3, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0x92, 0xf6, 0x40, 0xbf, + 0x80, 0x1e, 0xcb, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x0e, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xf8, 0x2e, 0x0e, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0x80, 0x1e, 0x4b, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x48, 0x96, 0x69, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0x88, 0x1e, 0xcb, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, 0xba, 0xa6, 0xac, 0xbf, + 0xcc, 0x7e, 0x22, 0xbf, 0x5a, 0x6e, 0x5f, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xbc, 0xa6, 0xac, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0x04, 0x07, 0x04, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0x6c, 0x46, 0x55, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xe6, 0x7d, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0xfd, 0x1a, 0x89, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x08, 0x07, 0x04, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x6e, 0xdf, 0xbe, 0x98, 0xf6, 0x40, 0x3f, + 0xd0, 0x7e, 0x22, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0x06, 0x07, 0x84, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0x38, 0xbe, 0x73, 0x3f, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0x48, 0x96, 0x69, 0x3f, 0xcc, 0x7e, 0x22, 0xbf, 0xe4, 0x56, 0x18, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xa6, 0xce, 0x36, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0xa6, 0xce, 0x36, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xd0, 0x7e, 0x22, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0xce, 0x7e, 0xa2, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xe4, 0x56, 0x18, 0x3f, + 0x94, 0xf6, 0xc0, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe4, 0x56, 0x18, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xe4, 0x56, 0x18, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, 0xe4, 0x56, 0x18, 0x3f, + 0xe4, 0x56, 0x18, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0x04, 0x07, 0x04, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0x36, 0x3f, 0x04, 0x07, 0x04, 0xbf, + 0xbc, 0xa6, 0x2c, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0xf3, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, + 0xe4, 0x56, 0x18, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x6e, 0xdf, 0xbe, 0xd0, 0x7e, 0x22, 0x3f, + 0x38, 0xbe, 0xf3, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0xa8, 0xce, 0x36, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, + 0x30, 0xbe, 0xf3, 0xbe, 0x5c, 0x6e, 0x5f, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xbc, 0xa6, 0x2c, 0x3f, 0xf0, 0x2e, 0x8e, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x08, 0x07, 0x84, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0x30, 0xbe, 0xf3, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x08, 0x07, 0x04, 0x3f, 0xf0, 0x2e, 0x8e, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x58, 0x6e, 0xdf, 0xbe, 0xa6, 0xce, 0x36, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x6e, 0xdf, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0x08, 0x07, 0x04, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x46, 0x96, 0x69, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x38, 0xbe, 0x73, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x92, 0xf6, 0x40, 0xbf, 0x08, 0x07, 0x04, 0x3f, + 0x38, 0xbe, 0xf3, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xfe, 0x1a, 0x89, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, 0xd0, 0x7e, 0x22, 0x3f, + 0x84, 0x1e, 0x4b, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x56, 0x18, 0xbf, + 0x04, 0x07, 0x04, 0xbf, 0x92, 0xf6, 0x40, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x84, 0x1e, 0xcb, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xbc, 0xa6, 0x2c, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0xe2, 0x56, 0x98, 0x3f, 0xbc, 0xa6, 0x2c, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0x73, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x2e, 0x8e, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xa7, 0xce, 0xb6, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xd8, 0x6a, 0x9d, 0x3f, + 0xc6, 0x92, 0xa7, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x46, 0x96, 0x69, 0xbf, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x94, 0xf6, 0xc0, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0x48, 0x96, 0x69, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x96, 0x69, 0xbf, 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x56, 0x98, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xa6, 0xce, 0x36, 0xbf, + 0x48, 0x96, 0x69, 0x3f, 0x04, 0x07, 0x04, 0xbf, 0x84, 0x1e, 0x4b, 0x3f, + 0x60, 0x6e, 0xdf, 0x3e, 0x5a, 0x6e, 0x5f, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x98, 0xf6, 0x40, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf8, 0x2e, 0x0e, 0x3f, 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0x70, 0x46, 0x55, 0x3f, + 0xf8, 0x2e, 0x8e, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x38, 0xbe, 0x73, 0x3f, 0xa6, 0xce, 0x36, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0x60, 0x6e, 0xdf, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x8e, 0x3e, 0x08, 0x07, 0x04, 0x3f, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xe4, 0x56, 0x18, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0x70, 0x46, 0x55, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xcc, 0x7e, 0x22, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x04, 0x07, 0x04, 0xbf, + 0xf4, 0x2e, 0x0e, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, 0x5c, 0x6e, 0x5f, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xcc, 0x7e, 0x22, 0xbf, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0x8e, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0x6c, 0x46, 0x55, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, 0xa6, 0xce, 0x36, 0xbf, + 0x48, 0x96, 0x69, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xf3, 0x2e, 0x8e, 0xbf, + 0x80, 0x1e, 0xcb, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0xe4, 0x56, 0x18, 0x3f, 0xd0, 0x7e, 0x22, 0x3f, + 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0x46, 0x96, 0x69, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x38, 0xbe, 0xf3, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, + 0x38, 0xbe, 0x73, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xbc, 0xa6, 0x2c, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0xea, 0x42, 0x93, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc8, 0x7e, 0xa2, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xfd, 0x1a, 0x89, 0xbf, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xa8, 0xce, 0x36, 0x3f, 0xec, 0x42, 0x93, 0x3f, 0xa8, 0xce, 0xb6, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xba, 0xa6, 0x2c, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, + 0xfd, 0x1a, 0x89, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x80, 0x1e, 0x4b, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6a, 0x9d, 0x3f, 0x08, 0x07, 0x84, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x70, 0x46, 0x55, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xe0, 0x56, 0x18, 0xbf, + 0x6c, 0x46, 0x55, 0xbf, 0xd0, 0x7e, 0x22, 0x3f, 0xa6, 0xce, 0x36, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x04, 0x07, 0x04, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, + 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xc4, 0x92, 0xa7, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x46, 0x55, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x84, 0x1e, 0x4b, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0x08, 0x07, 0x04, 0x3f, 0x5a, 0x6e, 0x5f, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0x94, 0xf6, 0xc0, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x6c, 0x46, 0x55, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0xf6, 0x2e, 0x8e, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xfe, 0x1a, 0x89, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0xba, 0xa6, 0xac, 0xbf, + 0xf8, 0x2e, 0x0e, 0x3f, 0xe0, 0x56, 0x18, 0xbf, 0xfe, 0x1a, 0x89, 0x3f, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0x48, 0x96, 0x69, 0x3f, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xf4, 0x2e, 0x0e, 0x40, + 0x38, 0xbe, 0xf3, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x38, 0xbe, 0xf3, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, + 0x84, 0x1e, 0x4b, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0xe4, 0x56, 0x18, 0x3f, + 0xd8, 0x6a, 0x9d, 0x3f, 0xe4, 0x56, 0x18, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xf8, 0x2e, 0x8e, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0xd8, 0x6a, 0x9d, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0xce, 0x7e, 0xa2, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xa8, 0xce, 0x36, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0xa8, 0xce, 0x36, 0x3f, + 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xd0, 0x7e, 0x22, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, 0xe0, 0x56, 0x18, 0xbf, + 0x5c, 0x6e, 0x5f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x34, 0xbe, 0x73, 0xbf, 0x38, 0xbe, 0x73, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0x84, 0x1e, 0x4b, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x38, 0xbe, 0xf3, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0xbc, 0xa6, 0x2c, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x70, 0x46, 0x55, 0x3f, + 0xa8, 0xce, 0x36, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, + 0xa8, 0xce, 0x36, 0x3f, 0xe2, 0x56, 0x98, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0x98, 0xf6, 0x40, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, + 0x48, 0x96, 0x69, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xfd, 0x1a, 0x89, 0xbf, 0x30, 0xbe, 0xf3, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xea, 0x42, 0x93, 0xbf, 0x80, 0x1e, 0x4b, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0x06, 0x07, 0x84, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0xfd, 0x1a, 0x89, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0xa6, 0xce, 0x36, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, 0xd0, 0x7e, 0xa2, 0x3e, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xea, 0x42, 0x93, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x5a, 0x6e, 0x5f, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0x4b, 0xbf, 0xa6, 0xce, 0x36, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0x73, 0x3e, 0xe4, 0x56, 0x18, 0x3f, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xba, 0xa6, 0x2c, 0xbf, + 0x30, 0xbe, 0xf3, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x92, 0xf6, 0x40, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xbc, 0xa6, 0x2c, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0xc6, 0x92, 0xa7, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0xd7, 0x6a, 0x9d, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x34, 0xbe, 0x73, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0xfe, 0x1a, 0x89, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xfe, 0x1a, 0x89, 0x3f, 0x5a, 0x6e, 0x5f, 0xbf, 0xe0, 0x56, 0x18, 0xbf, + 0xfd, 0x1a, 0x89, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, 0x6c, 0x46, 0x55, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xcc, 0x7e, 0x22, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, 0x6c, 0x46, 0x55, 0xbf, + 0x04, 0x07, 0x04, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xbe, 0xf3, 0xbd, 0x70, 0x46, 0x55, 0x3f, 0x38, 0xbe, 0x73, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0x04, 0x07, 0x04, 0xbf, 0x9d, 0xe2, 0xbb, 0xbf, + 0xc8, 0x7e, 0xa2, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xe4, 0x56, 0x18, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xbe, 0x73, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0x48, 0x96, 0x69, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x92, 0xf6, 0x40, 0xbf, 0xa8, 0xce, 0x36, 0x3f, + 0x80, 0x1e, 0xcb, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3f, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x5c, 0x6e, 0x5f, 0x3f, 0x30, 0xbe, 0xf3, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x6e, 0xdf, 0x3e, 0xe4, 0x56, 0x18, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0xf3, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xf6, 0x2e, 0x8e, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xa8, 0xce, 0x36, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc4, 0x92, 0xa7, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0x48, 0x96, 0x69, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0xf3, 0x2e, 0x8e, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, 0x04, 0x07, 0x04, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xf4, 0x2e, 0x0e, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x0e, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xe4, 0x56, 0x18, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0xf3, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x6c, 0x46, 0x55, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0xf8, 0x2e, 0x8e, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0x04, 0x07, 0x04, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0x34, 0xbe, 0x73, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x84, 0x1e, 0x4b, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, 0x04, 0x07, 0x04, 0xbf, + 0xf4, 0x2e, 0x0e, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x84, 0x1e, 0x4b, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0x5a, 0x6e, 0x5f, 0xbf, 0xe0, 0x56, 0x18, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xbc, 0xa6, 0x2c, 0x3f, + 0x60, 0x6e, 0xdf, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, + 0xa6, 0xce, 0x36, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xbe, 0xf3, 0xbe, 0x08, 0x07, 0x84, 0x3f, 0x70, 0x46, 0x55, 0x3f, + 0xf4, 0x2e, 0x0e, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x34, 0xbe, 0x73, 0xbf, 0xe0, 0x56, 0x18, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, + 0x5c, 0x6e, 0x5f, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0x36, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0x60, 0x6e, 0xdf, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1e, 0x4b, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0xf0, 0x2e, 0x8e, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x6c, 0x46, 0x55, 0xbf, 0x40, 0xbe, 0x73, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x80, 0x1e, 0xcb, 0xbe, 0xa6, 0xce, 0x36, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0x36, 0x3f, 0x5a, 0x6e, 0x5f, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0x38, 0xbe, 0xf3, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x2e, 0x8e, 0xbf, + 0x92, 0xf6, 0x40, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0xd0, 0x7e, 0x22, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x08, 0x07, 0x04, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xa8, 0xce, 0x36, 0x3f, 0x04, 0x07, 0x04, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xa6, 0xac, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xcc, 0x7e, 0x22, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0x24, 0xe6, 0x7d, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0x70, 0x46, 0x55, 0x3f, 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0xa8, 0xce, 0x36, 0x3f, 0x34, 0xbe, 0x73, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0xf6, 0x2e, 0x8e, 0x3f, 0xbc, 0xa6, 0x2c, 0x3f, + 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xcc, 0x7e, 0x22, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbf, + 0x24, 0xe6, 0x7d, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xfe, 0x1a, 0x89, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0x70, 0x46, 0x55, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, 0x24, 0xe6, 0x7d, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, + 0xe4, 0x56, 0x18, 0x3f, 0xa8, 0xce, 0x36, 0x3f, 0x20, 0xe6, 0x7d, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x34, 0xbe, 0x73, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xcd, 0x7e, 0xa2, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x8e, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xe4, 0x56, 0x18, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0xf8, 0x2e, 0x0e, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0xf4, 0x2e, 0x0e, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xf4, 0x2e, 0x0e, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, 0xcc, 0x7e, 0x22, 0xbf, + 0x06, 0x07, 0x84, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xf4, 0x2e, 0x0e, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x92, 0xf6, 0x40, 0xbf, + 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x70, 0x46, 0x55, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x98, 0xf6, 0x40, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, + 0x04, 0x07, 0x04, 0xbf, 0x08, 0x07, 0x84, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x56, 0x18, 0xbf, 0xf8, 0x2e, 0x0e, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0x36, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, + 0x58, 0x6e, 0xdf, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xa8, 0xce, 0x36, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x98, 0xf6, 0x40, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x04, 0x07, 0x04, 0xbf, 0x40, 0xbe, 0x73, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xf4, 0x2e, 0x0e, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0xbc, 0xa6, 0x2c, 0x3f, 0xba, 0xa6, 0x2c, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x04, 0x3f, 0xa6, 0xce, 0x36, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0xa8, 0xce, 0xb6, 0x3e, 0xa6, 0xce, 0x36, 0xbf, 0x08, 0x07, 0x04, 0x3f, + 0xe0, 0x56, 0x18, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xa8, 0xce, 0xb6, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0xd0, 0x7e, 0x22, 0x3f, + 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x88, 0x1e, 0xcb, 0x3e, 0x08, 0x07, 0x84, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0x5c, 0x6e, 0x5f, 0x3f, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xa6, 0xce, 0x36, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x8e, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, + 0x98, 0xf6, 0x40, 0x3f, 0x84, 0x1e, 0x4b, 0x3f, 0x48, 0x96, 0x69, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0x36, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x98, 0xf6, 0x40, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0x20, 0xe6, 0x7d, 0xbf, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xf8, 0x2e, 0x8e, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, 0xcc, 0x7e, 0x22, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0xa6, 0xce, 0x36, 0xbf, + 0xf4, 0x2e, 0x0e, 0xbf, 0x04, 0x07, 0x04, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xbc, 0xa6, 0x2c, 0x3f, + 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0x36, 0x3f, 0x04, 0x07, 0x04, 0xbf, + 0x84, 0x1e, 0x4b, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0x6c, 0x46, 0x55, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0x5a, 0x6e, 0x5f, 0xbf, 0x30, 0xbe, 0xf3, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, + 0x98, 0xf6, 0x40, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x70, 0x46, 0x55, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0xc8, 0x7e, 0xa2, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x92, 0xf6, 0x40, 0xbf, + 0x58, 0x6e, 0xdf, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xe4, 0x56, 0x18, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, 0x24, 0xe6, 0x7d, 0x3f, + 0xd0, 0x7e, 0x22, 0x3f, 0xd0, 0x7e, 0x22, 0x3f, 0x30, 0xbe, 0xf3, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, + 0xe4, 0x56, 0x18, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x5c, 0x6e, 0x5f, 0x3f, 0x5c, 0x6e, 0x5f, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, 0x34, 0xbe, 0x73, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x5a, 0x6e, 0x5f, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0x48, 0x96, 0x69, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0xa8, 0xce, 0xb6, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x56, 0x18, 0xbf, + 0xf4, 0x2e, 0x0e, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, 0xd0, 0x7e, 0x22, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0x84, 0x1e, 0x4b, 0x3f, 0x58, 0x6e, 0xdf, 0xbe, 0x5c, 0x6e, 0x5f, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xfd, 0x1a, 0x89, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x80, 0x1e, 0xcb, 0xbe, 0x84, 0x1e, 0x4b, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0xce, 0x36, 0x3f, 0x34, 0xbe, 0x73, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x70, 0x46, 0x55, 0x3f, + 0xf0, 0x2e, 0x8e, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x34, 0xbe, 0x73, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x38, 0xbe, 0xf3, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xbc, 0xa6, 0x2c, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0x92, 0xf6, 0x40, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0xfd, 0x1a, 0x89, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0x98, 0xf6, 0x40, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xba, 0xa6, 0x2c, 0xbf, 0x34, 0xbe, 0x73, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xd0, 0x7e, 0x22, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0x46, 0x55, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0x04, 0x07, 0x04, 0xbf, 0x40, 0xbe, 0x73, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x30, 0xbe, 0x73, 0xbe, 0x6c, 0x46, 0x55, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, + 0xf8, 0x2e, 0x8e, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x08, 0x07, 0x84, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0xbc, 0xa6, 0xac, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, + 0xba, 0xa6, 0x2c, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0x48, 0x96, 0x69, 0x3f, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x08, 0x07, 0x04, 0x3f, + 0x08, 0x07, 0x04, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, 0xec, 0x42, 0x93, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, + 0x04, 0x07, 0x04, 0xbf, 0x92, 0xf6, 0x40, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x84, 0x1e, 0x4b, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0xf8, 0x2e, 0x0e, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x04, 0x07, 0x04, 0xbf, + 0xf0, 0x2e, 0x8e, 0xbe, 0x6c, 0x46, 0x55, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0x36, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x48, 0x96, 0x69, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xf4, 0x2e, 0x0e, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x2e, 0x8e, 0x3e, 0x38, 0xbe, 0xf3, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xba, 0xa6, 0x2c, 0xbf, + 0xbc, 0xa6, 0x2c, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0x70, 0x46, 0x55, 0x3f, 0x80, 0x1e, 0xcb, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x38, 0xbe, 0xf3, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0x6c, 0x46, 0x55, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0xe4, 0x56, 0x18, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xcd, 0x7e, 0xa2, 0xbf, 0xa8, 0xce, 0xb6, 0x3e, + 0xa8, 0xce, 0xb6, 0xbe, 0x92, 0xf6, 0x40, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, + 0x08, 0x07, 0x84, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0xa8, 0xce, 0x36, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0xcc, 0x7e, 0x22, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0x36, 0x3f, + 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xe6, 0x7d, 0xbf, + 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x24, 0xe6, 0x7d, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x48, 0x96, 0x69, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x30, 0xbe, 0xf3, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x88, 0x1e, 0xcb, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0x24, 0xe6, 0x7d, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0x80, 0x1e, 0x4b, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf8, 0x2e, 0x0e, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x92, 0xf6, 0x40, 0xbf, 0xf8, 0x2e, 0x0e, 0x3f, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x60, 0x6e, 0xdf, 0x3e, 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xfd, 0x1a, 0x89, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0x73, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0x92, 0xf6, 0x40, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0x04, 0x07, 0x04, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x84, 0x1e, 0xcb, 0x3f, 0x04, 0x07, 0x04, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0x38, 0xbe, 0x73, 0x3f, 0x06, 0x07, 0x84, 0xbf, + 0x08, 0x07, 0x04, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xf3, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x38, 0xbe, 0xf3, 0x3e, 0x92, 0xf6, 0x40, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0x80, 0x1e, 0x4b, 0xbf, + 0x84, 0x1e, 0x4b, 0x3f, 0x30, 0xbe, 0xf3, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0xba, 0xa6, 0x2c, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, 0xcc, 0x7e, 0x22, 0xbf, + 0xba, 0xa6, 0x2c, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0xcb, 0xbe, + 0xea, 0x42, 0x93, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1e, 0xcb, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0x24, 0xe6, 0x7d, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x24, 0xe6, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0x36, 0x3f, + 0x80, 0x1e, 0xcb, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x5c, 0x6e, 0x5f, 0x3f, 0x5c, 0x6e, 0x5f, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xc8, 0x7e, 0xa2, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, + 0xe0, 0x56, 0x18, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, 0xb0, 0xba, 0xb1, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x24, 0xe6, 0x7d, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, 0xf3, 0x2e, 0x8e, 0xbf, + 0xfd, 0x1a, 0x89, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x84, 0x1e, 0x4b, 0x3f, 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0xd8, 0x6a, 0x9d, 0x3f, + 0x84, 0x1e, 0x4b, 0x3f, 0xf3, 0x2e, 0x8e, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xcc, 0x7e, 0x22, 0xbf, 0x30, 0xbe, 0x73, 0xbe, + 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbf, + 0x04, 0x07, 0x04, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x92, 0xf6, 0x40, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0x30, 0xbe, 0x73, 0xbe, 0x81, 0x1e, 0xcb, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0xf4, 0x2e, 0x0e, 0xbf, 0xe4, 0x56, 0x18, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6a, 0x9d, 0x3f, + 0xd0, 0x7e, 0xa2, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x46, 0x96, 0x69, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0x22, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0x88, 0x1e, 0xcb, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0x30, 0xbe, 0xf3, 0xbe, + 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0xe2, 0x56, 0x98, 0x3f, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x88, 0x1e, 0xcb, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xd0, 0x7e, 0x22, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, 0xc4, 0x92, 0xa7, 0xbf, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0x48, 0x96, 0x69, 0x3f, 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0x06, 0x07, 0x84, 0xbf, 0xe4, 0x56, 0x18, 0x3f, + 0xba, 0xa6, 0x2c, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x46, 0x55, 0x3f, + 0x80, 0x1e, 0x4b, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, 0x04, 0x07, 0x04, 0xbf, + 0xa8, 0xce, 0xb6, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0xfd, 0x1a, 0x89, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x80, 0x1e, 0xcb, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0x88, 0x1e, 0xcb, 0x3e, 0xfe, 0x1a, 0x89, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x04, 0x07, 0x04, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0x22, 0x3f, 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, 0x38, 0xbe, 0xf3, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x60, 0x6e, 0xdf, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0xe4, 0x56, 0x18, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0x36, 0x3f, + 0xf8, 0x2e, 0x8e, 0x3e, 0x30, 0xbe, 0x73, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0x36, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x70, 0x46, 0x55, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, + 0xd0, 0x7e, 0x22, 0x3f, 0xcc, 0x7e, 0x22, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x56, 0x18, 0xbf, + 0xf4, 0x2e, 0x0e, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0x88, 0x1e, 0xcb, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0x92, 0xf6, 0x40, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, + 0x08, 0x07, 0x84, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, 0x6c, 0x46, 0x55, 0xbf, + 0x5c, 0x6e, 0x5f, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0xe4, 0x56, 0x18, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0xd0, 0x7e, 0x22, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0x6c, 0x46, 0x55, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x80, 0x1e, 0x4b, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x5c, 0x6e, 0x5f, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0xd0, 0x7e, 0x22, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x07, 0x04, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0xd0, 0x7e, 0x22, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xfe, 0x1a, 0x89, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0xe4, 0x56, 0x18, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0xa6, 0xce, 0x36, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x70, 0x46, 0x55, 0x3f, 0x98, 0xf6, 0x40, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0xa8, 0xce, 0x36, 0x3f, 0x30, 0xbe, 0x73, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x70, 0x46, 0x55, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x38, 0xbe, 0xf3, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0x73, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0x22, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x60, 0x6e, 0xdf, 0x3e, 0x3e, 0xaa, 0xee, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xec, 0x42, 0x93, 0x3f, 0x70, 0x46, 0x55, 0x3f, 0x24, 0xe6, 0x7d, 0x3f, + 0xc8, 0x7e, 0xa2, 0xbe, 0x48, 0x96, 0x69, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x08, 0x07, 0x04, 0x3f, 0x08, 0x07, 0x04, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xa6, 0x2c, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, 0x5a, 0x6e, 0x5f, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, 0xf4, 0x2e, 0x0e, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x56, 0x18, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x40, 0xbe, 0x73, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0xf3, 0xbe, 0xd0, 0x7e, 0x22, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0x56, 0x18, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0x73, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0xa8, 0xce, 0x36, 0x3f, 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0x08, 0x07, 0x04, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0x22, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x5a, 0x6e, 0x5f, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, + 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x1e, 0x4b, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, 0x5a, 0x6e, 0x5f, 0xbf, + 0xf8, 0x2e, 0x0e, 0x3f, 0xb4, 0xba, 0xb1, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xd0, 0x7e, 0x22, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0x5a, 0x6e, 0x5f, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xbe, 0xf3, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x04, 0x07, 0x04, 0xbf, 0x98, 0xf6, 0x40, 0x3f, 0xe4, 0x56, 0x18, 0x3f, + 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0xf6, 0x2e, 0x8e, 0x3f, + 0x80, 0x1e, 0x4b, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x04, 0x07, 0x04, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0x92, 0xf6, 0x40, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, + 0xbc, 0xa6, 0x2c, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, + 0xd0, 0x7e, 0x22, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0x08, 0x07, 0x04, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x48, 0x96, 0x69, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, + 0xa0, 0xe2, 0xbb, 0x3f, 0x40, 0xbe, 0x73, 0x3e, 0x84, 0x1e, 0x4b, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0xfd, 0x1a, 0x89, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0x60, 0x6e, 0xdf, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, 0x04, 0x07, 0x04, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x7e, 0x22, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x84, 0x1e, 0x4b, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0xd0, 0x7e, 0x22, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, 0xba, 0xa6, 0x2c, 0xbf, + 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, + 0x30, 0xbe, 0xf3, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, 0x06, 0x07, 0x84, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x08, 0x07, 0x04, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x60, 0x6e, 0xdf, 0x3e, 0x6c, 0x46, 0x55, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, + 0x5a, 0x6e, 0x5f, 0xbf, 0xe0, 0x56, 0x18, 0xbf, 0x5a, 0x6e, 0x5f, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0x30, 0xbe, 0x73, 0xbe, 0xbc, 0xa6, 0x2c, 0x3f, + 0xd0, 0x7e, 0x22, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, 0xe0, 0x56, 0x98, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x58, 0x6e, 0xdf, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xe4, 0x56, 0x18, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x38, 0xbe, 0xf3, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0x70, 0x46, 0x55, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x08, 0x07, 0x04, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x08, 0x07, 0x04, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x5a, 0x6e, 0x5f, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0x36, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, + 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x08, 0x07, 0x04, 0x3f, 0x58, 0x6e, 0xdf, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0x34, 0xbe, 0x73, 0xbf, 0xe0, 0x56, 0x18, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, + 0xfe, 0x1a, 0x89, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, 0x5a, 0x6e, 0x5f, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x34, 0xbe, 0x73, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0x84, 0x1e, 0x4b, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x5c, 0x6e, 0x5f, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, 0x38, 0xbe, 0xf3, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0x08, 0x07, 0x04, 0x3f, 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x5a, 0x6e, 0x5f, 0xbf, 0x34, 0xbe, 0x73, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x04, 0x07, 0x04, 0xbf, 0xc8, 0x7e, 0xa2, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x5a, 0x6e, 0x5f, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, + 0xd0, 0x7e, 0x22, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x92, 0xf6, 0x40, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0x5a, 0x6e, 0x5f, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0x08, 0x07, 0x04, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0xf4, 0x2e, 0x0e, 0xbf, + 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0x73, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa6, 0xce, 0x36, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0x34, 0xbe, 0x73, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x60, 0x6e, 0xdf, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xf3, 0x3e, + 0xd0, 0x7e, 0x22, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0x6c, 0x46, 0x55, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x58, 0x6e, 0xdf, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x98, 0xf6, 0x40, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x88, 0x1e, 0xcb, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x58, 0x6e, 0xdf, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xbc, 0xa6, 0xac, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x98, 0xf6, 0x40, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xba, 0xa6, 0x2c, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0x40, 0xbe, 0x73, 0x3e, 0xa8, 0xce, 0x36, 0x3f, 0x80, 0x1e, 0x4b, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xbc, 0xa6, 0x2c, 0x3f, 0x30, 0xbe, 0x73, 0xbe, + 0x04, 0x07, 0x04, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0xa8, 0xce, 0x36, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0x92, 0xf6, 0x40, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0x90, 0x1e, 0x4b, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xa6, 0xce, 0x36, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x34, 0xbe, 0x73, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbf, + 0x08, 0x07, 0x04, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xbe, 0xf3, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x5a, 0x6e, 0x5f, 0xbf, + 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xcc, 0x7e, 0x22, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x92, 0xf6, 0x40, 0xbf, 0x30, 0xbe, 0x73, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7e, 0xa2, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x34, 0xbe, 0x73, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x98, 0xf6, 0x40, 0x3f, 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0x30, 0xbe, 0xf3, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0x48, 0x96, 0x69, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0xd0, 0x7e, 0x22, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x56, 0x98, 0xbf, 0xba, 0xa6, 0x2c, 0xbf, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0x73, 0x3e, 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1e, 0x4b, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xe4, 0x56, 0x18, 0x3f, 0xf0, 0x2e, 0x8e, 0xbe, + 0x58, 0x6e, 0xdf, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, 0x80, 0x1e, 0x4b, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xa8, 0xce, 0x36, 0x3f, 0xa8, 0xce, 0xb6, 0x3e, + 0xd0, 0x7e, 0x22, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0xea, 0x42, 0x93, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x92, 0xf6, 0x40, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x08, 0x07, 0x04, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0xf4, 0x2e, 0x0e, 0xbf, + 0xf4, 0x2e, 0x0e, 0xbf, 0xd0, 0x7e, 0x22, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0x73, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xf8, 0x2e, 0x0e, 0x3f, 0xe0, 0x56, 0x18, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x98, 0xf6, 0x40, 0x3f, 0xcc, 0x7e, 0x22, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xa6, 0xce, 0x36, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0x4b, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xba, 0xa6, 0x2c, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x04, 0x07, 0x04, 0xbf, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xf8, 0x2e, 0x0e, 0x3f, 0xa8, 0xce, 0x36, 0x3f, 0x30, 0xbe, 0xf3, 0xbe, + 0x08, 0x07, 0x84, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0xfd, 0x1a, 0x89, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0x22, 0x3e, + 0xba, 0xa6, 0xac, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0xd0, 0x7e, 0x22, 0x3f, 0xe4, 0x56, 0x18, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xa6, 0xce, 0x36, 0xbf, 0xc4, 0x92, 0xa7, 0xbf, + 0xd8, 0x6a, 0x9d, 0x3f, 0x92, 0xf6, 0x40, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xd8, 0x6a, 0x9d, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x06, 0x07, 0x84, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xba, 0xa6, 0x2c, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, 0x80, 0x1e, 0x4b, 0xbf, + 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0x94, 0xf6, 0xc0, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0xea, 0x42, 0x93, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, 0x06, 0x07, 0x84, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x88, 0x1e, 0xcb, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xcc, 0x7e, 0x22, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0xf3, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0xa2, 0x3e, + 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xbc, 0xa6, 0xac, 0x3f, + 0x04, 0x07, 0x04, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0x08, 0x07, 0x04, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0x22, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xa6, 0xce, 0x36, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0x08, 0x07, 0x04, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0x70, 0x46, 0x55, 0x3f, + 0xfe, 0x1a, 0x89, 0x3f, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x56, 0x18, 0xbf, + 0x08, 0x07, 0x04, 0x3f, 0xe0, 0x56, 0x18, 0xbf, 0xbc, 0xa6, 0x2c, 0x3f, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0xc8, 0x7e, 0xa2, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0xfe, 0x1a, 0x89, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0x04, 0x07, 0x04, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0x88, 0x1e, 0xcb, 0x3e, 0x98, 0xf6, 0x40, 0x3f, + 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x8e, 0x3e, + 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xea, 0x42, 0x93, 0xbf, + 0x60, 0x6e, 0xdf, 0x3e, 0x04, 0x07, 0x04, 0xbf, 0x38, 0xbe, 0xf3, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xbc, 0xa6, 0x2c, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, + 0xa8, 0xce, 0xb6, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x24, 0xe6, 0x7d, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0xd0, 0x7e, 0x22, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x5c, 0x6e, 0x5f, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x04, 0x07, 0x04, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x60, 0x6e, 0xdf, 0x3e, 0xba, 0xa6, 0x2c, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x84, 0x1e, 0x4b, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x38, 0xbe, 0xf3, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x07, 0x04, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xf4, 0x2e, 0x0e, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0x30, 0xbe, 0xf3, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, 0x08, 0x07, 0x04, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0x30, 0xbe, 0xf3, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xf6, 0x2e, 0x8e, 0x3f, 0xf0, 0x2e, 0x8e, 0xbe, 0x60, 0x6e, 0xdf, 0x3e, + 0xa8, 0xce, 0xb6, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xbc, 0xa6, 0x2c, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x84, 0x1e, 0x4b, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x6c, 0x46, 0x55, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, + 0x60, 0x6e, 0xdf, 0x3e, 0x00, 0x7f, 0x22, 0x3d, 0x92, 0xf6, 0x40, 0xbf, + 0x80, 0x1e, 0x4b, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, + 0x92, 0xf6, 0x40, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, + 0x40, 0xbe, 0xf3, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, 0xa8, 0xce, 0xb6, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0x30, 0xbe, 0xf3, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x34, 0xbe, 0x73, 0xbf, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0xf4, 0x2e, 0x0e, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0x73, 0x3e, 0xa8, 0xce, 0x36, 0x3f, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0xe4, 0x56, 0x18, 0x3f, + 0xc8, 0x7e, 0xa2, 0xbe, 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0x20, 0xe6, 0x7d, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x58, 0x6e, 0xdf, 0xbe, + 0x80, 0x1e, 0xcb, 0xbe, 0x46, 0x96, 0x69, 0xbf, 0x80, 0x1e, 0x4b, 0xbf, + 0xea, 0x42, 0x93, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0xd0, 0x7e, 0x22, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0x73, 0x3e, + 0x30, 0xbe, 0x73, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0x5a, 0x6e, 0x5f, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0x5c, 0x6e, 0x5f, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0x6c, 0x46, 0x55, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0x5a, 0x6e, 0x5f, 0xbf, + 0x5a, 0x6e, 0x5f, 0xbf, 0x80, 0x1e, 0x4b, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xba, 0xa6, 0x2c, 0xbf, 0x46, 0x96, 0x69, 0xbf, + 0x80, 0x1e, 0x4b, 0xbe, 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x0e, 0x3f, 0xbc, 0xa6, 0x2c, 0x3f, + 0x6c, 0x46, 0x55, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xa6, 0x2c, 0x3f, + 0xa8, 0xce, 0xb6, 0x3e, 0x98, 0xf6, 0x40, 0x3f, 0xe4, 0x56, 0x18, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xba, 0xa6, 0x2c, 0xbf, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xa6, 0xce, 0x36, 0xbf, + 0x80, 0x1e, 0xcb, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, + 0xc8, 0x7e, 0xa2, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, 0x60, 0x6e, 0xdf, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x48, 0x96, 0x69, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0x22, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, 0xc8, 0x7e, 0xa2, 0xbe, + 0xf4, 0x2e, 0x0e, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, + 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xf8, 0x2e, 0x0e, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, + 0x38, 0xbe, 0x73, 0x3f, 0xa8, 0xce, 0xb6, 0xbe, 0xf8, 0x2e, 0x0e, 0x3f, + 0x88, 0x1e, 0xcb, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x38, 0xbe, 0x73, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0xe0, 0x56, 0x18, 0xbf, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0x98, 0xf6, 0x40, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, + 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0x98, 0xf6, 0x40, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xcc, 0x7e, 0x22, 0xbf, 0xd0, 0x7e, 0x22, 0x3f, 0xbc, 0xa6, 0x2c, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0x38, 0xbe, 0xf3, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xba, 0xa6, 0x2c, 0xbf, 0xa8, 0xce, 0xb6, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, + 0x92, 0xf6, 0x40, 0xbf, 0x30, 0xbe, 0xf3, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x38, 0xbe, 0x73, 0x3f, 0xf4, 0x2e, 0x0e, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0xd0, 0x7e, 0x22, 0x3f, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x08, 0x07, 0x84, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xba, 0xa6, 0x2c, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0xc0, 0x7e, 0xa2, 0xbd, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x70, 0x46, 0x55, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0x73, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, + 0x08, 0x07, 0x04, 0x3f, 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xce, 0xb6, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x08, 0x07, 0x04, 0x3f, 0x46, 0x96, 0x69, 0xbf, + 0x80, 0x1e, 0xcb, 0xbe, 0xe0, 0x56, 0x18, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x38, 0xbe, 0xf3, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0x30, 0xbe, 0xf3, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xe6, 0x7d, 0xbf, + 0xe0, 0x56, 0x18, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0x08, 0x07, 0x04, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0xf4, 0x2e, 0x0e, 0xbf, 0x80, 0x1e, 0xcb, 0xbe, + 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0xa8, 0xce, 0x36, 0x3f, 0x98, 0xf6, 0x40, 0x3f, 0xf8, 0x2e, 0x8e, 0x3e, + 0x6c, 0x46, 0x55, 0xbf, 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0x80, 0x1e, 0x4b, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xa6, 0xce, 0x36, 0xbf, + 0xa8, 0xce, 0xb6, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0x22, 0xbd, + 0xcc, 0x7e, 0x22, 0xbf, 0x30, 0xbe, 0x73, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x20, 0xbe, 0xf3, 0xbd, 0xa6, 0xce, 0x36, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0xa8, 0xce, 0xb6, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x60, 0x6e, 0xdf, 0x3e, + 0x38, 0xbe, 0xf3, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, 0xd0, 0x7e, 0x22, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x38, 0xbe, 0x73, 0x3f, 0xf8, 0x2e, 0x0e, 0x3f, + 0x5c, 0x6e, 0x5f, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x5a, 0x6e, 0x5f, 0xbf, 0xfd, 0x1a, 0x89, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, + 0x48, 0x96, 0x69, 0x3f, 0x70, 0x46, 0x55, 0x3f, 0xa8, 0xce, 0xb6, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, + 0x38, 0xbe, 0x73, 0x3f, 0xcc, 0x7e, 0x22, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x34, 0xbe, 0x73, 0xbf, 0x88, 0x1e, 0xcb, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0x4b, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0x40, 0xbe, 0x73, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, + 0xa8, 0xce, 0xb6, 0x3e, 0xbc, 0xa6, 0x2c, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xa6, 0xce, 0x36, 0xbf, 0x5c, 0x6e, 0x5f, 0x3f, + 0x20, 0xe6, 0x7d, 0xbf, 0x04, 0x07, 0x04, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0xa2, 0x3e, 0xa8, 0xce, 0xb6, 0xbe, + 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0x22, 0xbe, + 0xf4, 0x2e, 0x0e, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0x88, 0x1e, 0xcb, 0x3e, 0xe0, 0x56, 0x18, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0xbc, 0xa6, 0x2c, 0x3f, + 0x92, 0xf6, 0x40, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, + 0x24, 0xe6, 0x7d, 0x3f, 0xe0, 0x7e, 0xa2, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xd0, 0x7e, 0xa2, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0x38, 0xbe, 0x73, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, + 0x88, 0x1e, 0xcb, 0x3e, 0x80, 0x1e, 0x4b, 0xbf, 0xa8, 0xce, 0x36, 0x3f, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, + 0xcc, 0x7e, 0x22, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xf3, 0x2e, 0x8e, 0xbf, 0x60, 0x6e, 0xdf, 0x3e, 0xd0, 0x7e, 0x22, 0x3e, + 0x38, 0xbe, 0xf3, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbe, 0x73, 0x3e, + 0x88, 0x1e, 0xcb, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x80, 0x1e, 0xcb, 0xbe, 0xa6, 0xce, 0x36, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0x80, 0x1e, 0x4b, 0xbf, 0xf4, 0x2e, 0x0e, 0xbf, 0x30, 0xbe, 0x73, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0x30, 0xbe, 0xf3, 0xbe, 0xa8, 0xce, 0xb6, 0x3e, + 0x60, 0x6e, 0xdf, 0x3e, 0x88, 0x1e, 0xcb, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x08, 0x07, 0x84, 0x3f, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xf8, 0x2e, 0x0e, 0x3f, 0x58, 0x6e, 0xdf, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0x20, 0xbe, 0xf3, 0xbd, 0xcd, 0x7e, 0xa2, 0xbf, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0x22, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0xe4, 0x56, 0x18, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0xa2, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0x98, 0xf6, 0x40, 0x3f, + 0xd0, 0x7e, 0x22, 0x3e, 0x58, 0x6e, 0xdf, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, + 0xa8, 0xce, 0xb6, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, + 0x00, 0x7f, 0x22, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0x73, 0x3e, + 0x20, 0xbe, 0xf3, 0xbd, 0xf6, 0x2e, 0x8e, 0x3f, 0x30, 0xbe, 0x73, 0xbe, + 0x48, 0x96, 0x69, 0x3f, 0xc0, 0x7e, 0xa2, 0xbd, 0x88, 0x1e, 0xcb, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0xc8, 0x7e, 0xa2, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0xbe, + 0x40, 0xbe, 0xf3, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, 0xd0, 0x7e, 0xa2, 0x3e, + 0x6c, 0x46, 0x55, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xd0, 0x7e, 0xa2, 0x3e, + 0x98, 0xf6, 0x40, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0x00, 0x7f, 0x22, 0x3d, + 0xf8, 0x2e, 0x0e, 0x3f, 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0xa2, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x46, 0x96, 0x69, 0xbf, + 0xd0, 0x7e, 0x22, 0x3e, 0x04, 0x07, 0x04, 0xbf, 0x40, 0xbe, 0xf3, 0x3d, + 0x34, 0xbe, 0x73, 0xbf, 0x00, 0x7f, 0x22, 0x3d, 0xf8, 0x2e, 0x0e, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0x88, 0x1e, 0xcb, 0x3e, 0xc4, 0x92, 0xa7, 0xbf, 0xf0, 0x2e, 0x8e, 0xbe, + 0xba, 0xa6, 0x2c, 0xbf, 0xd0, 0x7e, 0x22, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0x22, 0xbd, 0x5c, 0x6e, 0x5f, 0x3f, + 0x20, 0xbe, 0xf3, 0xbd, 0xf8, 0x2e, 0x8e, 0x3e, 0xbc, 0xa6, 0x2c, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0x46, 0x55, 0xbf, 0x08, 0x07, 0x04, 0x3f, + 0x40, 0xbe, 0x73, 0x3e, 0xa8, 0xce, 0x36, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbe, 0xf8, 0x2e, 0x8e, 0x3e, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x80, 0x1e, 0x4b, 0xbf, + 0x58, 0x6e, 0xdf, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xf8, 0x2e, 0x8e, 0x3e, 0x40, 0xbe, 0x73, 0x3e, 0x00, 0x7f, 0x22, 0x3d, + 0x00, 0x7f, 0x22, 0x3d, 0x84, 0x1e, 0x4b, 0x3f, 0x30, 0xbe, 0x73, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0x48, 0x96, 0x69, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, 0xcc, 0x7e, 0x22, 0xbf, + 0x80, 0x1e, 0x4b, 0xbf, 0xa8, 0xce, 0xb6, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0x22, 0x3e, 0x92, 0xf6, 0x40, 0xbf, 0xc0, 0x7e, 0x22, 0xbd, + 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, 0x80, 0x1e, 0xcb, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x5a, 0x6e, 0x5f, 0xbf, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0xa2, 0xbd, 0xa8, 0xce, 0xb6, 0x3e, 0x30, 0xbe, 0x73, 0xbe, + 0xf8, 0x2e, 0x8e, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0x08, 0x07, 0x04, 0x3f, + 0x40, 0xbe, 0xf3, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, 0xc0, 0x7e, 0x22, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0x22, 0xbe, + 0xc0, 0x7e, 0x22, 0xbe, 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xe0, 0x7e, 0xa2, 0x3d, 0x00, 0x7f, 0x22, 0x3d, 0x40, 0xbe, 0xf3, 0x3d, + 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0xfd, 0x1a, 0x89, 0xbf, 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0x80, 0x1e, 0x4b, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0xc0, 0x7e, 0x22, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0xf0, 0x2e, 0x8e, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, 0x00, 0x7f, 0x22, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0x90, 0x1e, 0x4b, 0x3e, 0x40, 0xbe, 0xf3, 0x3d, + 0x30, 0xbe, 0x73, 0xbe, 0x40, 0xbe, 0x73, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0xa2, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xcc, 0x7e, 0x22, 0xbf, 0xe0, 0x56, 0x18, 0xbf, + 0xc0, 0x7e, 0x22, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x4b, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xf8, 0x2e, 0x8e, 0x3e, 0xba, 0xa6, 0x2c, 0xbf, 0xf8, 0x2e, 0x8e, 0x3e, + 0x98, 0xf6, 0x40, 0x3f, 0xf3, 0x2e, 0x8e, 0xbf, 0x90, 0x1e, 0x4b, 0x3e, + 0x58, 0x6e, 0xdf, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x20, 0xbe, 0xf3, 0xbd, + 0xcd, 0x7e, 0xa2, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, 0xba, 0xa6, 0x2c, 0xbf, + 0xf8, 0x2e, 0x8e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x4b, 0xbf, + 0xa8, 0xce, 0xb6, 0x3e, 0xc8, 0x7e, 0xa2, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0xe0, 0x56, 0x18, 0xbf, 0x04, 0x07, 0x04, 0xbf, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0x22, 0xbd, 0xe0, 0x56, 0x18, 0xbf, 0x40, 0xbe, 0x73, 0x3e, + 0xf8, 0x2e, 0x0e, 0x3f, 0x40, 0xbe, 0xf3, 0x3d, 0xf8, 0x2e, 0x0e, 0x3f, + 0xc0, 0x7e, 0xa2, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0xd0, 0x7e, 0xa2, 0x3e, 0xf8, 0x2e, 0x8e, 0x3e, 0xc0, 0x7e, 0x22, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xc0, 0x7e, 0x22, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, + 0x00, 0x7f, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, 0x80, 0x1e, 0x4b, 0xbe, + 0xf0, 0x2e, 0x8e, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xea, 0x42, 0x93, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, 0x80, 0x1e, 0x4b, 0xbe, + 0xc0, 0x7e, 0xa2, 0xbd, 0x80, 0x1e, 0x4b, 0xbf, 0xc0, 0x7e, 0xa2, 0xbd, + 0x40, 0xbe, 0xf3, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x80, 0x1e, 0x4b, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0xe0, 0x7e, 0xa2, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7e, 0xa2, 0xbd, 0xf0, 0x2e, 0x8e, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0x80, 0x1e, 0xcb, 0xbe, 0xf0, 0x2e, 0x8e, 0xbe, + 0x70, 0x46, 0x55, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0xa2, 0xbd, + 0x08, 0x07, 0x04, 0x3f, 0xc0, 0x7e, 0x22, 0xbd, 0x20, 0xbe, 0xf3, 0xbd, + 0xc0, 0x7e, 0x22, 0xbd, 0x04, 0x07, 0x04, 0xbf, 0x80, 0x1e, 0x4b, 0xbe, + 0xa8, 0xce, 0xb6, 0x3e, 0xf8, 0x2e, 0x0e, 0x3f, 0xe4, 0x56, 0x18, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xbe, 0x73, 0xbe, 0x00, 0x7f, 0x22, 0x3d, + 0xe0, 0x7e, 0xa2, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x90, 0x1e, 0x4b, 0x3e, + 0x40, 0xbe, 0xf3, 0x3d, 0xa8, 0xce, 0x36, 0x3f, 0x38, 0xbe, 0xf3, 0x3e, + 0xea, 0x42, 0x93, 0xbf, 0xe0, 0x7e, 0xa2, 0x3d, 0x6c, 0x46, 0x55, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0x48, 0x96, 0x69, 0x3f, + 0x30, 0xbe, 0x73, 0xbe, 0x90, 0x1e, 0x4b, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, + 0x40, 0xbe, 0xf3, 0x3d, 0xf0, 0x2e, 0x8e, 0xbe, 0xba, 0xa6, 0x2c, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xe0, 0x7e, 0xa2, 0x3d, 0x30, 0xbe, 0x73, 0xbe, + 0x30, 0xbe, 0x73, 0xbe, 0x20, 0xbe, 0xf3, 0xbd, 0x98, 0xf6, 0x40, 0x3f, + 0xa8, 0xce, 0xb6, 0x3e, 0xfd, 0x1a, 0x89, 0xbf, 0x48, 0x96, 0x69, 0x3f, + 0xc0, 0x7e, 0x22, 0xbd, 0xc8, 0x7e, 0xa2, 0xbe, 0xc0, 0x7e, 0x22, 0xbd, + 0xc8, 0x7e, 0xa2, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x6c, 0x46, 0x55, 0xbf, + 0xc0, 0x7e, 0x22, 0xbd, 0xf8, 0x2e, 0x0e, 0x3f, 0x30, 0xbe, 0x73, 0xbe, + 0xd0, 0x7e, 0xa2, 0x3e, 0xe0, 0x7e, 0xa2, 0x3d, 0xa8, 0xce, 0xb6, 0x3e, + 0x80, 0x1e, 0x4b, 0xbe, 0x98, 0xf6, 0x40, 0x3f, 0xc0, 0x7e, 0x22, 0xbe, + 0x90, 0x1e, 0x4b, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x40, 0xbe, 0xf3, 0x3d, + 0xc8, 0x7e, 0xa2, 0xbe, 0xe0, 0x7e, 0xa2, 0x3d, 0x60, 0x6e, 0xdf, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xc0, 0x7e, 0xa2, 0xbd, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0x7e, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x7e, 0x22, 0x3e, + 0xf8, 0x2e, 0x8e, 0x3e, 0x20, 0xbe, 0xf3, 0xbd, 0x30, 0xbe, 0x73, 0xbe, + 0x20, 0xbe, 0xf3, 0xbd, 0xa8, 0xce, 0x36, 0x3f, 0x20, 0xbe, 0xf3, 0xbd, + 0x90, 0x1e, 0x4b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x07, 0x04, 0x3f, 0xd0, 0x7e, 0xa2, 0x3e, 0xd0, 0x7e, 0xa2, 0x3e, + 0x00, 0x7f, 0x22, 0x3d, 0xe0, 0x56, 0x18, 0xbf, 0x04, 0x07, 0x04, 0xbf, + 0x20, 0xbe, 0xf3, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, 0xc0, 0x7e, 0x22, 0xbd, + 0xc0, 0x7e, 0x22, 0xbe, 0xa8, 0xce, 0xb6, 0xbe, +}}; +const int32_t dnn_logits_biases__2__cf__2_shape[1] = {1}; const union { uint8_t bytes[4]; float values[1]; -} dnn_hiddenlayer_0_weights__1__cf__1_quantized_max = {{ - 0x6c, 0x68, 0xe9, 0x40, +} dnn_logits_biases__2__cf__2 = {{ + 0xa6, 0x1f, 0x7c, 0xbf, }}; - const int32_t dnn_hiddenlayer_0_biases__0__cf__0_shape[1] = {DNN_BIASES_SIZE}; const union { uint8_t bytes[2 * 2 * DNN_BIASES_SIZE]; float values[DNN_BIASES_SIZE]; } dnn_hiddenlayer_0_biases__0__cf__0 = {{ - 0xa2, 0x4b, 0x7a, 0xbf, 0xe5, 0x87, 0x2d, 0xbf, 0x88, 0x4c, 0x3c, 0x3f, - 0x01, 0x96, 0x04, 0x3e, 0xa5, 0x4c, 0x01, 0xbf, 0x91, 0x91, 0xfc, 0x3e, - 0xb8, 0x55, 0xa1, 0x3e, 0xf4, 0x2e, 0x06, 0xbf, 0x34, 0x8f, 0xcf, 0xbf, - 0x10, 0x78, 0x8a, 0x3e, 0x91, 0x66, 0x29, 0xc0, 0xa4, 0x76, 0x38, 0x3f, - 0x6f, 0x07, 0x0f, 0xbf, 0xcd, 0xff, 0x94, 0xbf, 0xa8, 0x02, 0x42, 0x3f, - 0xe2, 0x79, 0x01, 0xbf, 0x3b, 0x93, 0x28, 0xc0, 0x0f, 0x16, 0xe9, 0xbf, - 0xcb, 0x6f, 0x6b, 0x3f, 0x11, 0x78, 0x17, 0xbf, 0x80, 0x58, 0x02, 0xbe, - 0xfe, 0x94, 0x1c, 0xbf, 0x46, 0x20, 0x2b, 0xbf, 0x16, 0xd9, 0x80, 0xbf, - 0x53, 0x74, 0x42, 0x3f, 0x5d, 0xba, 0x5a, 0x3f, 0xbb, 0xfd, 0x80, 0x3e, - 0xa0, 0x14, 0x4f, 0x3f, 0x3e, 0x50, 0x6d, 0x3d, 0x62, 0x33, 0x30, 0x3e, - 0xfb, 0xe8, 0x44, 0xbd, 0x8f, 0xc8, 0x1a, 0x3f, 0xa8, 0x18, 0x79, 0xbf, - 0x4b, 0x9a, 0x3c, 0x3f, 0xc8, 0xb6, 0x81, 0xbf, 0xf3, 0xc9, 0xa9, 0x3e, - 0xd2, 0x08, 0x83, 0x3d, 0xcd, 0xa2, 0x2d, 0xbd, 0xd2, 0x65, 0x51, 0xbf, - 0x23, 0xdd, 0x4a, 0xbe, + 0x6c, 0xe2, 0x07, 0xbe, 0x14, 0x15, 0x1e, 0xbe, 0xa8, 0xd2, 0x85, 0xbe, + 0x06, 0x40, 0x00, 0xbe, 0xb3, 0xe1, 0x77, 0xbd, 0xd8, 0x95, 0x0b, 0x3d, + 0x32, 0x0e, 0x25, 0x3d, 0xb9, 0x56, 0x9d, 0xbd, 0x30, 0x71, 0x99, 0x3e, + 0xaa, 0x5a, 0x8e, 0xbe, 0x78, 0x29, 0xf0, 0xbd, 0x1b, 0x0f, 0xae, 0x3e, + 0xbd, 0xcd, 0xa7, 0xbf, 0x5f, 0xfe, 0x65, 0xbb, 0xa1, 0xca, 0x84, 0xbd, + 0x0f, 0x2a, 0x64, 0xbe, 0x27, 0x60, 0x4e, 0xbe, 0x4e, 0x28, 0x17, 0xbf, + 0x43, 0x74, 0xc4, 0xbd, 0xe8, 0x49, 0xf0, 0x3c, 0x2d, 0xad, 0xab, 0x3a, + 0xae, 0x02, 0x45, 0xbe, 0xcd, 0xea, 0x24, 0xbe, 0x41, 0x4a, 0x12, 0xbe, + 0xef, 0x7d, 0x46, 0xbd, 0x9e, 0x3a, 0x4e, 0x3d, 0xfb, 0xb0, 0xc0, 0xbd, + 0x81, 0xbd, 0x22, 0xbe, 0x51, 0x0e, 0x6d, 0xbe, 0xab, 0x98, 0x1c, 0xbe, + 0xd1, 0x65, 0xf3, 0xbd, 0x87, 0x52, 0xc7, 0x3e, 0xab, 0x33, 0xb2, 0x3e, + 0xae, 0xca, 0x16, 0xbe, 0x56, 0xb6, 0xbc, 0x3e, 0x0a, 0x85, 0x29, 0xbe, + 0xe7, 0xa0, 0x6a, 0xbe, 0xe1, 0xd7, 0x38, 0xbe, 0x0f, 0x12, 0xdc, 0xbe, + 0xa0, 0x9b, 0x90, 0xbe, }}; } // anonymous namespace @@ -2615,33 +3889,24 @@ FixedAllocations* __restrict fixed) { const int32_t features_shape[] = {1, FEATURES_SIZE}; - // dnn/hiddenlayer_0/weights/_1__cf__1 - DequantizeMinFirst<uint8_t>( - 2, dnn_hiddenlayer_0_weights__1__cf__1_quantized_const_shape, - dnn_hiddenlayer_0_weights__1__cf__1_quantized_const.values, - dnn_hiddenlayer_0_weights__1__cf__1_quantized_min.values, - dnn_hiddenlayer_0_weights__1__cf__1_quantized_max.values, fixed->alloc0); - - fixed->alloc0_shape[0] = FEATURES_SIZE; - fixed->alloc0_shape[1] = DNN_BIASES_SIZE; - // dnn/hiddenlayer_0/MatMul_merged_with_dnn/hiddenlayer_0/BiasAdd - FullyConnected<float>(features_shape, features, fixed->alloc0_shape, - fixed->alloc0, dnn_hiddenlayer_0_biases__0__cf__0_shape, - dnn_hiddenlayer_0_biases__0__cf__0.values, - fixed->alloc1); - fixed->alloc1_shape[0] = 1; - fixed->alloc1_shape[1] = DNN_BIASES_SIZE; - - // dnn/hiddenlayer_0/hiddenlayer_0/Relu - Relu<float>(2, // rank - fixed->alloc1_shape, fixed->alloc1, fixed->alloc0); + FullyConnected<float>( + features_shape, features, dnn_hiddenlayer_0_weights__1__cf__1_shape, + dnn_hiddenlayer_0_weights__1__cf__1.values, + dnn_hiddenlayer_0_biases__0__cf__0_shape, + dnn_hiddenlayer_0_biases__0__cf__0.values, fixed->alloc0); fixed->alloc0_shape[0] = 1; fixed->alloc0_shape[1] = DNN_BIASES_SIZE; + // dnn/hiddenlayer_0/hiddenlayer_0/Relu + Relu<float>(2, // rank + fixed->alloc0_shape, fixed->alloc0, fixed->alloc1); + fixed->alloc1_shape[0] = 1; + fixed->alloc1_shape[1] = DNN_BIASES_SIZE; + // dnn/logits/MatMul_merged_with_dnn/logits/BiasAdd FullyConnected<float>( - fixed->alloc0_shape, fixed->alloc0, dnn_logits_weights__3__cf__3_shape, + fixed->alloc1_shape, fixed->alloc1, dnn_logits_weights__3__cf__3_shape, dnn_logits_weights__3__cf__3.values, dnn_logits_biases__2__cf__2_shape, dnn_logits_biases__2__cf__2.values, prediction); }
diff --git a/chrome/browser/resource_coordinator/tab_ranker/native_inference.h b/chrome/browser/resource_coordinator/tab_ranker/native_inference.h index 26514aa..89e1fd6 100644 --- a/chrome/browser/resource_coordinator/tab_ranker/native_inference.h +++ b/chrome/browser/resource_coordinator/tab_ranker/native_inference.h
@@ -14,13 +14,13 @@ namespace tab_ranker { namespace tfnative_model { -constexpr int DNN_WEIGHTS_SIZE = 29160; constexpr int DNN_RANK = 2; -constexpr int FEATURES_SIZE = 729; +constexpr int FEATURES_SIZE = 281; constexpr int DNN_BIASES_SIZE = 40; +constexpr int DNN_WEIGHTS_SIZE = FEATURES_SIZE * DNN_BIASES_SIZE; struct alignas(16) FixedAllocations { - float alloc0[DNN_WEIGHTS_SIZE]; + float alloc0[DNN_BIASES_SIZE]; int32_t alloc0_shape[DNN_RANK]; float alloc1[DNN_BIASES_SIZE]; int32_t alloc1_shape[DNN_RANK];
diff --git a/chrome/browser/resource_coordinator/tab_ranker/tab_score_predictor.cc b/chrome/browser/resource_coordinator/tab_ranker/tab_score_predictor.cc index c3b8352..9320f21 100644 --- a/chrome/browser/resource_coordinator/tab_ranker/tab_score_predictor.cc +++ b/chrome/browser/resource_coordinator/tab_ranker/tab_score_predictor.cc
@@ -56,6 +56,7 @@ features["HasBeforeUnloadHandler"].set_bool_value( tab.has_before_unload_handler); features["HasFormEntry"].set_bool_value(tab.has_form_entry); + features["IsActive"].set_bool_value(window.is_active); features["IsPinned"].set_bool_value(tab.is_pinned); features["KeyEventCount"].set_int32_value(tab.key_event_count); features["MRUIndex"].set_int32_value(mru.index); @@ -79,6 +80,7 @@ features["SiteEngagementScore"].set_int32_value( tab.site_engagement_score.value()); } + features["ShowState"].set_int32_value(window.show_state); features["TabCount"].set_int32_value(window.tab_count); features["TimeFromBackgrounded"].set_int32_value(tab.time_from_backgrounded); features["TopDomain"].set_string_value(
diff --git a/chrome/browser/resource_coordinator/tab_ranker/tab_score_predictor_unittest.cc b/chrome/browser/resource_coordinator/tab_ranker/tab_score_predictor_unittest.cc index 45c5c5e0..f9cce97 100644 --- a/chrome/browser/resource_coordinator/tab_ranker/tab_score_predictor_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_ranker/tab_score_predictor_unittest.cc
@@ -6,7 +6,6 @@ #include <memory> -#include "base/time/time.h" #include "chrome/browser/resource_coordinator/tab_ranker/mru_features.h" #include "chrome/browser/resource_coordinator/tab_ranker/tab_features.h" #include "chrome/browser/resource_coordinator/tab_ranker/window_features.h" @@ -17,72 +16,18 @@ namespace tab_ranker { namespace { -// A URL whose host is not one of the top sites in the model. -const char* kUnseenHost = "www.example.com"; - -// Returns a set of features for a fairly typcial tab. If |user_activity| is -// true, the features will reflect some amount of user activity, e.g. -// navigations and input events. -// The TabFeatures returned can be used as a baseline for testing how changing a -// feature affects the score, but this is an imperfect testing method because -// features are inter-dependent in our model. -TabFeatures GetTabFeatures(std::string host, bool user_activity = false) { - // Assign typical/reasonable values for background tabs. - TabFeatures tab; - tab.has_before_unload_handler = true; - tab.has_form_entry = false; - tab.host = host; - tab.is_pinned = false; - tab.key_event_count = user_activity ? 20 : 0; - tab.mouse_event_count = user_activity ? 20 : 0; - tab.navigation_entry_count = user_activity ? 4 : 1; - tab.num_reactivations = user_activity ? 1 : 0; - tab.page_transition_core_type = ui::PAGE_TRANSITION_LINK; - tab.page_transition_from_address_bar = true; - tab.page_transition_is_redirect = false; - tab.site_engagement_score = user_activity ? 20 : 0; - tab.time_from_backgrounded = - base::TimeDelta::FromMinutes(10).InMilliseconds(); - // Even tabs with activity usually have 0 touch events. - tab.touch_event_count = 0; - tab.was_recently_audible = false; - - return tab; -} - // Returns a fairly typical set of window features. WindowFeatures GetWindowFeatures() { WindowFeatures window(SessionID::NewUnique(), metrics::WindowMetricsEvent::TYPE_TABBED); window.tab_count = 3; + window.is_active = true; + window.show_state = metrics::WindowMetricsEvent::SHOW_STATE_NORMAL; return window; } -// Returns some MRU features. -// // TODO: find actual nums -MRUFeatures GetMRUFeatures() { - MRUFeatures mru; - mru.index = 3; - mru.total = 6; - return mru; -} - -// These tests try to sanity-check the model by seeing how changing one feature -// impacts the score while everything else remains constant. -// For example, it seems reasonable to expect that a pinned tab would have a -// higher score than an unpinned tab, all else being equal. -// -// This won't always be the case, so these tests will be fragile, but *only* -// when updating the model; if the tests fail without changing the model, -// then the input to the model must have changed, which is probably a -// regression. -// -// If several tests fail locally after updating the model, check whether the -// features are being logged and set correctly, and think about why the model -// might be making counter-intuitive predictions. If everything checks out, try -// to find more realistic tab examples where the feature behaves as expected. -// If that fails, just remove the test -- the point is to avoid accidental model -// regressions, not to force fit a model to these expectations. +// These tests verify that the example_preprocessor_config.pb and +// native_inference.h code together generates correct scores. class TabScorePredictorTest : public testing::Test { public: TabScorePredictorTest() = default; @@ -91,8 +36,8 @@ protected: // Returns a prediction for the tab example. float ScoreTab(const TabFeatures& tab, - const WindowFeatures& window = GetWindowFeatures(), - const MRUFeatures& mru = GetMRUFeatures()) { + const WindowFeatures& window, + const MRUFeatures& mru) { float score = 0; EXPECT_EQ(TabRankerResult::kSuccess, tab_score_predictor_.ScoreTab(tab, window, mru, &score)); @@ -135,7 +80,7 @@ window.tab_count = 27; // Pre-calculated score using the generated model outside of Chrome. - EXPECT_FLOAT_EQ(8.0287771, ScoreTab(tab, window, mru)); + EXPECT_FLOAT_EQ(1.8338085, ScoreTab(tab, window, mru)); } // Checks the score for a different example that we have calculated a known @@ -164,107 +109,7 @@ window.tab_count = 127; // Pre-calculated score using the generated model outside of Chrome. - EXPECT_FLOAT_EQ(10.577342, ScoreTab(tab, window, mru)); -} - -TEST_F(TabScorePredictorTest, InactiveDuration) { - // A tab that has been in the background for a much shorter time is more - // likely to be reactivated. - TabFeatures shorter_example = GetTabFeatures(kUnseenHost); - TabFeatures longer_example = GetTabFeatures(kUnseenHost); - shorter_example.time_from_backgrounded = - base::TimeDelta::FromMinutes(1).InMilliseconds(); - longer_example.time_from_backgrounded = - base::TimeDelta::FromMinutes(1000).InMilliseconds(); - ASSERT_GT(ScoreTab(shorter_example), ScoreTab(longer_example)); -} - -TEST_F(TabScorePredictorTest, NavigationEntryCount) { - TabFeatures example = GetTabFeatures(kUnseenHost, true /*user_activity*/); - float default_score = ScoreTab(example); - - // A tab with more navigations is more likely to be reactivated. - example.navigation_entry_count = 10; - float navigated_score = ScoreTab(example); - ASSERT_GT(navigated_score, default_score); -} - -TEST_F(TabScorePredictorTest, NumReactivationBefore) { - TabFeatures example = GetTabFeatures(kUnseenHost, true /*user_activity*/); - example.num_reactivations = 0; - float no_reactivations_score = ScoreTab(example); - - // A tab with reactivations is more likely to be reactivated than one without. - example.num_reactivations = 10; - float reactivations_score = ScoreTab(example); - ASSERT_GT(reactivations_score, no_reactivations_score); - - // A tab with more reactivations is more likely to be reactivated. - example.num_reactivations = 20; - float more_reactivations_score = ScoreTab(example); - ASSERT_GT(more_reactivations_score, reactivations_score); -} - -TEST_F(TabScorePredictorTest, PageTransitionTypes) { - TabFeatures example = GetTabFeatures(kUnseenHost, true /*user_activity*/); - - example.page_transition_core_type = ui::PAGE_TRANSITION_LINK; - float link_score = ScoreTab(example); - - example.page_transition_core_type = ui::PAGE_TRANSITION_RELOAD; - float reload_score = ScoreTab(example); - - // A tab the user manually reloaded is more likely to be reactivated. - ASSERT_GT(reload_score, link_score); -} - -TEST_F(TabScorePredictorTest, SiteEngagementScore) { - TabFeatures example = GetTabFeatures(kUnseenHost, true /*user_activity*/); - example.site_engagement_score.reset(); - float engagement_score_0 = ScoreTab(example); - - // A site with low engagement ranks higher than one with no engagement. - example.site_engagement_score = 10; - float engagement_score_low = ScoreTab(example); - ASSERT_GT(engagement_score_low, engagement_score_0); - - // A site with moderate engagement ranks higher than one with low engagement. - example.site_engagement_score = 50; - float engagement_score_medium = ScoreTab(example); - ASSERT_GT(engagement_score_medium, engagement_score_low); - - example.site_engagement_score = 80; - float engagement_score_high = ScoreTab(example); - ASSERT_GT(engagement_score_high, engagement_score_medium); -} - -TEST_F(TabScorePredictorTest, TopURLHigherScore) { - // mail.google.com is more likely to be reactivated (ie, the user is more - // likely to return to a mail tab than an ordinary tab). - TabFeatures unseen_example = GetTabFeatures(kUnseenHost, true - /*user_activity*/); - TabFeatures higher_example = GetTabFeatures("mail.google.com", true - /*user_activity*/); - ASSERT_GT(ScoreTab(higher_example), ScoreTab(unseen_example)); -} - -TEST_F(TabScorePredictorTest, TopURLLowerScore) { - // Expect www.google.com tabs to be less likely to be reactivated. - TabFeatures unseen_example = - GetTabFeatures(kUnseenHost, true /*user_activity*/); - TabFeatures lower_example = - GetTabFeatures("www.google.com", true /*user_activity*/); - ASSERT_LT(ScoreTab(lower_example), ScoreTab(unseen_example)); -} - -TEST_F(TabScorePredictorTest, WasRecentlyAudible) { - TabFeatures example = GetTabFeatures(kUnseenHost, true /*user_activity*/); - float default_score = ScoreTab(example); - - // A recently audible tab is more likely to be reactivated. - example.was_recently_audible = true; - float recently_audible_score = ScoreTab(example); - ASSERT_GT(recently_audible_score, default_score); + EXPECT_FLOAT_EQ(8.7163248, ScoreTab(tab, window, mru)); } } // namespace tab_ranker
diff --git a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js index ec7bf67..146cd5c4 100644 --- a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js +++ b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js
@@ -10,7 +10,6 @@ const recommendAppsContainer = doc.getElementById('recommend-apps-container'); const item = doc.createElement('div'); item.classList.add('item'); - item.classList.add('checked'); item.setAttribute('data-packagename', appPackageName); const imagePicker = doc.createElement('div');
diff --git a/chrome/browser/resources/chromeos/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/chromevox/BUILD.gn index 9e91ae9..144f489 100644 --- a/chrome/browser/resources/chromeos/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/chromevox/BUILD.gn
@@ -30,6 +30,7 @@ "braille/braille_key_types.js", "braille/braille_table.js", "braille/braille_translator_manager.js", + "braille/bluetooth_braille_display_manager.js", "braille/expanding_braille_translator.js", "braille/liblouis.js", "braille/nav_braille.js", @@ -557,6 +558,7 @@ js2gtest("chromevox_unitjs_tests") { test_type = "webui" sources = [ + "braille/bluetooth_braille_display_manager_test.unitjs", "braille/braille_display_manager_test.unitjs", "braille/braille_input_handler_test.unitjs", "braille/expanding_braille_translator_test.unitjs",
diff --git a/chrome/browser/resources/chromeos/chromevox/braille/bluetooth_braille_display_manager.js b/chrome/browser/resources/chromeos/chromevox/braille/bluetooth_braille_display_manager.js new file mode 100644 index 0000000..1270f25 --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/braille/bluetooth_braille_display_manager.js
@@ -0,0 +1,215 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Abstracts away the details of chrome.bluetooth, + * chrome.bluetoothPrivate, and chrome.brailleDisplayPrivate for a UI component + * to interact with a bluetooth braille display. + */ + +goog.provide('BluetoothBrailleDisplayManager'); +goog.provide('BluetoothBrailleDisplayListener'); + +/** + * @interface + */ +BluetoothBrailleDisplayListener = function() {}; + +BluetoothBrailleDisplayListener.prototype = { + /** + * @param {!Array<chrome.bluetooth.Device>} displays + */ + onDisplayListChanged: function(displays) {}, + /** + * Called when a pincode is requested and a response can be made by calling + * BluetoothBrailleDisplayManager.finishPairing. + */ + onPincodeRequested: function() {}, +}; + +/** + * Manages interaction with the bluetooth and braille subsystems in Chrome. + * + * A caller can use this class by doing: + * var manager = new BluetoothBrailleDisplayManager(); + * manager.addListener(listenerObject); // listenerObject receives updates on + * // important events in bluetooth. + * manager.start(); // Starts bluetooth discovery. + * manager.connect(); // Connects to a discovered device received in the + * // listenerObject. + * manager.finishPairing(); // If a pairing request is sent to the + * // listenerObject, this is how a caller can respond. + * manager.stop(); // Stops discovery, but persists connections. + * @constructor + */ +BluetoothBrailleDisplayManager = function() { + /** @private {!Array<BluetoothBrailleDisplayListener>} */ + this.listeners_ = []; + + /** @private {!Array<string>} */ + this.displayNames_ = ['Focus 40 BT']; + + /** + * The display explicitly preferred by a caller via connect. Only one such + * display exists at a time. + * @private {string?} + */ + this.preferredDisplayAddress_ = + localStorage['preferredBrailleDisplayAddress']; + + /** + * Tracks whether the preferred display is connected. + * @private {boolean|null|undefined} + */ + this.preferredDisplayConnected_; + + chrome.bluetooth.onDeviceAdded.addListener( + this.handleDevicesChanged.bind(this)); + chrome.bluetooth.onDeviceChanged.addListener( + this.handleDevicesChanged.bind(this)); + chrome.bluetooth.onDeviceRemoved.addListener( + this.handleDevicesChanged.bind(this)); + chrome.bluetoothPrivate.onPairing.addListener(this.handlePairing.bind(this)); +}; + +BluetoothBrailleDisplayManager.prototype = { + /** + * Adds a new listener. + * @param {BluetoothBrailleDisplayListener} listener + */ + addListener: function(listener) { + this.listeners_.push(listener); + }, + + /** + * Starts discovering bluetooth devices. + */ + start: function() { + chrome.bluetooth.startDiscovery(); + }, + + /** + * Stops discovering bluetooth devices. + */ + stop: function() { + chrome.bluetooth.stopDiscovery(); + }, + + /** + * Connects to the given display. + *@param{!chrome.bluetooth.Device} display + */ + connect: function(display) { + if (this.preferredDisplayAddress_ === display.address || + !this.preferredDisplayAddress_) { + this.connectInternal(display); + } else { + chrome.bluetoothPrivate.disconnectAll( + this.preferredDisplayAddress_, () => { + this.connectInternal(display); + }); + } + }, + + /** + * @param{!chrome.bluetooth.Device} display + * @protected * + */ + connectInternal: function(display) { + this.preferredDisplayAddress_ = display.address; + localStorage['preferredBrailleDisplayAddress'] = display.address; + if (!display.connected) { + chrome.bluetoothPrivate.connect(display.address, (result) => { + if (!display.paired) + chrome.bluetoothPrivate.pair(display.address); + }); + return; + } + + if (!display.paired) + chrome.bluetoothPrivate.pair(display.address); + }, + + /** + * Disconnects the given display and clears it from Brltty. + * @param{!chrome.bluetooth.Device} display + */ + disconnect: function(display) { + chrome.bluetoothPrivate.disconnectAll(display.address); + chrome.brailleDisplayPrivate.updateBluetoothBrailleDisplayAddress(''); + }, + + /** + * Forgets the given display. + * @param {!chrome.bluetooth.Device} display + */ + forget: function(display) { + chrome.bluetoothPrivate.forgetDevice(display.address); + chrome.brailleDisplayPrivate.updateBluetoothBrailleDisplayAddress(''); + }, + + /** + * Finishes pairing in response to + * BluetoothBrailleDisplayListener.onPincodeRequested. + * @param{!chrome.bluetooth.Device} display + * @param{string} pincode * + */ + finishPairing: function(display, pincode) { + chrome.bluetoothPrivate.setPairingResponse( + {response: 'confirm', device: display, pincode: pincode}, () => {}); + }, + + /** + * @param{ chrome.bluetooth.Device=} opt_device + * @protected + */ + handleDevicesChanged: function(opt_device) { + chrome.bluetooth.getDevices((devices) => { + var displayList = devices.filter((device) => { + return this.displayNames_.some((name) => { + return device.name && device.name.indexOf(name) == 0; + }); + }); + if (displayList.length == 0) + return; + if (opt_device && !displayList.find((i) => i.name == opt_device.name)) + return; + + displayList.forEach((display) => { + if (this.preferredDisplayAddress_ == display.address) + this.handlePreferredDisplayConnectionStateChanged(display); + }); + this.listeners_.forEach((listener) => { + listener.onDisplayListChanged(displayList); + }); + }); + }, + + /** + * @param{chrome.bluetoothPrivate.PairingEvent} pairingEvent + * @protected + */ + handlePairing: function(pairingEvent) { + if (pairingEvent.pairing == + chrome.bluetoothPrivate.PairingEventType.REQUEST_PINCODE) + this.listeners_.forEach((listener) => listener.onPincodeRequested()); + }, + + /** + * @param{chrome.bluetooth.Device} display + * @protected + */ + handlePreferredDisplayConnectionStateChanged: function(display) { + if (display.connected === this.preferredDisplayConnected_) + return; + + this.preferredDisplayConnected_ = display.connected; + + // We do not clear the address seen by Brltty unless the caller explicitly + // disconnects or forgets the display via the public methods of this class. + if (display.connected) + chrome.brailleDisplayPrivate.updateBluetoothBrailleDisplayAddress( + display.address); + } +};
diff --git a/chrome/browser/resources/chromeos/chromevox/braille/bluetooth_braille_display_manager_test.unitjs b/chrome/browser/resources/chromeos/chromevox/braille/bluetooth_braille_display_manager_test.unitjs new file mode 100644 index 0000000..bc50a7aa --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/braille/bluetooth_braille_display_manager_test.unitjs
@@ -0,0 +1,227 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Include test fixture. +GEN_INCLUDE(['../testing/chromevox_unittest_base.js']); + +GEN_INCLUDE(['../testing/fake_objects.js']); + +// Fake out the Chrome API namespace we depend on. +var chrome = {}; +/** Fake chrome.brailleDisplayPrivate object. */ +chrome.brailleDisplayPrivate = {}; +/** Fake chrome.bluetooth object. */ +chrome.bluetooth = {}; +chrome.bluetooth.getDevices = (devices) => {}; +chrome.bluetooth.onDeviceAdded = new FakeChromeEvent(); +chrome.bluetooth.onDeviceChanged = new FakeChromeEvent(); +chrome.bluetooth.onDeviceRemoved = new FakeChromeEvent(); +/** Fake chrome.bluetoothPrivate object. */ +chrome.bluetoothPrivate = {}; +chrome.bluetoothPrivate.onPairing = new FakeChromeEvent(); +/** Fake chrome.accessibilityPrivate object. */ +chrome.accessibilityPrivate = {}; + +/** + * A fake BluetoothBraileDisplayManagerListener. + * @constructor + */ +function FakeBluetoothBrailleDisplayManagerListener() { + this.displays = []; + this.wasPincodeRequested = false; +}; + +FakeBluetoothBrailleDisplayManagerListener.prototype = { + onDisplayListChanged : function(displays){this.displays = displays; +} +, onPincodeRequested : function(displays) { + this.wasPincodeRequested = true; +} +, +} +; + +/** + * Test fixture. + * @constructor + * @extends {ChromeVoxUnitTestBase} + */ +function ChromeVoxBluetoothBrailleDisplayManagerUnitTest() { + ChromeVoxUnitTestBase.call(this); +} + +ChromeVoxBluetoothBrailleDisplayManagerUnitTest.prototype = { + __proto__ : ChromeVoxUnitTestBase.prototype, + + /** @override */ + isAsync : true, + + /** @override */ + closureModuleDeps : [ + 'BluetoothBrailleDisplayManager', + ] +}; + +TEST_F( + 'ChromeVoxBluetoothBrailleDisplayManagerUnitTest', + 'Connect', + function() { + var connectCalled = false; + chrome.bluetoothPrivate.connect = (result, callback) => { + connectCalled = true; + callback(); + }; + chrome.bluetoothPrivate.disconnectAll = assertNotReached; + chrome.bluetoothPrivate.pair = this.newCallback(); + var manager = new BluetoothBrailleDisplayManager(); + manager.connect({address : 'abcd', connected : false, paired : false}); + assertTrue(connectCalled); + }); + +TEST_F( + 'ChromeVoxBluetoothBrailleDisplayManagerUnitTest', + 'ConnectAlreadyPaired', + function() { + chrome.bluetoothPrivate.connect = this.newCallback(); + chrome.bluetoothPrivate.disconnectAll = assertNotReached; + chrome.bluetoothPrivate.pair = assertNotReached; + var manager = new BluetoothBrailleDisplayManager(); + manager.connect({address : 'abcd', connected : false, paired : true}); + }); + +TEST_F( + 'ChromeVoxBluetoothBrailleDisplayManagerUnitTest', + 'ConnectAlreadyConnectedNotPaired', + function() { + chrome.bluetoothPrivate.connect = assertNotReached; + chrome.bluetoothPrivate.disconnectAll = assertNotReached; + chrome.bluetoothPrivate.pair = this.newCallback(); + var manager = new BluetoothBrailleDisplayManager(); + manager.connect({address : 'abcd', connected : true, paired : false}); + }); + +TEST_F( + 'ChromeVoxBluetoothBrailleDisplayManagerUnitTest', + 'DisconnectPreviousPreferredOnConnectNewPreferred', + function() { + chrome.bluetoothPrivate.connect = + this.newCallback((address) => { assertEquals('abcd', address); }); + chrome.bluetoothPrivate.disconnectAll = + this.newCallback((address, callback) => { + assertEquals('1234', address); + callback(); + }); + localStorage['preferredBrailleDisplayAddress'] = '1234'; + var manager = new BluetoothBrailleDisplayManager(); + manager.connect({address : 'abcd', connected : false, paired : false}); + }); + +TEST_F( + 'ChromeVoxBluetoothBrailleDisplayManagerUnitTest', + 'ReconnectPreferred', + function() { + chrome.bluetoothPrivate.connect = this.newCallback(); + chrome.bluetoothPrivate.disconnectAll = assertNotReached; + localStorage['preferredBrailleDisplayAddress'] = 'abcd'; + var manager = new BluetoothBrailleDisplayManager(); + manager.connect({address : 'abcd', connected : false, paired : false}); + }); + +SYNC_TEST_F( + 'ChromeVoxBluetoothBrailleDisplayManagerUnitTest', + 'Listener', + function() { + var manager = new BluetoothBrailleDisplayManager(); + var listener = new FakeBluetoothBrailleDisplayManagerListener(); + manager.addListener(listener); + var devices = []; + chrome.bluetooth.getDevices = (callback) => callback(devices); + + // No devices have been added, removed, or changed. + manager.handleDevicesChanged(); + assertEquals(0, listener.displays.length); + + // A recognized braille display was added. + devices = [ {name : 'Focus 40 BT', address : '1234'} ]; + manager.handleDevicesChanged(); + assertEquals(1, listener.displays.length); + assertEquals('Focus 40 BT', listener.displays[0].name); + + // An unrecognized device was added. + devices = [ + {name : 'Focus 40 BT', address : '1234'}, + {name : 'headphones', address : '4321'} + ]; + manager.handleDevicesChanged(); + assertEquals(1, listener.displays.length); + assertEquals('Focus 40 BT', listener.displays[0].name); + + // A named variant of Focus 40 BT was added. + devices = [ + {name : 'Focus 40 BT', address : '1234'}, + {name : 'Focus 40 BT rev 123', address : '4321'} + ]; + manager.handleDevicesChanged(); + assertEquals(2, listener.displays.length); + assertEquals('Focus 40 BT', listener.displays[0].name); + assertEquals('Focus 40 BT rev 123', listener.displays[1].name); + }); + +TEST_F( + 'ChromeVoxBluetoothBrailleDisplayManagerUnitTest', + 'ConnectPreferredTriggersBrlttyUpdate', + function() { + chrome.brailleDisplayPrivate.updateBluetoothBrailleDisplayAddress = + this.newCallback((address) => { assertEquals('abcd', address); }); + + localStorage['preferredBrailleDisplayAddress'] = 'abcd'; + var manager = new BluetoothBrailleDisplayManager(); + var devices = []; + chrome.bluetooth.getDevices = (callback) => callback(devices); + + // No devices. + manager.handleDevicesChanged(); + + // A different device. + devices = [ {name : 'Headhpones', address : '1234', connected : true} ]; + manager.handleDevicesChanged(); + + // A focus, but different address. + devices = [ {name : 'Focus 40 BT', address : '1234', connected : true} ]; + manager.handleDevicesChanged(); + + // Finally, a device that is both connected and is our preferred device. + devices = [ {name : 'Focus 40 BT', address : 'abcd', connected : true} ]; + manager.handleDevicesChanged(); + }); + +TEST_F( + 'ChromeVoxBluetoothBrailleDisplayManagerUnitTest', + 'ForgetPreferredTriggersBrlttyUpdate', + function() { + chrome.bluetoothPrivate.forgetDevice = this.newCallback(); + chrome.brailleDisplayPrivate.updateBluetoothBrailleDisplayAddress = + this.newCallback((address) => { assertEquals('', address); }); + + var manager = new BluetoothBrailleDisplayManager(); + + // Forget the preferred device. Note there is no requirement that this + // device be preferred. + manager.forget('abcd'); + }); + +TEST_F( + 'ChromeVoxBluetoothBrailleDisplayManagerUnitTest', + 'DisconnectPreferredTriggersBrlttyUpdate', + function() { + chrome.bluetoothPrivate.disconnectAll = this.newCallback(); + chrome.brailleDisplayPrivate.updateBluetoothBrailleDisplayAddress = + this.newCallback((address) => { assertEquals('', address); }); + + var manager = new BluetoothBrailleDisplayManager(); + + // Disconnect the preferred device. Note there is no requirement that this + // device be preferred. + manager.disconnect('abcd'); + });
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js b/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js index 739fa68..faf846eb 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js
@@ -9,6 +9,7 @@ goog.provide('cvox.OptionsPage'); +goog.require('BluetoothBrailleDisplayManager'); goog.require('ConsoleTts'); goog.require('EventStreamLogger'); goog.require('Msgs');
diff --git a/chrome/browser/resources/chromeos/chromevox/host/chrome/externs.js b/chrome/browser/resources/chromeos/chromevox/host/chrome/externs.js index 21931e7..b51f998 100644 --- a/chrome/browser/resources/chromeos/chromevox/host/chrome/externs.js +++ b/chrome/browser/resources/chromeos/chromevox/host/chrome/externs.js
@@ -31,6 +31,13 @@ */ chrome.brailleDisplayPrivate.writeDots = function(cells, columns, rows) {}; + +/** + * @param {string} address + */ +chrome.brailleDisplayPrivate.updateBluetoothBrailleDisplayAddress = function( + address) {}; + /** * @const */
diff --git a/chrome/browser/resources/chromeos/chromevox/testing/assert_additions.js b/chrome/browser/resources/chromeos/chromevox/testing/assert_additions.js index 9e7a597..81af301 100644 --- a/chrome/browser/resources/chromeos/chromevox/testing/assert_additions.js +++ b/chrome/browser/resources/chromeos/chromevox/testing/assert_additions.js
@@ -103,5 +103,12 @@ assertEquals(JSON.stringify(arrayA), JSON.stringify(arrayB)); } +/** + * Asserts and fails immediately once called. + */ +function assertNotReached() { + assertFalse(true); +} + assertSame = assertEquals; assertNotSame = assertNotEquals;
diff --git a/chrome/browser/resources/print_preview/new/destination_settings.html b/chrome/browser/resources/print_preview/new/destination_settings.html index a7302ad..8200b9db 100644 --- a/chrome/browser/resources/print_preview/new/destination_settings.html +++ b/chrome/browser/resources/print_preview/new/destination_settings.html
@@ -17,6 +17,7 @@ <link rel="import" href="print_preview_shared_css.html"> <link rel="import" href="throbber_css.html"> <link rel="import" href="settings_section.html"> +<link rel="import" href="state.html"> <link rel="import" href="strings.html"> <dom-module id="print-preview-destination-settings">
diff --git a/chrome/browser/resources/print_preview/new/destination_settings.js b/chrome/browser/resources/print_preview/new/destination_settings.js index e16574bf..0fb6bd5 100644 --- a/chrome/browser/resources/print_preview/new/destination_settings.js +++ b/chrome/browser/resources/print_preview/new/destination_settings.js
@@ -59,7 +59,7 @@ */ shouldDisableButton_: function() { return !this.destinationStore || - (this.disabled && + (this.disabled && this.state != print_preview_new.State.NOT_READY && this.state != print_preview_new.State.INVALID_PRINTER); },
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index e5857a3..b7dce52 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1388,6 +1388,8 @@ "ash/multi_user/multi_user_window_manager_chromeos.h", "ash/multi_user/multi_user_window_manager_stub.cc", "ash/multi_user/multi_user_window_manager_stub.h", + "ash/multi_user/user_switch_animator_chromeos.cc", + "ash/multi_user/user_switch_animator_chromeos.h", "ash/network/data_promo_notification.cc", "ash/network/data_promo_notification.h", "ash/network/enrollment_dialog_view.cc",
diff --git a/chrome/browser/ui/ash/launcher/DEPS b/chrome/browser/ui/ash/launcher/DEPS index b870e12..192ab8b 100644 --- a/chrome/browser/ui/ash/launcher/DEPS +++ b/chrome/browser/ui/ash/launcher/DEPS
@@ -7,10 +7,6 @@ "arc_app_window_launcher_controller\.cc": [ "+ash/shell.h", ], - # https://crbug.com/875111 - "chrome_launcher_controller_unittest\.cc": [ - "+ash/multi_user/multi_user_window_manager.h", - ], # https://crbug.com/887156 "crostini_app_window_shelf_controller\.cc": [ "+ash/shell.h",
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc index efe84d3..ed06101 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -15,7 +15,6 @@ #include <vector> #include "ash/display/display_configuration_controller.h" -#include "ash/multi_user/multi_user_window_manager.h" #include "ash/public/cpp/app_list/internal_app_id_constants.h" #include "ash/public/cpp/shelf_item.h" #include "ash/public/cpp/shelf_item_delegate.h" @@ -1254,9 +1253,7 @@ const std::string email_string = user_name + "@example.com"; const AccountId account_id(AccountId::FromUserEmail(email_string)); // Add a user to the fake user manager. - auto* user = GetFakeUserManager()->AddUser(account_id); - ash_test_helper()->test_session_controller_client()->AddUserSession( - user->GetDisplayEmail()); + GetFakeUserManager()->AddUser(account_id); GetFakeUserManager()->LoginUser(account_id); @@ -1276,9 +1273,12 @@ // Switch to another user. void SwitchActiveUser(const AccountId& account_id) { GetFakeUserManager()->SwitchActiveUser(account_id); - ash::MultiUserWindowManager::Get()->SetAnimationSpeedForTest( - ash::MultiUserWindowManager::ANIMATION_SPEED_DISABLED); - ash::MultiUserWindowManager::Get()->OnActiveUserSessionChanged(account_id); + MultiUserWindowManagerChromeOS* manager = + static_cast<MultiUserWindowManagerChromeOS*>( + MultiUserWindowManager::GetInstance()); + manager->SetAnimationSpeedForTest( + MultiUserWindowManagerChromeOS::ANIMATION_SPEED_DISABLED); + manager->ActiveUserChanged(GetFakeUserManager()->FindUser(account_id)); launcher_controller_->browser_status_monitor_for_test()->ActiveUserChanged( account_id.GetUserEmail());
diff --git a/chrome/browser/ui/ash/multi_user/DEPS b/chrome/browser/ui/ash/multi_user/DEPS index 1a1ad789..6829ed24 100644 --- a/chrome/browser/ui/ash/multi_user/DEPS +++ b/chrome/browser/ui/ash/multi_user/DEPS
@@ -1,12 +1,14 @@ specific_include_rules = { - # https://crbug.com/756085 - "multi_user_window_manager_chromeos\.*": [ - "+ash/multi_user/multi_user_window_manager.h", - "+ash/multi_user/multi_user_window_manager_delegate.h", + # mash-ok. For Shell::tablet_mode_controller() (!mash) + "multi_user_window_manager_chromeos\.cc": [ + "+ash/shell.h", + "+ash/wm/tablet_mode/tablet_mode_controller.h", ], - # https://crbug.com/875111 - "multi_user_window_manager_chromeos_unittest\.cc": [ - "+ash/multi_user/user_switch_animator.h", - "+ash/session/session_controller.h", + # https://crbug.com/756085 + "user_switch_animator_chromeos\.cc": [ + "+ash/app_list/app_list_controller_impl.h", + "+ash/shell.h", + "+ash/wm/mru_window_tracker.h", + "+ash/wm/window_positioner.h", ], }
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc index 5d44e7b1..1e0e655 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc
@@ -76,14 +76,14 @@ multi_user_window_manager_ = new MultiUserWindowManagerChromeOS(AccountId::FromUserEmail("A")); multi_user_window_manager_->Init(); - ::MultiUserWindowManager::SetInstanceForTest(multi_user_window_manager_); + MultiUserWindowManager::SetInstanceForTest(multi_user_window_manager_); EXPECT_TRUE(multi_user_window_manager_); } void MultiUserContextMenuChromeOSTest::TearDown() { delete window_; - ::MultiUserWindowManager::DeleteInstance(); + MultiUserWindowManager::DeleteInstance(); AshTestBase::TearDown(); }
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager.h b/chrome/browser/ui/ash/multi_user/multi_user_window_manager.h index cc97703..ff84e8d8 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager.h +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager.h
@@ -34,14 +34,6 @@ // clean automatically all references of that window upon destruction. // - User changes will be tracked via observer. No need to call. // - All child windows will be owned by the same owner as its parent. -// -// WARNING: in mash this code ends up referencing windows with an aura Env -// of MUS *and* windows with an aura Env of LOCAL. This is because Arc/Crostini -// windows are created by Ash, and browser/app windows are created by the -// browser. Long term this code needs to be refactored out of chrome, at which -// time *all* windows should be created by Ash. https://crbug.com/875111 -// -// TODO(sky): rename this (and related classes). class MultiUserWindowManager { public: // Observer to notify of any window owner changes.
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc index 7184725..f2c4cc33 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
@@ -7,15 +7,21 @@ #include <set> #include <vector> -#include "ash/multi_user/multi_user_window_manager.h" +#include "ash/public/cpp/shell_window_ids.h" +#include "ash/public/interfaces/ash_window_manager.mojom.h" +#include "ash/shell.h" // mash-ok +#include "ash/wm/tablet_mode/tablet_mode_controller.h" // mash-ok +#include "base/auto_reset.h" +#include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" +#include "chrome/browser/ui/ash/media_client.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" +#include "chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h" #include "chrome/browser/ui/ash/session_controller_client.h" #include "chrome/browser/ui/ash/session_util.h" #include "chrome/browser/ui/browser.h" @@ -26,11 +32,32 @@ #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/mus/window_mus.h" +#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/window.h" +#include "ui/aura/window_event_dispatcher.h" +#include "ui/aura/window_tree_host.h" +#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_types.h" +#include "ui/events/event.h" +#include "ui/views/mus/mus_client.h" +#include "ui/wm/core/transient_window_manager.h" +#include "ui/wm/core/window_animations.h" +#include "ui/wm/core/window_util.h" namespace { +// The animation time in milliseconds for a single window which is fading +// in / out. +const int kAnimationTimeMS = 100; + +// The animation time in milliseconds for the fade in and / or out when +// switching users. +const int kUserFadeTimeMS = 110; + +// The animation time in ms for a window which get teleported to another screen. +const int kTeleportAnimationTimeMS = 300; + // Used for UMA metrics. Do not reorder. enum TeleportWindowType { TELEPORT_WINDOW_BROWSER = 0, @@ -80,8 +107,58 @@ NUM_TELEPORT_WINDOW_TYPES); } +bool HasSystemModalTransientChildWindow(aura::Window* window) { + if (window == nullptr) + return false; + + aura::Window* system_modal_container = window->GetRootWindow()->GetChildById( + ash::kShellWindowId_SystemModalContainer); + if (window->parent() == system_modal_container) + return true; + + aura::Window::Windows::const_iterator it = + wm::GetTransientChildren(window).begin(); + for (; it != wm::GetTransientChildren(window).end(); ++it) { + if (HasSystemModalTransientChildWindow(*it)) + return true; + } + return false; +} + } // namespace +// A class to temporarily change the animation properties for a window. +class AnimationSetter { + public: + AnimationSetter(aura::Window* window, int animation_time_in_ms) + : window_(window), + previous_animation_type_(wm::GetWindowVisibilityAnimationType(window_)), + previous_animation_time_( + wm::GetWindowVisibilityAnimationDuration(*window_)) { + wm::SetWindowVisibilityAnimationType( + window_, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); + wm::SetWindowVisibilityAnimationDuration( + window_, base::TimeDelta::FromMilliseconds(animation_time_in_ms)); + } + + ~AnimationSetter() { + wm::SetWindowVisibilityAnimationType(window_, previous_animation_type_); + wm::SetWindowVisibilityAnimationDuration(window_, previous_animation_time_); + } + + private: + // The window which gets used. + aura::Window* window_; + + // Previous animation type. + const int previous_animation_type_; + + // Previous animation time. + const base::TimeDelta previous_animation_time_; + + DISALLOW_COPY_AND_ASSIGN(AnimationSetter); +}; + // This class keeps track of all applications which were started for a user. // When an app gets created, the window will be tagged for that user. Note // that the destruction does not need to be tracked here since the universal @@ -108,13 +185,25 @@ MultiUserWindowManagerChromeOS::MultiUserWindowManagerChromeOS( const AccountId& current_account_id) : current_account_id_(current_account_id), - ash_multi_user_window_manager_( - std::make_unique<ash::MultiUserWindowManager>(this, - current_account_id)) {} + suppress_visibility_changes_(false), + animation_speed_(ANIMATION_SPEED_NORMAL) { + if (features::IsUsingWindowService()) { + ash_window_manager_ = + views::MusClient::Get() + ->window_tree_client() + ->BindWindowManagerInterface<ash::mojom::AshWindowManager>(); + } + + if (TabletModeClient::Get()) + tablet_mode_observer_.Add(TabletModeClient::Get()); +} MultiUserWindowManagerChromeOS::~MultiUserWindowManagerChromeOS() { - // This may trigger callbacks to us, delete it early on. - ash_multi_user_window_manager_.reset(); + // When the MultiUserWindowManager gets destroyed, ash::Shell is mostly gone. + // As such we should not try to finalize any outstanding user animations. + // Note that the destruction of the object can be done later. + if (animation_.get()) + animation_->CancelAnimation(); // Remove all window observers. WindowToEntryMap::iterator window = window_to_entry_.begin(); @@ -126,6 +215,9 @@ window = window_to_entry_.begin(); } + if (user_manager::UserManager::IsInitialized()) + user_manager::UserManager::Get()->RemoveSessionStateObserver(this); + // Remove all app observers. ProfileManager* profile_manager = g_browser_process->profile_manager(); // might be nullptr in unit tests. @@ -152,6 +244,10 @@ DCHECK(account_id_to_app_observer_.find(current_account_id_) == account_id_to_app_observer_.end()); + // Add a session state observer to be able to monitor session changes. + if (user_manager::UserManager::IsInitialized()) + user_manager::UserManager::Get()->AddSessionStateObserver(this); + // The BrowserListObserver would have been better to use then the old // notification system, but that observer fires before the window got created. registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED, @@ -172,23 +268,31 @@ DCHECK(account_id.is_valid()); if (GetWindowOwner(window) == account_id) return; - DCHECK(GetWindowOwner(window).empty()); window_to_entry_[window] = new WindowEntry(account_id); - ash_multi_user_window_manager_->SetWindowOwner(window, account_id); + // Remember the initial visibility of the window. + window_to_entry_[window]->set_show(window->IsVisible()); // Add observers to track state changes. window->AddObserver(this); + wm::TransientWindowManager::GetOrCreate(window)->AddObserver(this); // Check if this window was created due to a user interaction. If it was, // transfer it to the current user. if (window->GetProperty(aura::client::kCreatedByUserGesture)) window_to_entry_[window]->set_show_for_user(current_account_id_); + // Add all transient children to our set of windows. Note that the function + // will add the children but not the owner to the transient children map. + AddTransientOwnerRecursive(window, window); + // Notify entry adding. for (Observer& observer : observers_) observer.OnOwnerEntryAdded(window); + + if (!IsWindowOnDesktopOfUser(window, current_account_id_)) + SetWindowVisibility(window, false, 0); } const AccountId& MultiUserWindowManagerChromeOS::GetWindowOwner( @@ -200,7 +304,17 @@ void MultiUserWindowManagerChromeOS::ShowWindowForUser( aura::Window* window, const AccountId& account_id) { - ash_multi_user_window_manager_->ShowWindowForUser(window, account_id); + const AccountId previous_owner(GetUserPresentingWindow(window)); + if (!ShowWindowForUserIntern(window, account_id)) + return; + // The window switched to a new desktop and we have to switch to that desktop, + // but only when it was on the visible desktop and the the target is not the + // visible desktop. + if (account_id == current_account_id_ || + previous_owner != current_account_id_) + return; + + SessionControllerClient::DoSwitchActiveUser(account_id); } bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() const { @@ -277,12 +391,108 @@ observers_.RemoveObserver(observer); } +void MultiUserWindowManagerChromeOS::ActiveUserChanged( + const user_manager::User* active_user) { + // This needs to be set before the animation starts. + current_account_id_ = active_user->GetAccountId(); + + // Here to avoid a very nasty race condition, we must destruct any previously + // created animation before creating a new one. Otherwise, the newly + // constructed will hide all windows of the old user in the first step of the + // animation only to be reshown again by the destructor of the old animation. + animation_.reset(); + animation_.reset(new UserSwitchAnimatorChromeOS( + this, current_account_id_, + GetAdjustedAnimationTimeInMS(kUserFadeTimeMS))); + + // Call RequestCaptureState here instead of having MediaClient observe + // ActiveUserChanged because it must happen after + // MultiUserWindowManagerChromeOS is notified. The MediaClient may be null in + // tests. + if (MediaClient::Get()) + MediaClient::Get()->RequestCaptureState(); +} + void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) { + if (GetWindowOwner(window).empty()) { + // This must be a window in the transient chain - remove it and its + // children from the owner. + RemoveTransientOwnerRecursive(window); + return; + } + wm::TransientWindowManager::GetOrCreate(window)->RemoveObserver(this); // Remove the window from the owners list. delete window_to_entry_[window]; window_to_entry_.erase(window); } +void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanging( + aura::Window* window, + bool visible) { + // This command gets called first and immediately when show or hide gets + // called. We remember here the desired state for restoration IF we were + // not ourselves issuing the call. + // Note also that using the OnWindowVisibilityChanged callback cannot be + // used for this. + if (suppress_visibility_changes_) + return; + + WindowToEntryMap::iterator it = window_to_entry_.find(window); + // If the window is not owned by anyone it is shown on all desktops. + if (it != window_to_entry_.end()) { + // Remember what was asked for so that we can restore this when the user's + // desktop gets restored. + it->second->set_show(visible); + } else { + TransientWindowToVisibility::iterator it = + transient_window_to_visibility_.find(window); + if (it != transient_window_to_visibility_.end()) + it->second = visible; + } +} + +void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanged( + aura::Window* window, + bool visible) { + if (suppress_visibility_changes_) + return; + + // Don't allow to make the window visible if it shouldn't be. + if (visible && !IsWindowOnDesktopOfUser(window, current_account_id_)) { + SetWindowVisibility(window, false, 0); + return; + } + aura::Window* owned_parent = GetOwningWindowInTransientChain(window); + if (owned_parent && owned_parent != window && visible && + !IsWindowOnDesktopOfUser(owned_parent, current_account_id_)) + SetWindowVisibility(window, false, 0); +} + +void MultiUserWindowManagerChromeOS::OnTransientChildAdded( + aura::Window* window, + aura::Window* transient_window) { + if (!GetWindowOwner(window).empty()) { + AddTransientOwnerRecursive(transient_window, window); + return; + } + aura::Window* owned_parent = + GetOwningWindowInTransientChain(transient_window); + if (!owned_parent) + return; + + AddTransientOwnerRecursive(transient_window, owned_parent); +} + +void MultiUserWindowManagerChromeOS::OnTransientChildRemoved( + aura::Window* window, + aura::Window* transient_window) { + // Remove the transient child if the window itself is owned, or one of the + // windows in its transient parents chain. + if (!GetWindowOwner(window).empty() || + GetOwningWindowInTransientChain(window)) + RemoveTransientOwnerRecursive(transient_window); +} + void MultiUserWindowManagerChromeOS::Observe( int type, const content::NotificationSource& source, @@ -291,63 +501,131 @@ AddBrowserWindow(content::Source<Browser>(source).ptr()); } -void MultiUserWindowManagerChromeOS::OnOwnerEntryChanged( - aura::Window* window, - const AccountId& account_id, - bool was_minimized, - bool teleported) { - WindowToEntryMap::iterator it = window_to_entry_.find(window); - if (it == window_to_entry_.end()) +void MultiUserWindowManagerChromeOS::OnTabletModeToggled(bool enabled) { + if (!enabled) return; - if (was_minimized) - RecordUMAForTransferredWindowType(window); - - it->second->set_show_for_user(account_id); - - const AccountId& owner = GetWindowOwner(window); - if (owner.is_valid()) { - const user_manager::User* const window_owner = - user_manager::UserManager::IsInitialized() - ? user_manager::UserManager::Get()->FindUser(owner) - : nullptr; - if (window_owner && teleported) { - window->SetProperty( - aura::client::kAvatarIconKey, - new gfx::ImageSkia(GetAvatarImageForUser(window_owner))); + for (auto entry : window_to_entry_) { + aura::Window* window = entry.first; + if (ash_window_manager_) { + ash_window_manager_->AddWindowToTabletMode( + aura::WindowMus::Get(window)->server_id()); } else { - window->ClearProperty(aura::client::kAvatarIconKey); + ash::Shell::Get()->tablet_mode_controller()->AddWindow(window); } } - - for (Observer& observer : observers_) - observer.OnOwnerEntryChanged(window); } -void MultiUserWindowManagerChromeOS::OnWillSwitchActiveAccount( - const AccountId& account_id) { - current_account_id_ = account_id; +void MultiUserWindowManagerChromeOS::SetAnimationSpeedForTest( + MultiUserWindowManagerChromeOS::AnimationSpeed speed) { + animation_speed_ = speed; } -void MultiUserWindowManagerChromeOS::OnTransitionUserShelfToNewAccount() { - ChromeLauncherController* chrome_launcher_controller = - ChromeLauncherController::instance(); - // Some unit tests have no ChromeLauncherController. - if (chrome_launcher_controller) { - chrome_launcher_controller->ActiveUserChanged( - current_account_id_.GetUserEmail()); - } -} - -void MultiUserWindowManagerChromeOS::OnDidSwitchActiveAccount() { - for (Observer& observer : observers_) - observer.OnUserSwitchAnimationFinished(); +bool MultiUserWindowManagerChromeOS::IsAnimationRunningForTest() { + return animation_ && !animation_->IsAnimationFinished(); } const AccountId& MultiUserWindowManagerChromeOS::GetCurrentUserForTest() const { return current_account_id_; } +bool MultiUserWindowManagerChromeOS::ShowWindowForUserIntern( + aura::Window* window, + const AccountId& account_id) { + // If there is either no owner, or the owner is the current user, no action + // is required. + const AccountId& owner = GetWindowOwner(window); + if ((!owner.is_valid()) || + (owner == account_id && IsWindowOnDesktopOfUser(window, account_id))) + return false; + + bool minimized = wm::WindowStateIs(window, ui::SHOW_STATE_MINIMIZED); + // Check that we are not trying to transfer ownership of a minimized window. + if (account_id != owner && minimized) + return false; + + if (!minimized) { + // If the window was transferred without getting minimized, we should record + // the window type. Otherwise it falls back to the original desktop. + RecordUMAForTransferredWindowType(window); + } + + WindowToEntryMap::iterator it = window_to_entry_.find(window); + it->second->set_show_for_user(account_id); + + // Tests could either not have a UserManager or the UserManager does not + // know the window owner. + const user_manager::User* const window_owner = + user_manager::UserManager::IsInitialized() + ? user_manager::UserManager::Get()->FindUser(owner) + : nullptr; + + const bool teleported = !IsWindowOnDesktopOfUser(window, owner); + if (window_owner && teleported) { + window->SetProperty( + aura::client::kAvatarIconKey, + new gfx::ImageSkia(GetAvatarImageForUser(window_owner))); + } else { + window->ClearProperty(aura::client::kAvatarIconKey); + } + + // Show the window if the added user is the current one. + if (account_id == current_account_id_) { + // Only show the window if it should be shown according to its state. + if (it->second->show()) + SetWindowVisibility(window, true, kTeleportAnimationTimeMS); + } else { + SetWindowVisibility(window, false, kTeleportAnimationTimeMS); + } + + // Notify entry change. + for (Observer& observer : observers_) + observer.OnOwnerEntryChanged(window); + return true; +} + +void MultiUserWindowManagerChromeOS::SetWindowVisibility( + aura::Window* window, + bool visible, + int animation_time_in_ms) { + if (window->IsVisible() == visible) + return; + + // Hiding a system modal dialog should not be allowed. Instead we switch to + // the user which is showing the system modal window. + // Note that in some cases (e.g. unit test) windows might not have a root + // window. + if (!visible && window->GetRootWindow()) { + if (HasSystemModalTransientChildWindow(window)) { + // The window is system modal and we need to find the parent which owns + // it so that we can switch to the desktop accordingly. + AccountId account_id = GetUserPresentingWindow(window); + if (!account_id.is_valid()) { + aura::Window* owning_window = GetOwningWindowInTransientChain(window); + DCHECK(owning_window); + account_id = GetUserPresentingWindow(owning_window); + DCHECK(account_id.is_valid()); + } + SessionControllerClient::DoSwitchActiveUser(account_id); + return; + } + } + + // To avoid that these commands are recorded as any other commands, we are + // suppressing any window entry changes while this is going on. + base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true); + + if (visible) + ShowWithTransientChildrenRecursive(window, animation_time_in_ms); + else + SetWindowVisible(window, false, animation_time_in_ms); +} + +void MultiUserWindowManagerChromeOS::NotifyAfterUserSwitchAnimationFinished() { + for (Observer& observer : observers_) + observer.OnUserSwitchAnimationFinished(); +} + void MultiUserWindowManagerChromeOS::AddBrowserWindow(Browser* browser) { // A unit test (e.g. CrashRestoreComplexTest.RestoreSessionForThreeUsers) can // come here with no valid window. @@ -356,3 +634,127 @@ SetWindowOwner(browser->window()->GetNativeWindow(), multi_user_util::GetAccountIdFromProfile(browser->profile())); } + +void MultiUserWindowManagerChromeOS::ShowWithTransientChildrenRecursive( + aura::Window* window, + int animation_time_in_ms) { + aura::Window::Windows::const_iterator it = + wm::GetTransientChildren(window).begin(); + for (; it != wm::GetTransientChildren(window).end(); ++it) + ShowWithTransientChildrenRecursive(*it, animation_time_in_ms); + + // We show all children which were not explicitly hidden. + TransientWindowToVisibility::iterator it2 = + transient_window_to_visibility_.find(window); + if (it2 == transient_window_to_visibility_.end() || it2->second) + SetWindowVisible(window, true, animation_time_in_ms); +} + +aura::Window* MultiUserWindowManagerChromeOS::GetOwningWindowInTransientChain( + aura::Window* window) const { + if (!GetWindowOwner(window).empty()) + return NULL; + aura::Window* parent = wm::GetTransientParent(window); + while (parent) { + if (!GetWindowOwner(parent).empty()) + return parent; + parent = wm::GetTransientParent(parent); + } + return NULL; +} + +void MultiUserWindowManagerChromeOS::AddTransientOwnerRecursive( + aura::Window* window, + aura::Window* owned_parent) { + // First add all child windows. + aura::Window::Windows::const_iterator it = + wm::GetTransientChildren(window).begin(); + for (; it != wm::GetTransientChildren(window).end(); ++it) + AddTransientOwnerRecursive(*it, owned_parent); + + // If this window is the owned window, we do not have to handle it again. + if (window == owned_parent) + return; + + // Remember the current visibility. + DCHECK(transient_window_to_visibility_.find(window) == + transient_window_to_visibility_.end()); + transient_window_to_visibility_[window] = window->IsVisible(); + + // Add observers to track state changes. + window->AddObserver(this); + wm::TransientWindowManager::GetOrCreate(window)->AddObserver(this); + + // Hide the window if it should not be shown. Note that this hide operation + // will hide recursively this and all children - but we have already collected + // their initial view state. + if (!IsWindowOnDesktopOfUser(owned_parent, current_account_id_)) + SetWindowVisibility(window, false, kAnimationTimeMS); +} + +void MultiUserWindowManagerChromeOS::RemoveTransientOwnerRecursive( + aura::Window* window) { + // First remove all child windows. + aura::Window::Windows::const_iterator it = + wm::GetTransientChildren(window).begin(); + for (; it != wm::GetTransientChildren(window).end(); ++it) + RemoveTransientOwnerRecursive(*it); + + // Find from transient window storage the visibility for the given window, + // set the visibility accordingly and delete the window from the map. + TransientWindowToVisibility::iterator visibility_item = + transient_window_to_visibility_.find(window); + DCHECK(visibility_item != transient_window_to_visibility_.end()); + + window->RemoveObserver(this); + wm::TransientWindowManager::GetOrCreate(window)->RemoveObserver(this); + + bool unowned_view_state = visibility_item->second; + transient_window_to_visibility_.erase(visibility_item); + if (unowned_view_state && !window->IsVisible()) { + // To prevent these commands from being recorded as any other commands, we + // are suppressing any window entry changes while this is going on. + // Instead of calling SetWindowVisible, only show gets called here since all + // dependents have been shown previously already. + base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true); + window->Show(); + } +} + +void MultiUserWindowManagerChromeOS::SetWindowVisible( + aura::Window* window, + bool visible, + int animation_time_in_ms) { + // The TabletModeWindowManager will not handle invisible windows since they + // are not user activatable. Since invisible windows are not being tracked, + // we tell it to maximize / track this window now before it gets shown, to + // reduce animation jank from multiple resizes. + if (visible) { + if (ash_window_manager_) { + ash_window_manager_->AddWindowToTabletMode( + aura::WindowMus::Get(window)->server_id()); + } else { + ash::Shell::Get()->tablet_mode_controller()->AddWindow(window); + } + } + + // Under mash we apply visibility changes to the root so both the window frame + // and contents hide together. + if (features::IsUsingWindowService()) + window = window->GetRootWindow(); + + AnimationSetter animation_setter( + window, GetAdjustedAnimationTimeInMS(animation_time_in_ms)); + + if (visible) + window->Show(); + else + window->Hide(); +} + +int MultiUserWindowManagerChromeOS::GetAdjustedAnimationTimeInMS( + int default_time_in_ms) const { + return animation_speed_ == ANIMATION_SPEED_NORMAL + ? default_time_in_ms + : (animation_speed_ == ANIMATION_SPEED_FAST ? 10 : 0); +}
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h index 1db57996..4cb93c39 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h
@@ -9,23 +9,23 @@ #include <memory> #include <string> -#include "ash/multi_user/multi_user_window_manager_delegate.h" +#include "ash/public/interfaces/ash_window_manager.mojom.h" +#include "base/compiler_specific.h" #include "base/macros.h" #include "base/observer_list.h" +#include "base/scoped_observer.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" +#include "chrome/browser/ui/ash/tablet_mode_client.h" +#include "chrome/browser/ui/ash/tablet_mode_client_observer.h" #include "components/account_id/account_id.h" +#include "components/user_manager/user_manager.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "ui/aura/window_observer.h" +#include "ui/wm/core/transient_window_observer.h" -class AppObserver; class Browser; -namespace ash { -class MultiUserWindowManager; -class MultiUserWindowManagerChromeOSTest; -} // namespace ash - namespace content { class BrowserContext; } @@ -34,20 +34,41 @@ class Window; } // namespace aura -// This class is responsible for notifying Ash's MultiUserWindowManager of -// which aura::Windows are associated with which accounts. This class caches -// similar information to that of Ash's MultiUserWindowManager so that it can -// synchronously respond to requests for state (such as -// IsWindowOnDesktopOfUser()). -// -// TODO: don't use ash::MultiUserWindowManager directly, instead use it over -// a mojom. https://crbug.com/875111. +namespace ash { +class MultiUserWindowManagerChromeOSTest; +} // namespace ash + +class AppObserver; +class UserSwitchAnimatorChromeOS; + +// This ChromeOS implementation of the MultiUserWindowManager interface is +// detecting app and browser creations, tagging their windows automatically and +// using (currently) show and hide to make the owned windows visible - or not. +// If it becomes necessary, the function |SetWindowVisibility| can be +// overwritten to match new ways of doing this. +// Note: +// - aura::Window::Hide() is currently hiding the window and all owned transient +// children. However aura::Window::Show() is only showing the window itself. +// To address that, all transient children (and their children) are remembered +// in |transient_window_to_visibility_| and monitored to keep track of the +// visibility changes from the owning user. This way the visibility can be +// changed back to its requested state upon showing by us - or when the window +// gets detached from its current owning parent. class MultiUserWindowManagerChromeOS : public MultiUserWindowManager, - public ash::MultiUserWindowManagerDelegate, + public user_manager::UserManager::UserSessionStateObserver, public aura::WindowObserver, - public content::NotificationObserver { + public content::NotificationObserver, + public wm::TransientWindowObserver, + public TabletModeClientObserver { public: + // The speed which should be used to perform animations. + enum AnimationSpeed { + ANIMATION_SPEED_NORMAL, // The normal animation speed. + ANIMATION_SPEED_FAST, // Unit test speed which test animations. + ANIMATION_SPEED_DISABLED // Unit tests which do not require animations. + }; + // Create the manager and use |active_account_id| as the active user. explicit MultiUserWindowManagerChromeOS(const AccountId& active_account_id); ~MultiUserWindowManagerChromeOS() override; @@ -71,22 +92,33 @@ void AddObserver(Observer* observer) override; void RemoveObserver(Observer* observer) override; + // user_manager::UserManager::UserSessionStateObserver overrides: + void ActiveUserChanged(const user_manager::User* active_user) override; + // WindowObserver overrides: void OnWindowDestroyed(aura::Window* window) override; + void OnWindowVisibilityChanging(aura::Window* window, bool visible) override; + void OnWindowVisibilityChanged(aura::Window* window, bool visible) override; + + // TransientWindowObserver overrides: + void OnTransientChildAdded(aura::Window* window, + aura::Window* transient) override; + void OnTransientChildRemoved(aura::Window* window, + aura::Window* transient) override; // content::NotificationObserver overrides: void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) override; - // ash::MultiUserWindowManagerDelegate overrides: - void OnOwnerEntryChanged(aura::Window* window, - const AccountId& account_id, - bool was_minimized, - bool teleported) override; - void OnWillSwitchActiveAccount(const AccountId& account_id) override; - void OnTransitionUserShelfToNewAccount() override; - void OnDidSwitchActiveAccount() override; + // TabletModeClientObserver: + void OnTabletModeToggled(bool enabled) override; + + // Disable any animations for unit tests. + void SetAnimationSpeedForTest(AnimationSpeed speed); + + // Returns true when a user switch animation is running. For unit tests. + bool IsAnimationRunningForTest(); // Returns the current user for unit tests. const AccountId& GetCurrentUserForTest() const; @@ -97,8 +129,8 @@ class WindowEntry { public: explicit WindowEntry(const AccountId& account_id) - : owner_(account_id), show_for_user_(account_id) {} - ~WindowEntry() {} + : owner_(account_id), show_for_user_(account_id), show_(true) {} + virtual ~WindowEntry() {} // Returns the owner of this window. This cannot be changed. const AccountId& owner() const { return owner_; } @@ -106,12 +138,18 @@ // Returns the user for which this should be shown. const AccountId& show_for_user() const { return show_for_user_; } + // Returns if the window should be shown for the "show user" or not. + bool show() const { return show_; } + // Set the user which will display the window on the owned desktop. If // an empty user id gets passed the owner will be used. void set_show_for_user(const AccountId& account_id) { show_for_user_ = account_id.is_valid() ? account_id : owner_; } + // Sets if the window gets shown for the active user or not. + void set_show(bool show) { show_ = show; } + private: // The user id of the owner of this window. const AccountId owner_; @@ -119,11 +157,32 @@ // The user id of the user on which desktop the window gets shown. AccountId show_for_user_; + // True if the window should be visible for the user which shows the window. + bool show_; + DISALLOW_COPY_AND_ASSIGN(WindowEntry); }; - // TODO(sky): make this map to unique_ptr<WindowEntry>. - using WindowToEntryMap = std::map<aura::Window*, WindowEntry*>; + typedef std::map<aura::Window*, WindowEntry*> WindowToEntryMap; + + // Show a window for a user without switching the user. + // Returns true when the window moved to a new desktop. + bool ShowWindowForUserIntern(aura::Window* window, + const AccountId& account_id); + + // Show / hide the given window. Note: By not doing this within the functions, + // this allows to either switching to different ways to show/hide and / or to + // distinguish state changes performed by this class vs. state changes + // performed by the others. Note furthermore that system modal dialogs will + // not get hidden. We will switch instead to the owners desktop. + // The |animation_time_in_ms| is the time the animation should take. Set to 0 + // if it should get set instantly. + void SetWindowVisibility(aura::Window* window, + bool visible, + int animation_time_in_ms); + + // Notify the observers after the user switching animation is finished. + void NotifyAfterUserSwitchAnimationFinished(); const WindowToEntryMap& window_to_entry() { return window_to_entry_; } @@ -131,10 +190,40 @@ friend class ash::MultiUserWindowManagerChromeOSTest; typedef std::map<AccountId, AppObserver*> AccountIdToAppWindowObserver; + typedef std::map<aura::Window*, bool> TransientWindowToVisibility; // Add a browser window to the system so that the owner can be remembered. void AddBrowserWindow(Browser* browser); + // Show the window and its transient children. However - if a transient child + // was turned invisible by some other operation, it will stay invisible. + // Use the given |animation_time_in_ms| for transitioning. + void ShowWithTransientChildrenRecursive(aura::Window* window, + int animation_time_in_ms); + + // Find the first owned window in the chain. + // Returns NULL when the window itself is owned. + aura::Window* GetOwningWindowInTransientChain(aura::Window* window) const; + + // A |window| and its children were attached as transient children to an + // |owning_parent| and need to be registered. Note that the |owning_parent| + // itself will not be registered, but its children will. + void AddTransientOwnerRecursive(aura::Window* window, + aura::Window* owning_parent); + + // A window and its children were removed from its parent and can be + // unregistered. + void RemoveTransientOwnerRecursive(aura::Window* window); + + // Animate a |window| to be |visible| in |animation_time_in_ms|. + void SetWindowVisible(aura::Window* window, + bool visible, + int aimation_time_in_ms); + + // Get the animation time in milliseconds dependent on the |AnimationSpeed| + // from the passed |default_time_in_ms|. + int GetAdjustedAnimationTimeInMS(int default_time_in_ms) const; + // A lookup to see to which user the given window belongs to, where and if it // should get shown. WindowToEntryMap window_to_entry_; @@ -145,6 +234,9 @@ // An observer list to be notified upon window owner changes. base::ObserverList<Observer>::Unchecked observers_; + // A map which remembers for owned transient windows their own visibility. + TransientWindowToVisibility transient_window_to_visibility_; + // The currently selected active user. It is used to find the proper // visibility state in various cases. The state is stored here instead of // being read from the user manager to be in sync while a switch occurs. @@ -153,7 +245,20 @@ // The notification registrar to track the creation of browser windows. content::NotificationRegistrar registrar_; - std::unique_ptr<ash::MultiUserWindowManager> ash_multi_user_window_manager_; + // Suppress changes to the visibility flag while we are changing it ourselves. + bool suppress_visibility_changes_; + + // The speed which is used to perform any animations. + AnimationSpeed animation_speed_; + + // The animation between users. + std::unique_ptr<UserSwitchAnimatorChromeOS> animation_; + + // Only used in mash. + ash::mojom::AshWindowManagerAssociatedPtr ash_window_manager_; + + ScopedObserver<TabletModeClient, TabletModeClientObserver> + tablet_mode_observer_{this}; DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManagerChromeOS); };
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc index 1ff34c2..f73d0a0 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
@@ -9,11 +9,8 @@ #include "ash/display/screen_orientation_controller.h" #include "ash/display/screen_orientation_controller_test_api.h" -#include "ash/multi_user/multi_user_window_manager.h" -#include "ash/multi_user/user_switch_animator.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h" -#include "ash/session/session_controller.h" #include "ash/shelf/shelf_constants.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" @@ -32,7 +29,6 @@ #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" -#include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -43,6 +39,7 @@ #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h" +#include "chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h" #include "chrome/browser/ui/ash/session_controller_client.h" #include "chrome/browser/ui/ash/session_util.h" #include "chrome/browser/ui/ash/test_wallpaper_controller.h" @@ -59,7 +56,6 @@ #include "components/user_manager/user_info.h" #include "components/user_manager/user_manager.h" #include "ui/aura/client/aura_constants.h" -#include "ui/aura/test/env_test_helper.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/base/ui_base_types.h" @@ -124,25 +120,18 @@ fake_user_manager_(new chromeos::FakeChromeUserManager), user_manager_enabler_(base::WrapUnique(fake_user_manager_)) {} - // AshTestBase: void SetUp() override; void TearDown() override; protected: - void SwitchActiveUser(const AccountId& id) { - fake_user_manager_->SwitchActiveUser(id); - ash::MultiUserWindowManager::Get()->OnActiveUserSessionChanged(id); - } - // Set up the test environment for this many windows. void SetUpForThisManyWindows(int windows); // Switch the user and wait until the animation is finished. void SwitchUserAndWaitForAnimation(const AccountId& account_id) { - EnsureTestUser(account_id); - ash::MultiUserWindowManager::Get()->OnActiveUserSessionChanged(account_id); + multi_user_window_manager_->ActiveUserChanged(EnsureTestUser(account_id)); base::TimeTicks now = base::TimeTicks::Now(); - while (ash::MultiUserWindowManager::Get()->IsAnimationRunningForTest()) { + while (multi_user_window_manager_->IsAnimationRunningForTest()) { // This should never take longer then a second. ASSERT_GE(1000, (base::TimeTicks::Now() - now).InMilliseconds()); base::RunLoop().RunUntilIdle(); @@ -173,12 +162,8 @@ // Ensures that a user with the given |account_id| exists. const user_manager::User* EnsureTestUser(const AccountId& account_id) { const user_manager::User* user = fake_user_manager_->FindUser(account_id); - if (user) - return user; - - user = fake_user_manager_->AddUser(account_id); - ash_test_helper()->test_session_controller_client()->AddUserSession( - user->GetDisplayEmail()); + if (!user) + user = fake_user_manager_->AddUser(account_id); return user; } @@ -212,48 +197,51 @@ void ShowWindowForUserNoUserTransition(aura::Window* window, const AccountId& account_id) { - ash::MultiUserWindowManager::Get()->ShowWindowForUserIntern(window, - account_id); + multi_user_window_manager_->ShowWindowForUserIntern(window, account_id); } // The FakeChromeUserManager does not automatically call the window // manager. This function gets the current user from it and also sets it to // the multi user window manager. AccountId GetAndValidateCurrentUserFromSessionStateObserver() { - SessionController* session_controller = Shell::Get()->session_controller(); - session_controller->FlushMojoForTest(); - return session_controller->GetUserSessions()[0]->user_info->account_id; + const AccountId account_id = + user_manager()->GetActiveUser()->GetAccountId(); + if (account_id != multi_user_window_manager_->GetCurrentUserForTest()) { + multi_user_window_manager()->ActiveUserChanged( + fake_user_manager_->FindUser(account_id)); + } + + return account_id; } // Initiate a user transition. void StartUserTransitionAnimation(const AccountId& account_id) { - EnsureTestUser(account_id); - ash_test_helper()->test_session_controller_client()->SwitchActiveUser( - account_id); + // Ensures a user exists for the ActiveUserChanged call but do not make the + // user as logged in. The tests that call StartUserTransitionAnimation do + // not need a logged in user. Otherwise, profile switch also needs to + // be simulated so that CanShowWindowForUser works correctly. + multi_user_window_manager_->ActiveUserChanged(EnsureTestUser(account_id)); } // Call next animation step. void AdvanceUserTransitionAnimation() { - ash::MultiUserWindowManager::Get() - ->animation_->AdvanceUserTransitionAnimation(); + multi_user_window_manager_->animation_->AdvanceUserTransitionAnimation(); } // Return the user id of the wallpaper which is currently set. const std::string& GetWallpaperUserIdForTest() { - return ash::MultiUserWindowManager::Get() - ->animation_->wallpaper_user_id_for_test(); + return multi_user_window_manager_->animation_->wallpaper_user_id_for_test(); } // Returns true if the given window covers the screen. bool CoversScreen(aura::Window* window) { - return ash::UserSwitchAnimator::CoversScreen(window); + return UserSwitchAnimatorChromeOS::CoversScreen(window); } private: chromeos::ScopedStubInstallAttributes test_install_attributes_; // These get created for each session. - // TODO: convert to vector<std::unique_ptr<aura::Window>>. aura::Window::Windows windows_; // The instance of the MultiUserWindowManager. @@ -282,10 +270,6 @@ TestingBrowserProcess::GetGlobal()->local_state()); ash_test_helper()->set_test_shell_delegate(new TestShellDelegateChromeOS); AshTestBase::SetUp(); - // This test has mixed case user ids. - ash_test_helper() - ->test_session_controller_client() - ->set_use_lower_case_user_id(false); profile_manager_.reset( new TestingProfileManager(TestingBrowserProcess::GetGlobal())); ASSERT_TRUE(profile_manager_.get()->SetUp()); @@ -303,9 +287,9 @@ multi_user_window_manager_ = new MultiUserWindowManagerChromeOS(AccountId::FromUserEmail("A")); multi_user_window_manager_->Init(); - ash::MultiUserWindowManager::Get()->SetAnimationSpeedForTest( - ash::MultiUserWindowManager::ANIMATION_SPEED_DISABLED); - ::MultiUserWindowManager::SetInstanceForTest(multi_user_window_manager_); + multi_user_window_manager_->SetAnimationSpeedForTest( + MultiUserWindowManagerChromeOS::ANIMATION_SPEED_DISABLED); + MultiUserWindowManager::SetInstanceForTest(multi_user_window_manager_); EXPECT_TRUE(multi_user_window_manager_); wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>(); wallpaper_controller_client_->InitForTesting( @@ -320,7 +304,7 @@ windows_.erase(windows_.begin()); } - ::MultiUserWindowManager::DeleteInstance(); + MultiUserWindowManager::DeleteInstance(); AshTestBase::TearDown(); wallpaper_controller_client_.reset(); profile_manager_.reset(); @@ -369,8 +353,7 @@ // Check the basic assumptions: All windows are visible and there is no owner. EXPECT_EQ("S[], S[], S[]", GetStatus()); EXPECT_TRUE(multi_user_window_manager()); - EXPECT_EQ(multi_user_window_manager(), - ::MultiUserWindowManager::GetInstance()); + EXPECT_EQ(multi_user_window_manager(), MultiUserWindowManager::GetInstance()); EXPECT_FALSE(multi_user_window_manager()->AreWindowsSharedAmongUsers()); const AccountId account_id_A(AccountId::FromUserEmail("A")); @@ -847,6 +830,7 @@ EXPECT_FALSE(wm::GetWindowState(window(1))->IsMaximized()); Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); + multi_user_window_manager()->OnTabletModeToggled(true); EXPECT_TRUE(wm::GetWindowState(window(0))->IsMaximized()); EXPECT_TRUE(wm::GetWindowState(window(1))->IsMaximized()); @@ -854,6 +838,7 @@ // Tests that on exiting tablet mode, the window states return to not // maximized. Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false); + multi_user_window_manager()->OnTabletModeToggled(false); EXPECT_FALSE(wm::GetWindowState(window(0))->IsMaximized()); EXPECT_FALSE(wm::GetWindowState(window(1))->IsMaximized()); } @@ -866,15 +851,15 @@ const AccountId account_id_a(AccountId::FromUserEmail("a")); const AccountId account_id_b(AccountId::FromUserEmail("b")); - StartUserTransitionAnimation(account_id_a); + SessionControllerClient::DoSwitchActiveUser(account_id_a); // Making the window system modal should not change anything. MakeWindowSystemModal(window(0)); - EXPECT_EQ(account_id_a, GetAndValidateCurrentUserFromSessionStateObserver()); + EXPECT_EQ(account_id_a, user_manager()->GetActiveUser()->GetAccountId()); // Making the window owned by user B should switch users. multi_user_window_manager()->SetWindowOwner(window(0), account_id_b); - EXPECT_EQ(account_id_b, GetAndValidateCurrentUserFromSessionStateObserver()); + EXPECT_EQ(account_id_b, user_manager()->GetActiveUser()->GetAccountId()); } // Test that a system modal dialog will not switch desktop if active user has @@ -885,15 +870,15 @@ const AccountId account_id_a(AccountId::FromUserEmail("a")); const AccountId account_id_b(AccountId::FromUserEmail("b")); - StartUserTransitionAnimation(account_id_a); + SessionControllerClient::DoSwitchActiveUser(account_id_a); // Making the window system modal should not change anything. MakeWindowSystemModal(window(0)); - EXPECT_EQ(account_id_a, GetAndValidateCurrentUserFromSessionStateObserver()); + EXPECT_EQ(account_id_a, user_manager()->GetActiveUser()->GetAccountId()); // Making the window owned by user a should not switch users. multi_user_window_manager()->SetWindowOwner(window(0), account_id_a); - EXPECT_EQ(account_id_a, GetAndValidateCurrentUserFromSessionStateObserver()); + EXPECT_EQ(account_id_a, user_manager()->GetActiveUser()->GetAccountId()); } // Test that a system modal dialog will not switch if shown on correct desktop @@ -905,7 +890,7 @@ const AccountId account_id_a(AccountId::FromUserEmail("a")); const AccountId account_id_b(AccountId::FromUserEmail("b")); - StartUserTransitionAnimation(account_id_a); + SessionControllerClient::DoSwitchActiveUser(account_id_a); window(0)->Hide(); multi_user_window_manager()->SetWindowOwner(window(0), account_id_b); @@ -913,7 +898,7 @@ MakeWindowSystemModal(window(0)); // Showing the window should trigger no user switch. window(0)->Show(); - EXPECT_EQ(account_id_a, GetAndValidateCurrentUserFromSessionStateObserver()); + EXPECT_EQ(account_id_a, user_manager()->GetActiveUser()->GetAccountId()); } // Test that a system modal dialog will switch if shown on incorrect desktop but @@ -925,7 +910,7 @@ const AccountId account_id_a(AccountId::FromUserEmail("a")); const AccountId account_id_b(AccountId::FromUserEmail("b")); - StartUserTransitionAnimation(account_id_a); + SessionControllerClient::DoSwitchActiveUser(account_id_a); window(0)->Hide(); multi_user_window_manager()->SetWindowOwner(window(0), account_id_a); @@ -933,7 +918,7 @@ MakeWindowSystemModal(window(0)); // Showing the window should trigger a user switch. window(0)->Show(); - EXPECT_EQ(account_id_b, GetAndValidateCurrentUserFromSessionStateObserver()); + EXPECT_EQ(account_id_b, user_manager()->GetActiveUser()->GetAccountId()); } // Test that using the full user switch animations are working as expected. @@ -945,8 +930,8 @@ const AccountId account_id_C(AccountId::FromUserEmail("C")); // Turn the use of delays and animation on. - ash::MultiUserWindowManager::Get()->SetAnimationSpeedForTest( - ash::MultiUserWindowManager::ANIMATION_SPEED_FAST); + multi_user_window_manager()->SetAnimationSpeedForTest( + MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST); // Set some owners and make sure we got what we asked for. multi_user_window_manager()->SetWindowOwner(window(0), account_id_A); multi_user_window_manager()->SetWindowOwner(window(1), account_id_B); @@ -983,8 +968,8 @@ const AccountId account_id_B(AccountId::FromUserEmail("B")); // Turn the use of delays and animation on. - ash::MultiUserWindowManager::Get()->SetAnimationSpeedForTest( - ash::MultiUserWindowManager::ANIMATION_SPEED_FAST); + multi_user_window_manager()->SetAnimationSpeedForTest( + MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST); // Set some owners and make sure we got what we asked for. multi_user_window_manager()->SetWindowOwner(window(0), account_id_A); multi_user_window_manager()->SetWindowOwner(window(1), account_id_B); @@ -1004,8 +989,8 @@ const AccountId account_id_C(AccountId::FromUserEmail("C")); // Turn the use of delays and animation on. - ash::MultiUserWindowManager::Get()->SetAnimationSpeedForTest( - ash::MultiUserWindowManager::ANIMATION_SPEED_FAST); + multi_user_window_manager()->SetAnimationSpeedForTest( + MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST); // Set some owners and make sure we got what we asked for. multi_user_window_manager()->SetWindowOwner(window(0), account_id_A); multi_user_window_manager()->SetWindowOwner(window(1), account_id_B); @@ -1062,8 +1047,8 @@ const AccountId account_id_C(AccountId::FromUserEmail("C")); // Turn the use of delays and animation on. - ash::MultiUserWindowManager::Get()->SetAnimationSpeedForTest( - ash::MultiUserWindowManager::ANIMATION_SPEED_FAST); + multi_user_window_manager()->SetAnimationSpeedForTest( + MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST); // Set some owners and make sure we got what we asked for. multi_user_window_manager()->SetWindowOwner(window(0), account_id_A); wm::GetWindowState(window(0))->Maximize(); @@ -1107,8 +1092,8 @@ const AccountId account_id_C(AccountId::FromUserEmail("C")); // Turn the use of delays and animation on. - ash::MultiUserWindowManager::Get()->SetAnimationSpeedForTest( - ash::MultiUserWindowManager::ANIMATION_SPEED_FAST); + multi_user_window_manager()->SetAnimationSpeedForTest( + MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST); // Set some owners and make sure we got what we asked for. multi_user_window_manager()->SetWindowOwner(window(0), account_id_A); multi_user_window_manager()->SetWindowOwner(window(1), account_id_B); @@ -1153,8 +1138,8 @@ const AccountId account_id_C(AccountId::FromUserEmail("C")); // Turn the use of delays and animation on. - ash::MultiUserWindowManager::Get()->SetAnimationSpeedForTest( - ash::MultiUserWindowManager::ANIMATION_SPEED_FAST); + multi_user_window_manager()->SetAnimationSpeedForTest( + MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST); // Set some owners and make sure we got what we asked for. multi_user_window_manager()->SetWindowOwner(window(0), account_id_A); wm::GetWindowState(window(0))->Maximize(); @@ -1220,6 +1205,7 @@ const AccountId account_id_c(AccountId::FromUserEmail("c")); StartUserTransitionAnimation(account_id_a); + SessionControllerClient::DoSwitchActiveUser(account_id_a); // Set some owners and make sure we got what we asked for. multi_user_window_manager()->SetWindowOwner(window(0), account_id_a); @@ -1344,14 +1330,18 @@ wm::GetWindowState(window(2))->Minimize(); // Windows belonging to user2 (window #2 and #3) can't be activated by user1. - SwitchActiveUser(user1); + user_manager()->SwitchActiveUser(user1); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(user1)); EXPECT_TRUE(::wm::CanActivateWindow(window(0))); EXPECT_TRUE(::wm::CanActivateWindow(window(1))); EXPECT_FALSE(::wm::CanActivateWindow(window(2))); EXPECT_FALSE(::wm::CanActivateWindow(window(3))); // Windows belonging to user1 (window #0 and #1) can't be activated by user2. - SwitchActiveUser(user2); + user_manager()->SwitchActiveUser(user2); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(user2)); EXPECT_FALSE(::wm::CanActivateWindow(window(0))); EXPECT_FALSE(::wm::CanActivateWindow(window(1))); EXPECT_TRUE(::wm::CanActivateWindow(window(2))); @@ -1370,7 +1360,9 @@ multi_user_window_manager()->SetWindowOwner(window(0), user1); multi_user_window_manager()->SetWindowOwner(window(1), user2); - SwitchActiveUser(user1); + user_manager()->SwitchActiveUser(user1); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(user1)); EXPECT_TRUE(::wm::CanActivateWindow(window(0))); EXPECT_FALSE(::wm::CanActivateWindow(window(1))); @@ -1380,7 +1372,9 @@ EXPECT_FALSE(::wm::CanActivateWindow(window(0))); // Test that window #0 can be activated by user2. - SwitchActiveUser(user2); + user_manager()->SwitchActiveUser(user2); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(user2)); EXPECT_TRUE(::wm::CanActivateWindow(window(0))); EXPECT_TRUE(::wm::CanActivateWindow(window(1))); } @@ -1396,7 +1390,9 @@ multi_user_window_manager()->SetWindowOwner(window(0), user1); - SwitchActiveUser(user1); + user_manager()->SwitchActiveUser(user1); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(user1)); // Window #0 has no kAvatarIconKey property before teloporting. EXPECT_FALSE(window(0)->GetProperty(aura::client::kAvatarIconKey)); @@ -1421,7 +1417,9 @@ const AccountId account_id_B(AccountId::FromUserEmail("B")); AddTestUser(account_id_A); AddTestUser(account_id_B); - SwitchActiveUser(account_id_A); + user_manager()->SwitchActiveUser(account_id_A); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(account_id_A)); // Set the windows owner. ::wm::ActivationClient* activation_client = @@ -1443,11 +1441,15 @@ EXPECT_EQ(mru_list[1], window(1)); EXPECT_EQ(mru_list[2], window(2)); - SwitchActiveUser(account_id_B); + user_manager()->SwitchActiveUser(account_id_B); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(account_id_B)); EXPECT_EQ("H[A], H[A], H[A]", GetStatus()); EXPECT_EQ(activation_client->GetActiveWindow(), nullptr); - SwitchActiveUser(account_id_A); + user_manager()->SwitchActiveUser(account_id_A); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(account_id_A)); EXPECT_EQ("S[A], S[A], S[A]", GetStatus()); EXPECT_EQ(activation_client->GetActiveWindow(), window(0)); @@ -1467,7 +1469,9 @@ const AccountId account_id_B(AccountId::FromUserEmail("B")); AddTestUser(account_id_A); AddTestUser(account_id_B); - SwitchActiveUser(account_id_A); + user_manager()->SwitchActiveUser(account_id_A); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(account_id_A)); multi_user_window_manager()->SetWindowOwner(window(0), account_id_A); Profile* profile = multi_user_util::GetProfileFromAccountId(account_id_A); @@ -1482,7 +1486,9 @@ EXPECT_EQ(browser.get(), chrome::FindBrowserWithActiveWindow()); // Switch to another user's desktop with no active window. - SwitchActiveUser(account_id_B); + user_manager()->SwitchActiveUser(account_id_B); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(account_id_B)); EXPECT_EQ(browser.get(), BrowserList::GetInstance()->GetLastActive()); EXPECT_FALSE(browser->window()->IsActive()); EXPECT_EQ(nullptr, chrome::FindBrowserWithActiveWindow()); @@ -1502,15 +1508,19 @@ const AccountId user2(AccountId::FromUserEmail("B")); AddTestUser(user1); AddTestUser(user2); - SwitchActiveUser(user1); + user_manager()->SwitchActiveUser(user1); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(user1)); multi_user_window_manager()->SetWindowOwner(window(0), user1); multi_user_window_manager()->SetWindowOwner(window(1), user2); const gfx::Rect bounds(20, 20, 360, 100); window(0)->SetBounds(bounds); window(1)->SetBounds(bounds); - // Enter tablet mode. + // Enter tablet mode. Manually call OnTabletModeToggled because + // TabletModeClient is null during tests. Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); + multi_user_window_manager()->OnTabletModeToggled(true); // Tests that bounds of both windows are maximized. const gfx::Rect maximized_bounds(0, 0, 400, 200 - ShelfConstants::shelf_size()); @@ -1525,10 +1535,13 @@ test_api.SetDisplayRotation(display::Display::ROTATE_0, display::Display::RotationSource::ACTIVE); Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false); + multi_user_window_manager()->OnTabletModeToggled(false); // Tests that both windows have the same bounds as when they entered tablet // mode. - SwitchActiveUser(user2); + user_manager()->SwitchActiveUser(user2); + multi_user_window_manager()->ActiveUserChanged( + user_manager()->FindUser(user2)); EXPECT_EQ(bounds, window(0)->bounds()); EXPECT_EQ(bounds, window(1)->bounds()); }
diff --git a/ash/multi_user/user_switch_animator.cc b/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.cc similarity index 76% rename from ash/multi_user/user_switch_animator.cc rename to chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.cc index 54a2a3d..9d554296 100644 --- a/ash/multi_user/user_switch_animator.cc +++ b/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.cc
@@ -2,14 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/multi_user/user_switch_animator.h" +#include "chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h" -#include "ash/multi_user/multi_user_window_manager.h" -#include "ash/multi_user/multi_user_window_manager_delegate.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/window_positioner.h" +#include "base/macros.h" +#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" +#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h" +#include "chrome/browser/ui/ash/wallpaper_controller_client.h" #include "ui/aura/client/aura_constants.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_tree_owner.h" @@ -18,25 +19,23 @@ #include "ui/wm/core/window_util.h" #include "ui/wm/public/activation_client.h" -namespace ash { namespace { // The minimal possible animation time for animations which should happen // "instantly". -constexpr base::TimeDelta kMinimalAnimationTime = - base::TimeDelta::FromMilliseconds(1); +const int kMinimalAnimationTimeMS = 1; // logic while the user gets switched. class UserChangeActionDisabler { public: UserChangeActionDisabler() { - WindowPositioner::DisableAutoPositioning(true); - Shell::Get()->mru_window_tracker()->SetIgnoreActivations(true); + ash::WindowPositioner::DisableAutoPositioning(true); + ash::Shell::Get()->mru_window_tracker()->SetIgnoreActivations(true); } ~UserChangeActionDisabler() { - WindowPositioner::DisableAutoPositioning(false); - Shell::Get()->mru_window_tracker()->SetIgnoreActivations(false); + ash::WindowPositioner::DisableAutoPositioning(false); + ash::Shell::Get()->mru_window_tracker()->SetIgnoreActivations(false); } private: @@ -79,37 +78,36 @@ } // namespace -UserSwitchAnimator::UserSwitchAnimator( - MultiUserWindowManager* owner, - mojom::WallpaperUserInfoPtr wallpaper_user_info, - base::TimeDelta animation_speed) +UserSwitchAnimatorChromeOS::UserSwitchAnimatorChromeOS( + MultiUserWindowManagerChromeOS* owner, + const AccountId& new_account_id, + int animation_speed_ms) : owner_(owner), - wallpaper_user_info_(std::move(wallpaper_user_info)), - new_account_id_(wallpaper_user_info_->account_id), - animation_speed_(animation_speed), + new_account_id_(new_account_id), + animation_speed_ms_(animation_speed_ms), animation_step_(ANIMATION_STEP_HIDE_OLD_USER), screen_cover_(GetScreenCover(NULL)), windows_by_account_id_() { BuildUserToWindowsListMap(); AdvanceUserTransitionAnimation(); - if (animation_speed_.is_zero()) { + if (!animation_speed_ms_) { FinalizeAnimation(); } else { user_changed_animation_timer_.reset(new base::RepeatingTimer()); user_changed_animation_timer_->Start( - FROM_HERE, animation_speed_, - base::BindRepeating(&UserSwitchAnimator::AdvanceUserTransitionAnimation, - base::Unretained(this))); + FROM_HERE, base::TimeDelta::FromMilliseconds(animation_speed_ms_), + base::Bind(&UserSwitchAnimatorChromeOS::AdvanceUserTransitionAnimation, + base::Unretained(this))); } } -UserSwitchAnimator::~UserSwitchAnimator() { +UserSwitchAnimatorChromeOS::~UserSwitchAnimatorChromeOS() { FinalizeAnimation(); } // static -bool UserSwitchAnimator::CoversScreen(aura::Window* window) { +bool UserSwitchAnimatorChromeOS::CoversScreen(aura::Window* window) { // Full screen covers the screen naturally. Since a normal window can have the // same size as the work area, we only compare the bounds against the work // area. @@ -122,7 +120,7 @@ return work_area == bounds; } -void UserSwitchAnimator::AdvanceUserTransitionAnimation() { +void UserSwitchAnimatorChromeOS::AdvanceUserTransitionAnimation() { DCHECK_NE(animation_step_, ANIMATION_STEP_ENDED); TransitionWallpaper(animation_step_); @@ -140,8 +138,7 @@ case ANIMATION_STEP_FINALIZE: user_changed_animation_timer_.reset(); animation_step_ = ANIMATION_STEP_ENDED; - if (owner_->delegate_) - owner_->delegate_->OnDidSwitchActiveAccount(); + owner_->NotifyAfterUserSwitchAnimationFinished(); break; case ANIMATION_STEP_ENDED: NOTREACHED(); @@ -149,31 +146,29 @@ } } -void UserSwitchAnimator::CancelAnimation() { +void UserSwitchAnimatorChromeOS::CancelAnimation() { animation_step_ = ANIMATION_STEP_ENDED; } -void UserSwitchAnimator::FinalizeAnimation() { +void UserSwitchAnimatorChromeOS::FinalizeAnimation() { user_changed_animation_timer_.reset(); while (ANIMATION_STEP_ENDED != animation_step_) AdvanceUserTransitionAnimation(); } -void UserSwitchAnimator::TransitionWallpaper(AnimationStep animation_step) { - WallpaperController* wallpaper_controller = - Shell::Get()->wallpaper_controller(); - +void UserSwitchAnimatorChromeOS::TransitionWallpaper( + AnimationStep animation_step) { // Handle the wallpaper switch. if (animation_step == ANIMATION_STEP_HIDE_OLD_USER) { // Set the wallpaper cross dissolve animation duration to our complete // animation cycle for a fade in and fade out. - base::TimeDelta duration = - animation_speed_ * (NO_USER_COVERS_SCREEN == screen_cover_ ? 2 : 0); - wallpaper_controller->SetAnimationDuration( - duration > kMinimalAnimationTime ? duration : kMinimalAnimationTime); + int duration = + NO_USER_COVERS_SCREEN == screen_cover_ ? (2 * animation_speed_ms_) : 0; + WallpaperControllerClient::Get()->SetAnimationDuration( + base::TimeDelta::FromMilliseconds( + std::max(duration, kMinimalAnimationTimeMS))); if (screen_cover_ != NEW_USER_COVERS_SCREEN) { - DCHECK(wallpaper_user_info_); - wallpaper_controller->ShowUserWallpaper(std::move(wallpaper_user_info_)); + WallpaperControllerClient::Get()->ShowUserWallpaper(new_account_id_); wallpaper_user_id_for_test_ = (NO_USER_COVERS_SCREEN == screen_cover_ ? "->" : "") + new_account_id_.Serialize(); @@ -181,34 +176,37 @@ } else if (animation_step == ANIMATION_STEP_FINALIZE) { // Revert the wallpaper cross dissolve animation duration back to the // default. - if (screen_cover_ == NEW_USER_COVERS_SCREEN) { - DCHECK(wallpaper_user_info_); - wallpaper_controller->ShowUserWallpaper(std::move(wallpaper_user_info_)); - } + if (screen_cover_ == NEW_USER_COVERS_SCREEN) + WallpaperControllerClient::Get()->ShowUserWallpaper(new_account_id_); // Coming here the wallpaper user id is the final result. No matter how we // got here. wallpaper_user_id_for_test_ = new_account_id_.Serialize(); - wallpaper_controller->SetAnimationDuration(base::TimeDelta()); + WallpaperControllerClient::Get()->SetAnimationDuration(base::TimeDelta()); } } -void UserSwitchAnimator::TransitionUserShelf(AnimationStep animation_step) { +void UserSwitchAnimatorChromeOS::TransitionUserShelf( + AnimationStep animation_step) { if (animation_step != ANIMATION_STEP_SHOW_NEW_USER) return; - if (owner_->delegate_) - owner_->delegate_->OnTransitionUserShelfToNewAccount(); + ChromeLauncherController* chrome_launcher_controller = + ChromeLauncherController::instance(); + // Some unit tests have no ChromeLauncherController. + if (chrome_launcher_controller) { + chrome_launcher_controller->ActiveUserChanged( + new_account_id_.GetUserEmail()); + } } -void UserSwitchAnimator::TransitionWindows(AnimationStep animation_step) { +void UserSwitchAnimatorChromeOS::TransitionWindows( + AnimationStep animation_step) { // Disable the window position manager and the MRU window tracker temporarily. UserChangeActionDisabler disabler; // Animation duration. - base::TimeDelta duration = base::TimeDelta::FromMilliseconds( - std::max(kMinimalAnimationTime.InMilliseconds(), - 2 * animation_speed_.InMilliseconds())); + int duration = std::max(kMinimalAnimationTimeMS, 2 * animation_speed_ms_); switch (animation_step) { case ANIMATION_STEP_HIDE_OLD_USER: { @@ -231,7 +229,7 @@ // different than that of the for_show_account_id) should retrun to // their // original owners' desktops. - MultiUserWindowManager::WindowToEntryMap::const_iterator itr = + MultiUserWindowManagerChromeOS::WindowToEntryMap::const_iterator itr = owner_->window_to_entry().find(window); DCHECK(itr != owner_->window_to_entry().end()); if (show_for_account_id != itr->second->owner() && @@ -293,7 +291,7 @@ case ANIMATION_STEP_FINALIZE: { // Reactivate the MRU window of the new user. aura::Window::Windows mru_list = - Shell::Get()->mru_window_tracker()->BuildMruWindowList(); + ash::Shell::Get()->mru_window_tracker()->BuildMruWindowList(); if (!mru_list.empty()) { aura::Window* window = mru_list[0]; if (owner_->IsWindowOnDesktopOfUser(window, new_account_id_) && @@ -314,11 +312,13 @@ } } -UserSwitchAnimator::TransitioningScreenCover UserSwitchAnimator::GetScreenCover( - aura::Window* root_window) { +UserSwitchAnimatorChromeOS::TransitioningScreenCover +UserSwitchAnimatorChromeOS::GetScreenCover(aura::Window* root_window) { TransitioningScreenCover cover = NO_USER_COVERS_SCREEN; - for (auto& pair : owner_->window_to_entry()) { - aura::Window* window = pair.first; + for (MultiUserWindowManagerChromeOS::WindowToEntryMap::const_iterator it_map = + owner_->window_to_entry().begin(); + it_map != owner_->window_to_entry().end(); ++it_map) { + aura::Window* window = it_map->first; if (root_window && window->GetRootWindow() != root_window) continue; if (window->IsVisible() && CoversScreen(window)) { @@ -337,7 +337,7 @@ return cover; } -void UserSwitchAnimator::BuildUserToWindowsListMap() { +void UserSwitchAnimatorChromeOS::BuildUserToWindowsListMap() { // This is to be called only at the time this animation is constructed. DCHECK(windows_by_account_id_.empty()); @@ -362,5 +362,3 @@ } } } - -} // namespace ash
diff --git a/ash/multi_user/user_switch_animator.h b/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h similarity index 81% rename from ash/multi_user/user_switch_animator.h rename to chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h index 2f7ba50b5..fbfef100 100644 --- a/ash/multi_user/user_switch_animator.h +++ b/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h
@@ -2,31 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_MULTI_USER_USER_SWITCH_ANIMATOR_H_ -#define ASH_MULTI_USER_USER_SWITCH_ANIMATOR_H_ +#ifndef CHROME_BROWSER_UI_ASH_MULTI_USER_USER_SWITCH_ANIMATOR_CHROMEOS_H_ +#define CHROME_BROWSER_UI_ASH_MULTI_USER_USER_SWITCH_ANIMATOR_CHROMEOS_H_ #include <map> #include <memory> #include <string> -#include "ash/ash_export.h" -#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/macros.h" -#include "base/time/time.h" #include "base/timer/timer.h" #include "components/account_id/account_id.h" #include "ui/aura/window.h" -namespace ash { - -class MultiUserWindowManager; +class MultiUserWindowManagerChromeOS; // A class which performs transitions animations between users. Upon creation, // the animation gets started and upon destruction the animation gets finished // if not done yet. // Specifying |animation_disabled| upon creation will perform the transition // without visible animations. -class ASH_EXPORT UserSwitchAnimator { +class UserSwitchAnimatorChromeOS { public: // The animation step for the user change animation. enum AnimationStep { @@ -36,12 +31,10 @@ ANIMATION_STEP_ENDED // The animation has ended. }; - // Creates a UserSwitchAnimator to animate between the current user and - // |user_info|. - UserSwitchAnimator(MultiUserWindowManager* owner, - mojom::WallpaperUserInfoPtr user_info, - base::TimeDelta animation_speed); - ~UserSwitchAnimator(); + UserSwitchAnimatorChromeOS(MultiUserWindowManagerChromeOS* owner, + const AccountId& new_account_id, + int animation_speed_ms); + ~UserSwitchAnimatorChromeOS(); // Check if a window is covering the entire work area of the screen it is on. static bool CoversScreen(aura::Window* window); @@ -99,17 +92,13 @@ void BuildUserToWindowsListMap(); // The owning window manager. - MultiUserWindowManager* owner_; - - // Contains the wallpaper configuration for the user switching to. This is - // passed to the WallpaperController at the right time. - mojom::WallpaperUserInfoPtr wallpaper_user_info_; + MultiUserWindowManagerChromeOS* owner_; // The new user to set. AccountId new_account_id_; // The animation speed in ms. If 0, animations are disabled. - base::TimeDelta animation_speed_; + int animation_speed_ms_; // The next animation step for AdvanceUserTransitionAnimation(). AnimationStep animation_step_; @@ -128,9 +117,7 @@ // For unit tests: Check which wallpaper was set. std::string wallpaper_user_id_for_test_; - DISALLOW_COPY_AND_ASSIGN(UserSwitchAnimator); + DISALLOW_COPY_AND_ASSIGN(UserSwitchAnimatorChromeOS); }; -} // namespace ash - -#endif // ASH_MULTI_USER_USER_SWITCH_ANIMATOR_H_ +#endif // CHROME_BROWSER_UI_ASH_MULTI_USER_USER_SWITCH_ANIMATOR_CHROMEOS_H_
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 1ad6e17..a54d66f4 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -466,7 +466,7 @@ params.user_gesture); if (hosted_app_controller_) - hosted_app_controller_->UpdateLocationBarVisibility(false); + hosted_app_controller_->UpdateToolbarVisibility(false); // Create the extension window controller before sending notifications. extension_window_controller_.reset( @@ -1377,7 +1377,7 @@ command_controller_->TabStateChanged(); if (hosted_app_controller_) - hosted_app_controller_->UpdateLocationBarVisibility(true); + hosted_app_controller_->UpdateToolbarVisibility(true); } void Browser::VisibleSecurityStateChanged(WebContents* source) { @@ -1388,7 +1388,7 @@ UpdateToolbar(false); if (hosted_app_controller_) - hosted_app_controller_->UpdateLocationBarVisibility(true); + hosted_app_controller_->UpdateToolbarVisibility(true); } }
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h index 32e28018..3c5634e9 100644 --- a/chrome/browser/ui/browser_window.h +++ b/chrome/browser/ui/browser_window.h
@@ -244,6 +244,10 @@ // Updates the toolbar with the state for the specified |contents|. virtual void UpdateToolbar(content::WebContents* contents) = 0; + // Updates whether or not the toolbar is visible. Animates the transition if + // |animate| is true. + virtual void UpdateToolbarVisibility(bool visible, bool animate) = 0; + // Resets the toolbar's tab state for |contents|. virtual void ResetToolbarTabState(content::WebContents* contents) = 0;
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc index 9cd304e..45e95d9 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -77,6 +77,21 @@ namespace { +ContentSettingBubbleModel::ListItem CreateUrlListItem(int32_t id, + const GURL& url) { + // Empty URLs should get a placeholder. + // TODO(csharrison): See if we can DCHECK that the URL will be valid here. + base::string16 title = url.spec().empty() + ? l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) + : base::UTF8ToUTF16(url.spec()); + + // Format the title to include the unicode single dot bullet code-point + // \u2022 and two spaces. + title = l10n_util::GetStringFUTF16(IDS_LIST_BULLET, title); + return ContentSettingBubbleModel::ListItem(gfx::Image(), title, + true /* has_link */, id); +} + struct ContentSettingsTypeIdEntry { ContentSettingsType type; int id; @@ -751,10 +766,8 @@ // Initialize the radio group by setting the appropriate labels for the // content type and setting the default value based on the content setting. void ContentSettingSingleRadioGroup::SetRadioGroup() { - GURL url = web_contents()->GetURL(); + const GURL& url = web_contents()->GetURL(); base::string16 display_host = url_formatter::FormatUrlForSecurityDisplay(url); - if (display_host.empty()) - display_host = base::ASCIIToUTF16(url.spec()); TabSpecificContentSettings* content_settings = TabSpecificContentSettings::FromWebContents(web_contents()); @@ -950,8 +963,6 @@ const content::NotificationDetails& details) override; private: - ListItem CreateListItem(int32_t id, const GURL& id_and_url); - void OnListItemClicked(int index, int event_flags) override; int32_t item_id_from_item_index(int index) const { @@ -982,7 +993,7 @@ auto* helper = PopupBlockerTabHelper::FromWebContents(web_contents); std::map<int32_t, GURL> blocked_popups = helper->GetBlockedPopupRequests(); for (const auto& blocked_popup : blocked_popups) - AddListItem(CreateListItem(blocked_popup.first, blocked_popup.second)); + AddListItem(CreateUrlListItem(blocked_popup.first, blocked_popup.second)); popup_blocker_observer_.Add(helper); content_settings::RecordPopupsAction( @@ -991,7 +1002,7 @@ void ContentSettingPopupBubbleModel::BlockedPopupAdded(int32_t id, const GURL& url) { - AddListItem(CreateListItem(id, url)); + AddListItem(CreateUrlListItem(id, url)); } void ContentSettingPopupBubbleModel::Observe( @@ -1003,22 +1014,6 @@ popup_blocker_observer_.RemoveAll(); } -ContentSettingBubbleModel::ListItem -ContentSettingPopupBubbleModel::CreateListItem(int32_t id, const GURL& url) { - base::string16 title; - // The pop-up may not have a valid URL. - if (url.spec().empty()) - title = l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE); - else - title = base::UTF8ToUTF16(url.spec()); - - // Format the title to include the unicode single dot bullet code-point \u2022 - // and two spaces. - title = l10n_util::GetStringFUTF16(IDS_LIST_BULLET, title); - - return ListItem(gfx::Image(), title, true, id); -} - void ContentSettingPopupBubbleModel::OnListItemClicked(int index, int event_flags) { if (web_contents()) { @@ -1200,8 +1195,6 @@ radio_group.url = url; base::string16 display_host = url_formatter::FormatUrlForSecurityDisplay(url); - if (display_host.empty()) - display_host = base::UTF8ToUTF16(url.spec()); DCHECK(CameraAccessed() || MicrophoneAccessed()); int radio_allow_label_id = 0; @@ -1489,10 +1482,8 @@ // Initialize the radio group by setting the appropriate labels for the // content type and setting the default value based on the content setting. void ContentSettingDownloadsBubbleModel::SetRadioGroup() { - GURL url = web_contents()->GetURL(); + const GURL& url = web_contents()->GetURL(); base::string16 display_host = url_formatter::FormatUrlForSecurityDisplay(url); - if (display_host.empty()) - display_host = base::ASCIIToUTF16(url.spec()); DownloadRequestLimiter* download_request_limiter = g_browser_process->download_request_limiter(); @@ -1582,7 +1573,7 @@ // Build the blocked urls list. for (const auto& blocked_url : helper->blocked_urls()) - AddListItem(CreateListItem(blocked_url)); + AddListItem(CreateUrlListItem(0 /* id */, blocked_url)); helper->AddObserver(this); } @@ -1625,21 +1616,7 @@ void ContentSettingFramebustBlockBubbleModel::OnBlockedUrlAdded( const GURL& blocked_url) { - AddListItem(CreateListItem(blocked_url)); -} - -ContentSettingBubbleModel::ListItem -ContentSettingFramebustBlockBubbleModel::CreateListItem(const GURL& url) { - // Skip empty URLS. - base::string16 title = !url.spec().empty() - ? base::UTF8ToUTF16(url.spec()) - : l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE); - - // Format the title to include the unicode single dot bullet code-point - // \u2022 and two spaces. - title = l10n_util::GetStringFUTF16(IDS_LIST_BULLET, title); - - return ListItem(gfx::Image(), title, true, 0); + AddListItem(CreateUrlListItem(0 /* id */, blocked_url)); } // ContentSettingBubbleModel ---------------------------------------------------
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc index f18e404..9b2f1d15 100644 --- a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc +++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
@@ -183,7 +183,7 @@ return base::FeatureList::IsEnabled(::features::kDesktopPWAWindowing); } -bool HostedAppBrowserController::ShouldShowLocationBar() const { +bool HostedAppBrowserController::ShouldShowToolbar() const { // The extension can be null if this is invoked after uninstall. const Extension* extension = GetExtension(); if (!extension) @@ -194,7 +194,7 @@ const content::WebContents* web_contents = browser_->tab_strip_model()->GetActiveWebContents(); - // Don't show a location bar until a navigation has occurred. + // Don't show a toolbar until a navigation has occurred. if (!web_contents || web_contents->GetLastCommittedURL().is_empty()) return false; @@ -211,16 +211,16 @@ // starts, even if the navigation hasn't committed yet. GURL visible_url = web_contents->GetVisibleURL(); - // The current page must be secure for us to hide the location bar. However, - // the chrome-extension:// and chrome:// launch URL apps can hide the location - // bar, if the current WebContents URLs are the same as the launch scheme. + // The current page must be secure for us to hide the toolbar. However, + // the chrome-extension:// and chrome:// launch URL apps can hide the toolbar, + // if the current WebContents URLs are the same as the launch scheme. // // Note that the launch scheme may be insecure, but as long as the current - // page's scheme is secure, we can hide the location bar. + // page's scheme is secure, we can hide the toolbar. base::StringPiece secure_page_scheme = is_internal_launch_scheme ? launch_scheme : url::kHttpsScheme; - // Insecure page schemes show the location bar. + // Insecure page schemes show the toolbar. if (last_committed_url.scheme_piece() != secure_page_scheme || visible_url.scheme_piece() != secure_page_scheme) { return true; @@ -228,23 +228,21 @@ // Page URLs that are not within scope // (https://www.w3.org/TR/appmanifest/#dfn-within-scope) of the app - // corresponding to |launch_url| show the location bar. + // corresponding to |launch_url| show the toolbar. if (!IsSameScope(launch_url, last_committed_url, web_contents->GetBrowserContext()) || !IsSameScope(launch_url, visible_url, web_contents->GetBrowserContext())) return true; - // Insecure external web sites show the location bar. + // Insecure external web sites show the toolbar. if (!is_internal_launch_scheme && !IsSiteSecure(web_contents)) return true; return false; } -void HostedAppBrowserController::UpdateLocationBarVisibility( - bool animate) const { - browser_->window()->GetLocationBar()->UpdateLocationBarVisibility( - ShouldShowLocationBar(), animate); +void HostedAppBrowserController::UpdateToolbarVisibility(bool animate) const { + browser_->window()->UpdateToolbarVisibility(ShouldShowToolbar(), animate); } bool HostedAppBrowserController::ShouldShowHostedAppButtonContainer() const { @@ -299,7 +297,7 @@ // current page as the title. // Note: We only do this when the CustomTab UI is enabled, as otherwise the // title of the current page will not be displayed anywhere. - if (ShouldShowLocationBar() && + if (ShouldShowToolbar() && base::FeatureList::IsEnabled(features::kDesktopPWAsCustomTabUI)) { const Extension* extension = GetExtension(); return base::UTF8ToUTF16(extension->name());
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.h b/chrome/browser/ui/extensions/hosted_app_browser_controller.h index 5aa74b27..ba4dc95 100644 --- a/chrome/browser/ui/extensions/hosted_app_browser_controller.h +++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.h
@@ -57,8 +57,8 @@ bool IsForExperimentalHostedAppBrowser() const; // Whether the browser being controlled should be currently showing the - // location bar. - bool ShouldShowLocationBar() const; + // toolbar. + bool ShouldShowToolbar() const; // Returns true if the hosted app buttons should be shown in the frame for // this BrowserView. @@ -67,7 +67,7 @@ // Updates the location bar visibility based on whether it should be // currently visible or not. If |animate| is set, the change will be // animated. - void UpdateLocationBarVisibility(bool animate) const; + void UpdateToolbarVisibility(bool animate) const; // Returns the app icon for the window to use in the task list. gfx::ImageSkia GetWindowAppIcon() const;
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc index c1fdb44..567f70b 100644 --- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc +++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -137,15 +137,15 @@ } } -// Used by ShouldLocationBarForXXX. Performs a navigation and then checks that -// the location bar visibility is as expcted. -void NavigateAndCheckForLocationBar(Browser* browser, - const GURL& url, - bool expected_visibility, - bool proceed_through_interstitial = false) { +// Used by ShouldShowToolbarForXXX. Performs a navigation and then checks that +// the toolbar visibility is as expected. +void NavigateAndCheckForToolbar(Browser* browser, + const GURL& url, + bool expected_visibility, + bool proceed_through_interstitial = false) { NavigateToURLAndWait(browser, url, proceed_through_interstitial); EXPECT_EQ(expected_visibility, - browser->hosted_app_controller()->ShouldShowLocationBar()); + browser->hosted_app_controller()->ShouldShowToolbar()); } void CheckWebContentsHasAppPrefs(content::WebContents* web_contents) { @@ -313,6 +313,7 @@ https_server_.AddDefaultHandlers(base::FilePath(kDocRoot)); bool desktop_pwa_flag; + std::tie(app_type_, desktop_pwa_flag) = GetParam(); std::vector<base::Feature> enabled_features; std::vector<base::Feature> disabled_features = { @@ -325,6 +326,7 @@ enabled_features.push_back(features::kBookmarkApps); #endif } + scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); extensions::ExtensionBrowserTest::SetUp(); } @@ -609,28 +611,28 @@ browser()->tab_strip_model()->GetActiveWebContents()); } -// Check that the location bar is shown correctly. -IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowLocationBar) { +// Check that the toolbar is shown correctly. +IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowToolbar) { ASSERT_TRUE(https_server()->Start()); const GURL app_url = https_server()->GetURL("app.com", "/simple.html"); SetupAppWithURL(app_url); - // Navigate to the app's launch page; the location bar should be hidden. - NavigateAndCheckForLocationBar(app_browser_, app_url, false); + // Navigate to the app's launch page; the toolbar should be hidden. + NavigateAndCheckForToolbar(app_browser_, app_url, false); - // Navigate to another page on the same origin; the location bar should still + // Navigate to another page on the same origin; the toolbar should still // hidden. - NavigateAndCheckForLocationBar( + NavigateAndCheckForToolbar( app_browser_, https_server()->GetURL("app.com", "/empty.html"), false); - // Navigate to different origin; the location bar should now be visible. - NavigateAndCheckForLocationBar( + // Navigate to different origin; the toolbar should now be visible. + NavigateAndCheckForToolbar( app_browser_, https_server()->GetURL("foo.com", "/simple.html"), true); } -IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowLocationBarMixedContent) { +IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowToolbarMixedContent) { ASSERT_TRUE(https_server()->Start()); const GURL app_url = https_server()->GetURL("app.com", "/"); @@ -638,16 +640,15 @@ SetupAppWithURL(app_url); // Navigate to another page on the same origin, but with mixed content; the - // location bar should be shown. - NavigateAndCheckForLocationBar( + // toolbar should be shown. + NavigateAndCheckForToolbar( app_browser_, https_server()->GetURL("app.com", "/ssl/page_displays_insecure_content.html"), true); } -IN_PROC_BROWSER_TEST_P(HostedAppTest, - ShouldShowLocationBarDynamicMixedContent) { +IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowToolbarDynamicMixedContent) { ASSERT_TRUE(https_server()->Start()); ASSERT_TRUE(embedded_test_server()->Start()); @@ -656,31 +657,30 @@ SetupAppWithURL(app_url); // Navigate to a page on the same origin. Since mixed content hasn't been - // loaded yet, the location bar shouldn't be shown. - NavigateAndCheckForLocationBar(app_browser_, app_url, false); + // loaded yet, the toolbar shouldn't be shown. + NavigateAndCheckForToolbar(app_browser_, app_url, false); - // Load mixed content; now the location bar should be shown. + // Load mixed content; now the toolbar should be shown. content::WebContents* web_contents = app_browser_->tab_strip_model()->GetActiveWebContents(); EXPECT_TRUE(TryToLoadImage( web_contents, embedded_test_server()->GetURL("foo.com", kImagePath))); - EXPECT_TRUE(app_browser_->hosted_app_controller()->ShouldShowLocationBar()); + EXPECT_TRUE(app_browser_->hosted_app_controller()->ShouldShowToolbar()); } -IN_PROC_BROWSER_TEST_P(HostedAppTest, - ShouldShowLocationBarForHTTPAppSameOrigin) { +IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowToolbarForHTTPAppSameOrigin) { ASSERT_TRUE(embedded_test_server()->Start()); const GURL app_url = embedded_test_server()->GetURL("app.com", "/simple.html"); SetupAppWithURL(app_url); - // Navigate to the app's launch page; the location bar should be visible, even + // Navigate to the app's launch page; the toolbar should be visible, even // though it exactly matches the site, because it is not secure. - NavigateAndCheckForLocationBar(app_browser_, app_url, true); + NavigateAndCheckForToolbar(app_browser_, app_url, true); } -IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowLocationBarForHTTPAppHTTPSUrl) { +IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowToolbarForHTTPAppHTTPSUrl) { ASSERT_TRUE(https_server()->Start()); const GURL app_url = https_server()->GetURL("app.com", "/simple.html"); @@ -692,25 +692,24 @@ // "http" scheme. SetupAppWithURL(app_url.ReplaceComponents(scheme_http)); - // Navigate to the https version of the site; the location bar should + // Navigate to the https version of the site; the toolbar should // be hidden, as it is a more secure version of the site. - NavigateAndCheckForLocationBar(app_browser_, app_url, false); + NavigateAndCheckForToolbar(app_browser_, app_url, false); } -IN_PROC_BROWSER_TEST_P(HostedAppTest, - ShouldShowLocationBarForHTTPSAppSameOrigin) { +IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowToolbarForHTTPSAppSameOrigin) { ASSERT_TRUE(https_server()->Start()); const GURL app_url = https_server()->GetURL("app.com", "/simple.html"); SetupAppWithURL(app_url); - // Navigate to the app's launch page; the location bar should be hidden. - NavigateAndCheckForLocationBar(app_browser_, app_url, false); + // Navigate to the app's launch page; the toolbar should be hidden. + NavigateAndCheckForToolbar(app_browser_, app_url, false); } -// Check that the location bar is shown correctly for HTTPS apps when they +// Check that the toolbar is shown correctly for HTTPS apps when they // navigate to a HTTP page on the same origin. -IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowLocationBarForHTTPSAppHTTPUrl) { +IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowToolbarForHTTPSAppHTTPUrl) { ASSERT_TRUE(https_server()->Start()); const GURL app_url = https_server()->GetURL("app.com", "/simple.html"); @@ -719,38 +718,38 @@ GURL::Replacements scheme_http; scheme_http.SetSchemeStr("http"); - // Navigate to the http version of the site; the location bar should + // Navigate to the http version of the site; the toolbar should // be visible for the https version as it is not secure. - NavigateAndCheckForLocationBar(app_browser_, - app_url.ReplaceComponents(scheme_http), true); + NavigateAndCheckForToolbar(app_browser_, + app_url.ReplaceComponents(scheme_http), true); } -// Check that the location bar is shown correctly for apps that specify start +// Check that the toolbar is shown correctly for apps that specify start // URLs without the 'www.' prefix. -IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowLocationBarForAppWithoutWWW) { +IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowToolbarForAppWithoutWWW) { ASSERT_TRUE(https_server()->Start()); const GURL app_url = https_server()->GetURL("app.com", "/simple.html"); SetupAppWithURL(app_url); - // Navigate to the app's launch page; the location bar should be hidden. - NavigateAndCheckForLocationBar(app_browser_, app_url, false); + // Navigate to the app's launch page; the toolbar should be hidden. + NavigateAndCheckForToolbar(app_browser_, app_url, false); - // Navigate to the app's launch page with the 'www.' prefix; the location bar + // Navigate to the app's launch page with the 'www.' prefix; the toolbar // should be hidden. - NavigateAndCheckForLocationBar( + NavigateAndCheckForToolbar( app_browser_, https_server()->GetURL("www.app.com", "/simple.html"), false); - // Navigate to different origin; the location bar should now be visible. - NavigateAndCheckForLocationBar( + // Navigate to different origin; the toolbar should now be visible. + NavigateAndCheckForToolbar( app_browser_, https_server()->GetURL("www.foo.com", "/simple.html"), true); } -// Checks that the location bar is shown for an HTTPS app with an invalid +// Checks that the toolbar is shown for an HTTPS app with an invalid // certificate, if the user has previously proceeded through the interstitial. -IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowLocationBarDangerous) { +IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowToolbarDangerous) { // If DesktopPWAWindowing and CommittedInterstitials are enabled, we will // never load a dangerous app. Opening dangerous apps will always show an // interstitial and proceeding through it will redirect the navigation to a @@ -791,8 +790,8 @@ proceed_through_interstitial = false; } - NavigateAndCheckForLocationBar(app_browser_, app_url, true, - proceed_through_interstitial); + NavigateAndCheckForToolbar(app_browser_, app_url, true, + proceed_through_interstitial); } // Check that a subframe on a regular web page can navigate to a URL that @@ -986,7 +985,7 @@ ASSERT_TRUE(app_browser_->hosted_app_controller()); - NavigateAndCheckForLocationBar(app_browser_, GURL(kExampleURL), true); + NavigateAndCheckForToolbar(app_browser_, GURL(kExampleURL), true); } // Tests that desktop PWAs open links in the browser. @@ -1040,8 +1039,8 @@ InstallSecurePWA(); - // Location bar should not be visible in the app. - ASSERT_FALSE(app_browser_->hosted_app_controller()->ShouldShowLocationBar()); + // Toolbar should not be visible in the app. + ASSERT_FALSE(app_browser_->hosted_app_controller()->ShouldShowToolbar()); // The installed PWA's scope is app.com:{PORT}/ssl, // so app.com:{PORT}/accessibility_fail.html is out of scope. @@ -1050,7 +1049,7 @@ NavigateToURLAndWait(app_browser_, out_of_scope); // Location should be visible off scope. - ASSERT_TRUE(app_browser_->hosted_app_controller()->ShouldShowLocationBar()); + ASSERT_TRUE(app_browser_->hosted_app_controller()->ShouldShowToolbar()); } // Tests that PWA menus have an uninstall option. @@ -1509,15 +1508,14 @@ } #endif -// Check that the location bar is shown correctly with a System App. -IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest, - ShouldShowLocationBarForSystemApp) { +// Check that the toolbar is shown correctly with a System App. +IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest, ShouldShowToolbarForSystemApp) { const GURL app_url(chrome::kChromeUISettingsURL); SetupSystemAppWithURL(app_url); - // Navigate to the app's launch page; the location bar should be hidden. - NavigateAndCheckForLocationBar(app_browser_, app_url, false); + // Navigate to the app's launch page; the toolbar should be hidden. + NavigateAndCheckForToolbar(app_browser_, app_url, false); } IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest, EngagementHistogram) { @@ -2660,12 +2658,11 @@ } } -// Check that location bar is not shown for apps hosted within extensions pages. +// Check that toolbar is not shown for apps hosted within extensions pages. // This simulates a case where the user has manually navigated to a page hosted // within an extension, then added it as a bookmark app. // Regression test for https://crbug.com/828233. -IN_PROC_BROWSER_TEST_P(BookmarkAppOnlyTest, - ShouldShowLocationBarForExtensionPage) { +IN_PROC_BROWSER_TEST_P(BookmarkAppOnlyTest, ShouldShowToolbarForExtensionPage) { // Note: This involves the creation of *two* extensions: The first is a // regular (non-app) extension with a popup page. The second is a bookmark app // created from the popup page URL (allowing the extension's popup page to be @@ -2693,9 +2690,9 @@ CHECK(app_browser_); CHECK(app_browser_ != browser()); - // Navigate to the app's launch page; the location bar should not be visible, + // Navigate to the app's launch page; the toolbar should not be visible, // because extensions pages are secure. - NavigateAndCheckForLocationBar(app_browser_, popup_url, false); + NavigateAndCheckForToolbar(app_browser_, popup_url, false); } INSTANTIATE_TEST_CASE_P(/* no prefix */,
diff --git a/chrome/browser/ui/find_bar/find_bar_platform_helper_mac_interactive_uitest.mm b/chrome/browser/ui/find_bar/find_bar_platform_helper_mac_interactive_uitest.mm index eb38c953..a72aa94 100644 --- a/chrome/browser/ui/find_bar/find_bar_platform_helper_mac_interactive_uitest.mm +++ b/chrome/browser/ui/find_bar/find_bar_platform_helper_mac_interactive_uitest.mm
@@ -58,7 +58,7 @@ FindBarController* find_bar_controller = browser()->GetFindBarController(); ASSERT_NE(nullptr, find_bar_controller); - base::string16 empty_string(base::ASCIIToUTF16("")); + const base::string16 empty_string; find_bar_controller->SetText(empty_string); chrome::Find(browser()); @@ -90,7 +90,7 @@ browser_incognito->GetFindBarController(); ASSERT_NE(nullptr, find_bar_controller); - base::string16 empty_string(base::ASCIIToUTF16("")); + const base::string16 empty_string; find_bar_controller->SetText(empty_string); chrome::Find(browser_incognito); @@ -130,7 +130,7 @@ GURL url = GetURL(kSimple); ui_test_utils::NavigateToURL(browser(), url); - base::string16 empty_string(base::ASCIIToUTF16("")); + const base::string16 empty_string; find_bar_controller->SetText(empty_string); chrome::Find(browser()); @@ -221,7 +221,7 @@ content::WebContents* first_active_web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - base::string16 empty_string(base::ASCIIToUTF16("")); + const base::string16 empty_string; find_bar_controller->SetText(empty_string); chrome::Find(browser());
diff --git a/chrome/browser/ui/location_bar/location_bar.h b/chrome/browser/ui/location_bar/location_bar.h index 7858e11f..de39c740 100644 --- a/chrome/browser/ui/location_bar/location_bar.h +++ b/chrome/browser/ui/location_bar/location_bar.h
@@ -65,10 +65,6 @@ // Updates the visibility of the bookmark star. virtual void UpdateBookmarkStarVisibility() = 0; - // Updates the visibility of the location bar. Animates the transition if - // |animate| is true. - virtual void UpdateLocationBarVisibility(bool visible, bool animate) = 0; - // Saves the state of the location bar to the specified WebContents, so that // it can be restored later. (Done when switching tabs). virtual void SaveStateToContents(content::WebContents* contents) = 0;
diff --git a/chrome/browser/ui/views/OWNERS b/chrome/browser/ui/views/OWNERS index ac4bb15..75ed6a8 100644 --- a/chrome/browser/ui/views/OWNERS +++ b/chrome/browser/ui/views/OWNERS
@@ -13,4 +13,6 @@ per-file hung_renderer*=file://chrome/browser/ui/hung_renderer/OWNERS +per-file select_file_dialog_extension*=file://ui/file_manager/OWNERS + # COMPONENT: UI>Browser
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc index f170cf7c..fcceb2db 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc
@@ -1358,4 +1358,52 @@ views::LabelButton::ButtonState::STATE_NORMAL); } +// Tests the upload save bubble. Ensures that if the user is selecting an +// expired expiration date, it is not allowed to click [Save]. +IN_PROC_BROWSER_TEST_F( + SaveCardBubbleViewsFullFormBrowserTest, + Upload_SaveButtonIsDisabledIfExpiredExpirationDateAndExpirationDateRequested) { + // Enable the EditableExpirationDate experiment. + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillUpstreamEditableExpirationDate); + + // Set up the Payments RPC. + SetUploadDetailsRpcPaymentsAccepts(); + + // Submitting the form should still show the upload save bubble and legal + // footer, along with a pair of dropdowns specifically requesting the + // expiration date. (Must wait for response from Payments before accessing + // the controller.) + ResetEventWaiterForSequence( + {DialogEvent::REQUESTED_UPLOAD_SAVE, + DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + FillAndSubmitFormWithoutExpirationDate(); + WaitForObservedEvent(); + EXPECT_TRUE( + FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_UPLOAD)->visible()); + EXPECT_TRUE(FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)->visible()); + EXPECT_TRUE(FindViewInBubbleById(DialogViewId::EXPIRATION_DATE_VIEW)); + EXPECT_TRUE(FindViewInBubbleById(DialogViewId::EXPIRATION_DATE_DROPBOX_YEAR)); + EXPECT_TRUE( + FindViewInBubbleById(DialogViewId::EXPIRATION_DATE_DROPBOX_MONTH)); + + views::LabelButton* save_button = static_cast<views::LabelButton*>( + FindViewInBubbleById(DialogViewId::OK_BUTTON)); + views::Combobox* year_input = static_cast<views::Combobox*>( + FindViewInBubbleById(DialogViewId::EXPIRATION_DATE_DROPBOX_YEAR)); + views::Combobox* month_input = static_cast<views::Combobox*>( + FindViewInBubbleById(DialogViewId::EXPIRATION_DATE_DROPBOX_MONTH)); + + // Set now to next month. Setting test_clock will not affect the dropdown to + // be selected, so selecting the current January will always be expired. + autofill::TestAutofillClock test_clock; + test_clock.SetNow(base::Time::Now()); + test_clock.Advance(base::TimeDelta::FromDays(40)); + // Selecting expired date will disable [Save] button. + month_input->SetSelectedRow(1); + year_input->SetSelectedRow(1); + EXPECT_EQ(save_button->state(), + views::LabelButton::ButtonState::STATE_DISABLED); +} + } // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc index 3a28a48..17bac423 100644 --- a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/app/vector_icons/vector_icons.h" @@ -19,6 +20,8 @@ #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/legal_message_line.h" #include "components/autofill/core/browser/ui/save_card_bubble_controller.h" +#include "components/autofill/core/browser/validation.h" +#include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_features.h" #include "components/strings/grit/components_strings.h" #include "ui/base/l10n/l10n_util.h" @@ -103,13 +106,23 @@ &trimmed_text); return !trimmed_text.empty(); } - // If requesting the user select the expiration date, it cannot be unselected. + // If requesting the user select the expiration date, it cannot be unselected + // or expired. if (month_input_dropdown_ || year_input_dropdown_) { // Make sure we are not requesting cardholder name and expiration date at // the same time. DCHECK(!cardholder_name_textfield_); - return !(month_input_dropdown_->selected_index() == 0 || - year_input_dropdown_->selected_index() == 0); + int month_value = 0, year_value = 0; + if (!base::StringToInt(month_input_dropdown_->GetTextForRow( + month_input_dropdown_->selected_index()), + &month_value) || + !base::StringToInt(year_input_dropdown_->GetTextForRow( + year_input_dropdown_->selected_index()), + &year_value)) { + return false; + } + return IsValidCreditCardExpirationDate(year_value, month_value, + AutofillClock::Now()); } return true;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc index 62332db..296c3e0 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
@@ -47,6 +47,7 @@ #include "ui/aura/env_observer.h" #include "ui/aura/window.h" #include "ui/base/clipboard/clipboard.h" +#include "ui/base/test/test_clipboard.h" #include "ui/base/test/ui_controls.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/background.h" @@ -103,9 +104,9 @@ } // views::WidgetObserver: - void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override { + void OnWidgetActivationChanged(views::Widget* widget, bool active) override { CHECK_EQ(dialog_, widget); - if (visible) { + if (active) { dialog_created_ = true; dialog_->RemoveObserver(this); if (!quit_closure_.is_null()) @@ -162,11 +163,11 @@ explicit TabKeyWaiter(views::Widget* widget) : widget_(widget), received_tab_(false) { - widget_->GetNativeView()->AddPreTargetHandler(this); + widget_->GetNativeWindow()->AddPreTargetHandler(this); } ~TabKeyWaiter() override { - widget_->GetNativeView()->RemovePreTargetHandler(this); + widget_->GetNativeWindow()->RemovePreTargetHandler(this); } void WaitForTab() { @@ -315,6 +316,15 @@ // state calculated in GetPreferredSizeForContents(). EXPECT_TRUE(GetBookmarkButton(5)->visible()); EXPECT_FALSE(GetBookmarkButton(6)->visible()); + +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + // On desktop Linux, the bookmark bar context menu blocks on retrieving the + // clipboard selection from the X server (for the 'paste' item), so mock it + // out. + ui::Clipboard::SetClipboardForCurrentThread( + std::make_unique<ui::TestClipboard>()); + GetWidget()->Activate(); +#endif } void TearDown() override { @@ -490,8 +500,6 @@ // NOTE: this code assume there is a left margin, which is currently // true. If that changes, this code will need to find another empty space // to press the mouse on. - gfx::Point mouse_loc; - views::View::ConvertPointToScreen(bb_view_.get(), &mouse_loc); ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone( 0, 0, CreateEventTask(this, &BookmarkBarViewTest2::Step3))); } @@ -520,9 +528,8 @@ } }; -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) || defined(OS_WIN) -// TODO(erg): linux_aura bringup: http://crbug.com/163931 -// Disable this test on Win10: http://crbug.com/828063 +#if defined(OS_WIN) +// Disable this test on Win10: http://crbug.com/828063 #define MAYBE_HideOnDesktopClick DISABLED_HideOnDesktopClick #else #define MAYBE_HideOnDesktopClick HideOnDesktopClick @@ -1298,6 +1305,8 @@ class BookmarkBarViewTest12 : public BookmarkBarViewEventTestBase { protected: void DoTestOnMessageLoop() override { + base::RunLoop().RunUntilIdle(); + // Open up the other folder. views::LabelButton* button = bb_view_->other_bookmarks_button(); ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT, @@ -1330,7 +1339,9 @@ void Step3() { // Make sure the context menu is showing. views::MenuItemView* menu = bb_view_->GetContextMenu(); - ASSERT_TRUE(menu && menu->GetSubmenu() && menu->GetSubmenu()->IsShowing()); + ASSERT_TRUE(menu); + ASSERT_TRUE(menu->GetSubmenu()); + ASSERT_TRUE(menu->GetSubmenu()->IsShowing()); // Select the first item in the context menu (open all). views::MenuItemView* child_menu = @@ -1338,8 +1349,8 @@ ASSERT_TRUE(child_menu != NULL); // Click and wait until the dialog box appears. - auto dialog_waiter = std::make_unique<DialogWaiter>( - bb_view_->GetWidget()->GetNativeWindow()->env()); + auto dialog_waiter = + std::make_unique<DialogWaiter>(GetWidget()->GetNativeWindow()->env()); ui_test_utils::MoveMouseToCenterAndPress( child_menu, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP, base::Bind(&BookmarkBarViewTest12::Step4, base::Unretained(this), @@ -1354,7 +1365,7 @@ // receives the tab key. TabKeyWaiter tab_waiter(dialog); ASSERT_TRUE(ui_controls::SendKeyPress( - window_->GetNativeWindow(), ui::VKEY_TAB, false, false, false, false)); + dialog->GetNativeWindow(), ui::VKEY_TAB, false, false, false, false)); tab_waiter.WaitForTab(); // For some reason return isn't processed correctly unless we delay. @@ -1369,21 +1380,14 @@ DialogCloseWaiter waiter(dialog); // And press enter so that the cancel button is selected. ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone( - window_->GetNativeWindow(), ui::VKEY_RETURN, false, false, false, false, + dialog->GetNativeWindow(), ui::VKEY_RETURN, false, false, false, false, base::OnceClosure())); waiter.WaitForDialogClose(); Done(); } }; -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) -// TODO(erg): linux_aura bringup: http://crbug.com/163931 -#define MAYBE_CloseWithModalDialog DISABLED_CloseWithModalDialog -#else -#define MAYBE_CloseWithModalDialog CloseWithModalDialog -#endif - -VIEW_TEST(BookmarkBarViewTest12, MAYBE_CloseWithModalDialog) +VIEW_TEST(BookmarkBarViewTest12, CloseWithModalDialog) // Tests clicking on the separator of a context menu (this is for coverage of // bug 17862). @@ -1884,7 +1888,7 @@ } void Step3() { -#if defined(OS_CHROMEOS) +#if defined(OS_LINUX) ASSERT_EQ(test_view_->press_count(), 1); #else ASSERT_EQ(test_view_->press_count(), 2); @@ -1932,14 +1936,7 @@ TestViewForMenuExit* test_view_; }; -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) -// TODO(erg): linux_aura bringup: http://crbug.com/163931 -#define MAYBE_ContextMenuExitTest DISABLED_ContextMenuExitTest -#else -#define MAYBE_ContextMenuExitTest ContextMenuExitTest -#endif - -VIEW_TEST(BookmarkBarViewTest20, MAYBE_ContextMenuExitTest) +VIEW_TEST(BookmarkBarViewTest20, ContextMenuExitTest) // Tests context menu by way of opening a context menu for a empty folder menu. // The opened context menu should behave as it is from the folder button. @@ -2144,13 +2141,7 @@ BookmarkContextMenuNotificationObserver observer_; }; -#if defined(USE_OZONE) -// ozone bringup - http://crbug.com/401304 -#define MAYBE_ContextMenusKeyboard DISABLED_ContextMenusKeyboard -#else -#define MAYBE_ContextMenusKeyboard ContextMenusKeyboard -#endif -VIEW_TEST(BookmarkBarViewTest23, MAYBE_ContextMenusKeyboard) +VIEW_TEST(BookmarkBarViewTest23, ContextMenusKeyboard) // Test that pressing escape on a menu opened via the keyboard dismisses the // context menu but not the parent menu. @@ -2228,13 +2219,7 @@ BookmarkContextMenuNotificationObserver observer_; }; -#if defined(USE_OZONE) -// ozone bringup - http://crbug.com/401304 -#define MAYBE_ContextMenusKeyboardEscape DISABLED_ContextMenusKeyboardEscape -#else -#define MAYBE_ContextMenusKeyboardEscape ContextMenusKeyboardEscape -#endif -VIEW_TEST(BookmarkBarViewTest24, MAYBE_ContextMenusKeyboardEscape) +VIEW_TEST(BookmarkBarViewTest24, ContextMenusKeyboardEscape) #if defined(OS_WIN) // Tests that pressing the key KEYCODE closes the menu.
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 2ab5f23..67ef208 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1134,6 +1134,11 @@ toolbar_->Update(contents); } +void BrowserView::UpdateToolbarVisibility(bool visible, bool animate) { + if (toolbar_) + toolbar_->UpdateToolbarVisibility(visible, animate); +} + void BrowserView::ResetToolbarTabState(content::WebContents* contents) { // We may end up here during destruction. if (toolbar_)
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index c8820b0..a80f870 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -337,6 +337,7 @@ void SetFocusToLocationBar(bool select_all) override; void UpdateReloadStopState(bool is_loading, bool force) override; void UpdateToolbar(content::WebContents* contents) override; + void UpdateToolbarVisibility(bool visible, bool animate) override; void ResetToolbarTabState(content::WebContents* contents) override; void FocusToolbar() override; ToolbarActionsBar* GetToolbarActionsBar() override;
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 249a763..a2e2cc8e 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -269,8 +269,6 @@ // visible when the location entry has just been initialized. Update(nullptr); - size_animation_.Reset(1); - hover_animation_.SetSlideDuration(200); } @@ -377,8 +375,6 @@ if (!IsInitialized()) return min_size; - min_size.set_height(min_size.height() * size_animation_.GetCurrentValue()); - // Compute width of omnibox-leading content. int leading_width = 0; if (ShouldShowKeywordBubble()) { @@ -959,21 +955,6 @@ } } -void LocationBarView::UpdateLocationBarVisibility(bool visible, bool animate) { - if (!animate) { - size_animation_.Reset(visible ? 1 : 0); - SetVisible(visible); - return; - } - - if (visible) { - SetVisible(true); - size_animation_.Show(); - } else { - size_animation_.Hide(); - } -} - void LocationBarView::SaveStateToContents(WebContents* contents) { omnibox_view_->SaveStateToTab(contents); } @@ -1086,28 +1067,18 @@ //////////////////////////////////////////////////////////////////////////////// // LocationBarView, private gfx::AnimationDelegate implementation: void LocationBarView::AnimationProgressed(const gfx::Animation* animation) { - if (animation == &size_animation_) { - GetWidget()->non_client_view()->Layout(); - } else if (animation == &hover_animation_) { - RefreshBackground(); - } else { - NOTREACHED(); - } + DCHECK_EQ(animation, &hover_animation_); + RefreshBackground(); } void LocationBarView::AnimationEnded(const gfx::Animation* animation) { - if (animation == &size_animation_) { - AnimationProgressed(animation); - if (animation->GetCurrentValue() == 0) - SetVisible(false); - } else if (animation == &hover_animation_) { - AnimationProgressed(animation); - } + DCHECK_EQ(animation, &hover_animation_); + AnimationProgressed(animation); } void LocationBarView::AnimationCanceled(const gfx::Animation* animation) { - if (animation == &hover_animation_) - AnimationProgressed(animation); + DCHECK_EQ(animation, &hover_animation_); + AnimationProgressed(animation); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h index a39e379..1613556b 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.h +++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -325,7 +325,6 @@ void UpdateSaveCreditCardIcon() override; void UpdateLocalCardMigrationIcon() override; void UpdateBookmarkStarVisibility() override; - void UpdateLocationBarVisibility(bool visible, bool animation) override; void SaveStateToContents(content::WebContents* contents) override; const OmniboxView* GetOmniboxView() const override; LocationBarTesting* GetLocationBarForTesting() override; @@ -436,9 +435,6 @@ // user to clear all text. views::ImageButton* clear_all_button_ = nullptr; - // Animation to control showing / hiding the location bar. - gfx::SlideAnimation size_animation_{this}; - // Animation to change whole location bar background color on hover. gfx::SlideAnimation hover_animation_{this};
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index cb7262f2..bae1555 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -145,6 +145,8 @@ location_bar_ = new LocationBarView(browser_, browser_->profile(), browser_->command_controller(), this, !is_display_mode_normal()); + // Make sure the toolbar shows by default. + size_animation_.Reset(1); if (!is_display_mode_normal()) { AddChildView(location_bar_); @@ -267,6 +269,16 @@ initialized_ = true; } +void ToolbarView::AnimationEnded(const gfx::Animation* animation) { + AnimationProgressed(animation); + if (animation->GetCurrentValue() == 0) + SetToolbarVisibility(false); +} + +void ToolbarView::AnimationProgressed(const gfx::Animation* animation) { + GetWidget()->non_client_view()->Layout(); +} + void ToolbarView::Update(WebContents* tab) { if (location_bar_) location_bar_->Update(tab); @@ -276,6 +288,26 @@ reload_->set_menu_enabled(chrome::IsDebuggerAttachedToCurrentTab(browser_)); } +void ToolbarView::SetToolbarVisibility(bool visible) { + SetVisible(visible); + location_bar_->SetVisible(visible); +} + +void ToolbarView::UpdateToolbarVisibility(bool visible, bool animate) { + if (!animate) { + size_animation_.Reset(visible ? 1.0 : 0.0); + SetToolbarVisibility(visible); + return; + } + + if (visible) { + SetToolbarVisibility(true); + size_animation_.Show(); + } else { + size_animation_.Hide(); + } +} + void ToolbarView::ResetTabState(WebContents* tab) { if (location_bar_) location_bar_->ResetTabState(tab); @@ -768,6 +800,8 @@ ui::MaterialDesignController::touch_ui() ? 0 : 9; size.SetToMax(gfx::Size(0, content_height + extra_vertical_space)); } + + size.set_height(size.height() * size_animation_.GetCurrentValue()); return size; }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h index 16c0dac..6a89142 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -57,6 +57,7 @@ class ToolbarView : public views::AccessiblePaneView, public views::MenuButtonListener, public ui::AcceleratorProvider, + public gfx::AnimationDelegate, public LocationBarView::Delegate, public BrowserActionsContainer::Delegate, public CommandObserver, @@ -82,6 +83,10 @@ // as well. void Update(content::WebContents* tab); + // Updates the visibility of the toolbar, potentially animating the + // transition. + void UpdateToolbarVisibility(bool visible, bool animate); + // Clears the current state for |tab|. void ResetTabState(content::WebContents* tab); @@ -170,6 +175,10 @@ bool AcceleratorPressed(const ui::Accelerator& acc) override; void ChildPreferredSizeChanged(views::View* child) override; + bool is_display_mode_normal() const { + return display_mode_ == DISPLAYMODE_NORMAL; + } + protected: // AccessiblePaneView: bool SetPaneFocusAndFocusDefault() override; @@ -177,18 +186,23 @@ // ui::MaterialDesignControllerObserver: void OnTouchUiChanged() override; - bool is_display_mode_normal() const { - return display_mode_ == DISPLAYMODE_NORMAL; - } + // This controls Toolbar and LocationBar visibility. + // If we don't both, tab navigation from the app menu breaks + // on Chrome OS. + void SetToolbarVisibility(bool visible); private: // Types of display mode this toolbar can have. enum DisplayMode { - DISPLAYMODE_NORMAL, // Normal toolbar with buttons, etc. - DISPLAYMODE_LOCATION // Slimline toolbar showing only compact location - // bar, used for popups. + DISPLAYMODE_NORMAL, // Normal toolbar with buttons, etc. + DISPLAYMODE_LOCATION // Slimline toolbar showing only compact location + // bar, used for popups. }; + // AnimationDelegate: + void AnimationEnded(const gfx::Animation* animation) override; + void AnimationProgressed(const gfx::Animation* animation) override; + // AppMenuIconController::Delegate: void UpdateTypeAndSeverity( AppMenuIconController::TypeAndSeverity type_and_severity) override; @@ -227,6 +241,8 @@ void OnShowHomeButtonChanged(); + gfx::SlideAnimation size_animation_{this}; + // Controls. Most of these can be null, e.g. in popup windows. Only // |location_bar_| is guaranteed to exist. These pointers are owned by the // view hierarchy.
diff --git a/chrome/chrome_cleaner/chrome_utils/BUILD.gn b/chrome/chrome_cleaner/chrome_utils/BUILD.gn index d9fc74c..f7a99c0 100644 --- a/chrome/chrome_cleaner/chrome_utils/BUILD.gn +++ b/chrome/chrome_cleaner/chrome_utils/BUILD.gn
@@ -23,9 +23,25 @@ deps = [ ":chrome_util_lib", + ":force_installed_extension", "//base:base", + "//chrome/chrome_cleaner/logging/proto:shared_data_proto", "//chrome/chrome_cleaner/os:common_os", "//chrome/chrome_cleaner/parsers/json_parser", + "//chrome/chrome_cleaner/parsers/json_parser:json_splicer", + "//chrome/chrome_cleaner/parsers/parser_utils:parse_tasks_remaining_counter", + ] +} + +source_set("force_installed_extension") { + sources = [ + "force_installed_extension.cc", + "force_installed_extension.h", + ] + + deps = [ + ":extension_id", + "//chrome/chrome_cleaner/logging/proto:shared_data_proto", ] } @@ -41,7 +57,19 @@ "//base:base", "//base/test:test_support", "//chrome/chrome_cleaner/parsers/json_parser", + "//chrome/chrome_cleaner/test:test_extensions", "//chrome/chrome_cleaner/test:test_util", "//testing/gtest", ] } + +source_set("extension_id") { + sources = [ + "extension_id.cc", + "extension_id.h", + ] + + deps = [ + "//base:base", + ] +}
diff --git a/chrome/chrome_cleaner/chrome_utils/extension_id.cc b/chrome/chrome_cleaner/chrome_utils/extension_id.cc new file mode 100644 index 0000000..91d4444 --- /dev/null +++ b/chrome/chrome_cleaner/chrome_utils/extension_id.cc
@@ -0,0 +1,39 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/chrome_cleaner/chrome_utils/extension_id.h" + +#include <string> + +#include "base/logging.h" +#include "base/optional.h" + +namespace chrome_cleaner { + +base::Optional<ExtensionID> ExtensionID::Create(const std::string& value) { + if (ExtensionID::IsValidID(value)) { + return {ExtensionID(value)}; + } + return {}; +} + +ExtensionID::ExtensionID(const std::string& value) : value_(value) {} + +bool ExtensionID::IsValidID(const std::string& value) { + if (value.length() < 32) { + return false; + } + for (const auto& character : value) { + if (character < 'a' || character > 'p') { + return false; + } + } + return true; +} + +std::string ExtensionID::AsString() const { + return value_; +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/chrome_utils/extension_id.h b/chrome/chrome_cleaner/chrome_utils/extension_id.h new file mode 100644 index 0000000..03e4753d --- /dev/null +++ b/chrome/chrome_cleaner/chrome_utils/extension_id.h
@@ -0,0 +1,47 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_CHROME_CLEANER_CHROME_UTILS_EXTENSION_ID_H_ +#define CHROME_CHROME_CLEANER_CHROME_UTILS_EXTENSION_ID_H_ + +#include <string> + +#include "base/optional.h" + +namespace chrome_cleaner { + +// A wrapper around std::string which upholds the extension id invariants. +// An extension must be a unique identifier that is 32 characters long between +// 'a' - 'p' for each character. +class ExtensionID { + public: + // Creates an ExtensionID if the |value| is a valid extension id. + // If the extension id is invalid no ExtensionID is stored in the optional. + static base::Optional<ExtensionID> Create(const std::string& value); + // Determines if the |value| is a valid extension ID. + static bool IsValidID(const std::string& value); + + std::string AsString() const; + + bool operator==(const ExtensionID& other) const { + return value_ == other.value_; + } + + bool operator<(const ExtensionID& other) const { + return value_ < other.value_; + } + + bool operator>(const ExtensionID& other) const { + return value_ > other.value_; + } + + private: + explicit ExtensionID(const std::string& value); + + std::string value_; +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_CHROME_UTILS_EXTENSION_ID_H_
diff --git a/chrome/chrome_cleaner/chrome_utils/extensions_util.cc b/chrome/chrome_cleaner/chrome_utils/extensions_util.cc index ac79c873..35d0874 100644 --- a/chrome/chrome_cleaner/chrome_utils/extensions_util.cc +++ b/chrome/chrome_cleaner/chrome_utils/extensions_util.cc
@@ -10,6 +10,8 @@ #include <memory> #include <set> #include <string> +#include <utility> +#include <vector> #include "base/bind.h" #include "base/callback_helpers.h" @@ -28,6 +30,8 @@ #include "chrome/chrome_cleaner/os/registry.h" #include "chrome/chrome_cleaner/os/registry_util.h" #include "chrome/chrome_cleaner/os/system_util.h" +#include "chrome/chrome_cleaner/parsers/json_parser/json_splicer.h" +#include "chrome/chrome_cleaner/parsers/parser_utils/parse_tasks_remaining_counter.h" using base::WaitableEvent; @@ -36,36 +40,7 @@ const int kExtensionIdLength = 32; -class ParseTasksRemainingCounter - : public base::RefCountedThreadSafe<ParseTasksRemainingCounter> { - public: - ParseTasksRemainingCounter(size_t count, WaitableEvent* done) - : count_(count), done_(done) { - DCHECK(count_ > 0) << "Must be constructed with a positive count."; - } - - void Increment() { - DCHECK(count_ > 0) - << "Once decremented to zero, Increment should never be called."; - count_++; - } - - void Decrement() { - DCHECK(count_); - count_--; - if (count_ == 0) { - done_->Signal(); - } - } - - private: - friend class base::RefCountedThreadSafe<ParseTasksRemainingCounter>; - ~ParseTasksRemainingCounter() = default; - - size_t count_; - WaitableEvent* done_; -}; - +// TODO(joenotcharles): Use RegKeyPath instead. struct RegistryKey { HKEY hkey; const wchar_t* path; @@ -95,6 +70,21 @@ const wchar_t kMasterPreferencesFileName[] = L"master_preferences"; +// Removes the extension from the JSON. If the extension is not associated +// wih a valid file and JSON value then this function returns false and +// |json_result| is not modified. +bool RemoveExtensionFromJson(const ForceInstalledExtension& extension, + base::Value* json_result) { + DCHECK(json_result); + DCHECK(extension.policy_file); + if (!extension.policy_file->json) { + return false; + } + + bool result = RemoveKeyFromDictionary(json_result, extension.id.AsString()); + return result; +} + void GetForcelistPoliciesForAccessMask( REGSAM access_mask, std::vector<ExtensionPolicyRegistryEntry>* policies) { @@ -114,16 +104,50 @@ policies->emplace_back(extension_id, extension_forcelist_keys[i].hkey, extension_forcelist_keys[i].path, - forcelist_it.Name()); + forcelist_it.Name(), forcelist_it.Type(), + nullptr); } } } } +bool RemoveForcelistPolicyExtensionForAccessMask( + REGSAM access_mask, + const ForceInstalledExtension& extension) { + for (size_t i = 0; i < base::size(extension_forcelist_keys); ++i) { + std::vector<base::string16> keys; + base::win::RegistryValueIterator forcelist_it( + extension_forcelist_keys[i].hkey, extension_forcelist_keys[i].path, + access_mask); + for (; forcelist_it.Valid(); ++forcelist_it) { + base::string16 entry; + GetRegistryValueAsString(forcelist_it.Value(), forcelist_it.ValueSize(), + forcelist_it.Type(), &entry); + if (base::UTF16ToUTF8(entry.substr(0, kExtensionIdLength)) == + extension.id.AsString()) { + keys.push_back(forcelist_it.Name()); + } + } + base::win::RegKey key; + key.Open(extension_forcelist_keys[i].hkey, extension_forcelist_keys[i].path, + access_mask | KEY_WRITE); + for (base::string16& key_name : keys) { + LONG result = key.DeleteValue(key_name.c_str()); + if (result != ERROR_SUCCESS) { + LOG(WARNING) << "Could not delete value at key " << key_name + << ", error code: " << result; + return false; + } + } + } + return true; +} + void GetExtensionSettingsPoliciesFromParsedJson( const RegistryKey& registry_key, std::vector<ExtensionPolicyRegistryEntry>* policies, scoped_refptr<ParseTasksRemainingCounter> counter, + ContentType type, base::Optional<base::Value> json, const base::Optional<std::string>& error) { base::ScopedClosureRunner closure( @@ -140,6 +164,8 @@ return; } + scoped_refptr<RefValue> saved_json = + base::WrapRefCounted(new RefValue(json->Clone())); for (const auto& entry : *extension_settings) { const base::string16& extension_id = base::UTF8ToUTF16(entry.first); const std::unique_ptr<base::Value>& settings_value = entry.second; @@ -150,9 +176,9 @@ if (installation_mode != nullptr && installation_mode->GetString() == kExtensionSettingsForceInstalledValue) { - policies->emplace_back(extension_id, registry_key.hkey, - registry_key.path, - kExtensionSettingsRegistryEntryName); + policies->emplace_back( + extension_id, registry_key.hkey, registry_key.path, + kExtensionSettingsRegistryEntryName, type, saved_json); } } } @@ -168,7 +194,7 @@ extension_settings_keys[i].path, access_mask); base::string16 extension_settings; RegistryError error; - uint32_t type; + ContentType type; ReadRegistryValue(key, kExtensionSettingsRegistryEntryName, &extension_settings, &type, &error); @@ -185,7 +211,7 @@ json_parser->Parse( base::UTF16ToUTF8(extension_settings), base::BindOnce(&GetExtensionSettingsPoliciesFromParsedJson, - extension_settings_keys[i], policies, counter)); + extension_settings_keys[i], policies, counter, type)); } } @@ -208,10 +234,13 @@ return; } + scoped_refptr<RefValue> saved_json = + base::WrapRefCounted(new RefValue(json->Clone())); for (const auto& entry : *default_extensions) { base::string16 extension_id = base::UTF8ToUTF16(entry.first); - if (!base::ContainsValue(default_extension_whitelist, extension_id)) - policies->emplace_back(extension_id, extensions_file); + if (!base::ContainsValue(default_extension_whitelist, extension_id)) { + policies->emplace_back(extension_id, extensions_file, saved_json); + } } } @@ -241,9 +270,11 @@ base::DictionaryValue* extension_settings_dictionary; extension_settings->GetAsDictionary(&extension_settings_dictionary); + scoped_refptr<RefValue> saved_json = + base::WrapRefCounted(new RefValue(json->Clone())); for (const auto& entry : *extension_settings_dictionary) { base::string16 extension_id = base::UTF8ToUTF16(entry.first); - policies->emplace_back(extension_id, extensions_file); + policies->emplace_back(extension_id, extensions_file, saved_json); } } @@ -253,21 +284,33 @@ const base::string16& extension_id, HKEY hkey, const base::string16& path, - const base::string16& name) - : extension_id(extension_id), hkey(hkey), path(path), name(name) {} + const base::string16& name, + ContentType content_type, + scoped_refptr<RefValue> json) + : extension_id(extension_id), + hkey(hkey), + path(path), + name(name), + content_type(content_type), + json(std::move(json)) {} ExtensionPolicyRegistryEntry::ExtensionPolicyRegistryEntry( ExtensionPolicyRegistryEntry&&) = default; +ExtensionPolicyRegistryEntry::~ExtensionPolicyRegistryEntry() = default; + ExtensionPolicyRegistryEntry& ExtensionPolicyRegistryEntry::operator=( ExtensionPolicyRegistryEntry&&) = default; ExtensionPolicyFile::ExtensionPolicyFile(const base::string16& extension_id, - const base::FilePath& path) - : extension_id(extension_id), path(path) {} + const base::FilePath& path, + scoped_refptr<RefValue> json) + : extension_id(extension_id), path(path), json(std::move(json)) {} ExtensionPolicyFile::ExtensionPolicyFile(ExtensionPolicyFile&&) = default; +ExtensionPolicyFile::~ExtensionPolicyFile() = default; + ExtensionPolicyFile& ExtensionPolicyFile::operator=(ExtensionPolicyFile&&) = default; @@ -278,6 +321,19 @@ GetForcelistPoliciesForAccessMask(KEY_WOW64_64KEY, policies); } +bool RemoveForcelistPolicyExtension(const ForceInstalledExtension& extension) { + DCHECK(extension.install_method == POLICY_EXTENSION_FORCELIST); + // No need to check for policy_registry_entry, as it's not used in deletion. + + bool result = + RemoveForcelistPolicyExtensionForAccessMask(KEY_WOW64_32KEY, extension); + if (IsX64Architecture() && result) { + result = + RemoveForcelistPolicyExtensionForAccessMask(KEY_WOW64_64KEY, extension); + } + return result; +} + void GetNonWhitelistedDefaultExtensions( JsonParserAPI* json_parser, std::vector<ExtensionPolicyFile>* policies, @@ -317,6 +373,12 @@ } } +bool RemoveDefaultExtension(const ForceInstalledExtension& extension, + base::Value* json_result) { + DCHECK(extension.install_method == DEFAULT_APPS_EXTENSION); + return RemoveExtensionFromJson(extension, json_result); +} + void GetExtensionSettingsForceInstalledExtensions( JsonParserAPI* json_parser, std::vector<ExtensionPolicyRegistryEntry>* policies, @@ -335,6 +397,19 @@ counter->Decrement(); } +bool RemoveExtensionSettingsPoliciesExtension( + const ForceInstalledExtension& extension, + base::Value* json_result) { + DCHECK(extension.install_method == POLICY_EXTENSION_SETTINGS); + DCHECK(extension.policy_registry_entry); + DCHECK(json_result); + + if (!extension.policy_registry_entry->json.get()) { + return false; + } + return RemoveKeyFromDictionary(json_result, extension.id.AsString()); +} + void GetMasterPreferencesExtensions(JsonParserAPI* json_parser, std::vector<ExtensionPolicyFile>* policies, base::WaitableEvent* done) { @@ -373,4 +448,15 @@ } } +bool RemoveMasterPreferencesExtension(const ForceInstalledExtension& extension, + base::Value* json_result) { + DCHECK(extension.install_method == POLICY_MASTER_PREFERENCES); + DCHECK(json_result); + DCHECK(json_result->is_dict()); + // The extensions are stored in ["extensions"]["settings"] + base::Value* sub_dictionary = + json_result->FindPath({"extensions", "settings"}); + return RemoveExtensionFromJson(extension, sub_dictionary); +} + } // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/chrome_utils/extensions_util.h b/chrome/chrome_cleaner/chrome_utils/extensions_util.h index 37a3efc..f29628a 100644 --- a/chrome/chrome_cleaner/chrome_utils/extensions_util.h +++ b/chrome/chrome_cleaner/chrome_utils/extensions_util.h
@@ -9,25 +9,39 @@ #include "base/files/file_path.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" +#include "base/optional.h" #include "base/strings/string16.h" #include "base/synchronization/waitable_event.h" +#include "chrome/chrome_cleaner/chrome_utils/force_installed_extension.h" #include "chrome/chrome_cleaner/os/registry_util.h" #include "chrome/chrome_cleaner/parsers/json_parser/json_parser_api.h" namespace chrome_cleaner { +typedef base::RefCountedData<base::Value> RefValue; +typedef uint32_t ContentType; + +constexpr int64_t kParseAttemptTimeoutMilliseconds = 10000; + // A registry key that holds some form of policy for |extension_id|. struct ExtensionPolicyRegistryEntry { base::string16 extension_id; HKEY hkey; base::string16 path; base::string16 name; + ContentType content_type; + scoped_refptr<RefValue> json; ExtensionPolicyRegistryEntry(const base::string16& extension_id, HKEY hkey, const base::string16& path, - const base::string16& name); + const base::string16& name, + ContentType content_type, + scoped_refptr<RefValue>); ExtensionPolicyRegistryEntry(ExtensionPolicyRegistryEntry&&); + ~ExtensionPolicyRegistryEntry(); ExtensionPolicyRegistryEntry& operator=(ExtensionPolicyRegistryEntry&&); DISALLOW_COPY_AND_ASSIGN(ExtensionPolicyRegistryEntry); @@ -37,10 +51,13 @@ struct ExtensionPolicyFile { base::string16 extension_id; base::FilePath path; + scoped_refptr<RefValue> json; ExtensionPolicyFile(const base::string16& extension_id, - const base::FilePath& path); + const base::FilePath& path, + scoped_refptr<RefValue> json); ExtensionPolicyFile(ExtensionPolicyFile&&); + ~ExtensionPolicyFile(); ExtensionPolicyFile& operator=(ExtensionPolicyFile&&); DISALLOW_COPY_AND_ASSIGN(ExtensionPolicyFile); @@ -75,6 +92,32 @@ std::vector<ExtensionPolicyFile>* policies, base::WaitableEvent* done); +// Attempts to remove an |extension| installed through the whitelist. +// The extension id will be removed from the |json_result| passed in, so that +// the caller can build up the new JSON value before writing it to the disk. +// On failure returns false and doesn't modify the |json_result|. +bool RemoveDefaultExtension(const ForceInstalledExtension& extension, + base::Value* json_result); + +// Attempts to remove an extension installed through the forcelist. +// Return True on success. +bool RemoveForcelistPolicyExtension(const ForceInstalledExtension& extension); + +// Attempts to remove an extension installed from the policy settings +// The extension id will be removed from the |json_result| passed in so that +// the caller can build up a new JSON value before writing it to the registry. +// On failure returns false and does not modify the |json_result|. +bool RemoveExtensionSettingsPoliciesExtension( + const ForceInstalledExtension& extension, + base::Value* json_result); + +// Attempts to remove an extension installed through the master preferences. +// The extension id will be removed from the |json_result| passed in so that the +// caller can build up the a new JSON value before writing it to the disk. +// On failure returns false and does not modify the |json_result|. +bool RemoveMasterPreferencesExtension(const ForceInstalledExtension& extension, + base::Value* json_result); + } // namespace chrome_cleaner #endif // CHROME_CHROME_CLEANER_CHROME_UTILS_EXTENSIONS_UTIL_H_
diff --git a/chrome/chrome_cleaner/chrome_utils/extensions_util_unittest.cc b/chrome/chrome_cleaner/chrome_utils/extensions_util_unittest.cc index 1160219..c658152e7 100644 --- a/chrome/chrome_cleaner/chrome_utils/extensions_util_unittest.cc +++ b/chrome/chrome_cleaner/chrome_utils/extensions_util_unittest.cc
@@ -4,12 +4,18 @@ #include "chrome/chrome_cleaner/chrome_utils/extensions_util.h" +#include <memory> +#include <string> +#include <unordered_set> +#include <utility> #include <vector> #include "base/base_paths_win.h" #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/json/json_string_value_serializer.h" #include "base/path_service.h" +#include "base/stl_util.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/waitable_event.h" @@ -18,6 +24,7 @@ #include "base/test/test_timeouts.h" #include "base/win/registry.h" #include "chrome/chrome_cleaner/parsers/json_parser/test_json_parser.h" +#include "chrome/chrome_cleaner/test/test_extensions.h" #include "chrome/chrome_cleaner/test/test_file_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -29,91 +36,18 @@ const int kExtensionIdLength = 32; -struct TestRegistryEntry { - HKEY hkey; - const base::string16 path; - const base::string16 name; - const base::string16 value; +struct ExtensionIDHash { + size_t operator()(const ForceInstalledExtension& extension) const { + return std::hash<std::string>{}(extension.id.AsString()); + } }; -const TestRegistryEntry extension_forcelist_entries[] = { - {HKEY_LOCAL_MACHINE, kChromePoliciesForcelistKeyPath, L"test1", - L"ababababcdcdcdcdefefefefghghghgh;https://test.test/crx" - L"update2/crx"}, - {HKEY_CURRENT_USER, kChromePoliciesForcelistKeyPath, L"test2", - L"aaaabbbbccccddddeeeeffffgggghhhh;https://test.test/crx" - L"update2/crx"}}; - -const wchar_t kFakeChromeFolder[] = L"google\\chrome\\application\\42.12.34.56"; - -const wchar_t kTestExtensionId1[] = L"ababababcdcdcdcdefefefefghghghgh"; -const wchar_t kTestExtensionId2[] = L"aaaabbbbccccddddeeeeffffgggghhhh"; -const char kDefaultExtensionsJson[] = - R"( - { - "ababababcdcdcdcdefefefefghghghgh" : { - "external_update_url":"https://test.test/crx" - }, - "aaaabbbbccccddddeeeeffffgggghhhh" : { - "external_update_url":"https://test.test/crx" - }, - // Google Sheets - "aapocclcgogkmnckokdopfmhonfmgoek" : { - "external_update_url":"https://test.test/crx" - }, - })"; -const char kInvalidDefaultExtensionsJson[] = "{ json: invalid }"; - -// ExtensionSettings that has two force_installed extensions and two not. -const wchar_t kExtensionSettingsJson[] = - LR"( - { - "ababababcdcdcdcdefefefefghghghgh": { - "installation_mode": "force_installed", - "update_url":"https://test.test/crx" - }, - "aaaabbbbccccddddeeeeffffgggghhhh": { - "installation_mode": "force_installed", - "update_url":"https://test.test/crx" - }, - "extensionwithinstallmodeblockeda": { - "installation_mode": "blocked", - "update_url":"https://test.test/crx" - }, - "extensionwithnosettingsabcdefghi": {} - })"; -const TestRegistryEntry extension_settings_entry = { - HKEY_LOCAL_MACHINE, L"software\\policies\\google\\chrome", - L"ExtensionSettings", kExtensionSettingsJson}; - -const wchar_t kChromeExePath[] = L"google\\chrome\\application"; -const wchar_t kMasterPreferencesFileName[] = L"master_preferences"; -const char kMasterPreferencesJson[] = - R"( - { - "homepage": "http://dev.chromium.org/", - "extensions": { - "settings": { - "ababababcdcdcdcdefefefefghghghgh": { - "location": 1, - "manifest": { - "name": "Test extension" - } - }, - "aaaabbbbccccddddeeeeffffgggghhhh": { - "location": 1, - "manifest": { - "name": "Another one" - } - } - } - } - })"; -const char kMasterPreferencesJsonNoExtensions[] = - R"( - { - "homepage": "http://dev.chromium.org/" - })"; +struct ExtensionIDEqual { + bool operator()(const ForceInstalledExtension& lhs, + const ForceInstalledExtension& rhs) const { + return lhs.id == rhs.id; + } +}; bool ExtensionPolicyRegistryEntryFound( TestRegistryEntry test_entry, @@ -135,11 +69,11 @@ registry_util::RegistryOverrideManager registry_override; registry_override.OverrideRegistry(HKEY_CURRENT_USER); registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE); - for (const TestRegistryEntry& policy : extension_forcelist_entries) { + for (const TestRegistryEntry& policy : kExtensionForcelistEntries) { base::win::RegKey policy_key; ASSERT_EQ(ERROR_SUCCESS, policy_key.Create(policy.hkey, policy.path.c_str(), KEY_ALL_ACCESS)); - DCHECK(policy_key.Valid()); + ASSERT_TRUE(policy_key.Valid()); ASSERT_EQ(ERROR_SUCCESS, policy_key.WriteValue(policy.name.c_str(), policy.value.c_str())); } @@ -147,11 +81,52 @@ std::vector<ExtensionPolicyRegistryEntry> policies; GetExtensionForcelistRegistryPolicies(&policies); - for (const TestRegistryEntry& expected_result : extension_forcelist_entries) { + for (const TestRegistryEntry& expected_result : kExtensionForcelistEntries) { EXPECT_TRUE(ExtensionPolicyRegistryEntryFound(expected_result, policies)); } } +TEST(ExtensionsUtilTest, RemoveForcelistPolicyExtensions) { + registry_util::RegistryOverrideManager registry_override; + registry_override.OverrideRegistry(HKEY_CURRENT_USER); + registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE); + for (const TestRegistryEntry& policy : kExtensionForcelistEntries) { + base::win::RegKey policy_key; + ASSERT_EQ(ERROR_SUCCESS, policy_key.Create(policy.hkey, policy.path.c_str(), + KEY_ALL_ACCESS)); + DCHECK(policy_key.Valid()); + ASSERT_EQ(ERROR_SUCCESS, + policy_key.WriteValue(policy.name.c_str(), policy.value.c_str())); + base::string16 value; + policy_key.ReadValue(policy.name.c_str(), &value); + ASSERT_EQ(value, policy.value); + } + + std::vector<ForceInstalledExtension> extensions; + std::vector<ExtensionPolicyRegistryEntry> policies; + GetExtensionForcelistRegistryPolicies(&policies); + for (ExtensionPolicyRegistryEntry& policy : policies) { + ForceInstalledExtension extension( + ExtensionID::Create(base::UTF16ToUTF8(policy.extension_id)).value(), + POLICY_EXTENSION_FORCELIST, "", ""); + extension.policy_registry_entry = + std::make_shared<ExtensionPolicyRegistryEntry>(std::move(policy)); + extensions.push_back(extension); + } + + for (ForceInstalledExtension& extension : extensions) { + base::win::RegKey policy_key; + ASSERT_TRUE(RemoveForcelistPolicyExtension(extension)); + ASSERT_EQ(ERROR_SUCCESS, + policy_key.Open(extension.policy_registry_entry->hkey, + extension.policy_registry_entry->path.c_str(), + KEY_READ)); + base::string16 value; + policy_key.ReadValue(extension.policy_registry_entry->name.c_str(), &value); + ASSERT_EQ(value, L""); + } +} + TEST(ExtensionsUtilTest, GetNonWhitelistedDefaultExtensions) { // Set up a fake default extensions JSON file. base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES); @@ -200,6 +175,69 @@ ::testing::UnorderedElementsAreArray(found_extension_ids)); } +TEST(ExtensionsUtilTest, RemoveNonWhitelistedDefaultExtensions) { + // Set up a fake default extensions JSON file. + base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES); + base::FilePath program_files_dir; + ASSERT_TRUE( + base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir)); + + base::FilePath fake_apps_dir( + program_files_dir.Append(kFakeChromeFolder).Append(L"default_apps")); + ASSERT_TRUE(base::CreateDirectoryAndGetError(fake_apps_dir, nullptr)); + + base::FilePath default_extensions_file = + fake_apps_dir.Append(L"external_extensions.json"); + CreateFileWithContent(default_extensions_file, kDefaultExtensionsJson, + sizeof(kDefaultExtensionsJson) - 1); + ASSERT_TRUE(base::PathExists(default_extensions_file)); + + // Set up an invalid default extensions JSON file + base::ScopedPathOverride program_files_x86_override( + base::DIR_PROGRAM_FILESX86); + ASSERT_TRUE( + base::PathService::Get(base::DIR_PROGRAM_FILESX86, &program_files_dir)); + + fake_apps_dir = + program_files_dir.Append(kFakeChromeFolder).Append(L"default_apps"); + ASSERT_TRUE(base::CreateDirectoryAndGetError(fake_apps_dir, nullptr)); + + default_extensions_file = fake_apps_dir.Append(L"external_extensions.json"); + CreateFileWithContent(default_extensions_file, kInvalidDefaultExtensionsJson, + sizeof(kInvalidDefaultExtensionsJson) - 1); + ASSERT_TRUE(base::PathExists(default_extensions_file)); + + TestJsonParser json_parser; + std::vector<ExtensionPolicyFile> policies; + base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + GetNonWhitelistedDefaultExtensions(&json_parser, &policies, &done); + ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout())); + + std::vector<ForceInstalledExtension> extensions; + for (ExtensionPolicyFile& policy : policies) { + ForceInstalledExtension extension( + ExtensionID::Create(base::UTF16ToUTF8(policy.extension_id)).value(), + DEFAULT_APPS_EXTENSION, "", ""); + extension.policy_file = + std::make_shared<ExtensionPolicyFile>(std::move(policy)); + extensions.push_back(extension); + } + base::Value json_result = extensions[0].policy_file->json->data.Clone(); + for (ForceInstalledExtension& extension : extensions) { + ASSERT_TRUE(RemoveDefaultExtension(extension, &json_result)); + } + std::string result; + JSONStringValueSerializer serializer(&result); + ASSERT_TRUE(serializer.Serialize(json_result)); + ASSERT_EQ(result, kValidDefaultExtensionsJson); + base::Value original = json_result.Clone(); + for (ForceInstalledExtension& extension : extensions) { + ASSERT_FALSE(RemoveDefaultExtension(extension, &json_result)); + ASSERT_EQ(original, json_result); + } +} + TEST(ExtensionsUtilTest, GetNonWhitelistedDefaultExtensionsNoFilesFound) { base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES); base::ScopedPathOverride program_files_x86_override( @@ -223,13 +261,12 @@ base::win::RegKey settings_key; ASSERT_EQ(ERROR_SUCCESS, - settings_key.Create(extension_settings_entry.hkey, - extension_settings_entry.path.c_str(), - KEY_ALL_ACCESS)); - DCHECK(settings_key.Valid()); + settings_key.Create(HKEY_LOCAL_MACHINE, + kExtensionSettingsPolicyPath, KEY_ALL_ACCESS)); + ASSERT_TRUE(settings_key.Valid()); ASSERT_EQ(ERROR_SUCCESS, - settings_key.WriteValue(extension_settings_entry.name.c_str(), - extension_settings_entry.value.c_str())); + settings_key.WriteValue(kExtensionSettingsName, + kExtensionSettingsJsonOnlyForced)); TestJsonParser json_parser; std::vector<ExtensionPolicyRegistryEntry> policies; @@ -239,8 +276,8 @@ ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout())); // Check that only the two force installed extensions were found - const base::string16 expected_extension_ids[] = {kTestExtensionId1, - kTestExtensionId2}; + const base::string16 expected_extension_ids[] = {kTestExtensionId4, + kTestExtensionId5}; const base::string16 found_extension_ids[] = {policies[0].extension_id, policies[1].extension_id}; EXPECT_THAT(expected_extension_ids, @@ -249,9 +286,106 @@ // Also check that the collected registry entries match the values in the // registry. for (const ExtensionPolicyRegistryEntry& policy : policies) { - EXPECT_EQ(policy.hkey, extension_settings_entry.hkey); - EXPECT_EQ(policy.path, extension_settings_entry.path); - EXPECT_EQ(policy.name, extension_settings_entry.name); + EXPECT_EQ(policy.hkey, HKEY_LOCAL_MACHINE); + EXPECT_EQ(policy.path, kExtensionSettingsPolicyPath); + EXPECT_EQ(policy.name, kExtensionSettingsName); + } +} + +TEST(ExtensionsUtilTest, RemoveExtensionSettingsForceInstalledExtensions) { + registry_util::RegistryOverrideManager registry_override; + registry_override.OverrideRegistry(HKEY_CURRENT_USER); + registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE); + + base::win::RegKey settings_key; + ASSERT_EQ(ERROR_SUCCESS, + settings_key.Create(HKEY_LOCAL_MACHINE, + kExtensionSettingsPolicyPath, KEY_ALL_ACCESS)); + DCHECK(settings_key.Valid()); + ASSERT_EQ(ERROR_SUCCESS, + settings_key.WriteValue(kExtensionSettingsName, + kExtensionSettingsJsonOnlyForced)); + + TestJsonParser json_parser; + std::vector<ExtensionPolicyRegistryEntry> policies; + base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + GetExtensionSettingsForceInstalledExtensions(&json_parser, &policies, &done); + ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout())); + + std::unordered_set<ForceInstalledExtension, ExtensionIDHash, ExtensionIDEqual> + extensions; + base::Value json_result = policies[0].json->data.Clone(); + for (ExtensionPolicyRegistryEntry& policy : policies) { + ForceInstalledExtension extension( + ExtensionID::Create(base::UTF16ToUTF8(policy.extension_id)).value(), + POLICY_EXTENSION_SETTINGS, "", ""); + extension.policy_registry_entry = + std::make_shared<ExtensionPolicyRegistryEntry>(std::move(policy)); + extensions.insert(extension); + } + + for (const ForceInstalledExtension& extension : extensions) { + ASSERT_TRUE( + RemoveExtensionSettingsPoliciesExtension(extension, &json_result)); + } + std::string result; + JSONStringValueSerializer serializer(&result); + ASSERT_TRUE(serializer.Serialize(json_result)); + ASSERT_EQ(result, "{}"); + base::Value original = json_result.Clone(); + for (const ForceInstalledExtension& extension : extensions) { + ASSERT_FALSE( + RemoveExtensionSettingsPoliciesExtension(extension, &json_result)); + ASSERT_EQ(original, json_result); + } +} + +TEST(ExtensionsUtilTest, RemoveSomeExtensionSettingsForceInstalledExtensions) { + registry_util::RegistryOverrideManager registry_override; + registry_override.OverrideRegistry(HKEY_CURRENT_USER); + registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE); + + base::win::RegKey settings_key; + ASSERT_EQ(ERROR_SUCCESS, + settings_key.Create(HKEY_LOCAL_MACHINE, + kExtensionSettingsPolicyPath, KEY_ALL_ACCESS)); + DCHECK(settings_key.Valid()); + ASSERT_EQ(ERROR_SUCCESS, settings_key.WriteValue(kExtensionSettingsName, + kExtensionSettingsJson)); + + TestJsonParser json_parser; + std::vector<ExtensionPolicyRegistryEntry> policies; + base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + GetExtensionSettingsForceInstalledExtensions(&json_parser, &policies, &done); + ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout())); + + std::unordered_set<ForceInstalledExtension, ExtensionIDHash, ExtensionIDEqual> + extensions; + base::Value json_result = policies[0].json->data.Clone(); + for (ExtensionPolicyRegistryEntry& policy : policies) { + ForceInstalledExtension extension( + ExtensionID::Create(base::UTF16ToUTF8(policy.extension_id)).value(), + POLICY_EXTENSION_SETTINGS, "", ""); + extension.policy_registry_entry = + std::make_shared<ExtensionPolicyRegistryEntry>(std::move(policy)); + extensions.insert(extension); + } + + for (const ForceInstalledExtension& extension : extensions) { + ASSERT_TRUE( + RemoveExtensionSettingsPoliciesExtension(extension, &json_result)); + } + std::string result; + JSONStringValueSerializer serializer(&result); + ASSERT_TRUE(serializer.Serialize(json_result)); + ASSERT_EQ(result, kValidExtensionSettingsJson); + base::Value original = json_result.Clone(); + for (const ForceInstalledExtension& extension : extensions) { + ASSERT_FALSE( + RemoveExtensionSettingsPoliciesExtension(extension, &json_result)); + ASSERT_EQ(original, json_result); } } @@ -295,8 +429,8 @@ GetMasterPreferencesExtensions(&json_parser, &policies, &done); ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout())); - const base::string16 expected_extension_ids[] = {kTestExtensionId1, - kTestExtensionId2}; + const base::string16 expected_extension_ids[] = {kTestExtensionId6, + kTestExtensionId7}; ASSERT_EQ(base::size(expected_extension_ids), policies.size()); const base::string16 found_extension_ids[] = {policies[0].extension_id, policies[1].extension_id}; @@ -304,6 +438,48 @@ ::testing::UnorderedElementsAreArray(found_extension_ids)); } +TEST(ExtensionsUtilTest, RemoveMasterPreferencesExtensionsNoneFound) { + // Set up a fake master preferences JSON file. + base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES); + base::FilePath program_files_dir; + ASSERT_TRUE( + base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir)); + + base::FilePath chrome_dir(program_files_dir.Append(kChromeExePath)); + ASSERT_TRUE(base::CreateDirectoryAndGetError(chrome_dir, nullptr)); + + base::FilePath master_preferences = + chrome_dir.Append(kMasterPreferencesFileName); + CreateFileWithContent(master_preferences, kMasterPreferencesJson, + sizeof(kMasterPreferencesJson) - 1); + ASSERT_TRUE(base::PathExists(master_preferences)); + + TestJsonParser json_parser; + std::vector<ExtensionPolicyFile> policies; + base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + GetMasterPreferencesExtensions(&json_parser, &policies, &done); + ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout())); + + std::vector<ForceInstalledExtension> extensions; + for (ExtensionPolicyFile& policy : policies) { + ForceInstalledExtension extension( + ExtensionID::Create(base::UTF16ToUTF8(policy.extension_id)).value(), + POLICY_MASTER_PREFERENCES, "", ""); + extension.policy_file = + std::make_shared<ExtensionPolicyFile>(std::move(policy)); + extensions.push_back(extension); + } + base::Value json_result = extensions[0].policy_file->json->data.Clone(); + for (ForceInstalledExtension& extension : extensions) { + ASSERT_TRUE(RemoveMasterPreferencesExtension(extension, &json_result)); + } + std::string result; + JSONStringValueSerializer serializer(&result); + ASSERT_TRUE(serializer.Serialize(json_result)); + ASSERT_EQ(result, kValidMasterPreferencesJson); +} + TEST(ExtensionsUtilTest, GetMasterPreferencesExtensionsNoneFound) { // Set up a fake master preferences JSON file. base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES);
diff --git a/chrome/chrome_cleaner/chrome_utils/force_installed_extension.cc b/chrome/chrome_cleaner/chrome_utils/force_installed_extension.cc new file mode 100644 index 0000000..08c6750 --- /dev/null +++ b/chrome/chrome_cleaner/chrome_utils/force_installed_extension.cc
@@ -0,0 +1,69 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/chrome_cleaner/chrome_utils/force_installed_extension.h" + +#include <string> +#include <utility> + +namespace chrome_cleaner { + +ForceInstalledExtension::ForceInstalledExtension( + const ExtensionID& id, + ExtensionInstallMethod install_method, + const std::string& update_url, + const std::string& manifest_permissions) + : id(std::move(id)), + install_method(std::move(install_method)), + update_url(std::move(update_url)), + manifest_permissions(std::move(manifest_permissions)) {} + +ForceInstalledExtension& ForceInstalledExtension::operator=( + const ForceInstalledExtension& other) = default; +ForceInstalledExtension& ForceInstalledExtension::operator=( + ForceInstalledExtension&& other) = default; +ForceInstalledExtension::ForceInstalledExtension( + ExtensionID id, + ExtensionInstallMethod install_method) + : id(std::move(id)), install_method(std::move(install_method)) {} + +ForceInstalledExtension::ForceInstalledExtension( + const ForceInstalledExtension& extension) = default; +ForceInstalledExtension::ForceInstalledExtension( + ForceInstalledExtension&& extension) = default; + +ForceInstalledExtension::~ForceInstalledExtension() = default; + +bool ForceInstalledExtension::operator==( + const ForceInstalledExtension& other) const { + // Don't include policy pointers in comparison because that metadata + // is only used when writing out the results of transforming the values. + return id == other.id && install_method == other.install_method && + update_url == other.update_url && + manifest_permissions == other.manifest_permissions; +} + +bool ForceInstalledExtension::operator<( + const ForceInstalledExtension& other) const { + if (id < other.id) { + return true; + } else if (id > other.id) { + return false; + } else if (install_method < other.install_method) { + return true; + } else if (install_method > other.install_method) { + return false; + } else if (update_url < other.update_url) { + return true; + } else if (update_url > other.update_url) { + return false; + } else if (manifest_permissions < other.manifest_permissions) { + return true; + } else if (manifest_permissions > other.manifest_permissions) { + return false; + } + return false; +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/chrome_utils/force_installed_extension.h b/chrome/chrome_cleaner/chrome_utils/force_installed_extension.h new file mode 100644 index 0000000..b21fd769 --- /dev/null +++ b/chrome/chrome_cleaner/chrome_utils/force_installed_extension.h
@@ -0,0 +1,55 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_CHROME_CLEANER_CHROME_UTILS_FORCE_INSTALLED_EXTENSION_H_ +#define CHROME_CHROME_CLEANER_CHROME_UTILS_FORCE_INSTALLED_EXTENSION_H_ + +#include <memory> +#include <string> + +#include "chrome/chrome_cleaner/chrome_utils/extension_id.h" +#include "chrome/chrome_cleaner/logging/proto/shared_data.pb.h" + +namespace chrome_cleaner { + +// Forward declare to avoid dependency cycle. +struct ExtensionPolicyRegistryEntry; +struct ExtensionPolicyFile; + +// An extension that has been force installed. +struct ForceInstalledExtension { + ForceInstalledExtension(const ExtensionID& id, + ExtensionInstallMethod install_method, + const std::string& update_url, + const std::string& manifest_permissions); + ForceInstalledExtension(ExtensionID id, + ExtensionInstallMethod install_method); + + ForceInstalledExtension(const ForceInstalledExtension& extension); + ForceInstalledExtension(ForceInstalledExtension&& extension); + ForceInstalledExtension& operator=(const ForceInstalledExtension& other); + ForceInstalledExtension& operator=(ForceInstalledExtension&& other); + ~ForceInstalledExtension(); + bool operator==(const ForceInstalledExtension& other) const; + bool operator<(const ForceInstalledExtension& other) const; + + ExtensionID id; + ExtensionInstallMethod install_method; + std::string update_url; + std::string manifest_permissions; + std::shared_ptr<ExtensionPolicyRegistryEntry> policy_registry_entry; + std::shared_ptr<ExtensionPolicyFile> policy_file; +}; + +// Overload to compare by Extension IDs, useful when constructing sets +struct ExtensionIDCompare { + bool operator()(const ForceInstalledExtension& lhs, + const ForceInstalledExtension& rhs) const { + return lhs.id < rhs.id; + } +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_CHROME_UTILS_FORCE_INSTALLED_EXTENSION_H_
diff --git a/chrome/chrome_cleaner/parsers/parser_utils/BUILD.gn b/chrome/chrome_cleaner/parsers/parser_utils/BUILD.gn new file mode 100644 index 0000000..b9025c8 --- /dev/null +++ b/chrome/chrome_cleaner/parsers/parser_utils/BUILD.gn
@@ -0,0 +1,14 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +static_library("parse_tasks_remaining_counter") { + sources = [ + "parse_tasks_remaining_counter.cc", + "parse_tasks_remaining_counter.h", + ] + + deps = [ + "//base:base", + ] +}
diff --git a/chrome/chrome_cleaner/parsers/parser_utils/parse_tasks_remaining_counter.cc b/chrome/chrome_cleaner/parsers/parser_utils/parse_tasks_remaining_counter.cc new file mode 100644 index 0000000..d218678 --- /dev/null +++ b/chrome/chrome_cleaner/parsers/parser_utils/parse_tasks_remaining_counter.cc
@@ -0,0 +1,33 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/chrome_cleaner/parsers/parser_utils/parse_tasks_remaining_counter.h" + +#include "base/memory/ref_counted.h" +#include "base/synchronization/waitable_event.h" + +namespace chrome_cleaner { + +ParseTasksRemainingCounter::ParseTasksRemainingCounter( + size_t count, + base::WaitableEvent* done) + : count_(count), done_(done) { + DCHECK(count_ > 0) << "Must be constructed with a positive count."; +} + +void ParseTasksRemainingCounter::Increment() { + DCHECK(count_ > 0) + << "Once decremented to zero, Increment should never be called."; + count_++; +} + +void ParseTasksRemainingCounter::Decrement() { + DCHECK(count_); + count_--; + if (count_ == 0) { + done_->Signal(); + } +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/parsers/parser_utils/parse_tasks_remaining_counter.h b/chrome/chrome_cleaner/parsers/parser_utils/parse_tasks_remaining_counter.h new file mode 100644 index 0000000..3070580 --- /dev/null +++ b/chrome/chrome_cleaner/parsers/parser_utils/parse_tasks_remaining_counter.h
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_CHROME_CLEANER_PARSERS_PARSER_UTILS_PARSE_TASKS_REMAINING_COUNTER_H_ +#define CHROME_CHROME_CLEANER_PARSERS_PARSER_UTILS_PARSE_TASKS_REMAINING_COUNTER_H_ + +#include "base/memory/ref_counted.h" +#include "base/synchronization/waitable_event.h" + +namespace chrome_cleaner { + +class ParseTasksRemainingCounter + : public base::RefCountedThreadSafe<ParseTasksRemainingCounter> { + public: + ParseTasksRemainingCounter(size_t count, base::WaitableEvent* done); + void Increment(); + void Decrement(); + + private: + friend class base::RefCountedThreadSafe<ParseTasksRemainingCounter>; + ~ParseTasksRemainingCounter() = default; + + size_t count_; + base::WaitableEvent* done_; +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_PARSERS_PARSER_UTILS_PARSE_TASKS_REMAINING_COUNTER_H_
diff --git a/chrome/chrome_cleaner/test/BUILD.gn b/chrome/chrome_cleaner/test/BUILD.gn index 37fc2f3..a4be344 100644 --- a/chrome/chrome_cleaner/test/BUILD.gn +++ b/chrome/chrome_cleaner/test/BUILD.gn
@@ -71,6 +71,18 @@ ] } +source_set("test_extensions") { + sources = [ + "test_extensions.cc", + "test_extensions.h", + ] + + deps = [ + "//base:base", + "//chrome/chrome_cleaner/os:common_os", + ] +} + source_set("test_pup_data") { testonly = true
diff --git a/chrome/chrome_cleaner/test/test_extensions.cc b/chrome/chrome_cleaner/test/test_extensions.cc new file mode 100644 index 0000000..83375fa --- /dev/null +++ b/chrome/chrome_cleaner/test/test_extensions.cc
@@ -0,0 +1,18 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/chrome_cleaner/test/test_extensions.h" + +namespace chrome_cleaner { + +TestRegistryEntry::TestRegistryEntry(HKEY hkey, + const base::string16& path, + const base::string16& name, + const base::string16& value) + : hkey(hkey), path(path), name(name), value(value) {} +TestRegistryEntry::TestRegistryEntry(const TestRegistryEntry& other) = default; +TestRegistryEntry& TestRegistryEntry::operator=( + const TestRegistryEntry& other) = default; + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/test_extensions.h b/chrome/chrome_cleaner/test/test_extensions.h new file mode 100644 index 0000000..03e54c8 --- /dev/null +++ b/chrome/chrome_cleaner/test/test_extensions.h
@@ -0,0 +1,132 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_CHROME_CLEANER_TEST_TEST_EXTENSIONS_H_ +#define CHROME_CHROME_CLEANER_TEST_TEST_EXTENSIONS_H_ + +#include "base/win/registry.h" +#include "chrome/chrome_cleaner/os/registry_util.h" + +namespace chrome_cleaner { + +struct TestRegistryEntry { + HKEY hkey; + base::string16 path; + base::string16 name; + base::string16 value; + + TestRegistryEntry(HKEY hkey, + const base::string16& path, + const base::string16& name, + const base::string16& value); + TestRegistryEntry(const TestRegistryEntry& other); + TestRegistryEntry& operator=(const TestRegistryEntry& other); +}; + +const wchar_t kChromeExePath[] = L"google\\chrome\\application"; +const wchar_t kFakeChromeFolder[] = L"google\\chrome\\application\\42.12.34.56"; +const wchar_t kExtensionSettingsPolicyPath[] = + L"software\\policies\\google\\chrome"; +const wchar_t kExtensionSettingsName[] = L"ExtensionSettings"; +const wchar_t kMasterPreferencesFileName[] = L"master_preferences"; +const wchar_t kTestExtensionId1[] = L"ababababcdcdcdcdefefefefghghghgh"; +const wchar_t kTestExtensionId2[] = L"aaaabbbbccccddddeeeeffffgggghhhh"; +const wchar_t kTestExtensionId3[] = L"hhhheeeeebbbbbccccddddaaaaabcdef"; +const wchar_t kTestExtensionId4[] = L"abcdefghgfedcbabcdefghgfedcbaced"; +const wchar_t kTestExtensionId5[] = L"dcbdcbdcbdcbdcbdcbdcbdcbdcbdcbcd"; +const wchar_t kTestExtensionId6[] = L"egegegegegegegegegegegegegegegeg"; +const wchar_t kTestExtensionId7[] = L"nopnopnopnopnopnopnopnopnopnopno"; + +// Test force installed extension settings +const TestRegistryEntry kExtensionForcelistEntries[] = { + {HKEY_LOCAL_MACHINE, kChromePoliciesForcelistKeyPath, L"test1", + base::string16(kTestExtensionId3) + L"https://test.test/crxupdate2/crx"}}; +const char kValidExtensionSettingsJson[] = + "{\"extensionwithinstallmodeblockeda\":{\"installation_mode\":\"blocked\"," + "\"update_url\":" + "\"https://test.test/crx\"},\"extensionwithnosettingsabcdefghi\":{}}"; +const wchar_t kExtensionSettingsJson[] = + LR"( + { + "dcbdcbdcbdcbdcbdcbdcbdcbdcbdcbcd": { + "installation_mode": "force_installed", + "update_url":"https://test.test/crx" + }, + "abcdefghgfedcbabcdefghgfedcbaced" : { + "installation_mode": "force_installed", + "update_url":"https://test.test/crx" + }, + "extensionwithinstallmodeblockeda": { + "installation_mode": "blocked", + "update_url":"https://test.test/crx" + }, + "extensionwithnosettingsabcdefghi": {} + })"; +const wchar_t kExtensionSettingsJsonOnlyForced[] = + LR"( + { + "dcbdcbdcbdcbdcbdcbdcbdcbdcbdcbcd": { + "installation_mode": "force_installed", + "update_url":"https://test.test/crx" + }, + "abcdefghgfedcbabcdefghgfedcbaced": { + "installation_mode": "force_installed", + "update_url":"https://test.test/crx" + } + })"; + +// Test force installed default extensions +const char kInvalidDefaultExtensionsJson[] = "{ json: invalid }"; +const char kDefaultExtensionsJson[] = + R"( + { + "ababababcdcdcdcdefefefefghghghgh" : { + "external_update_url":"https://test.test/crx" + }, + "aaaabbbbccccddddeeeeffffgggghhhh" : { + "external_update_url":"https://test.test/crx" + }, + // Google Sheets + "aapocclcgogkmnckokdopfmhonfmgoek" : { + "external_update_url":"https://test.test/crx" + }, + })"; +const char kValidDefaultExtensionsJson[] = + "{\"aapocclcgogkmnckokdopfmhonfmgoek\":{" + "\"external_update_url\":\"https://test.test/crx\"}}"; + +// Test force installed master preferences +const char kMasterPreferencesJson[] = + R"( + { + "homepage": "http://dev.chromium.org/", + "extensions": { + "settings": { + "egegegegegegegegegegegegegegegeg": { + "location": 1, + "manifest": { + "name": "Test extension" + } + }, + "nopnopnopnopnopnopnopnopnopnopno": { + "location": 1, + "manifest": { + "name": "Another one" + } + } + } + } + })"; +const char kValidMasterPreferencesJson[] = + "{\"extensions\":{\"settings\":{}},\"homepage\":\"http://dev.chromium.org/" + "\"}"; +const char kMasterPreferencesJsonNoExtensions[] = + R"( +{ + "homepage": "http://dev.chromium.org/" +})"; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_TEST_TEST_EXTENSIONS_H_
diff --git a/chrome/services/app_service/README.md b/chrome/services/app_service/README.md index 68aafff..bc2f230 100644 --- a/chrome/services/app_service/README.md +++ b/chrome/services/app_service/README.md
@@ -1,20 +1,371 @@ -# Chrome Apps Platform Foundation +# App Service -Chrome features multiple app platforms, including PWAs (desktop and mobile), -ARC++ (Chrome OS), and Chrome apps (now deprecated). Each of these is based on -different underlying technologies, but UX-wise, it is an explicit goal to -minimize the differences between them and give users the feeling that all apps -have as similar properties, management, and features as possible. +Chrome, and especially Chrome OS, has apps, e.g. chat apps and camera apps. -This directory contains generic code to facilitate app platforms on Chrome -communicating with the browser and each other. This layer consists of -app-platform-agnostic code, which each app platform's custom implementation -then plugs into. Example features include: +There are a number (lets call it `M`) of different places or app Consumers, +usually UI (user interfaces) related, where users interact with their installed +apps: e.g. launcher, search bar, shelf, New Tab Page, the `chrome://apps` page, +permissions or settings pages, picking and running default handlers for URLs, +MIME types or intents, etc. -* `app_service` - a central service for information on installed apps -* `app_registry` - the central registry for installed apps contained within -the app service +There is also a different number (`N`) of app platforms or app Providers: +built-in apps, extension-backed apps, PWAs (progressive web apps), ARC++ +(Android apps), Crostini (Linux apps), etc. -Over time, it is intended to reduce the dependencies of this layer on Chrome -browser through refactoring work, with the eventual goal of moving this -directory to chrome/services. +Historically, each of the `M` Consumers hard-coded each of the `N` Providers, +leading to `M×N` code paths that needed maintaining, or updating every time `M` +or `N` was incremented. + +This document describes the App Service, an intermediary between app Consumers +and app Providers. This simplifies `M×N` code paths to `M+N` code paths, each +side with a uniform API, reducing code duplication and improving behavioral +consistency. This service (a Mojo service) could potentially be spun out into a +new process, for the usual +[Servicification](https://www.chromium.org/servicification) benefits (e.g. +self-contained services are easier to test and to sandbox), and would also +facilitate Chrome OS apps that aren't tied to the browser, e.g. Ash apps. + +The App Service can be decomposed into a number of aspects. In all cases, it +provides to Consumers a uniform API over the various Provider implementations, +for these aspects: + +- App Registry: list the installed apps. +- App Icon Factory: load an app's icon, at various resolutions. +- App Runner: launch apps and track app instances. +- App Installer: install, uninstall and update apps. +- App Coordinator: keep system-wide settings, e.g. default handlers. + +Some things are still the responsbility of individual Consumers or Providers. +For example, the order in which the apps' icons are presented in the launcher +is a launcher-specific detail, not a system-wide detail, and is managed by the +launcher, not the App Service. Similarly, Android-specific VM configuration is +Android-specific, not generalizable system-wide, and is managed by the Android +provider (ARC++). + + +## Profiles + +Talk of *the* App Service is an over-simplification. There will be *an* App +Service instance per Profile, as apps can be installed for *a* Profile. + +Note that this doesn't require the App Service to know about Profiles. Instead, +Profile-specific code (e.g. a KeyedService) finds the Mojo service Connector +for a Profile, creates an App Service and binds the two (App Service and +Connector), but the App Service itself doesn't know about Profiles per se. + + +# App Registry + +The App Registry's one-liner mission is: + + - I would like to be able to for-each over all the apps in Chrome. + +An obvious initial design for the App Registry involves three actors (Consumers +⇔ Service ⇔ Providers) with the middle actor (the App Registry Mojo service) +being a relatively thick implementation with a traditional `GetFoo`, `SetBar`, +`AddObserver` style API. The drawback is that Consumers are often UI surfaces +and UI code likes synchronous APIs, but Mojo APIs are generally asynchronous, +especially as it may cross process boundaries. + +Instead, we use four actors (Consumers ↔ Proxy ⇔ Service ⇔ Providers), with the +Consumers ↔ Proxy connection being synchronous and in-process, lighter than the +async / out-of-process ⇔ connections. The Proxy implementation is relatively +thick and the Service implementation is relatively thin, almost trivially so. +Being able to for-each over all the apps is: + + for (const auto& app : GetAppServiceProxy(profile).GetCache().GetAllApps()) { + DoSomethingWith(app); + } + +The Proxy is expected to be in the same process as its Consumers, and the Proxy +would be a singleton (per Profile) within that process: Consumers would connect +to *the* in-process Proxy. If all of the app UI code is in the browser process, +the Proxy would also be in the browser process. If app UI code migrated to e.g. +a separate Ash process, then the Proxy would move with them. There might be +multiple Proxies, one per process (per Profile). + + +## Code Location + +Some code is tied to a particular process, some code is not. For example, the +per-Profile `AppServiceProxy` obviously contains Profile-related code (i.e. a +`KeyedService`, so that browser code can find *the* `AppServiceProxy` for a +given Profile) that is tied to being in the browser process. The +`AppServiceProxy` also contains process-agnostic code (code that could +conceivably be used by an `AppServiceProxy` living in an Ash process), such as +code to cache and update the set of known apps (as in, the `App` Mojo type). +Specifically, the `AppServiceProxy` code is split into two locations, one under +`//chrome/browser` and one not: + + - `//chrome/browser/apps/foundation/app_service` + - `//chrome/services/app_service` + +On the Provider side, code specific to extension-backed applications or web +applications (as opposed to ARC++ or Crostini applications) lives under: + + - `//chrome/browser/extensions` + - `//chrome/browser/web_applications` + + +## Matchmaking and Publish / Subscribe + +The `AppService` itself does not have an `GetAllApps` method. It doesn't do +much, and it doesn't keep much state. Instead, the App Registry aspect of the +`AppService` is little more than a well known meeting place for `Publisher`s +(i.e. Providers) and `Subscriber`s (i.e. Proxies) to discover each other. An +analogy is that it's a matchmaker for `Publisher`s and `Subscriber`s, although +it matches all to all instead of one to one. `Publisher`s don't meet +`Subscriber`s directly, they meet the matchmaker, who introduces them to +`Subscriber`s. + +Once a `Publisher` and `Subscriber` connect, the Pub-side sends the Sub-side a +stream of `App`s (calling the `Subscriber`'s `OnApps` method). On the initial +connection, the `Publisher` calls `OnApps` with "here's all the apps that I +(the `Publisher`) know about", with additional `OnApps` calls made as apps are +installed, uninstalled, updated, etc. + +As mentioned, the App Registry aspect of the `AppService` doesn't do much. Its +part of the `AppService` Mojo interface is: + + interface AppService { + // App Registry methods. + RegisterPublisher(Publisher publisher, AppType app_type); + RegisterSubscriber(Subscriber subscriber, ConnectOptions? opts); + + // Some additional methods; not App Registry related. + }; + + interface Publisher { + // App Registry methods. + Connect(Subscriber subscriber, ConnectOptions? opts); + + // Some additional methods; not App Registry related. + }; + + interface Subscriber { + OnApps(array<App> apps); + }; + + enum AppType { + kUnknown, + kArc, + kCrostini, + kWeb, + }; + + struct ConnectOptions { + // TBD: some way to represent l10n info such as the UI language. + }; + +Whenever a new `Publisher` is registered, it is connected with all of the +previously registered `Subscriber`s, and vice versa. Once a `Publisher` is +connected directly to a `Subscriber`, the `AppService` is no longer involved. +Even as new apps are installed, uninstalled, updated, etc., the app's +`Publisher` talks directly to each of its (previously connected) `Subscriber`s, +without involving the `AppService`. + +TBD: whether we need un-registration and dis-connect mechanisms. + + +## The App Type + +The one Mojo struct type, `App`, represents both a state, "an app that's ready +to run", and a delta or change in state, "here's what's new about an app". +Deltas include events like "an app was just installed" or "just uninstalled" or +"its icon was updated". + +This is achieved by having every `App` field (other than `App.app_type` and +`App.app_id`) be optional. Either optional in the Mojo sense, with type `T?` +instead of a plain `T`, or if that isn't possible in Mojo (e.g. for integer or +enum fields), as a semantic convention above the Mojo layer: 0 is reserved to +mean "unknown". For example, the `App.show_in_launcher` field is a `Ternary`, +not a `bool`. + +An `App.readiness` field represents whether an app is installed (i.e. ready to +launch), uninstalled or otherwise disabled. "An app was just installed" is +represented by a delta whose `readiness` is `kReady` and the old state's +`readiness` being some other value. This is at the Mojo level. At the C++ +level, the `AppUpdate` wrapper type (see below) can provide helper +`WasJustInstalled` methods. + +The `App`, `Readiness` and `Ternary` types are: + + struct App { + AppType app_type; + string app_id; + + // The fields above are mandatory. Everything else below is optional. + + Readiness readiness; + string? name; + IconKey? icon_key; + Ternary show_in_launcher; + // etc. + }; + + enum Readiness { + kUnknown = 0, + kReady, // Installed and launchable. + kDisabledByBlacklist, // Disabled by SafeBrowsing. + kDisabledByPolicy, // Disabled by admin policy. + kDisabledByUser, // Disabled by explicit user action. + kUninstalledByUser, + }; + + enum Ternary { + kUnknown = 0, + kNo, + kYes, + }; + + // struct IconKey is discussed in the "App Icon Factory" section. + +A new state can be mechanically computed from an old state and a delta (both of +which have the same type: `App`). Specifically, last known value wins. Any +known field in the delta overwrites the corresponding field in the old state, +any unknown field in the delta is ignored. For example, if an app's name +changed but its icon didn't, the delta's `App.name` field (a +`base::Optional<std::string>`) would be known (not `base::nullopt`) and copied +over but its `App.icon` field would be unknown (`base::nullopt`) and not copied +over. + +The current state is thus the merger or sum of all previous deltas, including +the initial state being a delta against the ground state of "all unknown". The +`AppServiceProxy` tracks the state of its apps, and implements the +(in-process) Observer pattern so that UI surfaces can e.g. update themselves as +new apps are installed. There's only one method, `OnAppUpdate`, as opposed to +separate `OnAppInstalled`, `OnAppUninstalled`, `OnAppNameChanged`, etc. +methods. An `AppUpdate` is a pair of `App` values: old state and delta. + + class AppRegistryCache { + public: + class Observer : public base::CheckedObserver { + public: + ~Observer() override {} + virtual void OnAppUpdate(const AppUpdate& update) = 0; + }; + + // Etc. + }; + + +# App Icon Factory + +Icon data (even compressed as a PNG) is bulky, relative to the rest of the +`App` type. `Publisher`s will generally serve icon data lazily, on demand, +especially as the desired icon resolutions (e.g. 64px or 256px) aren't known +up-front. Instead of sending an icon at all possible resolutions, the +`Publisher` sends an `IconKey`: enough information (when combined with the +`AppType app_type` and `string app_id`) to load the icon at given resoultions. +The `IconKey` is an `IconType icon_type` plus additional data (`uint64 u_key` +and `string s_key`) whose semantics depend on the `icon_type`. + +For example, some icons are statically built into the Chrome or Chrome OS +binary, as PNG-formatted resources, and can be loaded (synchronously, without +sandboxing). They can be loaded from a `u_key` resource ID. Some icons are +dynamically (and asynchronously) loaded from the extension database on disk. +They can be loaded from the `app_id` alone. + +TBD: for extension-backed icons, some sort of timestamp or version in the +`IconKey` (probably encoded in the `u_key`) so that an icon update results in a +different `IconKey`. + +Consumers (via the `AppServiceProxy`) can always ask the `AppService` to load +an icon. As an optimization, if the `AppServiceProxy` knows how to load an icon +for a given `IconKey`, it can skip the Mojo round trip and bulk data IPC and +load it directly instead. For example, it may know how to load icons from a +statically built resource ID. + + interface AppService { + // App Icon Factory methods. + LoadIcon(AppType app_type, + string app_id, IconKey icon_key, LoadIconOptions? opts) => (gfx.mojom.ImageSkia image); + + // Some additional methods; not App Icon Factory related. + }; + + interface Publisher { + // App Icon Factory methods. + LoadIcon(string app_id, IconKey icon_key, LoadIconOptions? opts) => (gfx.mojom.ImageSkia image); + + // Some additional methods; not App Icon Factory related. + }; + + enum IconType { + kUnknown, + kExtension, + kResource, + }; + + struct IconKey { + IconType icon_type; + // The semantics of u_key and s_key depend on the icon_type. + uint64 u_key; + string s_key; + }; + + struct LoadIconOptions { + // TBD: desired resolutions (e.g. 64px or 256px). This could move out of + // LoadIconOptions to be a mandatory (not optional) LoadIcon arg. + }; + +TBD: post-processing effects like rounded corners, badges or grayed out (for +disabled apps) icons. + + +# App Runner + +Each `Publisher` has (`Publisher`-specific) implementations of e.g. launching an +app and populating a context menu. The `AppService` presents a uniform API to +trigger these, forwarding each call on to the relevant `Publisher`: + + interface AppService { + // App Runner methods. + Launch(AppType app_type, string app_id, LaunchOptions? opts); + // etc. + + // Some additional methods; not App Runner related. + }; + + interface Publisher { + // App Runner methods. + Launch(string app_id, LaunchOptions? opts); + // etc. + + // Some additional methods; not App Runner related. + }; + + struct LaunchOptions { + // TBD. + }; + +TBD: details for context menus. + +TBD: be able to for-each over all the app *instances*, including multiple +instances (e.g. multiple windows) of the one app. + + +# App Installer + +This includes Provider-facing API (not Consumer-facing API like the majority of +the `AppService`) to help install and uninstall apps consistently. For example, +one part of app installation is adding an icon shortcut (e.g. on the Desktop +for Windows, on the Shelf for Chrome OS). This helper code should be written +once (in the `AppService`), not `N` times in `N` Providers. + +TBD: details. + + +# App Coordinator + +This keeps system-wide or for-apps-as-a-whole preferences and settings, e.g. +out of all of the installed apps, which app has the user preferred for photo +editing. Consumer- or Provider-specific settings, e.g. icon order in the Chrome +OS shelf, or Crostini VM configuration, is out of scope of the App Service. + +TBD: details. + + +--- + +Updated on 2018-11-15.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index c80ee09..3ec6998f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1745,6 +1745,7 @@ "../browser/chromeos/login/webview_login_browsertest.cc", "../browser/chromeos/login/wizard_controller_browsertest.cc", "../browser/chromeos/net/network_portal_detector_impl_browsertest.cc", + "../browser/chromeos/network_change_manager_client_browsertest.cc", "../browser/chromeos/policy/affiliation_test_helper.cc", "../browser/chromeos/policy/affiliation_test_helper.h", "../browser/chromeos/policy/blocking_login_browsertest.cc",
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h index 7d79007..6269eb692 100644 --- a/chrome/test/base/test_browser_window.h +++ b/chrome/test/base/test_browser_window.h
@@ -90,6 +90,7 @@ void SetFocusToLocationBar(bool select_all) override {} void UpdateReloadStopState(bool is_loading, bool force) override {} void UpdateToolbar(content::WebContents* contents) override {} + void UpdateToolbarVisibility(bool visible, bool animate) override {} void ResetToolbarTabState(content::WebContents* contents) override {} void FocusToolbar() override {} ToolbarActionsBar* GetToolbarActionsBar() override; @@ -196,7 +197,6 @@ void UpdateSaveCreditCardIcon() override {} void UpdateLocalCardMigrationIcon() override {} void UpdateBookmarkStarVisibility() override {} - void UpdateLocationBarVisibility(bool visible, bool animate) override {} void SaveStateToContents(content::WebContents* contents) override {} void Revert() override {} const OmniboxView* GetOmniboxView() const override;
diff --git a/chrome/test/data/android/render_tests/ContextualSuggestionsTest.full_height_scrolled.Nexus_5-19.png b/chrome/test/data/android/render_tests/ContextualSuggestionsTest.full_height_scrolled.Nexus_5-19.png index 3ce7ed7..189e6a1 100644 --- a/chrome/test/data/android/render_tests/ContextualSuggestionsTest.full_height_scrolled.Nexus_5-19.png +++ b/chrome/test/data/android/render_tests/ContextualSuggestionsTest.full_height_scrolled.Nexus_5-19.png Binary files differ
diff --git a/chrome/test/data/android/render_tests/ContextualSuggestionsTest.suggestion_image_loading.Nexus_5-19.png b/chrome/test/data/android/render_tests/ContextualSuggestionsTest.suggestion_image_loading.Nexus_5-19.png index 9c5f9e6bd..afef95e 100644 --- a/chrome/test/data/android/render_tests/ContextualSuggestionsTest.suggestion_image_loading.Nexus_5-19.png +++ b/chrome/test/data/android/render_tests/ContextualSuggestionsTest.suggestion_image_loading.Nexus_5-19.png Binary files differ
diff --git a/chrome/test/data/navigation_predictor/page_with_same_host_anchor_element.html b/chrome/test/data/navigation_predictor/page_with_same_host_anchor_element.html new file mode 100644 index 0000000..5e28a73 --- /dev/null +++ b/chrome/test/data/navigation_predictor/page_with_same_host_anchor_element.html
@@ -0,0 +1,8 @@ +<html> + <head> + </head> + <body> + <a id="google" href="https://google.com">Google</a> + <a id="example" href="iframe_simple_page_with_anchors">Example</a> + </body> +</html> \ No newline at end of file
diff --git a/chromecast/browser/cast_media_blocker_unittest.cc b/chromecast/browser/cast_media_blocker_unittest.cc index bc96121..6aea51d 100644 --- a/chromecast/browser/cast_media_blocker_unittest.cc +++ b/chromecast/browser/cast_media_blocker_unittest.cc
@@ -67,8 +67,6 @@ media_blocker_ = std::make_unique<CastMediaBlocker>(media_session_.get()); } - void TearDown() override { content::RenderViewHostTestHarness::TearDown(); } - void MediaSessionChanged(bool controllable, bool suspended) { media_blocker_->MediaSessionStateChanged(controllable, suspended); }
diff --git a/chromeos/network/BUILD.gn b/chromeos/network/BUILD.gn index e879cf3..efa967c 100644 --- a/chromeos/network/BUILD.gn +++ b/chromeos/network/BUILD.gn
@@ -13,12 +13,12 @@ deps = [ "//base", "//base:i18n", - "//chromeos/dbus", - "//chromeos/login", "//chromeos:chromeos_constants", "//chromeos:chromeos_export", "//chromeos:policy_certificate_provider", "//chromeos:tools", + "//chromeos/dbus", + "//chromeos/login", "//components/account_id", "//components/device_event_log", "//components/onc", @@ -70,10 +70,6 @@ "network_cert_migrator.h", "network_certificate_handler.cc", "network_certificate_handler.h", - "network_change_notifier_chromeos.cc", - "network_change_notifier_chromeos.h", - "network_change_notifier_factory_chromeos.cc", - "network_change_notifier_factory_chromeos.h", "network_configuration_handler.cc", "network_configuration_handler.h", "network_configuration_observer.h", @@ -171,13 +167,13 @@ deps = [ ":network", "//base", - "//base/test:test_support", "//base:i18n", - "//chromeos/dbus", - "//chromeos/login", + "//base/test:test_support", "//chromeos:chromeos_constants", "//chromeos:policy_certificate_provider", "//chromeos:test_support_source_set", + "//chromeos/dbus", + "//chromeos/login", "//components/onc", "//components/prefs", "//components/prefs:test_support", @@ -200,7 +196,6 @@ "managed_network_configuration_handler_unittest.cc", "network_cert_loader_unittest.cc", "network_cert_migrator_unittest.cc", - "network_change_notifier_chromeos_unittest.cc", "network_configuration_handler_unittest.cc", "network_connect_unittest.cc", "network_connection_handler_impl_unittest.cc",
diff --git a/chromeos/network/managed_state.h b/chromeos/network/managed_state.h index 1aa7db53..c03a698 100644 --- a/chromeos/network/managed_state.h +++ b/chromeos/network/managed_state.h
@@ -89,6 +89,9 @@ update_requested_ = update_requested; } + void set_path_for_testing(const std::string& path) { path_ = path; } + void set_type_for_testing(const std::string& type) { type_ = type; } + // Returns true if |type_| matches |pattern|. bool Matches(const NetworkTypePattern& pattern) const; @@ -120,7 +123,6 @@ void set_type(const std::string& type) { type_ = type; } private: - friend class NetworkChangeNotifierChromeosUpdateTest; friend class NetworkStateHandler; friend class ash::network_icon::NetworkIconTest; friend class chromeos::tether::NetworkListSorterTest;
diff --git a/chromeos/network/network_change_notifier_chromeos.cc b/chromeos/network/network_change_notifier_chromeos.cc deleted file mode 100644 index 2fffa00fd..0000000 --- a/chromeos/network/network_change_notifier_chromeos.cc +++ /dev/null
@@ -1,304 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <string> - -#include "base/bind.h" -#include "base/location.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/threading/thread_task_runner_handle.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/network/network_change_notifier_chromeos.h" -#include "chromeos/network/network_event_log.h" -#include "chromeos/network/network_state.h" -#include "chromeos/network/network_state_handler.h" -#include "net/dns/dns_config_service_posix.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -// DNS config services on Chrome OS are signalled by the network state handler -// rather than relying on watching files in /etc. -class NetworkChangeNotifierChromeos::DnsConfigService - : public net::internal::DnsConfigServicePosix { - public: - DnsConfigService(); - ~DnsConfigService() override; - - // net::internal::DnsConfigService() overrides. - bool StartWatching() override; - - virtual void OnNetworkChange(); -}; - -NetworkChangeNotifierChromeos::DnsConfigService::DnsConfigService() = default; - -NetworkChangeNotifierChromeos::DnsConfigService::~DnsConfigService() = default; - -bool NetworkChangeNotifierChromeos::DnsConfigService::StartWatching() { - // DNS config changes are handled and notified by the network state handlers. - return true; -} - -void NetworkChangeNotifierChromeos::DnsConfigService::OnNetworkChange() { - InvalidateConfig(); - InvalidateHosts(); - ReadNow(); -} - -NetworkChangeNotifierChromeos::NetworkChangeNotifierChromeos() - : NetworkChangeNotifier(NetworkChangeCalculatorParamsChromeos()), - connection_type_(CONNECTION_NONE), - max_bandwidth_mbps_( - NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype( - SUBTYPE_NONE)), - task_runner_(base::ThreadTaskRunnerHandle::Get()), - weak_ptr_factory_(this) { - poll_callback_ = base::Bind(&NetworkChangeNotifierChromeos::PollForState, - weak_ptr_factory_.GetWeakPtr()); -} - -NetworkChangeNotifierChromeos::~NetworkChangeNotifierChromeos() = default; - -void NetworkChangeNotifierChromeos::Initialize() { - DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this); - NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE); - - dns_config_service_.reset(new DnsConfigService()); - dns_config_service_->WatchConfig( - base::Bind(net::NetworkChangeNotifier::SetDnsConfig)); - - PollForState(); -} - -void NetworkChangeNotifierChromeos::PollForState() { - // Update initial connection state. - DefaultNetworkChanged( - NetworkHandler::Get()->network_state_handler()->DefaultNetwork()); -} - -void NetworkChangeNotifierChromeos::Shutdown() { - dns_config_service_.reset(); - NetworkHandler::Get()->network_state_handler()->RemoveObserver( - this, FROM_HERE); - DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this); -} - -net::NetworkChangeNotifier::ConnectionType -NetworkChangeNotifierChromeos::GetCurrentConnectionType() const { - // Re-evaluate connection state if we are offline since there is little - // cost to doing so. Since we are in the context of a const method, - // this is done through a closure that holds a non-const reference to - // |this|, to allow PollForState() to modify our cached state. - // TODO(gauravsh): Figure out why we would have missed this notification. - if (connection_type_ == CONNECTION_NONE) - task_runner_->PostTask(FROM_HERE, poll_callback_); - return connection_type_; -} - -void NetworkChangeNotifierChromeos::GetCurrentMaxBandwidthAndConnectionType( - double* max_bandwidth_mbps, - ConnectionType* connection_type) const { - *connection_type = connection_type_; - *max_bandwidth_mbps = max_bandwidth_mbps_; -} - -void NetworkChangeNotifierChromeos::SuspendDone( - const base::TimeDelta& sleep_duration) { - // Force invalidation of network resources on resume. - NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); -} - - -void NetworkChangeNotifierChromeos::DefaultNetworkChanged( - const chromeos::NetworkState* default_network) { - bool connection_type_changed = false; - bool ip_address_changed = false; - bool dns_changed = false; - bool max_bandwidth_changed = false; - - UpdateState(default_network, &connection_type_changed, &ip_address_changed, - &dns_changed, &max_bandwidth_changed); - - if (connection_type_changed) - NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange(); - if (ip_address_changed) - NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); - if (dns_changed) - dns_config_service_->OnNetworkChange(); - if (max_bandwidth_changed || connection_type_changed) { - NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChange( - max_bandwidth_mbps_, connection_type_); - } -} - -void NetworkChangeNotifierChromeos::UpdateState( - const chromeos::NetworkState* default_network, - bool* connection_type_changed, - bool* ip_address_changed, - bool* dns_changed, - bool* max_bandwidth_changed) { - *connection_type_changed = false; - *ip_address_changed = false; - *dns_changed = false; - *max_bandwidth_changed = false; - - if (!default_network || !default_network->IsConnectedState()) { - // If we lost a default network, we must update our state and notify - // observers, otherwise we have nothing to do. - if (connection_type_ != CONNECTION_NONE) { - NET_LOG_EVENT("NCNDefaultNetworkLost", service_path_); - *ip_address_changed = true; - *dns_changed = true; - *connection_type_changed = true; - *max_bandwidth_changed = true; - connection_type_ = CONNECTION_NONE; - max_bandwidth_mbps_ = - GetMaxBandwidthMbpsForConnectionSubtype(SUBTYPE_NONE); - service_path_.clear(); - ip_address_.clear(); - dns_servers_.clear(); - } - return; - } - - // We do have a default network and it is connected. - net::NetworkChangeNotifier::ConnectionType new_connection_type = - ConnectionTypeFromShill(default_network->type(), - default_network->network_technology()); - if (new_connection_type != connection_type_) { - NET_LOG_EVENT( - "NCNDefaultConnectionTypeChanged", - base::StringPrintf("%s -> %s", ConnectionTypeToString(connection_type_), - ConnectionTypeToString(new_connection_type))); - *connection_type_changed = true; - } - if (default_network->path() != service_path_) { - NET_LOG_EVENT("NCNDefaultNetworkServicePathChanged", - base::StringPrintf("%s -> %s", service_path_.c_str(), - default_network->path().c_str())); - - // If we had a default network service change, network resources - // must always be invalidated. - *ip_address_changed = true; - *dns_changed = true; - } - - std::string new_ip_address = default_network->GetIpAddress(); - if (new_ip_address != ip_address_) { - // Is this a state update with an online->online transition? - bool stayed_online = - (!*connection_type_changed && connection_type_ != CONNECTION_NONE); - - bool is_suppressed = true; - // Suppress IP address change signalling on online->online transitions - // when getting an IP address update for the first time. - if (!(stayed_online && ip_address_.empty())) { - is_suppressed = false; - *ip_address_changed = true; - } - NET_LOG_EVENT(base::StringPrintf("%s%s", "NCNDefaultIPAddressChanged", - is_suppressed ? " (Suppressed)" : ""), - base::StringPrintf("%s -> %s", ip_address_.c_str(), - new_ip_address.c_str())); - } - std::string new_dns_servers = default_network->GetDnsServersAsString(); - if (new_dns_servers != dns_servers_) { - NET_LOG_EVENT("NCNDefaultDNSServerChanged", - base::StringPrintf("%s -> %s", dns_servers_.c_str(), - new_dns_servers.c_str())); - *dns_changed = true; - } - - connection_type_ = new_connection_type; - service_path_ = default_network->path(); - ip_address_ = new_ip_address; - dns_servers_ = new_dns_servers; - double old_max_bandwidth = max_bandwidth_mbps_; - max_bandwidth_mbps_ = - GetMaxBandwidthMbpsForConnectionSubtype(GetConnectionSubtype( - default_network->type(), default_network->network_technology())); - if (max_bandwidth_mbps_ != old_max_bandwidth) - *max_bandwidth_changed = true; -} - -// static -net::NetworkChangeNotifier::ConnectionType -NetworkChangeNotifierChromeos::ConnectionTypeFromShill( - const std::string& type, const std::string& technology) { - if (NetworkTypePattern::Ethernet().MatchesType(type)) - return CONNECTION_ETHERNET; - else if (type == shill::kTypeWifi) - return CONNECTION_WIFI; - else if (type == shill::kTypeWimax) - return CONNECTION_4G; - else if (type == shill::kTypeBluetooth) - return CONNECTION_BLUETOOTH; - - if (type != shill::kTypeCellular) - return CONNECTION_UNKNOWN; - - // For cellular types, mapping depends on the technology. - if (technology == shill::kNetworkTechnologyEvdo || - technology == shill::kNetworkTechnologyGsm || - technology == shill::kNetworkTechnologyUmts || - technology == shill::kNetworkTechnologyHspa) { - return CONNECTION_3G; - } else if (technology == shill::kNetworkTechnologyHspaPlus || - technology == shill::kNetworkTechnologyLte || - technology == shill::kNetworkTechnologyLteAdvanced) { - return CONNECTION_4G; - } else { - return CONNECTION_2G; // Default cellular type is 2G. - } -} - -// static -net::NetworkChangeNotifier::ConnectionSubtype -NetworkChangeNotifierChromeos::GetConnectionSubtype( - const std::string& type, - const std::string& technology) { - if (type != shill::kTypeCellular) - return SUBTYPE_UNKNOWN; - - if (technology == shill::kNetworkTechnology1Xrtt) - return SUBTYPE_1XRTT; - if (technology == shill::kNetworkTechnologyEvdo) - return SUBTYPE_EVDO_REV_0; - if (technology == shill::kNetworkTechnologyGsm) - return SUBTYPE_GSM; - if (technology == shill::kNetworkTechnologyGprs) - return SUBTYPE_GPRS; - if (technology == shill::kNetworkTechnologyEdge) - return SUBTYPE_EDGE; - if (technology == shill::kNetworkTechnologyUmts) - return SUBTYPE_UMTS; - if (technology == shill::kNetworkTechnologyHspa) - return SUBTYPE_HSPA; - if (technology == shill::kNetworkTechnologyHspaPlus) - return SUBTYPE_HSPAP; - if (technology == shill::kNetworkTechnologyLte) - return SUBTYPE_LTE; - if (technology == shill::kNetworkTechnologyLteAdvanced) - return SUBTYPE_LTE_ADVANCED; - - return SUBTYPE_UNKNOWN; -} - -// static -net::NetworkChangeNotifier::NetworkChangeCalculatorParams -NetworkChangeNotifierChromeos::NetworkChangeCalculatorParamsChromeos() { - NetworkChangeCalculatorParams params; - // Delay values arrived at by simple experimentation and adjusted so as to - // produce a single signal when switching between network connections. - params.ip_address_offline_delay_ = base::TimeDelta::FromMilliseconds(4000); - params.ip_address_online_delay_ = base::TimeDelta::FromMilliseconds(1000); - params.connection_type_offline_delay_ = - base::TimeDelta::FromMilliseconds(500); - params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(500); - return params; -} - -} // namespace chromeos
diff --git a/chromeos/network/network_change_notifier_chromeos.h b/chromeos/network/network_change_notifier_chromeos.h deleted file mode 100644 index ff23f8f..0000000 --- a/chromeos/network/network_change_notifier_chromeos.h +++ /dev/null
@@ -1,118 +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 CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_ -#define CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_ - -#include <memory> -#include <string> - -#include "base/callback.h" -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" -#include "chromeos/chromeos_export.h" -#include "chromeos/dbus/power_manager_client.h" -#include "chromeos/network/network_state_handler_observer.h" -#include "net/base/network_change_notifier.h" - -namespace chromeos { - -class CHROMEOS_EXPORT NetworkChangeNotifierChromeos - : public net::NetworkChangeNotifier, - public chromeos::PowerManagerClient::Observer, - public chromeos::NetworkStateHandlerObserver { - public: - NetworkChangeNotifierChromeos(); - ~NetworkChangeNotifierChromeos() override; - - // Starts observing changes from the network state handler. - void Initialize(); - - // Stops observing changes from the network state handler. - void Shutdown(); - - // NetworkChangeNotifier overrides. - net::NetworkChangeNotifier::ConnectionType GetCurrentConnectionType() - const override; - void GetCurrentMaxBandwidthAndConnectionType( - double* max_bandwidth_mbps, - ConnectionType* connection_type) const override; - - // PowerManagerClient::Observer overrides. - void SuspendDone(const base::TimeDelta& sleep_duration) override; - - // NetworkStateHandlerObserver overrides. - void DefaultNetworkChanged( - const chromeos::NetworkState* default_network) override; - - private: - FRIEND_TEST_ALL_PREFIXES(NetworkChangeNotifierChromeosTest, - ConnectionTypeFromShill); - friend class NetworkChangeNotifierChromeosUpdateTest; - - class DnsConfigService; - - // Updates the notifier state based on a default network update. - // |connection_type_changed| is set to true if we must report a connection - // type change. - // |ip_address_changed| is set to true if we must report an IP address change. - // |dns_changed| is set to true if we must report a DNS config change. - // |max_bandwidth_changed| is set to true if we must report a max bandwidth - // change. - void UpdateState(const chromeos::NetworkState* default_network, - bool* connection_type_changed, - bool* ip_address_changed, - bool* dns_changed, - bool* max_bandwidth_changed); - - // Proactively retrieves current network state from the network - // state handler and calls UpdateState with the result. - void PollForState(); - - // Maps the shill network type and technology to its NetworkChangeNotifier - // equivalent. - static net::NetworkChangeNotifier::ConnectionType - ConnectionTypeFromShill(const std::string& type, - const std::string& technology); - - // Maps the shill network type and technology to its NetworkChangeNotifier - // subtype equivalent. - static net::NetworkChangeNotifier::ConnectionSubtype GetConnectionSubtype( - const std::string& type, - const std::string& technology); - - // Calculates parameters used for network change notifier online/offline - // signals. - static net::NetworkChangeNotifier::NetworkChangeCalculatorParams - NetworkChangeCalculatorParamsChromeos(); - - NetworkChangeNotifier::ConnectionType connection_type_; - // IP address for the current default network. - std::string ip_address_; - // DNS servers for the current default network. - std::string dns_servers_; - // Service path for the current default network. - std::string service_path_; - - // The maximum theoretical bandwidth in megabits per second for the current - // default network. - double max_bandwidth_mbps_; - - std::unique_ptr<DnsConfigService> dns_config_service_; - - // Callback for refreshing network state. - base::Closure poll_callback_; - - // For setting up network refresh polling callbacks. - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - base::WeakPtrFactory<NetworkChangeNotifierChromeos> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierChromeos); -}; - -} // namespace chromeos - -#endif // CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_
diff --git a/chromeos/network/network_change_notifier_chromeos_unittest.cc b/chromeos/network/network_change_notifier_chromeos_unittest.cc deleted file mode 100644 index bba16c6..0000000 --- a/chromeos/network/network_change_notifier_chromeos_unittest.cc +++ /dev/null
@@ -1,372 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/network/network_change_notifier_chromeos.h" - -#include <stddef.h> - -#include <string> - -#include "base/message_loop/message_loop.h" -#include "base/strings/string_split.h" -#include "chromeos/network/network_change_notifier_factory_chromeos.h" -#include "chromeos/network/network_state.h" -#include "net/base/network_change_notifier.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace chromeos { - -namespace { - -const char kDnsServers1[] = "192.168.0.1,192.168.0.2"; -const char kDnsServers2[] = "192.168.3.1,192.168.3.2"; -const char kIpAddress1[] = "192.168.1.1"; -const char kIpAddress2[] = "192.168.1.2"; -const char kService1[] = "/service/1"; -const char kService2[] = "/service/2"; -const char kService3[] = "/service/3"; - -// These values come from -// http://w3c.github.io/netinfo/#underlying-connection-technology. For types -// that have unknown subtypes (wifi and ethernet) positive infinity is used as -// per the spec. -const double kExpectedNoneMaxBandwidth = 0; -const double kExpectedWifiMaxBandwidth = - std::numeric_limits<double>::infinity(); -const double kExpectedEthernetMaxBandwidth = - std::numeric_limits<double>::infinity(); -const double kExpectedLteMaxBandwidth = 100; -const double kExpectedEvdoMaxBandwidth = 2.46; -const double kExpectedHspaMaxBandwidth = 3.6; - -struct NotifierState { - net::NetworkChangeNotifier::ConnectionType type; - const char* service_path; - const char* ip_address; - const char* dns_servers; - double max_bandwidth; -}; - -struct DefaultNetworkState { - bool is_connected; - const char* type; - const char* network_technology; - const char* service_path; - const char* ip_address; - const char* dns_servers; -}; - -struct NotifierUpdateTestCase { - const char* test_description; - NotifierState initial_state; - DefaultNetworkState default_network_state; - NotifierState expected_state; - bool expected_type_changed; - bool expected_ip_changed; - bool expected_dns_changed; - bool expected_max_bandwidth_changed; -}; - -} // namespace - -using net::NetworkChangeNotifier; - -TEST(NetworkChangeNotifierChromeosTest, ConnectionTypeFromShill) { - struct TypeMapping { - const char* shill_type; - const char* technology; - NetworkChangeNotifier::ConnectionType connection_type; - }; - TypeMapping type_mappings[] = { - { shill::kTypeEthernet, "", NetworkChangeNotifier::CONNECTION_ETHERNET }, - { shill::kTypeWifi, "", NetworkChangeNotifier::CONNECTION_WIFI }, - { shill::kTypeWimax, "", NetworkChangeNotifier::CONNECTION_4G }, - { "unknown type", "unknown technology", - NetworkChangeNotifier::CONNECTION_UNKNOWN }, - { shill::kTypeCellular, shill::kNetworkTechnology1Xrtt, - NetworkChangeNotifier::CONNECTION_2G }, - { shill::kTypeCellular, shill::kNetworkTechnologyGprs, - NetworkChangeNotifier::CONNECTION_2G }, - { shill::kTypeCellular, shill::kNetworkTechnologyEdge, - NetworkChangeNotifier::CONNECTION_2G }, - { shill::kTypeCellular, shill::kNetworkTechnologyEvdo, - NetworkChangeNotifier::CONNECTION_3G }, - { shill::kTypeCellular, shill::kNetworkTechnologyGsm, - NetworkChangeNotifier::CONNECTION_3G }, - { shill::kTypeCellular, shill::kNetworkTechnologyUmts, - NetworkChangeNotifier::CONNECTION_3G }, - { shill::kTypeCellular, shill::kNetworkTechnologyHspa, - NetworkChangeNotifier::CONNECTION_3G }, - { shill::kTypeCellular, shill::kNetworkTechnologyHspaPlus, - NetworkChangeNotifier::CONNECTION_4G }, - { shill::kTypeCellular, shill::kNetworkTechnologyLte, - NetworkChangeNotifier::CONNECTION_4G }, - { shill::kTypeCellular, shill::kNetworkTechnologyLteAdvanced, - NetworkChangeNotifier::CONNECTION_4G }, - { shill::kTypeCellular, "unknown technology", - NetworkChangeNotifier::CONNECTION_2G } - }; - - for (size_t i = 0; i < arraysize(type_mappings); ++i) { - NetworkChangeNotifier::ConnectionType type = - NetworkChangeNotifierChromeos::ConnectionTypeFromShill( - type_mappings[i].shill_type, type_mappings[i].technology); - EXPECT_EQ(type_mappings[i].connection_type, type); - } -} - -class NetworkChangeNotifierChromeosUpdateTest : public testing::Test { - protected: - NetworkChangeNotifierChromeosUpdateTest() : default_network_("") { - } - ~NetworkChangeNotifierChromeosUpdateTest() override = default; - - void SetNotifierState(const NotifierState& notifier_state) { - notifier_.connection_type_ = notifier_state.type; - notifier_.service_path_ = notifier_state.service_path; - notifier_.ip_address_ = notifier_state.ip_address; - notifier_.max_bandwidth_mbps_ = notifier_state.max_bandwidth; - notifier_.dns_servers_ = notifier_state.dns_servers; - } - - void VerifyNotifierState(const NotifierState& notifier_state) { - EXPECT_EQ(notifier_state.type, notifier_.connection_type_); - EXPECT_EQ(notifier_state.service_path, notifier_.service_path_); - EXPECT_EQ(notifier_state.ip_address, notifier_.ip_address_); - EXPECT_EQ(notifier_state.max_bandwidth, notifier_.max_bandwidth_mbps_); - EXPECT_EQ(notifier_state.dns_servers, notifier_.dns_servers_); - } - - // Sets the default network state used for notifier updates. - void SetDefaultNetworkState( - const DefaultNetworkState& default_network_state) { - default_network_.visible_ = true; - if (default_network_state.is_connected) - default_network_.connection_state_ = shill::kStateOnline; - else - default_network_.connection_state_ = shill::kStateConfiguration; - default_network_.type_ = default_network_state.type; - default_network_.network_technology_ = - default_network_state.network_technology; - default_network_.path_ = default_network_state.service_path; - base::Value ipv4_properties(base::Value::Type::DICTIONARY); - ipv4_properties.SetKey(shill::kAddressProperty, - base::Value(default_network_state.ip_address)); - std::vector<std::string> dns_servers = - base::SplitString(default_network_state.dns_servers, ",", - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - base::ListValue dns_servers_value; - dns_servers_value.AppendStrings(dns_servers); - ipv4_properties.SetKey(shill::kNameServersProperty, - std::move(dns_servers_value)); - default_network_.IPConfigPropertiesChanged(ipv4_properties); - } - - // Process an default network update based on the state of |default_network_|. - void ProcessDefaultNetworkUpdate(bool* type_changed, - bool* ip_changed, - bool* dns_changed, - bool* max_bandwidth_changed) { - notifier_.UpdateState(&default_network_, type_changed, ip_changed, - dns_changed, max_bandwidth_changed); - } - - private: - base::MessageLoop message_loop_; - NetworkState default_network_; - NetworkChangeNotifierChromeos notifier_; -}; - -NotifierUpdateTestCase test_cases[] = { - {"Online -> Offline", - {NetworkChangeNotifier::CONNECTION_ETHERNET, - kService1, - kIpAddress1, - kDnsServers1, - kExpectedEthernetMaxBandwidth}, - {false, shill::kTypeEthernet, "", kService1, "", ""}, - {NetworkChangeNotifier::CONNECTION_NONE, - "", - "", - "", - kExpectedNoneMaxBandwidth}, - true, - true, - true, - true}, - {"Offline -> Offline", - {NetworkChangeNotifier::CONNECTION_NONE, - "", - "", - "", - kExpectedNoneMaxBandwidth}, - {false, shill::kTypeEthernet, "", kService1, kIpAddress1, kDnsServers1}, - {NetworkChangeNotifier::CONNECTION_NONE, - "", - "", - "", - kExpectedNoneMaxBandwidth}, - false, - false, - false, - false}, - {"Offline -> Online", - {NetworkChangeNotifier::CONNECTION_NONE, - "", - "", - "", - kExpectedNoneMaxBandwidth}, - {true, shill::kTypeEthernet, "", kService1, kIpAddress1, kDnsServers1}, - {NetworkChangeNotifier::CONNECTION_ETHERNET, - kService1, - kIpAddress1, - kDnsServers1, - kExpectedEthernetMaxBandwidth}, - true, - true, - true, - true}, - {"Online -> Online (new default service, different connection type)", - {NetworkChangeNotifier::CONNECTION_ETHERNET, - kService1, - kIpAddress1, - kDnsServers1, - kExpectedEthernetMaxBandwidth}, - {true, shill::kTypeWifi, "", kService2, kIpAddress1, kDnsServers1}, - {NetworkChangeNotifier::CONNECTION_WIFI, - kService2, - kIpAddress1, - kDnsServers1, - kExpectedWifiMaxBandwidth}, - true, - true, - true, - false}, - {"Online -> Online (new default service, same connection type)", - {NetworkChangeNotifier::CONNECTION_WIFI, - kService2, - kIpAddress1, - kDnsServers1, - kExpectedWifiMaxBandwidth}, - {true, shill::kTypeWifi, "", kService3, kIpAddress1, kDnsServers1}, - {NetworkChangeNotifier::CONNECTION_WIFI, - kService3, - kIpAddress1, - kDnsServers1, - kExpectedWifiMaxBandwidth}, - false, - true, - true, - false}, - {"Online -> Online (same default service, first IP address update)", - {NetworkChangeNotifier::CONNECTION_WIFI, - kService3, - "", - kDnsServers1, - kExpectedWifiMaxBandwidth}, - {true, shill::kTypeWifi, "", kService3, kIpAddress2, kDnsServers1}, - {NetworkChangeNotifier::CONNECTION_WIFI, - kService3, - kIpAddress2, - kDnsServers1, - kExpectedWifiMaxBandwidth}, - false, - false, - false, - false}, - {"Online -> Online (same default service, new IP address, same DNS)", - {NetworkChangeNotifier::CONNECTION_WIFI, - kService3, - kIpAddress1, - kDnsServers1, - kExpectedWifiMaxBandwidth}, - {true, shill::kTypeWifi, "", kService3, kIpAddress2, kDnsServers1}, - {NetworkChangeNotifier::CONNECTION_WIFI, - kService3, - kIpAddress2, - kDnsServers1, - kExpectedWifiMaxBandwidth}, - false, - true, - false, - false}, - {"Online -> Online (same default service, same IP address, new DNS)", - {NetworkChangeNotifier::CONNECTION_WIFI, - kService3, - kIpAddress2, - kDnsServers1, - kExpectedWifiMaxBandwidth}, - {true, shill::kTypeWifi, "", kService3, kIpAddress2, kDnsServers2}, - {NetworkChangeNotifier::CONNECTION_WIFI, - kService3, - kIpAddress2, - kDnsServers2, - kExpectedWifiMaxBandwidth}, - false, - false, - true, - false}, - {"Online -> Online (change of technology but not connection type)", - {NetworkChangeNotifier::CONNECTION_3G, - kService3, - kIpAddress2, - kDnsServers1, - kExpectedEvdoMaxBandwidth}, - {true, - shill::kTypeCellular, - shill::kNetworkTechnologyHspa, - kService3, - kIpAddress2, - kDnsServers1}, - {NetworkChangeNotifier::CONNECTION_3G, - kService3, - kIpAddress2, - kDnsServers1, - kExpectedHspaMaxBandwidth}, - false, - false, - false, - true}, - {"Online -> Online (change of technology and connection type)", - {NetworkChangeNotifier::CONNECTION_3G, - kService3, - kIpAddress2, - kDnsServers1, - kExpectedEvdoMaxBandwidth}, - {true, - shill::kTypeCellular, - shill::kNetworkTechnologyLte, - kService3, - kIpAddress2, - kDnsServers1}, - {NetworkChangeNotifier::CONNECTION_4G, - kService3, - kIpAddress2, - kDnsServers1, - kExpectedLteMaxBandwidth}, - true, - false, - false, - true}}; - -TEST_F(NetworkChangeNotifierChromeosUpdateTest, UpdateDefaultNetwork) { - for (size_t i = 0; i < arraysize(test_cases); ++i) { - SCOPED_TRACE(test_cases[i].test_description); - SetNotifierState(test_cases[i].initial_state); - SetDefaultNetworkState(test_cases[i].default_network_state); - bool type_changed = false, ip_changed = false, dns_changed = false, - max_bandwidth_changed = false; - ProcessDefaultNetworkUpdate(&type_changed, &ip_changed, &dns_changed, - &max_bandwidth_changed); - VerifyNotifierState(test_cases[i].expected_state); - EXPECT_EQ(test_cases[i].expected_type_changed, type_changed); - EXPECT_EQ(test_cases[i].expected_ip_changed, ip_changed); - EXPECT_EQ(test_cases[i].expected_dns_changed, dns_changed); - EXPECT_EQ(test_cases[i].expected_max_bandwidth_changed, - max_bandwidth_changed); - } -} - -} // namespace chromeos
diff --git a/chromeos/network/network_change_notifier_factory_chromeos.cc b/chromeos/network/network_change_notifier_factory_chromeos.cc deleted file mode 100644 index 1d73c3e..0000000 --- a/chromeos/network/network_change_notifier_factory_chromeos.cc +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/network/network_change_notifier_factory_chromeos.h" - -#include "chromeos/network/network_change_notifier_chromeos.h" - -namespace chromeos { - -namespace { - -NetworkChangeNotifierChromeos* g_network_change_notifier_chromeos = NULL; - -} // namespace - -net::NetworkChangeNotifier* -NetworkChangeNotifierFactoryChromeos::CreateInstance() { - DCHECK(!g_network_change_notifier_chromeos); - g_network_change_notifier_chromeos = new NetworkChangeNotifierChromeos(); - return g_network_change_notifier_chromeos; -} - -// static -NetworkChangeNotifierChromeos* -NetworkChangeNotifierFactoryChromeos::GetInstance() { - return g_network_change_notifier_chromeos; -} - -} // namespace chromeos
diff --git a/chromeos/network/network_change_notifier_factory_chromeos.h b/chromeos/network/network_change_notifier_factory_chromeos.h deleted file mode 100644 index a60e5e8..0000000 --- a/chromeos/network/network_change_notifier_factory_chromeos.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 CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_FACTORY_CHROMEOS_H_ -#define CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_FACTORY_CHROMEOS_H_ - -#include "base/compiler_specific.h" -#include "chromeos/chromeos_export.h" -#include "net/base/network_change_notifier_factory.h" - -namespace chromeos { - -class NetworkChangeNotifierChromeos; - -class CHROMEOS_EXPORT NetworkChangeNotifierFactoryChromeos - : public net::NetworkChangeNotifierFactory { - public: - NetworkChangeNotifierFactoryChromeos() {} - - // net::NetworkChangeNotifierFactory overrides. - net::NetworkChangeNotifier* CreateInstance() override; - - static NetworkChangeNotifierChromeos* GetInstance(); -}; - -} // namespace chromeos - -#endif // CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_FACTORY_CHROMEOS_H_
diff --git a/chromeos/network/network_state.h b/chromeos/network/network_state.h index 9dfdc07b..e5805b7 100644 --- a/chromeos/network/network_state.h +++ b/chromeos/network/network_state.h
@@ -194,6 +194,11 @@ // Returns |error_| if valid, otherwise returns |last_error_|. std::string GetErrorState() const; + // Setters for testing. + void set_network_technology_for_testing(const std::string& technology) { + network_technology_ = technology; + } + // Helpers (used e.g. when a state, error, or shill dictionary is cached) static bool StateIsConnected(const std::string& connection_state); static bool StateIsConnecting(const std::string& connection_state); @@ -205,7 +210,6 @@ private: friend class MobileActivatorTest; friend class NetworkStateHandler; - friend class NetworkChangeNotifierChromeosUpdateTest; FRIEND_TEST_ALL_PREFIXES(NetworkStateTest, TetherProperties); // Updates |name_| from the 'WiFi.HexSSID' entry in |properties|, which must
diff --git a/components/arc/arc_prefs.cc b/components/arc/arc_prefs.cc index f13fdbc..8b16ce62 100644 --- a/components/arc/arc_prefs.cc +++ b/components/arc/arc_prefs.cc
@@ -60,6 +60,10 @@ const char kArcPackages[] = "arc.packages"; // A preference that indicates that Play Auto Install flow was already started. const char kArcPaiStarted[] = "arc.pai.started"; +// A preference that indicates that provisioning was initiated from OOBE. This +// is preserved across Chrome restart. +const char kArcProvisioningInitiatedFromOobe[] = + "arc.provisioning.initiated.from.oobe"; // A preference that indicates that Play Fast App Reinstall flow was already // started. const char kArcFastAppReinstallStarted[] = "arc.fast.app.reinstall.started"; @@ -147,6 +151,7 @@ registry->RegisterBooleanPref(kArcFastAppReinstallStarted, false); registry->RegisterListPref(kArcFastAppReinstallPackages); registry->RegisterBooleanPref(kArcPolicyComplianceReported, false); + registry->RegisterBooleanPref(kArcProvisioningInitiatedFromOobe, false); registry->RegisterBooleanPref(kArcSignedIn, false); registry->RegisterBooleanPref(kArcSkippedReportingNotice, false); registry->RegisterBooleanPref(kArcTermsAccepted, false);
diff --git a/components/arc/arc_prefs.h b/components/arc/arc_prefs.h index 2a900ca..00f728b 100644 --- a/components/arc/arc_prefs.h +++ b/components/arc/arc_prefs.h
@@ -29,6 +29,7 @@ ARC_EXPORT extern const char kArcLocationServiceEnabled[]; ARC_EXPORT extern const char kArcPackages[]; ARC_EXPORT extern const char kArcPaiStarted[]; +ARC_EXPORT extern const char kArcProvisioningInitiatedFromOobe[]; ARC_EXPORT extern const char kArcPushInstallAppsRequested[]; ARC_EXPORT extern const char kArcPushInstallAppsPending[]; ARC_EXPORT extern const char kArcSetNotificationsEnabledDeferred[];
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc b/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc index 6842cc8b1..abdd68294 100644 --- a/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc +++ b/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
@@ -461,7 +461,7 @@ fake_activity), package_name + "." + fake_activity); - std::string empty_string = ""; + const std::string empty_string; EXPECT_EQ(ArcIntentHelperBridge::AppendStringToIntentHelperPackageName( empty_string), package_name + ".");
diff --git a/components/drive/drive_notification_manager.cc b/components/drive/drive_notification_manager.cc index 3f789e5..175d304ec 100644 --- a/components/drive/drive_notification_manager.cc +++ b/components/drive/drive_notification_manager.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/metrics/histogram_macros.h" +#include "base/rand_util.h" #include "base/strings/char_traits.h" #include "base/strings/strcat.h" #include "base/strings/string_util.h" @@ -25,11 +26,10 @@ // The polling interval time is used when XMPP is enabled. Theoretically // polling should be unnecessary if XMPP is enabled, but just in case. -const int kSlowPollingIntervalInSecs = 300; +const int kSlowPollingIntervalInSecs = 3600; // The period to batch together invalidations before passing them to observers. -constexpr base::TimeDelta kInvalidationBatchInterval = - base::TimeDelta::FromSeconds(5); +constexpr int kInvalidationBatchIntervalSecs = 15; // The sync invalidation object ID for Google Drive. const char kDriveInvalidationObjectId[] = "CHANGELOG"; @@ -49,16 +49,11 @@ push_notification_registered_(false), push_notification_enabled_(false), observers_notified_(false), + batch_timer_(clock), weak_ptr_factory_(this) { DCHECK(invalidation_service_); RegisterDriveNotifications(); RestartPollingTimer(); - - batch_timer_ = std::make_unique<base::RetainingOneShotTimer>( - FROM_HERE, kInvalidationBatchInterval, - base::BindRepeating(&DriveNotificationManager::OnBatchTimerExpired, - weak_ptr_factory_.GetWeakPtr()), - clock); } DriveNotificationManager::~DriveNotificationManager() { @@ -122,12 +117,12 @@ // See crbug.com/320878. invalidation_map.AcknowledgeAll(); - if (!batch_timer_->IsRunning() && !invalidated_change_ids_.empty()) { + if (!batch_timer_.IsRunning() && !invalidated_change_ids_.empty()) { // Stop the polling timer as we'll be sending a batch soon. polling_timer_.Stop(); // Restart the timer to send the batch when the timer fires. - batch_timer_->Reset(); + RestartBatchTimer(); } } @@ -175,14 +170,30 @@ const int interval_secs = (push_notification_enabled_ ? kSlowPollingIntervalInSecs : kFastPollingIntervalInSecs); + + int jitter = base::RandInt(0, interval_secs); + polling_timer_.Stop(); polling_timer_.Start( - FROM_HERE, base::TimeDelta::FromSeconds(interval_secs), + FROM_HERE, base::TimeDelta::FromSeconds(interval_secs + jitter), base::BindOnce(&DriveNotificationManager::NotifyObserversToUpdate, weak_ptr_factory_.GetWeakPtr(), NOTIFICATION_POLLING, std::map<std::string, int64_t>())); } +void DriveNotificationManager::RestartBatchTimer() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + int jitter = base::RandInt(0, kInvalidationBatchIntervalSecs); + + batch_timer_.Stop(); + batch_timer_.Start( + FROM_HERE, + base::TimeDelta::FromSeconds(kInvalidationBatchIntervalSecs + jitter), + base::BindOnce(&DriveNotificationManager::OnBatchTimerExpired, + weak_ptr_factory_.GetWeakPtr())); +} + void DriveNotificationManager::NotifyObserversToUpdate( NotificationSource source, std::map<std::string, int64_t> invalidations) {
diff --git a/components/drive/drive_notification_manager.h b/components/drive/drive_notification_manager.h index 38febf49..ba6981b 100644 --- a/components/drive/drive_notification_manager.h +++ b/components/drive/drive_notification_manager.h
@@ -86,6 +86,10 @@ // Restarts the polling timer. Used for polling-based notification. void RestartPollingTimer(); + // Restarts the batch notification timer. Used for batching together XMPP + // notifications so we can smooth out the traffic on the drive backends. + void RestartBatchTimer(); + // Notifies the observers that it's time to check for updates. // |source| indicates where the notification comes from. void NotifyObserversToUpdate(NotificationSource source, @@ -123,7 +127,7 @@ // This timer is used to batch together invalidations. The invalidation // service can send many invalidations for the same id in rapid succession, // batching them together and removing duplicates is an optimzation. - std::unique_ptr<base::RetainingOneShotTimer> batch_timer_; + base::OneShotTimer batch_timer_; // The batch of invalidation id's that we've seen from the invaliation // service, will be reset when when send the invalidations to the observers.
diff --git a/components/drive/drive_notification_manager_unittest.cc b/components/drive/drive_notification_manager_unittest.cc index c34a7d1e..0a9543bb 100644 --- a/components/drive/drive_notification_manager_unittest.cc +++ b/components/drive/drive_notification_manager_unittest.cc
@@ -162,7 +162,7 @@ syncer::Invalidation::InitUnknownVersion(kDefaultCorpusObjectId)); EXPECT_TRUE(drive_notification_observer_->GetNotificationIds().empty()); - task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(5)); + task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(30)); // Default corpus is has the id "" when sent to observers. std::map<std::string, int64_t> expected_ids = {{"", -1}}; @@ -181,7 +181,7 @@ syncer::Invalidation::Init(kDefaultCorpusObjectId, 1, "")); EXPECT_TRUE(drive_notification_observer_->GetNotificationIds().empty()); - task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(5)); + task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(30)); // Default corpus is has the id "" when sent to observers. expected_ids = {{"", 2}}; @@ -193,7 +193,7 @@ syncer::Invalidation::Init(team_drive_1_object_id, 2, "")); EXPECT_TRUE(drive_notification_observer_->GetNotificationIds().empty()); - task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(5)); + task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(30)); expected_ids = {{team_drive_id_1, 2}}; EXPECT_EQ(expected_ids, drive_notification_observer_->GetNotificationIds()); drive_notification_observer_->ClearNotificationIds(); @@ -214,7 +214,7 @@ EXPECT_TRUE(drive_notification_observer_->GetNotificationIds().empty()); - task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(5)); + task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(30)); expected_ids = {{"", 2}, {team_drive_id_1, 2}}; EXPECT_EQ(expected_ids, drive_notification_observer_->GetNotificationIds()); }
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index e65f3a5..4041b40 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -41,8 +41,12 @@ "wayland_keyboard_delegate.h", "wayland_pointer_delegate.cc", "wayland_pointer_delegate.h", + "wayland_touch_delegate.cc", + "wayland_touch_delegate.h", "zcr_notification_shell.cc", "zcr_notification_shell.h", + "zwp_input_timestamps_manager.cc", + "zwp_input_timestamps_manager.h", "zwp_text_input_manager.cc", "zwp_text_input_manager.h", ]
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index 6db47b2..230c637 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -98,7 +98,9 @@ #include "components/exo/wayland/wayland_input_delegate.h" #include "components/exo/wayland/wayland_keyboard_delegate.h" #include "components/exo/wayland/wayland_pointer_delegate.h" +#include "components/exo/wayland/wayland_touch_delegate.h" #include "components/exo/wayland/zcr_notification_shell.h" +#include "components/exo/wayland/zwp_input_timestamps_manager.h" #include "components/exo/wayland/zwp_text_input_manager.h" #include "components/exo/wm_helper.h" #include "components/exo/wm_helper_chromeos.h" @@ -3596,80 +3598,6 @@ //////////////////////////////////////////////////////////////////////////////// // wl_touch_interface: -// Touch delegate class that accepts events for surfaces owned by the same -// client as a touch resource. -class WaylandTouchDelegate : public WaylandInputDelegate, public TouchDelegate { - public: - explicit WaylandTouchDelegate(wl_resource* touch_resource) - : touch_resource_(touch_resource) {} - - // Overridden from TouchDelegate: - void OnTouchDestroying(Touch* touch) override { delete this; } - bool CanAcceptTouchEventsForSurface(Surface* surface) const override { - wl_resource* surface_resource = GetSurfaceResource(surface); - // We can accept events for this surface if the client is the same as the - // touch resource. - return surface_resource && - wl_resource_get_client(surface_resource) == client(); - } - void OnTouchDown(Surface* surface, - base::TimeTicks time_stamp, - int id, - const gfx::PointF& location) override { - wl_resource* surface_resource = GetSurfaceResource(surface); - DCHECK(surface_resource); - SendTimestamp(time_stamp); - wl_touch_send_down(touch_resource_, next_serial(), - TimeTicksToMilliseconds(time_stamp), surface_resource, - id, wl_fixed_from_double(location.x()), - wl_fixed_from_double(location.y())); - } - void OnTouchUp(base::TimeTicks time_stamp, int id) override { - SendTimestamp(time_stamp); - wl_touch_send_up(touch_resource_, next_serial(), - TimeTicksToMilliseconds(time_stamp), id); - } - void OnTouchMotion(base::TimeTicks time_stamp, - int id, - const gfx::PointF& location) override { - SendTimestamp(time_stamp); - wl_touch_send_motion(touch_resource_, TimeTicksToMilliseconds(time_stamp), - id, wl_fixed_from_double(location.x()), - wl_fixed_from_double(location.y())); - } - void OnTouchShape(int id, float major, float minor) override { - if (wl_resource_get_version(touch_resource_) >= - WL_TOUCH_SHAPE_SINCE_VERSION) { - wl_touch_send_shape(touch_resource_, id, wl_fixed_from_double(major), - wl_fixed_from_double(minor)); - } - } - void OnTouchFrame() override { - if (wl_resource_get_version(touch_resource_) >= - WL_TOUCH_FRAME_SINCE_VERSION) { - wl_touch_send_frame(touch_resource_); - } - wl_client_flush(client()); - } - void OnTouchCancel() override { - wl_touch_send_cancel(touch_resource_); - } - - private: - // The client who own this touch instance. - wl_client* client() const { return wl_resource_get_client(touch_resource_); } - - // Returns the next serial to use for keyboard events. - uint32_t next_serial() const { - return wl_display_next_serial(wl_client_get_display(client())); - } - - // The touch resource associated with the touch. - wl_resource* const touch_resource_; - - DISALLOW_COPY_AND_ASSIGN(WaylandTouchDelegate); -}; - void touch_release(wl_client* client, wl_resource* resource) { wl_resource_destroy(resource); } @@ -4855,94 +4783,6 @@ nullptr); } -//////////////////////////////////////////////////////////////////////////////// -// input_timestamps_v1 interface: - -class WaylandInputTimestamps : public WaylandInputDelegate::Observer { - public: - WaylandInputTimestamps(wl_resource* resource, WaylandInputDelegate* delegate) - : resource_(resource), delegate_(delegate) { - delegate_->AddObserver(this); - } - - ~WaylandInputTimestamps() override { - if (delegate_) - delegate_->RemoveObserver(this); - } - - // Overridden from WaylandInputDelegate::Observer: - void OnDelegateDestroying(WaylandInputDelegate* delegate) override { - DCHECK(delegate_ == delegate); - delegate_ = nullptr; - } - void OnSendTimestamp(base::TimeTicks time_stamp) override { - timespec ts = (time_stamp - base::TimeTicks()).ToTimeSpec(); - - zwp_input_timestamps_v1_send_timestamp( - resource_, static_cast<uint64_t>(ts.tv_sec) >> 32, - ts.tv_sec & 0xffffffff, ts.tv_nsec); - } - - private: - wl_resource* const resource_; - WaylandInputDelegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(WaylandInputTimestamps); -}; - -void input_timestamps_destroy(struct wl_client* client, - struct wl_resource* resource) { - wl_resource_destroy(resource); -} - -const struct zwp_input_timestamps_v1_interface input_timestamps_implementation = - {input_timestamps_destroy}; - -//////////////////////////////////////////////////////////////////////////////// -// input_timestamps_manager_v1 interface: - -void input_timestamps_manager_destroy(struct wl_client* client, - struct wl_resource* resource) { - wl_resource_destroy(resource); -} - -template <typename T, typename D> -void input_timestamps_manager_get_timestamps(wl_client* client, - wl_resource* resource, - uint32_t id, - wl_resource* input_resource) { - wl_resource* input_timestamps_resource = - wl_resource_create(client, &zwp_input_timestamps_v1_interface, 1, id); - - auto input_timestamps = std::make_unique<WaylandInputTimestamps>( - input_timestamps_resource, - static_cast<WaylandInputDelegate*>( - static_cast<D*>(GetUserDataAs<T>(input_resource)->delegate()))); - - SetImplementation(input_timestamps_resource, &input_timestamps_implementation, - std::move(input_timestamps)); -} - -const struct zwp_input_timestamps_manager_v1_interface - input_timestamps_manager_implementation = { - input_timestamps_manager_destroy, - input_timestamps_manager_get_timestamps<Keyboard, - WaylandKeyboardDelegate>, - input_timestamps_manager_get_timestamps<Pointer, - WaylandPointerDelegate>, - input_timestamps_manager_get_timestamps<Touch, WaylandTouchDelegate>}; - -void bind_input_timestamps_manager(wl_client* client, - void* data, - uint32_t version, - uint32_t id) { - wl_resource* resource = wl_resource_create( - client, &zwp_input_timestamps_manager_v1_interface, 1, id); - - wl_resource_set_implementation( - resource, &input_timestamps_manager_implementation, nullptr, nullptr); -} - } // namespace ////////////////////////////////////////////////////////////////////////////////
diff --git a/components/exo/wayland/wayland_touch_delegate.cc b/components/exo/wayland/wayland_touch_delegate.cc new file mode 100644 index 0000000..af0087e --- /dev/null +++ b/components/exo/wayland/wayland_touch_delegate.cc
@@ -0,0 +1,83 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/exo/wayland/wayland_touch_delegate.h" + +#include <wayland-server-core.h> +#include <wayland-server-protocol-core.h> + +#include "components/exo/touch.h" +#include "components/exo/wayland/server_util.h" + +namespace exo { +namespace wayland { + +WaylandTouchDelegate::WaylandTouchDelegate(wl_resource* touch_resource) + : touch_resource_(touch_resource) {} + +void WaylandTouchDelegate::OnTouchDestroying(Touch* touch) { + delete this; +} + +bool WaylandTouchDelegate::CanAcceptTouchEventsForSurface( + Surface* surface) const { + wl_resource* surface_resource = GetSurfaceResource(surface); + // We can accept events for this surface if the client is the same as the + // touch resource. + return surface_resource && + wl_resource_get_client(surface_resource) == client(); +} +void WaylandTouchDelegate::OnTouchDown(Surface* surface, + base::TimeTicks time_stamp, + int id, + const gfx::PointF& location) { + wl_resource* surface_resource = GetSurfaceResource(surface); + DCHECK(surface_resource); + SendTimestamp(time_stamp); + wl_touch_send_down(touch_resource_, next_serial(), + TimeTicksToMilliseconds(time_stamp), surface_resource, id, + wl_fixed_from_double(location.x()), + wl_fixed_from_double(location.y())); +} +void WaylandTouchDelegate::OnTouchUp(base::TimeTicks time_stamp, int id) { + SendTimestamp(time_stamp); + wl_touch_send_up(touch_resource_, next_serial(), + TimeTicksToMilliseconds(time_stamp), id); +} +void WaylandTouchDelegate::OnTouchMotion(base::TimeTicks time_stamp, + int id, + const gfx::PointF& location) { + SendTimestamp(time_stamp); + wl_touch_send_motion(touch_resource_, TimeTicksToMilliseconds(time_stamp), id, + wl_fixed_from_double(location.x()), + wl_fixed_from_double(location.y())); +} +void WaylandTouchDelegate::OnTouchShape(int id, float major, float minor) { + if (wl_resource_get_version(touch_resource_) >= + WL_TOUCH_SHAPE_SINCE_VERSION) { + wl_touch_send_shape(touch_resource_, id, wl_fixed_from_double(major), + wl_fixed_from_double(minor)); + } +} +void WaylandTouchDelegate::OnTouchFrame() { + if (wl_resource_get_version(touch_resource_) >= + WL_TOUCH_FRAME_SINCE_VERSION) { + wl_touch_send_frame(touch_resource_); + } + wl_client_flush(client()); +} +void WaylandTouchDelegate::OnTouchCancel() { + wl_touch_send_cancel(touch_resource_); +} + +wl_client* WaylandTouchDelegate::client() const { + return wl_resource_get_client(touch_resource_); +} + +uint32_t WaylandTouchDelegate::next_serial() const { + return wl_display_next_serial(wl_client_get_display(client())); +} + +} // namespace wayland +} // namespace exo
diff --git a/components/exo/wayland/wayland_touch_delegate.h b/components/exo/wayland/wayland_touch_delegate.h new file mode 100644 index 0000000..c6b4298d --- /dev/null +++ b/components/exo/wayland/wayland_touch_delegate.h
@@ -0,0 +1,54 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_EXO_WAYLAND_WAYLAND_TOUCH_DELEGATE_H_ +#define COMPONENTS_EXO_WAYLAND_WAYLAND_TOUCH_DELEGATE_H_ + +#include "components/exo/touch_delegate.h" +#include "components/exo/wayland/wayland_input_delegate.h" + +struct wl_client; +struct wl_resource; + +namespace exo { +namespace wayland { + +// Touch delegate class that accepts events for surfaces owned by the same +// client as a touch resource. +class WaylandTouchDelegate : public WaylandInputDelegate, public TouchDelegate { + public: + explicit WaylandTouchDelegate(wl_resource* touch_resource); + + // Overridden from TouchDelegate: + void OnTouchDestroying(Touch* touch) override; + bool CanAcceptTouchEventsForSurface(Surface* surface) const override; + void OnTouchDown(Surface* surface, + base::TimeTicks time_stamp, + int id, + const gfx::PointF& location) override; + void OnTouchUp(base::TimeTicks time_stamp, int id) override; + void OnTouchMotion(base::TimeTicks time_stamp, + int id, + const gfx::PointF& location) override; + void OnTouchShape(int id, float major, float minor) override; + void OnTouchFrame() override; + void OnTouchCancel() override; + + private: + // The client who own this touch instance. + wl_client* client() const; + + // Returns the next serial to use for keyboard events. + uint32_t next_serial() const; + + // The touch resource associated with the touch. + wl_resource* const touch_resource_; + + DISALLOW_COPY_AND_ASSIGN(WaylandTouchDelegate); +}; + +} // namespace wayland +} // namespace exo + +#endif // COMPONENTS_EXO_WAYLAND_WAYLAND_TOUCH_DELEGATE_H_
diff --git a/components/exo/wayland/zwp_input_timestamps_manager.cc b/components/exo/wayland/zwp_input_timestamps_manager.cc new file mode 100644 index 0000000..e104eddf --- /dev/null +++ b/components/exo/wayland/zwp_input_timestamps_manager.cc
@@ -0,0 +1,116 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/exo/wayland/zwp_input_timestamps_manager.h" + +#include <input-timestamps-unstable-v1-server-protocol.h> +#include <wayland-server-core.h> +#include <wayland-server-protocol-core.h> + +#include "components/exo/keyboard.h" +#include "components/exo/pointer.h" +#include "components/exo/touch.h" +#include "components/exo/wayland/server_util.h" +#include "components/exo/wayland/wayland_input_delegate.h" +#include "components/exo/wayland/wayland_keyboard_delegate.h" +#include "components/exo/wayland/wayland_pointer_delegate.h" +#include "components/exo/wayland/wayland_touch_delegate.h" + +namespace exo { +namespace wayland { + +namespace { + +//////////////////////////////////////////////////////////////////////////////// +// input_timestamps_v1 interface: + +class WaylandInputTimestamps : public WaylandInputDelegate::Observer { + public: + WaylandInputTimestamps(wl_resource* resource, WaylandInputDelegate* delegate) + : resource_(resource), delegate_(delegate) { + delegate_->AddObserver(this); + } + + ~WaylandInputTimestamps() override { + if (delegate_) + delegate_->RemoveObserver(this); + } + + // Overridden from WaylandInputDelegate::Observer: + void OnDelegateDestroying(WaylandInputDelegate* delegate) override { + DCHECK(delegate_ == delegate); + delegate_ = nullptr; + } + void OnSendTimestamp(base::TimeTicks time_stamp) override { + timespec ts = (time_stamp - base::TimeTicks()).ToTimeSpec(); + + zwp_input_timestamps_v1_send_timestamp( + resource_, static_cast<uint64_t>(ts.tv_sec) >> 32, + ts.tv_sec & 0xffffffff, ts.tv_nsec); + } + + private: + wl_resource* const resource_; + WaylandInputDelegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(WaylandInputTimestamps); +}; + +void input_timestamps_destroy(struct wl_client* client, + struct wl_resource* resource) { + wl_resource_destroy(resource); +} + +const struct zwp_input_timestamps_v1_interface input_timestamps_implementation = + {input_timestamps_destroy}; + +//////////////////////////////////////////////////////////////////////////////// +// input_timestamps_manager_v1 interface: + +void input_timestamps_manager_destroy(struct wl_client* client, + struct wl_resource* resource) { + wl_resource_destroy(resource); +} + +template <typename T, typename D> +void input_timestamps_manager_get_timestamps(wl_client* client, + wl_resource* resource, + uint32_t id, + wl_resource* input_resource) { + wl_resource* input_timestamps_resource = + wl_resource_create(client, &zwp_input_timestamps_v1_interface, 1, id); + + auto input_timestamps = std::make_unique<WaylandInputTimestamps>( + input_timestamps_resource, + static_cast<WaylandInputDelegate*>( + static_cast<D*>(GetUserDataAs<T>(input_resource)->delegate()))); + + SetImplementation(input_timestamps_resource, &input_timestamps_implementation, + std::move(input_timestamps)); +} + +const struct zwp_input_timestamps_manager_v1_interface + input_timestamps_manager_implementation = { + input_timestamps_manager_destroy, + input_timestamps_manager_get_timestamps<Keyboard, + WaylandKeyboardDelegate>, + input_timestamps_manager_get_timestamps<Pointer, + WaylandPointerDelegate>, + input_timestamps_manager_get_timestamps<Touch, WaylandTouchDelegate>}; + +} // namespace + +void bind_input_timestamps_manager(wl_client* client, + void* data, + uint32_t version, + uint32_t id) { + wl_resource* resource = wl_resource_create( + client, &zwp_input_timestamps_manager_v1_interface, 1, id); + + wl_resource_set_implementation( + resource, &input_timestamps_manager_implementation, nullptr, nullptr); +} + +} // namespace wayland +} // namespace exo
diff --git a/components/exo/wayland/zwp_input_timestamps_manager.h b/components/exo/wayland/zwp_input_timestamps_manager.h new file mode 100644 index 0000000..e55d7c78 --- /dev/null +++ b/components/exo/wayland/zwp_input_timestamps_manager.h
@@ -0,0 +1,23 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_EXO_WAYLAND_ZWP_INPUT_TIMESTAMPS_MANAGER_H_ +#define COMPONENTS_EXO_WAYLAND_ZWP_INPUT_TIMESTAMPS_MANAGER_H_ + +#include <stdint.h> + +struct wl_client; + +namespace exo { +namespace wayland { + +void bind_input_timestamps_manager(wl_client* client, + void* data, + uint32_t version, + uint32_t id); + +} // namespace wayland +} // namespace exo + +#endif // COMPONENTS_EXO_WAYLAND_ZWP_INPUT_TIMESTAMPS_MANAGER_H_
diff --git a/components/gwp_asan/client/BUILD.gn b/components/gwp_asan/client/BUILD.gn index f98a82e6..8f7b7ea 100644 --- a/components/gwp_asan/client/BUILD.gn +++ b/components/gwp_asan/client/BUILD.gn
@@ -5,6 +5,8 @@ component("client") { output_name = "gwp_asan_client" sources = [ + "crash_key.cc", + "crash_key.h", "export.h", "gwp_asan.cc", "gwp_asan.h", @@ -18,6 +20,7 @@ deps = [ "//base", "//base/allocator:buildflags", + "//components/crash/core/common:crash_key", "//components/gwp_asan/common", ] } @@ -31,6 +34,7 @@ ":client", "//base/allocator:buildflags", "//base/test:test_support", + "//components/crash/core/common:crash_key", "//components/gwp_asan/common", "//testing/gtest", ]
diff --git a/components/gwp_asan/client/DEPS b/components/gwp_asan/client/DEPS new file mode 100644 index 0000000..90e574c --- /dev/null +++ b/components/gwp_asan/client/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+components/crash/core/common/crash_key.h", +]
diff --git a/components/gwp_asan/client/crash_key.cc b/components/gwp_asan/client/crash_key.cc new file mode 100644 index 0000000..d4de6e7 --- /dev/null +++ b/components/gwp_asan/client/crash_key.cc
@@ -0,0 +1,22 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +#include "components/gwp_asan/client/crash_key.h" + +#include "base/debug/crash_logging.h" +#include "base/strings/stringprintf.h" +#include "components/crash/core/common/crash_key.h" +#include "components/gwp_asan/common/crash_key_name.h" + +namespace gwp_asan { +namespace internal { + +void RegisterAllocatorAddress(void* gpa_ptr) { + static crash_reporter::CrashKeyString<24> gpa_crash_key(kGpaCrashKey); + gpa_crash_key.Set( + base::StringPrintf("%zx", reinterpret_cast<uintptr_t>(gpa_ptr))); +} + +} // namespace internal +} // namespace gwp_asan
diff --git a/components/gwp_asan/client/crash_key.h b/components/gwp_asan/client/crash_key.h new file mode 100644 index 0000000..4e2209f --- /dev/null +++ b/components/gwp_asan/client/crash_key.h
@@ -0,0 +1,19 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_GWP_ASAN_CLIENT_CRASH_KEY_H_ +#define COMPONENTS_GWP_ASAN_CLIENT_CRASH_KEY_H_ + +namespace gwp_asan { +namespace internal { + +// Registers a crash key that both signals to the crash handler that GWP-ASan +// has been enabled and also where to find the GuardedPageAllocator for this +// process. +void RegisterAllocatorAddress(void* gpa_ptr); + +} // namespace internal +} // namespace gwp_asan + +#endif // COMPONENTS_GWP_ASAN_CLIENT_CRASH_KEY_H_
diff --git a/components/gwp_asan/client/sampling_allocator_shims.cc b/components/gwp_asan/client/sampling_allocator_shims.cc index 39db16b..ae35b91b 100644 --- a/components/gwp_asan/client/sampling_allocator_shims.cc +++ b/components/gwp_asan/client/sampling_allocator_shims.cc
@@ -16,6 +16,7 @@ #include "base/process/process_metrics.h" #include "base/rand_util.h" #include "build/build_config.h" +#include "components/gwp_asan/client/crash_key.h" #include "components/gwp_asan/client/export.h" #include "components/gwp_asan/common/guarded_page_allocator.h" @@ -231,6 +232,7 @@ void InstallAllocatorHooks(size_t num_pages, size_t sampling_frequency) { #if BUILDFLAG(USE_ALLOCATOR_SHIM) GetGpa().Init(num_pages); + RegisterAllocatorAddress(&GetGpa()); sampling_state.Init(sampling_frequency); base::allocator::InsertAllocatorDispatch(&g_allocator_dispatch); #else
diff --git a/components/gwp_asan/client/sampling_allocator_shims_unittest.cc b/components/gwp_asan/client/sampling_allocator_shims_unittest.cc index 7b5dd857..f5752ef3 100644 --- a/components/gwp_asan/client/sampling_allocator_shims_unittest.cc +++ b/components/gwp_asan/client/sampling_allocator_shims_unittest.cc
@@ -10,10 +10,13 @@ #include "base/allocator/allocator_shim.h" #include "base/allocator/buildflags.h" #include "base/process/process_metrics.h" +#include "base/strings/string_number_conversions.h" #include "base/test/gtest_util.h" #include "base/test/multiprocess_test.h" #include "base/test/test_timeouts.h" #include "build/build_config.h" +#include "components/crash/core/common/crash_key.h" +#include "components/gwp_asan/common/crash_key_name.h" #include "components/gwp_asan/common/guarded_page_allocator.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/multiprocess_func_list.h" @@ -37,6 +40,7 @@ constexpr size_t kLoopIterations = kSamplingFrequency * 32; constexpr int kSuccess = 0; +constexpr int kFailure = 1; class SamplingAllocatorShimsTest : public base::MultiProcessTest { protected: @@ -157,13 +161,30 @@ free(alloc); } - return kSuccess + 1; + return kFailure; } TEST_F(SamplingAllocatorShimsTest, Calloc) { runTest("Calloc"); } +MULTIPROCESS_TEST_MAIN(CrashKey) { + InstallAllocatorHooks(GuardedPageAllocator::kGpaMaxPages, kSamplingFrequency); + + std::string crash_key = crash_reporter::GetCrashKeyValue(kGpaCrashKey); + + uint64_t value; + if (!base::HexStringToUInt64(crash_key, &value) || + value != reinterpret_cast<uintptr_t>(&GetGpaForTesting())) + return kFailure; + + return kSuccess; +} + +TEST_F(SamplingAllocatorShimsTest, CrashKey) { + runTest("CrashKey"); +} + } // namespace } // namespace internal
diff --git a/components/gwp_asan/common/BUILD.gn b/components/gwp_asan/common/BUILD.gn index 82d0ff8..310eb53 100644 --- a/components/gwp_asan/common/BUILD.gn +++ b/components/gwp_asan/common/BUILD.gn
@@ -6,6 +6,7 @@ static_library("common") { sources = [ + "crash_key_name.h", "guarded_page_allocator.cc", "guarded_page_allocator.h", "guarded_page_allocator_win.cc",
diff --git a/components/gwp_asan/common/crash_key_name.h b/components/gwp_asan/common/crash_key_name.h new file mode 100644 index 0000000..90d18a62f --- /dev/null +++ b/components/gwp_asan/common/crash_key_name.h
@@ -0,0 +1,18 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_GWP_ASAN_COMMON_CRASH_KEY_NAME_H_ +#define COMPONENTS_GWP_ASAN_COMMON_CRASH_KEY_NAME_H_ + +namespace gwp_asan { +namespace internal { + +// The name of the crash key used to convey the address of the +// GuardedPageAllocator to the crash handler. +const char kGpaCrashKey[] = "guarded-page-allocator-address"; + +} // namespace internal +} // namespace gwp_asan + +#endif // COMPONENTS_GWP_ASAN_COMMON_CRASH_KEY_NAME_H_
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn index 43c5967..92d4ef2a 100644 --- a/components/viz/common/BUILD.gn +++ b/components/viz/common/BUILD.gn
@@ -89,6 +89,8 @@ "gl_helper.h", "gl_helper_scaling.cc", "gl_helper_scaling.h", + "gl_i420_converter.cc", + "gl_i420_converter.h", "gl_scaler.cc", "gl_scaler.h", "gpu/context_cache_controller.cc", @@ -237,6 +239,8 @@ "frame_sinks/copy_output_util_unittest.cc", "frame_sinks/delay_based_time_source_unittest.cc", "gl_helper_unittest.cc", + "gl_i420_converter_pixeltest.cc", + "gl_i420_converter_unittest.cc", "gl_scaler_overscan_pixeltest.cc", "gl_scaler_pixeltest.cc", "gl_scaler_shader_pixeltest.cc",
diff --git a/components/viz/common/gl_i420_converter.cc b/components/viz/common/gl_i420_converter.cc new file mode 100644 index 0000000..3bfc042 --- /dev/null +++ b/components/viz/common/gl_i420_converter.cc
@@ -0,0 +1,208 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/common/gl_i420_converter.h" + +#include <utility> + +#include "components/viz/common/gpu/context_provider.h" + +namespace viz { + +GLI420Converter::GLI420Converter( + scoped_refptr<ContextProvider> context_provider) + : GLI420Converter(std::move(context_provider), true) {} + +GLI420Converter::GLI420Converter( + scoped_refptr<ContextProvider> context_provider, + bool allow_mrt_path) + : context_provider_(std::move(context_provider)), + step1_(context_provider_), + step2_(context_provider_) { + context_provider_->AddObserver(this); + if (!allow_mrt_path || step1_.GetMaxDrawBuffersSupported() < 2) { + step3_ = std::make_unique<GLScaler>(context_provider_); + step4_ = std::make_unique<GLScaler>(context_provider_); + } +} + +GLI420Converter::~GLI420Converter() { + OnContextLost(); // Free context-related resources. +} + +bool GLI420Converter::Configure(const Parameters& params) { + Parameters step1_params = params; + if (!step1_params.output_color_space.IsValid()) { + step1_params.output_color_space = gfx::ColorSpace::CreateREC709(); + } + + // Configure the "step 1" scaler. + if (is_using_mrt_path()) { + step1_params.export_format = Parameters::ExportFormat::NV61; + DCHECK_EQ(step1_params.swizzle[0], params.swizzle[0]); + step1_params.swizzle[1] = GL_RGBA; // Don't swizzle 2nd rendering target. + } else { + step1_params.export_format = Parameters::ExportFormat::INTERLEAVED_QUADS; + step1_params.swizzle[0] = GL_RGBA; // Will swizzle in steps 2-4. + } + if (!step1_.Configure(step1_params)) { + return false; + } + + // Configure the "step 2" scaler (and steps 3 and 4 for the non-MRT path) that + // further transform the output from the "step 1" scaler to produce the final + // outputs. + Parameters step2_params; + step2_params.scale_to = gfx::Vector2d(1, 1); + step2_params.source_color_space = step1_params.output_color_space; + step2_params.output_color_space = step1_params.output_color_space; + // Use FAST quality, a single bilinear pass, because there will either be no + // scaling or exactly 50% scaling. + step2_params.quality = Parameters::Quality::FAST; + step2_params.swizzle[0] = params.swizzle[0]; + if (is_using_mrt_path()) { + // NV61 provides half-width and full-height U/V. I420 U/V planes are + // half-width and half-height. So, scale Y by 50%. + step2_params.scale_from = gfx::Vector2d(1, 2); + step2_params.export_format = + Parameters::ExportFormat::DEINTERLEAVE_PAIRWISE; + step2_params.swizzle[1] = step2_params.swizzle[0]; + if (!step2_.Configure(step2_params)) { + return false; + } + } else { + // Extract a full-size Y plane from the interleaved YUVA from step 1. + step2_params.scale_from = gfx::Vector2d(1, 1); + step2_params.export_format = Parameters::ExportFormat::CHANNEL_0; + if (!step2_.Configure(step2_params)) { + return false; + } + // Extract half-size U/V planes from the interleaved YUVA from step 1. + step2_params.scale_from = gfx::Vector2d(2, 2); + step2_params.export_format = Parameters::ExportFormat::CHANNEL_1; + if (!step3_->Configure(step2_params)) { + return false; + } + step2_params.export_format = Parameters::ExportFormat::CHANNEL_2; + if (!step4_->Configure(step2_params)) { + return false; + } + } + + params_ = params; + return true; +} + +bool GLI420Converter::Convert(GLuint src_texture, + const gfx::Size& src_texture_size, + const gfx::Vector2d& src_offset, + const gfx::Rect& output_rect, + const GLuint yuv_textures[3]) { + DCHECK_EQ(output_rect.x() % 8, 0); + DCHECK_EQ(output_rect.width() % 8, 0); + DCHECK_EQ(output_rect.y() % 2, 0); + DCHECK_EQ(output_rect.height() % 2, 0); + + if (!context_provider_) { + return false; + } + + if (is_using_mrt_path()) { + const gfx::Rect luma_output_rect(output_rect.x() / 4, output_rect.y(), + output_rect.width() / 4, + output_rect.height()); + EnsureIntermediateTextureDefined(luma_output_rect.size()); + const gfx::Rect chroma_output_rect( + gfx::Size(luma_output_rect.width() / 2, luma_output_rect.height() / 2)); + return (step1_.ScaleToMultipleOutputs( + src_texture, src_texture_size, src_offset, yuv_textures[0], + intermediate_texture_, luma_output_rect) && + step2_.ScaleToMultipleOutputs(intermediate_texture_, + intermediate_texture_size_, + gfx::Vector2d(), yuv_textures[1], + yuv_textures[2], chroma_output_rect)); + } + + // Non-MRT path: + EnsureIntermediateTextureDefined(output_rect.size()); + const gfx::Rect luma_output_rect(0, 0, output_rect.width() / 4, + output_rect.height()); + const gfx::Rect chroma_output_rect(0, 0, luma_output_rect.width() / 2, + luma_output_rect.height() / 2); + return (step1_.Scale(src_texture, src_texture_size, src_offset, + intermediate_texture_, output_rect) && + step2_.Scale(intermediate_texture_, intermediate_texture_size_, + gfx::Vector2d(), yuv_textures[0], luma_output_rect) && + step3_->Scale(intermediate_texture_, intermediate_texture_size_, + gfx::Vector2d(), yuv_textures[1], chroma_output_rect) && + step4_->Scale(intermediate_texture_, intermediate_texture_size_, + gfx::Vector2d(), yuv_textures[2], chroma_output_rect)); +} + +// static +gfx::Rect GLI420Converter::ToAlignedRect(const gfx::Rect& rect) { + // Origin coordinates: FLOOR(...) + const int aligned_x = + ((rect.x() < 0) ? ((rect.x() - 7) / 8) : (rect.x() / 8)) * 8; + const int aligned_y = + ((rect.y() < 0) ? ((rect.y() - 1) / 2) : (rect.y() / 2)) * 2; + // Span coordinates: CEIL(...) + const int aligned_right = + ((rect.right() < 0) ? (rect.right() / 8) : ((rect.right() + 7) / 8)) * 8; + const int aligned_bottom = + ((rect.bottom() < 0) ? (rect.bottom() / 2) : ((rect.bottom() + 1) / 2)) * + 2; + return gfx::Rect(aligned_x, aligned_y, aligned_right - aligned_x, + aligned_bottom - aligned_y); +} + +// static +bool GLI420Converter::ParametersAreEquivalent(const Parameters& a, + const Parameters& b) { + const auto Resolve = [](Parameters params) { + // Per header comments, if an invalid output_color_space is specified, use + // REC709. + if (!params.output_color_space.IsValid()) { + params.output_color_space = gfx::ColorSpace::CreateREC709(); + } + // Both of these fields are overwritten, in Configure(), whether the MRT + // path is going to be used or not. So, for the purposes of "equivalence," + // just set these like the MRT path would. + params.export_format = Parameters::ExportFormat::NV61; + params.swizzle[1] = GL_RGBA; + return params; + }; + return GLScaler::ParametersAreEquivalent(Resolve(a), Resolve(b)); +} + +void GLI420Converter::EnsureIntermediateTextureDefined( + const gfx::Size& required) { + if (intermediate_texture_size_ == required) { + return; + } + auto* const gl = context_provider_->ContextGL(); + if (intermediate_texture_ == 0) { + gl->GenTextures(1, &intermediate_texture_); + } + gl->BindTexture(GL_TEXTURE_2D, intermediate_texture_); + gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, required.width(), required.height(), + 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + intermediate_texture_size_ = required; +} + +void GLI420Converter::OnContextLost() { + if (intermediate_texture_ != 0) { + if (auto* gl = context_provider_->ContextGL()) { + gl->DeleteTextures(1, &intermediate_texture_); + } + intermediate_texture_ = 0; + intermediate_texture_size_ = gfx::Size(); + } + if (context_provider_) { + context_provider_->RemoveObserver(this); + context_provider_ = nullptr; + } +} + +} // namespace viz
diff --git a/components/viz/common/gl_i420_converter.h b/components/viz/common/gl_i420_converter.h new file mode 100644 index 0000000..779445a --- /dev/null +++ b/components/viz/common/gl_i420_converter.h
@@ -0,0 +1,194 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_COMMON_GL_I420_CONVERTER_H_ +#define COMPONENTS_VIZ_COMMON_GL_I420_CONVERTER_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/memory/scoped_refptr.h" +#include "components/viz/common/gl_scaler.h" +#include "components/viz/common/gpu/context_lost_observer.h" +#include "components/viz/common/viz_common_export.h" +#include "ui/gfx/color_space.h" +#include "ui/gfx/geometry/size.h" + +namespace gfx { +class Rect; +class Vector2d; +} // namespace gfx + +namespace viz { + +class ContextProvider; + +// A convenience wrapper around GLScaler that also reformats the scaler's output +// from interleaved RGBA to I420 planes. The I420 format consists of three +// planes of image data: the Y (luma) plane at full size, plus U and V (chroma) +// planes at half-width and half-height. There are two possible modes of +// operation (auto-detected at runtime): +// +// The faster, multiple rendering target (MRT) path: If the platform supports +// MRTs (most of the GPUs in use today), scaling and conversion is a two step +// process: +// +// Step 1: Produce NV61 format output, a luma plane and a UV-interleaved +// image. The luma plane is the same as the desired I420 luma plane. Note, +// that the UV image is of half-width but not yet half-height. +// +// (interleaved quads) +// RGBA RGBA RGBA RGBA RGBA RGBA RGBA RGBA +// RGBA RGBA RGBA RGBA RGBA RGBA RGBA RGBA +// RGBA RGBA RGBA RGBA RGBA RGBA RGBA RGBA +// RGBA RGBA RGBA RGBA RGBA RGBA RGBA RGBA +// | +// | (luma plane) (chroma, interleaved) +// | YYYY YYYY UVUV UVUV +// +---> { YYYY YYYY + UVUV UVUV } +// YYYY YYYY UVUV UVUV +// YYYY YYYY UVUV UVUV +// +// Step 2: Derives the two I420 chroma planes from the UV-interleaved image +// from Step 1. This step separates the U and V pixels into separate planes, +// and also scales the height by half. This produces the desired I420 chroma +// planes. +// +// (chroma, interleaved) (two chroma planes) +// UVUV UVUV +// UVUV UVUV --> { UUUU + VVVV } +// UVUV UVUV UUUU VVVV +// UVUV UVUV +// +// The non-MRT path: For platforms that can only render to a single target at a +// time. This first scales the source to its final size and color-converts, +// transforming an RGBA input into a YUVA output. Then, it scans the YUVA image +// three times to generate each of the Y+U+V planes. +// +// Texture packing: OpenGLES2 treats all of the input and output textures as +// RGBA format. See comments for the Convert() method, which explains how the +// planar image data is packed into GL_RGBA textures, how the output textures +// should be sized, and why there are alignment requirements when specifying the +// output rect. +class VIZ_COMMON_EXPORT GLI420Converter : public ContextLostObserver { + public: + // GLI420Converter uses the exact same parameters as GLScaler. + using Parameters = GLScaler::Parameters; + + explicit GLI420Converter(scoped_refptr<ContextProvider> context_provider); + ~GLI420Converter() final; + + // Returns true if the GL context provides the necessary support for enabling + // precise color management (see Parameters::enable_precise_color_management). + bool SupportsPreciseColorManagement() const { + return step1_.SupportsPreciseColorManagement(); + } + + // [Re]Configure the converter with the given |new_params|. Returns true on + // success, or false on failure. If |new_params| does not specify an + // |output_color_space|, it will be default to REC709. + bool Configure(const Parameters& new_params) WARN_UNUSED_RESULT; + + // Returns the currently-configured and resolved Parameters. Results are + // undefined if Configure() has never been called successfully. + const Parameters& params() const { return params_; } + + // Scales a portion of |src_texture|, then format-converts it to three I420 + // planes, placing the results into |yuv_textures| at offset (0, 0). Returns + // true to indicate success, or false if this GLI420Converter is not valid. + // + // |src_texture_size| is the full, allocated size of the |src_texture|. This + // is required for computing texture coordinate transforms (and only because + // the OpenGL ES 2.0 API lacks the ability to query this info). + // + // |src_offset| is the offset in the source texture corresponding to point + // (0,0) in the source/output coordinate spaces. This prevents the need for + // extra texture copies just to re-position the source coordinate system. + // + // |aligned_output_rect| selects the region to draw (in the scaled, not the + // source, coordinate space). This is used to save work in cases where only a + // portion needs to be re-scaled. Because of the way the planar image data is + // packed in the output textures, the output rect's coordinates must be + // aligned (see ToAlignedRect() below). + // + // The |yuv_textures| are packed with planar data, meaning that each RGBA quad + // contains four pixel values: R is pixel 0, G is pixel 1, and so on. This + // makes it trivial to read-back the textures from a pixel buffer as a + // sequence of unsigned bytes. Thus, the output texture for the Y plane should + // be defined as GL_RGBA and be at least 1/4 the width of that specified in + // |aligned_output_rect|. Similarly, the output textures for the U and V + // planes should be defined as GL_RGBA and have at least 1/8 the width and 1/2 + // the height of |aligned_output_rect|. + // + // WARNING: The output will always be placed at (0, 0) in the output textures, + // and not at |aligned_output_rect.origin()|. + // + // Note that the |src_texture| will have the min/mag filter set to GL_LINEAR + // and wrap_s/t set to CLAMP_TO_EDGE in this call. + bool Convert(GLuint src_texture, + const gfx::Size& src_texture_size, + const gfx::Vector2d& src_offset, + const gfx::Rect& aligned_output_rect, + const GLuint yuv_textures[3]); + + // Returns the smallest Rect that encloses |rect| and lays on aligned + // boundaries, as required by the |aligned_output_rect| argument passed to + // Convert(). The horizontal coordinates will always be a multiple of 8, and + // the vertical coordinates a multiple of 2. + static gfx::Rect ToAlignedRect(const gfx::Rect& rect); + + // Returns true if configuring a GLI420Converter with either |a| or |b| will + // produce identical behaviors and results. + static bool ParametersAreEquivalent(const Parameters& a, const Parameters& b); + + private: + friend class GLI420ConverterPixelTest; + + GLI420Converter(scoped_refptr<ContextProvider> context_provider, + bool allow_mrt_path); + + bool is_using_mrt_path() const { return !step3_; } + + // Creates or re-defines the intermediate texture, to ensure a texture of the + // given |required| size is defined. + void EnsureIntermediateTextureDefined(const gfx::Size& required); + + // ContextLostObserver implementation. + void OnContextLost() final; + + // The provider of the GL context. This is non-null while the GL context is + // valid and GLI420Converter is observing for context loss. + scoped_refptr<ContextProvider> context_provider_; + + // Scales the source content and produces either: + // * MRT path: NV61-format output in two textures. + // * Non-MRT path: YUVA interleaved output in one texture. + GLScaler step1_; + + // Holds the results from executing the first-stage |scaler_|, and is read by + // the other scalers: + // * MRT path: This holds the UV-interleaved data (2nd rendering target). + // * Non-MRT path: The scaled YUVA interleaved data. + GLuint intermediate_texture_ = 0; + gfx::Size intermediate_texture_size_; + + // Step 2 operation using the |intermediate_texture_| as input: + // * MRT path: Separates-out the U and V planes (and scales height by half). + // * Non-MRT path: Extracts the luma plane. + GLScaler step2_; + + // Steps 3 and 4 are used by the non-MRT path only, to extract the two chroma + // planes from |intermediate_texture_|. + std::unique_ptr<GLScaler> step3_; + std::unique_ptr<GLScaler> step4_; + + // The Parameters that were provided to the last successful Configure() call. + Parameters params_; + + DISALLOW_COPY_AND_ASSIGN(GLI420Converter); +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_COMMON_GL_I420_CONVERTER_H_
diff --git a/components/viz/common/gl_i420_converter_pixeltest.cc b/components/viz/common/gl_i420_converter_pixeltest.cc new file mode 100644 index 0000000..d6e27e9 --- /dev/null +++ b/components/viz/common/gl_i420_converter_pixeltest.cc
@@ -0,0 +1,127 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/common/gl_i420_converter.h" + +#include "cc/test/pixel_test.h" +#include "cc/test/pixel_test_utils.h" +#include "components/viz/common/gl_scaler_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkColor.h" + +namespace viz { + +class GLI420ConverterPixelTest : public cc::PixelTest, + public GLScalerTestUtil, + public testing::WithParamInterface<bool> { + public: + bool allow_mrt_path() const { return GetParam(); } + GLI420Converter* converter() const { return converter_.get(); } + + GLuint CreateTexture(const gfx::Size& size) { + return texture_helper_->CreateTexture(size); + } + + GLuint UploadTexture(const SkBitmap& bitmap) { + return texture_helper_->UploadTexture(bitmap); + } + + SkBitmap DownloadTexture(GLuint texture, const gfx::Size& size) { + return texture_helper_->DownloadTexture(texture, size); + } + + protected: + void SetUp() final { + cc::PixelTest::SetUpGLWithoutRenderer(false); + converter_.reset(new GLI420Converter(context_provider(), allow_mrt_path())); + texture_helper_ = std::make_unique<GLScalerTestTextureHelper>( + context_provider()->ContextGL()); + } + + void TearDown() final { + texture_helper_.reset(); + converter_.reset(); + cc::PixelTest::TearDown(); + } + + private: + std::unique_ptr<GLI420Converter> converter_; + std::unique_ptr<GLScalerTestTextureHelper> texture_helper_; +}; + +// Note: This test is pretty much the same as +// GLScalerPixelTest.Example_ScaleAndExportForScreenVideoCapture. The goal of +// this pixel test is to just confirm that everything internal to +// GLI420Converter has been plumbed-through correctly. +TEST_P(GLI420ConverterPixelTest, ScaleAndConvert) { + // These parameters have been chosen based on: 1) overriding defaults, to + // confirm Parameters plumbing; and 2) typical operation on most platforms + // (e.g., flipped source textures, the need to swizzle outputs, etc.). + GLI420Converter::Parameters params; + params.scale_from = gfx::Vector2d(2160, 1440); + params.scale_to = gfx::Vector2d(1280, 720); + params.source_color_space = DefaultRGBColorSpace(); + params.output_color_space = DefaultYUVColorSpace(); + params.enable_precise_color_management = + converter()->SupportsPreciseColorManagement(); + params.quality = GLScaler::Parameters::Quality::GOOD; + params.is_flipped_source = true; + params.flip_output = true; + params.swizzle[0] = GL_BGRA_EXT; // Swizzle for readback. + ASSERT_TRUE(converter()->Configure(params)); + + constexpr gfx::Size kSourceSize = gfx::Size(2160, 1440); + const GLuint src_texture = UploadTexture( + CreateVerticallyFlippedBitmap(CreateSMPTETestImage(kSourceSize))); + constexpr gfx::Rect kOutputRect = gfx::Rect(0, 0, 1280, 720); + ASSERT_EQ(kOutputRect, GLI420Converter::ToAlignedRect(kOutputRect)); + SkBitmap expected = CreateSMPTETestImage(kOutputRect.size()); + ConvertBitmapToYUV(&expected); + + // While the output size is 1280x720, the packing of 4 pixels into one RGBA + // quad means that the texture width must be divided by 4 (for the Y + // plane). Then, the other two planes are half the size of the Y plane in both + // dimensions. + const gfx::Size y_plane_size(kOutputRect.width() / 4, kOutputRect.height()); + const gfx::Size chroma_plane_size(y_plane_size.width() / 2, + y_plane_size.height() / 2); + const GLuint yuv_textures[3] = {CreateTexture(y_plane_size), + CreateTexture(chroma_plane_size), + CreateTexture(chroma_plane_size)}; + + ASSERT_TRUE(converter()->Convert(src_texture, kSourceSize, gfx::Vector2d(), + kOutputRect, yuv_textures)); + + // Download the textures, and unpack them into an interleaved YUV bitmap, for + // comparison against the |expected| rendition. + SkBitmap actual = AllocateRGBABitmap(kOutputRect.size()); + actual.eraseColor(SkColorSetARGB(0xff, 0x00, 0x80, 0x80)); + SkBitmap y_plane = DownloadTexture(yuv_textures[0], y_plane_size); + SwizzleBitmap(&y_plane); + UnpackPlanarBitmap(y_plane, 0, &actual); + SkBitmap u_plane = DownloadTexture(yuv_textures[1], chroma_plane_size); + SwizzleBitmap(&u_plane); + UnpackPlanarBitmap(u_plane, 1, &actual); + SkBitmap v_plane = DownloadTexture(yuv_textures[2], chroma_plane_size); + SwizzleBitmap(&v_plane); + UnpackPlanarBitmap(v_plane, 2, &actual); + + // Provide generous error limits to account for the chroma subsampling in the + // |actual| result when compared to the perfect |expected| rendition. + constexpr float kAvgAbsoluteErrorLimit = 16.f; + constexpr int kMaxAbsoluteErrorLimit = 0x80; + EXPECT_TRUE(cc::FuzzyPixelComparator(false, 100.f, 0.f, + kAvgAbsoluteErrorLimit, + kMaxAbsoluteErrorLimit, 0) + .Compare(expected, actual)) + << "\nActual: " << cc::GetPNGDataUrl(actual) + << "\nExpected: " << cc::GetPNGDataUrl(expected); +} + +// Run the tests twice, once disallowing use of the MRT path, and once allowing +// its use (auto-detecting whether the current platform supports it). +INSTANTIATE_TEST_CASE_P(, GLI420ConverterPixelTest, testing::Bool()); + +} // namespace viz
diff --git a/components/viz/common/gl_i420_converter_unittest.cc b/components/viz/common/gl_i420_converter_unittest.cc new file mode 100644 index 0000000..9fd42188 --- /dev/null +++ b/components/viz/common/gl_i420_converter_unittest.cc
@@ -0,0 +1,77 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/common/gl_i420_converter.h" + +#include <string> + +#include "base/strings/stringprintf.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkRect.h" +#include "ui/gfx/geometry/rect.h" + +namespace viz { +namespace { + +// Syntactic convenience: It's clearer to express the tests in terms of +// left+top+right+bottom coordinates, rather than gfx::Rect's x+y+width+height +// scheme. +SkIRect ToAlignedRect(const SkIRect& rect) { + const gfx::Rect& result = GLI420Converter::ToAlignedRect( + gfx::Rect(rect.fLeft, rect.fTop, rect.fRight - rect.fLeft, + rect.fBottom - rect.fTop)); + return SkIRect{result.x(), result.y(), result.right(), result.bottom()}; +} + +// Logging convenience. +std::string ToString(const SkIRect& rect) { + return base::StringPrintf("%d,%d~%d%d", rect.fLeft, rect.fTop, rect.fRight, + rect.fBottom); +} + +TEST(GLI420ConverterTest, AlignsOutputRects) { + struct { + SkIRect expected; + SkIRect input; + } kTestCases[] = { + {SkIRect{0, 0, 0, 0}, SkIRect{0, 0, 0, 0}}, + + {SkIRect{-16, 0, 16, 4}, SkIRect{-9, 0, 16, 4}}, + {SkIRect{-8, 0, 16, 4}, SkIRect{-8, 0, 16, 4}}, + {SkIRect{-8, 0, 16, 4}, SkIRect{-7, 0, 16, 4}}, + {SkIRect{-8, 0, 16, 4}, SkIRect{-1, 0, 16, 4}}, + {SkIRect{0, 0, 16, 4}, SkIRect{0, 0, 16, 4}}, + {SkIRect{0, 0, 16, 4}, SkIRect{1, 0, 16, 4}}, + {SkIRect{0, 0, 16, 4}, SkIRect{7, 0, 16, 4}}, + {SkIRect{8, 0, 16, 4}, SkIRect{8, 0, 16, 4}}, + {SkIRect{8, 0, 16, 4}, SkIRect{9, 0, 16, 4}}, + + {SkIRect{0, -4, 16, 4}, SkIRect{0, -3, 16, 4}}, + {SkIRect{0, -2, 16, 4}, SkIRect{0, -2, 16, 4}}, + {SkIRect{0, -2, 16, 4}, SkIRect{0, -1, 16, 4}}, + {SkIRect{0, 0, 16, 4}, SkIRect{0, 0, 16, 4}}, + {SkIRect{0, 0, 16, 4}, SkIRect{0, 1, 16, 4}}, + {SkIRect{0, 2, 16, 4}, SkIRect{0, 2, 16, 4}}, + {SkIRect{0, 2, 16, 4}, SkIRect{0, 3, 16, 4}}, + + {SkIRect{0, 0, 8, 2}, SkIRect{0, 0, 1, 2}}, + {SkIRect{0, 0, 8, 2}, SkIRect{0, 0, 7, 2}}, + {SkIRect{0, 0, 8, 2}, SkIRect{0, 0, 8, 2}}, + {SkIRect{0, 0, 16, 2}, SkIRect{0, 0, 9, 2}}, + + {SkIRect{0, 0, 8, 2}, SkIRect{0, 0, 8, 1}}, + {SkIRect{0, 0, 8, 2}, SkIRect{0, 0, 8, 2}}, + {SkIRect{0, 0, 8, 4}, SkIRect{0, 0, 8, 3}}, + {SkIRect{0, 0, 8, 4}, SkIRect{0, 0, 8, 4}}, + }; + + for (const auto& test_case : kTestCases) { + EXPECT_EQ(test_case.expected, ToAlignedRect(test_case.input)) + << "ToAlignedRect(" << ToString(test_case.input) << ") should be " + << ToString(test_case.expected); + } +} + +} // namespace +} // namespace viz
diff --git a/components/viz/common/gl_scaler.cc b/components/viz/common/gl_scaler.cc index b65c2335..24f4088 100644 --- a/components/viz/common/gl_scaler.cc +++ b/components/viz/common/gl_scaler.cc
@@ -344,6 +344,36 @@ to.y()); } +// static +bool GLScaler::ParametersAreEquivalent(const Parameters& a, + const Parameters& b) { + if (!ParametersHasSameScaleRatio(a, b.scale_from, b.scale_to) || + a.enable_precise_color_management != b.enable_precise_color_management || + a.quality != b.quality || a.is_flipped_source != b.is_flipped_source || + a.flip_output != b.flip_output || a.export_format != b.export_format || + a.swizzle[0] != b.swizzle[0] || a.swizzle[1] != b.swizzle[1]) { + return false; + } + + const gfx::ColorSpace source_color_space_a = + a.source_color_space.IsValid() ? a.source_color_space + : gfx::ColorSpace::CreateSRGB(); + const gfx::ColorSpace source_color_space_b = + b.source_color_space.IsValid() ? b.source_color_space + : gfx::ColorSpace::CreateSRGB(); + if (source_color_space_a != source_color_space_b) { + return false; + } + + const gfx::ColorSpace output_color_space_a = a.output_color_space.IsValid() + ? a.output_color_space + : source_color_space_a; + const gfx::ColorSpace output_color_space_b = b.output_color_space.IsValid() + ? b.output_color_space + : source_color_space_b; + return output_color_space_a == output_color_space_b; +} + void GLScaler::OnContextLost() { // The destruction order here is important due to data dependencies. chain_.reset(); @@ -685,6 +715,7 @@ } GLScaler::Parameters::Parameters() = default; +GLScaler::Parameters::Parameters(const Parameters& other) = default; GLScaler::Parameters::~Parameters() = default; // static
diff --git a/components/viz/common/gl_scaler.h b/components/viz/common/gl_scaler.h index eb65815..dd1dd7b3 100644 --- a/components/viz/common/gl_scaler.h +++ b/components/viz/common/gl_scaler.h
@@ -187,6 +187,7 @@ }; Parameters(); + Parameters(const Parameters& other); ~Parameters(); }; @@ -208,8 +209,9 @@ // Returns the currently-configured and resolved Parameters. Note that these // Parameters might not be exactly the same as those that were passed to - // Configure() because some properties (e.g., color spaces) are auto-resolved. - // Results are undefined if Configure() has never been called successfully. + // Configure() because some properties (e.g., color spaces) are auto-resolved; + // however, ParametersAreEquivalent() will still return true. Results are + // undefined if Configure() has never been called successfully. const Parameters& params() const { return params_; } // Scales a portion of |src_texture| and draws the result into |dest_texture| @@ -258,6 +260,10 @@ const gfx::Vector2d& from, const gfx::Vector2d& to); + // Returns true if configuring a GLScaler with either |a| or |b| will produce + // identical behaviors and results. + static bool ParametersAreEquivalent(const Parameters& a, const Parameters& b); + private: friend class GLScalerOverscanPixelTest; friend class GLScalerShaderPixelTest;
diff --git a/components/viz/common/gl_scaler_unittest.cc b/components/viz/common/gl_scaler_unittest.cc index 7cc690c..109a7461 100644 --- a/components/viz/common/gl_scaler_unittest.cc +++ b/components/viz/common/gl_scaler_unittest.cc
@@ -158,6 +158,7 @@ const auto srgb = gfx::ColorSpace::CreateSRGB(); EXPECT_EQ(srgb, scaler.params().source_color_space); EXPECT_EQ(srgb, scaler.params().output_color_space); + EXPECT_TRUE(GLScaler::ParametersAreEquivalent(params, scaler.params())); // Source space set to XYZD50 with no output space specified: Both should // resolve to XYZD50. @@ -166,6 +167,7 @@ EXPECT_TRUE(scaler.Configure(params)); EXPECT_EQ(xyzd50, scaler.params().source_color_space); EXPECT_EQ(xyzd50, scaler.params().output_color_space); + EXPECT_TRUE(GLScaler::ParametersAreEquivalent(params, scaler.params())); // Source space set to XYZD50 with output space set to P3D65: Nothing should // change. @@ -174,6 +176,7 @@ EXPECT_TRUE(scaler.Configure(params)); EXPECT_EQ(xyzd50, scaler.params().source_color_space); EXPECT_EQ(p3d65, scaler.params().output_color_space); + EXPECT_TRUE(GLScaler::ParametersAreEquivalent(params, scaler.params())); } TEST_F(GLScalerTest, Configure_RequiresValidSwizzles) {
diff --git a/components/viz/service/display/display_unittest.cc b/components/viz/service/display/display_unittest.cc index 84f2cc2..df4cda8 100644 --- a/components/viz/service/display/display_unittest.cc +++ b/components/viz/service/display/display_unittest.cc
@@ -3299,24 +3299,23 @@ } { - CompositorFrame frame = - CompositorFrameBuilder() - .AddRenderPass(gfx::Rect(sub_surface_size), gfx::Rect()) - .SetFrameToken(2) - .SetRequestPresentationFeedback(true) - .Build(); + CompositorFrame frame = CompositorFrameBuilder() + .AddRenderPass(gfx::Rect(sub_surface_size), + gfx::Rect(sub_surface_size)) + .SetFrameToken(2) + .SetRequestPresentationFeedback(true) + .Build(); EXPECT_CALL(sub_client, DidReceiveCompositorFrameAck(_)).Times(1); - EXPECT_CALL( - sub_client, - DidPresentCompositorFrame( - 2, testing::Field(&gfx::PresentationFeedback::flags, - gfx::PresentationFeedback::Flags::kFailure))) - .Times(1); sub_support->SubmitCompositorFrame(sub_local_surface_id, std::move(frame)); display_->DrawAndSwap(); RunAllPendingInMessageLoop(); + + // Both frames with frame-tokens 1 and 2 requested presentation-feedback. + ASSERT_EQ(2u, sub_support->presentation_feedbacks().size()); + EXPECT_TRUE(sub_support->presentation_feedbacks().count(1)); + EXPECT_TRUE(sub_support->presentation_feedbacks().count(2)); } {
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 efba340..baf56be 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -46,6 +46,7 @@ // BeginFrameSource does not call into |this| after it's deleted. callback_received_begin_frame_ = true; callback_received_receive_ack_ = true; + presentation_feedbacks_.clear(); SetNeedsBeginFrame(false); // For display root surfaces the surface is no longer going to be visible. @@ -71,6 +72,7 @@ // No video capture clients should remain after calling // UnregisterCompositorFrameSinkSupport(). DCHECK(capture_clients_.empty()); + DCHECK(!added_frame_observer_); } void CompositorFrameSinkSupport::SetUpHitTest( @@ -540,9 +542,9 @@ uint32_t presentation_token, const gfx::PresentationFeedback& feedback) { DCHECK(presentation_token); - if (client_) { - client_->DidPresentCompositorFrame(presentation_token, feedback); - } + DCHECK(!presentation_feedbacks_.count(presentation_token)); + presentation_feedbacks_.emplace(presentation_token, feedback); + UpdateNeedsBeginFramesInternal(); } void CompositorFrameSinkSupport::DidRejectCompositorFrame( @@ -585,14 +587,16 @@ HandleCallback(); } - if (client_ && client_needs_begin_frame_) { + if (client_ && + (client_needs_begin_frame_ || !presentation_feedbacks_.empty())) { BeginFrameArgs copy_args = args; copy_args.trace_id = ComputeTraceId(); TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Graphics.Pipeline", TRACE_ID_GLOBAL(copy_args.trace_id), TRACE_EVENT_FLAG_FLOW_OUT, "step", "IssueBeginFrame"); - client_->OnBeginFrame(copy_args); + client_->OnBeginFrame(copy_args, std::move(presentation_feedbacks_)); + presentation_feedbacks_.clear(); } } @@ -611,9 +615,9 @@ return; // We require a begin frame if there's a callback pending, or if the client - // requested it. + // requested it, or if the client needs to get some presentation feedbacks. bool needs_begin_frame = - client_needs_begin_frame_ || + client_needs_begin_frame_ || !presentation_feedbacks_.empty() || (compositor_frame_callback_ && !callback_received_begin_frame_); if (needs_begin_frame == added_frame_observer_)
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 4823d4d..0babe97 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/containers/flat_map.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/time/time.h" @@ -79,6 +80,11 @@ FrameSinkManagerImpl* frame_sink_manager() { return frame_sink_manager_; } + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + presentation_feedbacks() { + return presentation_feedbacks_; + } + // Viz hit-test setup is only called when |is_root_| is true (except on // android webview). void SetUpHitTest( @@ -296,6 +302,7 @@ bool callback_received_receive_ack_ = true; uint32_t trace_sequence_ = 0; + base::flat_map<uint32_t, gfx::PresentationFeedback> presentation_feedbacks_; uint32_t last_evicted_parent_sequence_number_ = 0; base::WeakPtrFactory<CompositorFrameSinkSupport> weak_factory_;
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc index 4e2f4b64..6970a1e 100644 --- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc +++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
@@ -282,13 +282,12 @@ client_->DidReceiveCompositorFrameAck(); } -void DirectLayerTreeFrameSink::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) { - client_->DidPresentCompositorFrame(presentation_token, feedback); -} +void DirectLayerTreeFrameSink::OnBeginFrame( + const BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) { + for (const auto& pair : feedbacks) + client_->DidPresentCompositorFrame(pair.first, pair.second); -void DirectLayerTreeFrameSink::OnBeginFrame(const BeginFrameArgs& args) { DCHECK_LE(pipeline_reporting_frame_times_.size(), 25u); // Note that client_name is constant during the lifetime of the process and // it's either "Browser" or "Renderer".
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h index 3072f21..3d3af24 100644 --- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h +++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
@@ -90,10 +90,9 @@ // mojom::CompositorFrameSinkClient implementation: void DidReceiveCompositorFrameAck( const std::vector<ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override; - void OnBeginFrame(const BeginFrameArgs& args) override; + void OnBeginFrame(const BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) override; void ReclaimResources( const std::vector<ReturnedResource>& resources) override; void OnBeginFramePausedChanged(bool paused) override;
diff --git a/components/viz/service/surfaces/surface_unittest.cc b/components/viz/service/surfaces/surface_unittest.cc index 4af65f9..27caa7d 100644 --- a/components/viz/service/surfaces/surface_unittest.cc +++ b/components/viz/service/surfaces/surface_unittest.cc
@@ -56,13 +56,10 @@ .SetFrameToken(2) .SetRequestPresentationFeedback(true) .Build(); - EXPECT_CALL(client, DidPresentCompositorFrame( - 1, testing::Field( - &gfx::PresentationFeedback::flags, - gfx::PresentationFeedback::Flags::kFailure))) - .Times(1); EXPECT_CALL(client, DidReceiveCompositorFrameAck(testing::_)).Times(1); support->SubmitCompositorFrame(local_surface_id, std::move(frame)); + ASSERT_EQ(1u, support->presentation_feedbacks().size()); + EXPECT_EQ(1u, support->presentation_feedbacks().begin()->first); testing::Mock::VerifyAndClearExpectations(&client); } }
diff --git a/components/viz/test/fake_compositor_frame_sink_client.cc b/components/viz/test/fake_compositor_frame_sink_client.cc index db34218..818237d 100644 --- a/components/viz/test/fake_compositor_frame_sink_client.cc +++ b/components/viz/test/fake_compositor_frame_sink_client.cc
@@ -14,11 +14,9 @@ InsertResources(resources); } -void FakeCompositorFrameSinkClient::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) {} - -void FakeCompositorFrameSinkClient::OnBeginFrame(const BeginFrameArgs& args) {} +void FakeCompositorFrameSinkClient::OnBeginFrame( + const BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) {} void FakeCompositorFrameSinkClient::ReclaimResources( const std::vector<ReturnedResource>& resources) {
diff --git a/components/viz/test/fake_compositor_frame_sink_client.h b/components/viz/test/fake_compositor_frame_sink_client.h index e2d22d54..5bfb364 100644 --- a/components/viz/test/fake_compositor_frame_sink_client.h +++ b/components/viz/test/fake_compositor_frame_sink_client.h
@@ -20,10 +20,9 @@ // mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const std::vector<ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override; - void OnBeginFrame(const BeginFrameArgs& args) override; + void OnBeginFrame(const BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) override; void ReclaimResources( const std::vector<ReturnedResource>& resources) override; void OnBeginFramePausedChanged(bool paused) override;
diff --git a/components/viz/test/mock_compositor_frame_sink_client.h b/components/viz/test/mock_compositor_frame_sink_client.h index b3f0a11..67c3fd5 100644 --- a/components/viz/test/mock_compositor_frame_sink_client.h +++ b/components/viz/test/mock_compositor_frame_sink_client.h
@@ -27,9 +27,10 @@ // mojom::CompositorFrameSinkClient implementation. MOCK_METHOD1(DidReceiveCompositorFrameAck, void(const std::vector<ReturnedResource>&)); - MOCK_METHOD2(DidPresentCompositorFrame, - void(uint32_t, const gfx::PresentationFeedback&)); - MOCK_METHOD1(OnBeginFrame, void(const BeginFrameArgs&)); + MOCK_METHOD2( + OnBeginFrame, + void(const BeginFrameArgs&, + const base::flat_map<uint32_t, gfx::PresentationFeedback>&)); MOCK_METHOD1(ReclaimResources, void(const std::vector<ReturnedResource>&)); MOCK_METHOD2(WillDrawSurface, void(const LocalSurfaceId&, const gfx::Rect&)); MOCK_METHOD1(OnBeginFramePausedChanged, void(bool paused));
diff --git a/components/viz/test/test_layer_tree_frame_sink.cc b/components/viz/test/test_layer_tree_frame_sink.cc index 0acc210..de20db78 100644 --- a/components/viz/test/test_layer_tree_frame_sink.cc +++ b/components/viz/test/test_layer_tree_frame_sink.cc
@@ -238,13 +238,11 @@ client_->DidReceiveCompositorFrameAck(); } -void TestLayerTreeFrameSink::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) { - client_->DidPresentCompositorFrame(presentation_token, feedback); -} - -void TestLayerTreeFrameSink::OnBeginFrame(const BeginFrameArgs& args) { +void TestLayerTreeFrameSink::OnBeginFrame( + const BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) { + for (const auto& pair : feedbacks) + client_->DidPresentCompositorFrame(pair.first, pair.second); external_begin_frame_source_.OnBeginFrame(args); }
diff --git a/components/viz/test/test_layer_tree_frame_sink.h b/components/viz/test/test_layer_tree_frame_sink.h index a27069a..7b41bf3 100644 --- a/components/viz/test/test_layer_tree_frame_sink.h +++ b/components/viz/test/test_layer_tree_frame_sink.h
@@ -100,10 +100,9 @@ // mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const std::vector<ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override; - void OnBeginFrame(const BeginFrameArgs& args) override; + void OnBeginFrame(const BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) override; void ReclaimResources( const std::vector<ReturnedResource>& resources) override; void OnBeginFramePausedChanged(bool paused) override;
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index f9118502..b58c979 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h
@@ -174,6 +174,9 @@ media::UserInputMonitor* user_input_monitor() const { return user_input_monitor_.get(); } + net::NetworkChangeNotifier* network_change_notifier() const { + return network_change_notifier_.get(); + } #if defined(OS_CHROMEOS) KeyboardMicRegistration* keyboard_mic_registration() {
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc index 00195cbc..8fd0cac 100644 --- a/content/browser/frame_host/render_widget_host_view_guest.cc +++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -241,9 +241,9 @@ gfx::PointF RenderWidgetHostViewGuest::TransformPointToRootCoordSpaceF( const gfx::PointF& point) { + viz::SurfaceId surface_id = GetCurrentSurfaceId(); // LocalSurfaceId is not needed in Viz hit-test. - if (!guest_ || - (!use_viz_hit_test_ && !last_activated_surface_info_.is_valid())) { + if (!guest_ || (!use_viz_hit_test_ && !surface_id.is_valid())) { return point; } @@ -255,8 +255,8 @@ // TODO(wjmaclean): If we knew that TransformPointToLocalCoordSpace would // guarantee not to change transformed_point on failure, then we could skip // checking the function return value and directly return transformed_point. - if (!root_rwhv->TransformPointToLocalCoordSpace( - point, last_activated_surface_info_.id(), &transformed_point)) { + if (!root_rwhv->TransformPointToLocalCoordSpace(point, surface_id, + &transformed_point)) { return point; } return transformed_point; @@ -266,19 +266,19 @@ const gfx::PointF& point, const viz::SurfaceId& original_surface, gfx::PointF* transformed_point) { + viz::SurfaceId surface_id = GetCurrentSurfaceId(); *transformed_point = point; - if (!guest_ || !last_activated_surface_info_.is_valid()) + if (!guest_ || !surface_id.is_valid()) return false; - if (original_surface == last_activated_surface_info_.id()) + if (original_surface == surface_id) return true; *transformed_point = gfx::ConvertPointToPixel(current_surface_scale_factor(), point); viz::SurfaceHittest hittest(nullptr, GetFrameSinkManager()->surface_manager()); - if (!hittest.TransformPointToTargetSurface(original_surface, - last_activated_surface_info_.id(), + if (!hittest.TransformPointToTargetSurface(original_surface, surface_id, transformed_point)) { return false; }
diff --git a/content/browser/media/session/media_session_impl_uma_unittest.cc b/content/browser/media/session/media_session_impl_uma_unittest.cc index 83dc5677..fe84189 100644 --- a/content/browser/media/session/media_session_impl_uma_unittest.cc +++ b/content/browser/media/session/media_session_impl_uma_unittest.cc
@@ -74,8 +74,6 @@ StartPlayer(); } - void TearDown() override { RenderViewHostImplTestHarness::TearDown(); } - protected: MediaSessionImpl* GetSession() { return MediaSessionImpl::Get(contents()); }
diff --git a/content/browser/net_info_browsertest.cc b/content/browser/net_info_browsertest.cc index e506f12..56ab286 100644 --- a/content/browser/net_info_browsertest.cc +++ b/content/browser/net_info_browsertest.cc
@@ -109,13 +109,6 @@ void SetUp() override { net::NetworkChangeNotifier::SetTestNotificationsOnly(true); -#if defined(OS_CHROMEOS) - // ChromeOS's NetworkChangeNotifier isn't known to content and therefore - // doesn't get created in content_browsertests. Insert a mock - // NetworkChangeNotifier. - net::NetworkChangeNotifier::CreateMock(); -#endif - content::ContentBrowserTest::SetUp(); }
diff --git a/content/browser/network_service_instance.cc b/content/browser/network_service_instance.cc index 5438bae..786a90e 100644 --- a/content/browser/network_service_instance.cc +++ b/content/browser/network_service_instance.cc
@@ -16,6 +16,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "build/build_config.h" +#include "content/browser/browser_main_loop.h" #include "content/browser/network_service_client.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -187,6 +188,10 @@ return g_network_service; } +net::NetworkChangeNotifier* GetNetworkChangeNotifier() { + return BrowserMainLoop::GetInstance()->network_change_notifier(); +} + void FlushNetworkServiceInstanceForTesting() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
diff --git a/content/browser/network_service_restart_browsertest.cc b/content/browser/network_service_restart_browsertest.cc index 9145b6f..8953cb1 100644 --- a/content/browser/network_service_restart_browsertest.cc +++ b/content/browser/network_service_restart_browsertest.cc
@@ -116,8 +116,10 @@ class ServiceWorkerStatusObserver : public ServiceWorkerContextCoreObserver { public: void WaitForState(EmbeddedWorkerStatus expected_status) { - if (latest_status_ == expected_status) - return; + for (const auto& status : statuses_in_past_) { + if (status == expected_status) + return; + } expected_status_ = expected_status; base::RunLoop loop; @@ -128,7 +130,7 @@ private: void OnRunningStateChanged(int64_t version_id, EmbeddedWorkerStatus running_status) override { - latest_status_ = running_status; + statuses_in_past_.push_back(running_status); if (expected_status_.has_value() && running_status == expected_status_.value()) { std::move(callback_).Run(); @@ -136,7 +138,7 @@ } base::Optional<EmbeddedWorkerStatus> expected_status_; - EmbeddedWorkerStatus latest_status_; + std::vector<EmbeddedWorkerStatus> statuses_in_past_; base::OnceClosure callback_; }; @@ -692,20 +694,10 @@ EXPECT_EQ(last_request_relative_url(), "/title2.html"); } -// Flaky on Linux TSan and Android ASan (https://crbug.com/889855) -#if (defined(OS_LINUX) && defined(THREAD_SANITIZER)) || \ - (defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)) -#define MAYBE_FetchFromServiceWorkerControlledPage_NoFetchHandler \ - DISABLED_FetchFromServiceWorkerControlledPage_NoFetchHandler -#else -#define MAYBE_FetchFromServiceWorkerControlledPage_NoFetchHandler \ - FetchFromServiceWorkerControlledPage_NoFetchHandler -#endif // Make sure fetch from a page controlled by a service worker which doesn't have // a fetch handler works after crash. -IN_PROC_BROWSER_TEST_F( - NetworkServiceRestartBrowserTest, - MAYBE_FetchFromServiceWorkerControlledPage_NoFetchHandler) { +IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, + FetchFromServiceWorkerControlledPage_NoFetchHandler) { StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( BrowserContext::GetDefaultStoragePartition(browser_context())); ServiceWorkerStatusObserver observer; @@ -743,19 +735,10 @@ service_worker_context->RemoveObserver(&observer); } -// Flaky on Linux TSan and Android ASan (https://crbug.com/889855) -#if (defined(OS_LINUX) && defined(THREAD_SANITIZER)) || \ - (defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)) -#define MAYBE_FetchFromServiceWorkerControlledPage_PassThrough \ - DISABLED_FetchFromServiceWorkerControlledPage_PassThrough -#else -#define MAYBE_FetchFromServiceWorkerControlledPage_PassThrough \ - FetchFromServiceWorkerControlledPage_PassThrough -#endif // Make sure fetch from a page controlled by a service worker which has a fetch // handler but falls back to the network works after crash. IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, - MAYBE_FetchFromServiceWorkerControlledPage_PassThrough) { + FetchFromServiceWorkerControlledPage_PassThrough) { StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( BrowserContext::GetDefaultStoragePartition(browser_context())); ServiceWorkerStatusObserver observer; @@ -793,20 +776,10 @@ service_worker_context->RemoveObserver(&observer); } -// Flaky on Linux TSan and Android ASan (https://crbug.com/889855) -#if (defined(OS_LINUX) && defined(THREAD_SANITIZER)) || \ - (defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)) -#define MAYBE_FetchFromServiceWorkerControlledPage_RespondWithFetch \ - DISABLED_FetchFromServiceWorkerControlledPage_RespondWithFetch -#else -#define MAYBE_FetchFromServiceWorkerControlledPage_RespondWithFetch \ - FetchFromServiceWorkerControlledPage_RespondWithFetch -#endif // Make sure fetch from a page controlled by a service worker which has a fetch // handler and responds with fetch() works after crash. -IN_PROC_BROWSER_TEST_F( - NetworkServiceRestartBrowserTest, - MAYBE_FetchFromServiceWorkerControlledPage_RespondWithFetch) { +IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, + FetchFromServiceWorkerControlledPage_RespondWithFetch) { StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( BrowserContext::GetDefaultStoragePartition(browser_context())); ServiceWorkerStatusObserver observer;
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index f427fc90..2ff513d 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -52,7 +52,7 @@ DCHECK(host_frame_sink_manager_); viz::ReportFirstSurfaceActivation should_report_first_surface_activation = viz::ReportFirstSurfaceActivation::kNo; -#ifdef CHROME_OS +#ifdef OS_CHROMEOS should_report_first_surface_activation = viz::ReportFirstSurfaceActivation::kYes; #endif @@ -287,13 +287,6 @@ renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources); } -void DelegatedFrameHost::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) { - renderer_compositor_frame_sink_->DidPresentCompositorFrame(presentation_token, - feedback); -} - void DelegatedFrameHost::ReclaimResources( const std::vector<viz::ReturnedResource>& resources) { renderer_compositor_frame_sink_->ReclaimResources(resources); @@ -319,9 +312,11 @@ client_->OnFrameTokenChanged(frame_token); } -void DelegatedFrameHost::OnBeginFrame(const viz::BeginFrameArgs& args) { +void DelegatedFrameHost::OnBeginFrame( + const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) { if (renderer_compositor_frame_sink_) - renderer_compositor_frame_sink_->OnBeginFrame(args); + renderer_compositor_frame_sink_->OnBeginFrame(args, feedbacks); client_->OnBeginFrame(args.frame_time); }
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h index 6656a1a..9689e8e 100644 --- a/content/browser/renderer_host/delegated_frame_host.h +++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -91,10 +91,9 @@ // viz::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override; - void OnBeginFrame(const viz::BeginFrameArgs& args) override; + void OnBeginFrame(const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) override; void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override; void OnBeginFramePausedChanged(bool paused) override;
diff --git a/content/browser/renderer_host/delegated_frame_host_client_android.cc b/content/browser/renderer_host/delegated_frame_host_client_android.cc index 6a80e15..dac54bc 100644 --- a/content/browser/renderer_host/delegated_frame_host_client_android.cc +++ b/content/browser/renderer_host/delegated_frame_host_client_android.cc
@@ -25,11 +25,9 @@ render_widget_host_view_->DidReceiveCompositorFrameAck(resources); } -void DelegatedFrameHostClientAndroid::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) { - render_widget_host_view_->DidPresentCompositorFrame(presentation_token, - feedback); +void DelegatedFrameHostClientAndroid::DidPresentCompositorFrames( + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) { + render_widget_host_view_->DidPresentCompositorFrames(feedbacks); } void DelegatedFrameHostClientAndroid::ReclaimResources(
diff --git a/content/browser/renderer_host/delegated_frame_host_client_android.h b/content/browser/renderer_host/delegated_frame_host_client_android.h index 8af91b6..28e1752 100644 --- a/content/browser/renderer_host/delegated_frame_host_client_android.h +++ b/content/browser/renderer_host/delegated_frame_host_client_android.h
@@ -23,9 +23,9 @@ private: // DelegatedFrameHostAndroid::Client implementation. void SetBeginFrameSource(viz::BeginFrameSource* begin_frame_source) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override; + void DidPresentCompositorFrames( + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) + override; void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; void ReclaimResources(
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 93de0a60..cb745652 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -942,12 +942,12 @@ renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources); } -void RenderWidgetHostViewAndroid::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) { +void RenderWidgetHostViewAndroid::DidPresentCompositorFrames( + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) { DCHECK(using_browser_compositor_); - renderer_compositor_frame_sink_->DidPresentCompositorFrame(presentation_token, - feedback); + presentation_feedbacks_ = feedbacks; + if (!presentation_feedbacks_.empty()) + AddBeginFrameRequest(BEGIN_FRAME); } void RenderWidgetHostViewAndroid::ReclaimResources( @@ -1526,7 +1526,9 @@ if (sync_compositor_) { sync_compositor_->BeginFrame(view_.GetWindowAndroid(), args); } else if (renderer_compositor_frame_sink_) { - renderer_compositor_frame_sink_->OnBeginFrame(args); + renderer_compositor_frame_sink_->OnBeginFrame(args, + presentation_feedbacks_); + presentation_feedbacks_.clear(); } }
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index c46d6af7..a1ccad9 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -236,8 +236,8 @@ // Used by DelegatedFrameHostClientAndroid. void SetBeginFrameSource(viz::BeginFrameSource* begin_frame_source); - void DidPresentCompositorFrame(uint32_t presentation_token, - const gfx::PresentationFeedback& feedback); + void DidPresentCompositorFrames( + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks); void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources); void ReclaimResources(const std::vector<viz::ReturnedResource>& resources); @@ -509,6 +509,8 @@ viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_; bool is_first_navigation_ = true; + base::flat_map<uint32_t, gfx::PresentationFeedback> presentation_feedbacks_; + base::WeakPtrFactory<RenderWidgetHostViewAndroid> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroid);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 32aca12..2f878e4 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -2487,6 +2487,15 @@ if (!focused_view) return; + // IMF relies on the |OnCaretBoundsChanged| for the surrounding text changed + // events to IME. Explicitly call |OnCaretBoundsChanged| here so that IMF can + // know about the surrounding text changes when the caret bounds are not + // changed. e.g. When the rendered text is wider than the input field, + // deleting the last character won't change the caret bounds but will change + // the surrounding text. + if (GetInputMethod()) + GetInputMethod()->OnCaretBoundsChanged(this); + #if defined(USE_X11) const TextInputManager::TextSelection* selection = GetTextInputManager()->GetTextSelection(focused_view);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index a6bb1c2..f567a62 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -414,6 +414,8 @@ HitTestRegionListSubmitted); FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithMemoryPressure); + FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraInputMethodTest, + OnCaretBoundsChanged); FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraKeyboardTest, KeyboardObserverDestroyed); FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraKeyboardTest,
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 6873f27c..508f325 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
@@ -6601,6 +6601,68 @@ parent_view_->GetFocusReason()); } +class RenderWidgetHostViewAuraInputMethodTest + : public RenderWidgetHostViewAuraTest, + public ui::InputMethodObserver { + public: + RenderWidgetHostViewAuraInputMethodTest() = default; + ~RenderWidgetHostViewAuraInputMethodTest() override{}; + void SetUp() override { + input_method_ = new ui::MockInputMethod(nullptr); + // transfers ownership. + ui::SetUpInputMethodForTesting(input_method_); + SetUpEnvironment(); + text_input_client_ = nullptr; + } + + // Override from ui::InputMethodObserver. + void OnFocus() override {} + void OnBlur() override {} + void OnCaretBoundsChanged(const ui::TextInputClient* client) override { + text_input_client_ = client; + } + void OnTextInputStateChanged(const ui::TextInputClient* client) override {} + void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {} + void OnShowVirtualKeyboardIfEnabled() override {} + + protected: + // Not owned. + ui::MockInputMethod* input_method_ = nullptr; + const ui::TextInputClient* text_input_client_; + + DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraInputMethodTest); +}; + +// This test is for notifying InputMethod for surrounding text changes. +TEST_F(RenderWidgetHostViewAuraInputMethodTest, OnCaretBoundsChanged) { + ui::InputMethod* input_method = parent_view_->GetInputMethod(); + if (input_method != input_method_) { + // Some platform doesn't support mocking input method. e.g. InputMethodMus. + // In that case, ignore this test. + // TODO(shuchen): support mocking InputMethodMus, http://crbug.com/905518. + return; + } + ActivateViewForTextInputManager(parent_view_, ui::TEXT_INPUT_TYPE_TEXT); + input_method->SetFocusedTextInputClient(parent_view_); + input_method->AddObserver(this); + + parent_view_->SelectionChanged(base::string16(), 0, gfx::Range()); + EXPECT_EQ(parent_view_, text_input_client_); + + text_input_client_ = nullptr; + + WidgetHostMsg_SelectionBounds_Params params; + params.is_anchor_first = true; + params.anchor_dir = blink::kWebTextDirectionLeftToRight; + params.focus_dir = blink::kWebTextDirectionLeftToRight; + params.anchor_rect = gfx::Rect(0, 0, 10, 10); + params.focus_rect = gfx::Rect(10, 10, 10, 10); + parent_view_->SelectionBoundsChanged(params); + EXPECT_EQ(parent_view_, text_input_client_); + + input_method->RemoveObserver(this); +} + #if defined(OS_WIN) class MockInputMethodKeyboardController final : public ui::InputMethodKeyboardController {
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc index 5673360..97c7697 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -82,7 +82,10 @@ frame_sink_id_ = viz::FrameSinkId(); } else { GetHostFrameSinkManager()->RegisterFrameSinkId( - frame_sink_id_, this, viz::ReportFirstSurfaceActivation::kYes); + frame_sink_id_, this, + enable_surface_synchronization_ + ? viz::ReportFirstSurfaceActivation::kNo + : viz::ReportFirstSurfaceActivation::kYes); GetHostFrameSinkManager()->SetFrameSinkDebugLabel( frame_sink_id_, "RenderWidgetHostViewChildFrame"); CreateCompositorFrameSinkSupport(); @@ -228,7 +231,7 @@ } bool RenderWidgetHostViewChildFrame::IsSurfaceAvailableForCopy() const { - return has_frame_; + return GetLocalSurfaceIdAllocation().IsValid(); } void RenderWidgetHostViewChildFrame::EnsureSurfaceSynchronizedForLayoutTest() { @@ -575,19 +578,11 @@ renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources); } -void RenderWidgetHostViewChildFrame::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) { - renderer_compositor_frame_sink_->DidPresentCompositorFrame(presentation_token, - feedback); -} - void RenderWidgetHostViewChildFrame::DidCreateNewRendererCompositorFrameSink( viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) { ResetCompositorFrameSinkSupport(); renderer_compositor_frame_sink_ = renderer_compositor_frame_sink; CreateCompositorFrameSinkSupport(); - has_frame_ = false; } void RenderWidgetHostViewChildFrame::SetParentFrameSinkId( @@ -616,6 +611,8 @@ void RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedder() { if (features::IsMultiProcessMash()) return; + if (enable_surface_synchronization_) + return; if (!last_activated_surface_info_.is_valid()) return; FirstSurfaceActivation(last_activated_surface_info_); @@ -644,15 +641,6 @@ support_->DidNotProduceFrame(ack); } -void RenderWidgetHostViewChildFrame::ProcessFrameSwappedCallbacks() { - std::vector<base::OnceClosure> process_callbacks; - // Swap the vectors to avoid re-entrancy issues due to calls to - // RegisterFrameSwappedCallback() while running the OnceClosures. - process_callbacks.swap(frame_swapped_callbacks_); - for (base::OnceClosure& callback : process_callbacks) - std::move(callback).Run(); -} - void RenderWidgetHostViewChildFrame::TransformPointToRootSurface( gfx::PointF* point) { // This function is called by RenderWidgetHostInputEventRouter only for @@ -742,14 +730,13 @@ gfx::PointF RenderWidgetHostViewChildFrame::TransformPointToRootCoordSpaceF( const gfx::PointF& point) { + viz::SurfaceId surface_id = GetCurrentSurfaceId(); // LocalSurfaceId is not needed in Viz hit-test. - if (!frame_connector_ || - (!use_viz_hit_test_ && !last_activated_surface_info_.is_valid())) { + if (!frame_connector_ || (!use_viz_hit_test_ && !surface_id.is_valid())) { return point; } - return frame_connector_->TransformPointToRootCoordSpace( - point, last_activated_surface_info_.id()); + return frame_connector_->TransformPointToRootCoordSpace(point, surface_id); } bool RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpaceLegacy( @@ -757,12 +744,12 @@ const viz::SurfaceId& original_surface, gfx::PointF* transformed_point) { *transformed_point = point; - if (!frame_connector_ || !last_activated_surface_info_.is_valid()) + viz::SurfaceId surface_id = GetCurrentSurfaceId(); + if (!frame_connector_ || !surface_id.is_valid()) return false; return frame_connector_->TransformPointToLocalCoordSpaceLegacy( - point, original_surface, last_activated_surface_info_.id(), - transformed_point); + point, original_surface, surface_id, transformed_point); } bool RenderWidgetHostViewChildFrame::TransformPointToCoordSpaceForView( @@ -770,9 +757,9 @@ RenderWidgetHostViewBase* target_view, gfx::PointF* transformed_point, viz::EventSource source) { + viz::SurfaceId surface_id = GetCurrentSurfaceId(); // LocalSurfaceId is not needed in Viz hit-test. - if (!frame_connector_ || - (!use_viz_hit_test_ && !last_activated_surface_info_.is_valid())) { + if (!frame_connector_ || (!use_viz_hit_test_ && !surface_id.is_valid())) { return false; } @@ -782,8 +769,7 @@ } return frame_connector_->TransformPointToCoordSpaceForView( - point, target_view, last_activated_surface_info_.id(), transformed_point, - source); + point, target_view, surface_id, transformed_point, source); } gfx::PointF RenderWidgetHostViewChildFrame::TransformRootPointToViewCoordSpace( @@ -840,21 +826,12 @@ void RenderWidgetHostViewChildFrame::SpeakSelection() {} #endif // defined(OS_MACOSX) -void RenderWidgetHostViewChildFrame::RegisterFrameSwappedCallback( - base::OnceClosure callback) { - frame_swapped_callbacks_.emplace_back(std::move(callback)); -} - void RenderWidgetHostViewChildFrame::CopyFromSurface( const gfx::Rect& src_subrect, const gfx::Size& output_size, base::OnceCallback<void(const SkBitmap&)> callback) { if (!IsSurfaceAvailableForCopy()) { - // Defer submitting the copy request until after a frame is drawn, at which - // point we should be guaranteed that the surface is available. - RegisterFrameSwappedCallback(base::BindOnce( - &RenderWidgetHostViewChildFrame::CopyFromSurface, AsWeakPtr(), - src_subrect, output_size, std::move(callback))); + std::move(callback).Run(SkBitmap()); return; } @@ -869,11 +846,13 @@ std::move(callback))); if (src_subrect.IsEmpty()) { - request->set_area(gfx::Rect(last_activated_surface_info_.size_in_pixels())); + request->set_area(gfx::Rect(GetCompositorViewportPixelSize())); } else { + ScreenInfo screen_info; + GetScreenInfo(&screen_info); // |src_subrect| is in DIP coordinates; convert to Surface coordinates. - request->set_area(gfx::ScaleToRoundedRect( - src_subrect, last_activated_surface_info_.device_scale_factor())); + request->set_area( + gfx::ScaleToRoundedRect(src_subrect, screen_info.device_scale_factor)); } if (!output_size.IsEmpty()) { @@ -889,8 +868,8 @@ gfx::Vector2d(output_size.width(), output_size.height())); } - GetHostFrameSinkManager()->RequestCopyOfOutput( - last_activated_surface_info_.id(), std::move(request)); + GetHostFrameSinkManager()->RequestCopyOfOutput(GetCurrentSurfaceId(), + std::move(request)); } void RenderWidgetHostViewChildFrame::ReclaimResources( @@ -900,10 +879,11 @@ } void RenderWidgetHostViewChildFrame::OnBeginFrame( - const viz::BeginFrameArgs& args) { + const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) { host_->ProgressFlingIfNeeded(args.frame_time); if (renderer_compositor_frame_sink_) - renderer_compositor_frame_sink_->OnBeginFrame(args); + renderer_compositor_frame_sink_->OnBeginFrame(args, feedbacks); } void RenderWidgetHostViewChildFrame::OnBeginFramePausedChanged(bool paused) { @@ -913,10 +893,12 @@ void RenderWidgetHostViewChildFrame::OnFirstSurfaceActivation( const viz::SurfaceInfo& surface_info) { + if (enable_surface_synchronization_) { + NOTREACHED(); + return; + } last_activated_surface_info_ = surface_info; - has_frame_ = true; FirstSurfaceActivation(surface_info); - ProcessFrameSwappedCallbacks(); } void RenderWidgetHostViewChildFrame::OnFrameTokenChanged(uint32_t frame_token) {
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h index 7ab9e260..b121cf3e 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.h +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -195,10 +195,9 @@ // viz::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override; - void OnBeginFrame(const viz::BeginFrameArgs& args) override; + void OnBeginFrame(const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) override; void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override; void OnBeginFramePausedChanged(bool paused) override; @@ -234,8 +233,6 @@ void UpdateRenderThrottlingStatus(); - bool has_frame() { return has_frame_; } - ui::TextInputType GetTextInputType() const; bool GetSelectionRange(gfx::Range* range) const; @@ -320,7 +317,6 @@ const bool enable_viz_; const bool enable_surface_synchronization_; - bool has_frame_ = false; viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ = nullptr;
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc index 9b006fe..72d509d 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -198,6 +198,9 @@ // Verify that RenderWidgetHostViewChildFrame passes the child's SurfaceId to // FrameConnectorDelegate to be sent to the embedding renderer. TEST_F(RenderWidgetHostViewChildFrameTest, PassesSurfaceId) { + if (features::IsSurfaceSynchronizationEnabled()) + return; + gfx::Size view_size(100, 100); gfx::Rect view_rect(view_size); float scale_factor = 1.f;
diff --git a/content/browser/tracing/tracing_controller_browsertest.cc b/content/browser/tracing/tracing_controller_browsertest.cc index 8288bd6..31bf7d5 100644 --- a/content/browser/tracing/tracing_controller_browsertest.cc +++ b/content/browser/tracing/tracing_controller_browsertest.cc
@@ -19,7 +19,6 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/trace_uploader.h" -#include "content/public/browser/tracing_controller.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" @@ -128,8 +127,6 @@ ContentBrowserTest::SetUp(); } - void TearDown() override { ContentBrowserTest::TearDown(); } - void Navigate(Shell* shell) { NavigateToURL(shell, GetTestUrl("", "title.html")); }
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 46a904a5..9894fec 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -437,9 +437,6 @@ WebRuntimeFeatures::EnablePreloadImageSrcSetEnabled(true); } - WebRuntimeFeatures::EnableNestedWorkers( - base::FeatureList::IsEnabled(blink::features::kNestedWorkers)); - if (base::FeatureList::IsEnabled( features::kExperimentalProductivityFeatures)) { WebRuntimeFeatures::EnableExperimentalProductivityFeatures(true);
diff --git a/content/common/user_agent.cc b/content/common/user_agent.cc index 4ec56383..544ccc3 100644 --- a/content/common/user_agent.cc +++ b/content/common/user_agent.cc
@@ -22,11 +22,30 @@ namespace content { +namespace { + #if defined(OS_ANDROID) const base::Feature kAndroidUserAgentStringContainsBuildId{ "AndroidUserAgentStringContainsBuildId", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // defined(OS_ANDROID) +std::string GetUserAgentPlatform() { + return +#if defined(OS_WIN) + ""; +#elif defined(OS_MACOSX) + "Macintosh; "; +#elif defined(USE_X11) || defined(USE_OZONE) + "X11; "; // strange, but that's what Firefox uses +#elif defined(OS_ANDROID) + "Linux; "; +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + "Unknown; "; +#endif +} + +} // namespace + std::string GetWebKitVersion() { return base::StringPrintf("%d.%d (%s)", WEBKIT_VERSION_MAJOR, @@ -115,24 +134,9 @@ return os_cpu; } -std::string getUserAgentPlatform() { - return -#if defined(OS_WIN) - ""; -#elif defined(OS_MACOSX) - "Macintosh; "; -#elif defined(USE_X11) || defined(USE_OZONE) - "X11; "; // strange, but that's what Firefox uses -#elif defined(OS_ANDROID) - "Linux; "; -#elif defined(OS_POSIX) || defined(OS_FUCHSIA) - "Unknown; "; -#endif -} - std::string BuildUserAgentFromProduct(const std::string& product) { std::string os_info; - base::StringAppendF(&os_info, "%s%s", getUserAgentPlatform().c_str(), + base::StringAppendF(&os_info, "%s%s", GetUserAgentPlatform().c_str(), BuildOSCpuInfo(false).c_str()); return BuildUserAgentFromOSAndProduct(os_info, product); } @@ -143,7 +147,7 @@ const std::string& extra_os_info, bool include_android_build_number) { std::string os_info; - base::StringAppendF(&os_info, "%s%s%s", getUserAgentPlatform().c_str(), + base::StringAppendF(&os_info, "%s%s%s", GetUserAgentPlatform().c_str(), BuildOSCpuInfo(include_android_build_number).c_str(), extra_os_info.c_str()); return BuildUserAgentFromOSAndProduct(os_info, product);
diff --git a/content/public/browser/network_service_instance.h b/content/public/browser/network_service_instance.h index 71d916a..17f9cbd 100644 --- a/content/public/browser/network_service_instance.h +++ b/content/public/browser/network_service_instance.h
@@ -11,6 +11,10 @@ #include "base/callback_list.h" #include "content/common/content_export.h" +namespace net { +class NetworkChangeNotifier; +} // namespace net + namespace network { class NetworkConnectionTracker; class NetworkService; @@ -55,6 +59,9 @@ // service is enabled. CONTENT_EXPORT network::NetworkService* GetNetworkServiceImpl(); +// Returns the global NetworkChangeNotifier instance. +CONTENT_EXPORT net::NetworkChangeNotifier* GetNetworkChangeNotifier(); + // Call |FlushForTesting()| on cached |NetworkServicePtr|. For testing only. // Must only be called on the UI thread. CONTENT_EXPORT void FlushNetworkServiceInstanceForTesting();
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc index 1253f538..2458c61 100644 --- a/content/public/test/browser_test_base.cc +++ b/content/public/test/browser_test_base.cc
@@ -61,6 +61,12 @@ #include "base/process/process_handle.h" #endif +#if defined(OS_CHROMEOS) +#include "content/public/browser/network_service_instance.h" +#include "net/base/network_change_notifier.h" +#include "net/base/network_change_notifier_chromeos.h" +#endif + #if defined(USE_AURA) #include "content/browser/compositor/image_transport_factory.h" #include "ui/aura/test/event_generator_delegate_aura.h" // nogncheck @@ -379,6 +385,17 @@ signal(SIGTERM, DumpStackTraceSignalHandler); #endif // defined(OS_POSIX) +#if defined(OS_CHROMEOS) + // Manually set the connection type since ChromeOS's NetworkChangeNotifier + // implementation relies on some other class controlling it (normally + // NetworkChangeManagerClient), which may not be set up in all browser tests. + net::NetworkChangeNotifierChromeos* network_change_notifier = + static_cast<net::NetworkChangeNotifierChromeos*>( + content::GetNetworkChangeNotifier()); + network_change_notifier->OnConnectionChanged( + net::NetworkChangeNotifier::CONNECTION_ETHERNET); +#endif + if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableTracing)) { base::trace_event::TraceConfig trace_config(
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/content/renderer/android/synchronous_layer_tree_frame_sink.cc index c554efa..ffc95a2 100644 --- a/content/renderer/android/synchronous_layer_tree_frame_sink.cc +++ b/content/renderer/android/synchronous_layer_tree_frame_sink.cc
@@ -520,12 +520,9 @@ ReclaimResources(resources); } -void SynchronousLayerTreeFrameSink::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) {} - void SynchronousLayerTreeFrameSink::OnBeginFrame( - const viz::BeginFrameArgs& args) {} + const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) {} void SynchronousLayerTreeFrameSink::ReclaimResources( const std::vector<viz::ReturnedResource>& resources) {
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.h b/content/renderer/android/synchronous_layer_tree_frame_sink.h index 8dd2dca..0a1e39d 100644 --- a/content/renderer/android/synchronous_layer_tree_frame_sink.h +++ b/content/renderer/android/synchronous_layer_tree_frame_sink.h
@@ -109,10 +109,9 @@ // viz::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override; - void OnBeginFrame(const viz::BeginFrameArgs& args) override; + void OnBeginFrame(const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) override; void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override; void OnBeginFramePausedChanged(bool paused) override;
diff --git a/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc b/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc index e601eb6..d7436721 100644 --- a/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc +++ b/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
@@ -9,8 +9,10 @@ #include "content/child/image_decoder.h" #include "content/public/renderer/associated_resource_fetcher.h" #include "services/network/public/mojom/request_context_frame_type.mojom.h" +#include "third_party/blink/public/platform/web_security_origin.h" #include "third_party/blink/public/platform/web_url_response.h" #include "third_party/blink/public/web/web_associated_url_loader_options.h" +#include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/geometry/size.h" @@ -38,11 +40,17 @@ WebAssociatedURLLoaderOptions options; fetcher_->SetLoaderOptions(options); - // To prevent cache tainting, the favicon requests have to by-pass the service - // workers. This should ideally not happen or at least not all the time. - // See https://crbug.com/448427 - if (request_context == blink::mojom::RequestContextType::FAVICON) - fetcher_->SetSkipServiceWorker(true); + if (request_context == blink::mojom::RequestContextType::FAVICON) { + // To prevent cache tainting, the cross-origin favicon requests have to + // by-pass the service workers. This should ideally not happen. But Chrome’s + // ThumbnailDatabase is using the icon URL as a key of the "favicons" table. + // So if we don't set the skip flag here, malicious service workers can + // override the favicon image of any origins. + if (!frame->GetDocument().GetSecurityOrigin().CanAccess( + blink::WebSecurityOrigin::Create(image_url_))) { + fetcher_->SetSkipServiceWorker(true); + } + } fetcher_->SetCacheMode(cache_mode);
diff --git a/content/test/data/lite_js_test.mojom b/content/test/data/lite_js_test.mojom index 0188bbd..ef64bf4 100644 --- a/content/test/data/lite_js_test.mojom +++ b/content/test/data/lite_js_test.mojom
@@ -4,6 +4,10 @@ module lite_js_test.mojom; +struct TestStruct { + int32 x; +}; + // An interface whose definition covers various types of message signatures in // order to exercise the lite JS mojom bindings. interface TestMessageTarget { @@ -17,6 +21,8 @@ Repeat(string? message, array<int32>? numbers) => (string? message, array<int32>? numbers); + Flatten(array<TestStruct> values) => (array<int32> values); + RequestSubinterface(Subinterface& request, SubinterfaceClient client); };
diff --git a/content/test/fake_renderer_compositor_frame_sink.h b/content/test/fake_renderer_compositor_frame_sink.h index fce5b155..3c0da96 100644 --- a/content/test/fake_renderer_compositor_frame_sink.h +++ b/content/test/fake_renderer_compositor_frame_sink.h
@@ -28,10 +28,9 @@ // viz::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override {} - void OnBeginFrame(const viz::BeginFrameArgs& args) override {} + void OnBeginFrame(const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) override {} void OnBeginFramePausedChanged(bool paused) override {} void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override;
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 779cf81..f441788e 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -109,6 +109,8 @@ # TODO(http://crbug.com/887241): Upgrade the drivers on the bots. self.Fail('conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop.html', ['linux', 'nvidia'], bug=772651) + self.Fail('conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop.html', + ['android', 'nvidia'], bug=905370) self.Fail('conformance/glsl/bugs/' + 'vector-scalar-arithmetic-inside-loop-complex.html', ['nvidia'], bug=772651)
diff --git a/gpu/command_buffer/common/common_cmd_format.h b/gpu/command_buffer/common/common_cmd_format.h index c5a3e30a..538844ab 100644 --- a/gpu/command_buffer/common/common_cmd_format.h +++ b/gpu/command_buffer/common/common_cmd_format.h
@@ -12,6 +12,7 @@ #include <string.h> #include "base/atomicops.h" +#include "base/numerics/checked_math.h" #include "gpu/command_buffer/common/cmd_buffer_common.h" namespace gpu { @@ -33,25 +34,38 @@ // Returns the total size in bytes of the SizedResult for a given number of // results including the size field. - static size_t ComputeSize(size_t num_results) { - return sizeof(T) * num_results + sizeof(uint32_t); // NOLINT + static uint32_t ComputeSize(base::CheckedNumeric<uint32_t> num_results) { + base::CheckedNumeric<uint32_t> size = num_results; + size *= sizeof(T); + size += sizeof(uint32_t); + return size.ValueOrDie(); } // Returns the maximum number of results for a given buffer size. static uint32_t ComputeMaxResults(size_t size_of_buffer) { - return (size_of_buffer >= sizeof(uint32_t)) - ? ((size_of_buffer - sizeof(uint32_t)) / sizeof(T)) - : 0; // NOLINT + base::CheckedNumeric<uint32_t> max_results = 0; + if (size_of_buffer >= sizeof(uint32_t)) { + max_results = size_of_buffer; + max_results -= sizeof(uint32_t); + max_results /= sizeof(T); + } + return max_results.ValueOrDefault(0); } // Set the size for a given number of results. - void SetNumResults(size_t num_results) { - size = sizeof(T) * num_results; // NOLINT + void SetNumResults(base::CheckedNumeric<uint32_t> num_results) { + base::CheckedNumeric<uint32_t> bytes = num_results; + bytes *= sizeof(T); + size = bytes.ValueOrDie(); } // Get the number of elements in the result int32_t GetNumResults() const { - return size / sizeof(T); // NOLINT + // TODO(piman): return uint32_t here to remove the need for checked + // numerics. + base::CheckedNumeric<uint32_t> num_results = size; + num_results /= sizeof(T); + return num_results.ValueOrDie<int32_t>(); } // Copy the result.
diff --git a/gpu/command_buffer/service/mailbox_manager_unittest.cc b/gpu/command_buffer/service/mailbox_manager_unittest.cc index ffbe752..0404b33 100644 --- a/gpu/command_buffer/service/mailbox_manager_unittest.cc +++ b/gpu/command_buffer/service/mailbox_manager_unittest.cc
@@ -43,8 +43,6 @@ DCHECK(manager_->UsesSync()); } - void TearDown() override { GpuServiceTest::TearDown(); } - Texture* CreateTexture() { return new Texture(1); }
diff --git a/ios/chrome/browser/ui/open_in_controller_unittest.mm b/ios/chrome/browser/ui/open_in_controller_unittest.mm index e353cb4db..703b6c5 100644 --- a/ios/chrome/browser/ui/open_in_controller_unittest.mm +++ b/ios/chrome/browser/ui/open_in_controller_unittest.mm
@@ -38,8 +38,6 @@ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_)) {} - void TearDown() override { PlatformTest::TearDown(); } - void SetUp() override { PlatformTest::SetUp();
diff --git a/media/audio/audio_output_proxy_unittest.cc b/media/audio/audio_output_proxy_unittest.cc index ff493b6..29e7381 100644 --- a/media/audio/audio_output_proxy_unittest.cc +++ b/media/audio/audio_output_proxy_unittest.cc
@@ -495,8 +495,6 @@ class AudioOutputResamplerTest : public AudioOutputProxyTest { public: - void TearDown() override { AudioOutputProxyTest::TearDown(); } - void InitDispatcher(base::TimeDelta close_delay) override { // Use a low sample rate and large buffer size when testing otherwise the // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e.,
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index 5123e32e..1ecb3f2 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc
@@ -1242,7 +1242,7 @@ } uint8_t* data = reinterpret_cast<uint8_t*>( - base::AlignedAlloc(total_buffer_size, kFrameAddressAlignment)); + base::AlignedAlloc(total_buffer_size, layout_.buffer_addr_align())); if (zero_initialize_memory) { memset(data, 0, total_buffer_size); }
diff --git a/media/base/video_frame.h b/media/base/video_frame.h index b3d9dea..596eb13 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h
@@ -46,9 +46,7 @@ kFrameSizeAlignment = 16, kFrameSizePadding = 16, - // Note: This value is dependent on what's used by ffmpeg, do not change - // without inspecting av_frame_get_buffer() first. - kFrameAddressAlignment = 32 + kFrameAddressAlignment = VideoFrameLayout::kBufferAddressAlignment }; enum {
diff --git a/media/base/video_frame_layout.cc b/media/base/video_frame_layout.cc index df4a040..c63ffdd5 100644 --- a/media/base/video_frame_layout.cc +++ b/media/base/video_frame_layout.cc
@@ -105,7 +105,8 @@ VideoPixelFormat format, const gfx::Size& coded_size, std::vector<Plane> planes, - std::vector<size_t> buffer_sizes) { + std::vector<size_t> buffer_sizes, + size_t buffer_addr_align) { // NOTE: Even if format is UNKNOWN, it is valid if coded_sizes is not Empty(). // TODO(crbug.com/896135): Return base::nullopt, // if (format != PIXEL_FORMAT_UNKNOWN || !coded_sizes.IsEmpty()) @@ -114,17 +115,19 @@ // TODO(crbug.com/896135): Return base::nullopt, // if (buffer_sizes.size() > planes.size()) return VideoFrameLayout(format, coded_size, std::move(planes), - std::move(buffer_sizes)); + std::move(buffer_sizes), buffer_addr_align); } VideoFrameLayout::VideoFrameLayout(VideoPixelFormat format, const gfx::Size& coded_size, std::vector<Plane> planes, - std::vector<size_t> buffer_sizes) + std::vector<size_t> buffer_sizes, + size_t buffer_addr_align) : format_(format), coded_size_(coded_size), planes_(std::move(planes)), - buffer_sizes_(std::move(buffer_sizes)) {} + buffer_sizes_(std::move(buffer_sizes)), + buffer_addr_align_(buffer_addr_align) {} VideoFrameLayout::~VideoFrameLayout() = default; VideoFrameLayout::VideoFrameLayout(const VideoFrameLayout&) = default;
diff --git a/media/base/video_frame_layout.h b/media/base/video_frame_layout.h index 56e9a822..fc33f93f 100644 --- a/media/base/video_frame_layout.h +++ b/media/base/video_frame_layout.h
@@ -30,6 +30,11 @@ // Note that it is copyable. class MEDIA_EXPORT VideoFrameLayout { public: + // Default alignment for buffers. + // Note: This value is dependent on what's used by ffmpeg, do not change + // without inspecting av_frame_get_buffer() first. + static constexpr size_t kBufferAddressAlignment = 32; + struct Plane { Plane() = default; Plane(int32_t stride, size_t offset) : stride(stride), offset(offset) {} @@ -55,6 +60,8 @@ // The size of |buffer_sizes| must be less than or equal to |planes|. // Unless they are specified, num_planes() is NumPlanes(|format|) and // num_buffers() is 0. + // |buffer_addr_align| can be specified to request a specific buffer memory + // alignment. // The returned base::Optional will be base::nullopt if the configured values // are invalid. static base::Optional<VideoFrameLayout> Create(VideoPixelFormat format, @@ -73,7 +80,8 @@ VideoPixelFormat format, const gfx::Size& coded_size, std::vector<Plane> planes, - std::vector<size_t> buffer_sizes = {}); + std::vector<size_t> buffer_sizes = {}, + size_t buffer_addr_align = kBufferAddressAlignment); VideoFrameLayout() = delete; VideoFrameLayout(const VideoFrameLayout&); @@ -101,11 +109,17 @@ // Composes VideoFrameLayout as human readable string. std::string ToString() const; + // Returns the required memory alignment for buffers. + size_t buffer_addr_align() const { + return buffer_addr_align_; + } + private: VideoFrameLayout(VideoPixelFormat format, const gfx::Size& coded_size, std::vector<Plane> planes, - std::vector<size_t> buffer_sizes); + std::vector<size_t> buffer_sizes, + size_t buffer_addr_align); VideoPixelFormat format_; @@ -122,6 +136,11 @@ // Vector of sizes for each buffer, typically greater or equal to the area of // |coded_size_|. std::vector<size_t> buffer_sizes_; + + // Memory address alignment of the buffers. This is only relevant when + // allocating physical memory for the buffer, so it doesn't need to be + // serialized when frames are passed through Mojo. + size_t buffer_addr_align_; }; // Outputs VideoFrameLayout::Plane to stream.
diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc index 94e6b9a..544f747 100644 --- a/media/gpu/v4l2/v4l2_device.cc +++ b/media/gpu/v4l2/v4l2_device.cc
@@ -1288,9 +1288,14 @@ return base::nullopt; } } + + // Some V4L2 devices expect buffers to be page-aligned. We cannot detect + // such devices individually, so set this as a video frame layout property. + constexpr size_t buffer_alignment = 0x1000; + return VideoFrameLayout::CreateWithPlanes( video_format, gfx::Size(pix_mp.width, pix_mp.height), std::move(planes), - std::move(buffer_sizes)); + std::move(buffer_sizes), buffer_alignment); } void V4L2Device::GetSupportedResolution(uint32_t pixelformat,
diff --git a/mojo/public/js/bindings_lite.js b/mojo/public/js/bindings_lite.js index d5d2391f..39c798e 100644 --- a/mojo/public/js/bindings_lite.js +++ b/mojo/public/js/bindings_lite.js
@@ -724,16 +724,37 @@ * @param {number} length * @return {number} */ -mojo.internal.computeArraySize = function(arraySpec, length) { +mojo.internal.computeInlineArraySize = function(arraySpec, value) { if (arraySpec.elementType === mojo.mojom.Bool) { - return mojo.internal.kArrayHeaderSize + (length + 7) >> 3; + return mojo.internal.kArrayHeaderSize + (value.length + 7) >> 3; } else { return mojo.internal.kArrayHeaderSize + - length * arraySpec.elementType.$.arrayElementSize; + value.length * arraySpec.elementType.$.arrayElementSize; } }; /** + * @param {!mojo.internal.ArraySpec} arraySpec + * @param {number} length + * @return {number} + */ +mojo.internal.computeTotalArraySize = function(arraySpec, value) { + const inlineSize = mojo.internal.computeInlineArraySize(arraySpec, value); + if (!arraySpec.elementType.$.computePayloadSize) + return inlineSize; + + let totalSize = inlineSize; + for (let elementValue of value) { + if (!mojo.internal.isNullOrUndefined(elementValue)) { + totalSize += mojo.internal.align( + arraySpec.elementType.$.computePayloadSize(elementValue), 8); + } + } + + return totalSize; +}; + +/** * @param {!DataView} dataView * @param {number} byteOffset * @return {number} @@ -908,7 +929,7 @@ * @param {*} value */ encodeArray(arraySpec, offset, value) { - const arraySize = mojo.internal.computeArraySize(arraySpec, value.length); + const arraySize = mojo.internal.computeInlineArraySize(arraySpec, value); const arrayData = this.message_.allocate(arraySize); const arrayEncoder = new mojo.internal.Encoder(this.message_, arrayData); this.encodeOffset(offset, arrayData.byteOffset); @@ -1573,8 +1594,8 @@ return decoder.decodeString(byteOffset); }, computePayloadSize: function(value) { - return mojo.internal.computeArraySize( - {elementType: mojo.mojom.Uint8}, value.length); + return mojo.internal.computeTotalArraySize( + {elementType: mojo.mojom.Uint8}, value); }, arrayElementSize: 8, isValidObjectKeyType: true, @@ -1604,7 +1625,7 @@ return decoder.decodeArray(arraySpec, byteOffset); }, computePayloadSize: function(value) { - return mojo.internal.computeArraySize(arraySpec, value.length); + return mojo.internal.computeTotalArraySize(arraySpec, value); }, arrayElementSize: 8, isValidObjectKeyType: false, @@ -1637,16 +1658,19 @@ return decoder.decodeMap(mapSpec, byteOffset); }, computePayloadSize: function(value) { - const numEntries = - (value instanceof Map) ? value.size : Object.keys(value).length; + const keys = (value instanceof Map) ? Array.from(value.keys()) : + Object.keys(value); + const values = (value instanceof Map) ? Array.from(value.values()) : + keys.map(k => value[k]); + return mojo.internal.kMapDataSize + - mojo.internal.computeArraySize({elementType: keyType}, numEntries) + - mojo.internal.computeArraySize( + mojo.internal.computeTotalArraySize({elementType: keyType}, keys) + + mojo.internal.computeTotalArraySize( { elementType: valueType, elementNullable: valueNullable, }, - numEntries); + values); }, arrayElementSize: 8, isValidObjectKeyType: false,
diff --git a/net/BUILD.gn b/net/BUILD.gn index 8e9aa787..ae95989 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -475,6 +475,8 @@ "base/network_activity_monitor.h", "base/network_change_notifier.cc", "base/network_change_notifier.h", + "base/network_change_notifier_chromeos.cc", + "base/network_change_notifier_chromeos.h", "base/network_change_notifier_factory.h", "base/network_change_notifier_linux.cc", "base/network_change_notifier_linux.h", @@ -4691,6 +4693,7 @@ "base/mime_util_unittest.cc", "base/net_string_util_unittest.cc", "base/network_activity_monitor_unittest.cc", + "base/network_change_notifier_chromeos_unittest.cc", "base/network_change_notifier_unittest.cc", "base/network_change_notifier_win_unittest.cc", "base/network_interfaces_linux_unittest.cc",
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index 2361ffb..10d9cdcd 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc
@@ -33,6 +33,8 @@ #include "net/base/network_change_notifier_linux.h" #elif defined(OS_MACOSX) #include "net/base/network_change_notifier_mac.h" +#elif defined(OS_CHROMEOS) +#include "net/base/network_change_notifier_chromeos.h" #elif defined(OS_FUCHSIA) #include "net/base/network_change_notifier_fuchsia.h" #endif @@ -206,15 +208,12 @@ new NetworkChangeNotifierWin(); network_change_notifier->WatchForAddressChange(); return network_change_notifier; -#elif defined(OS_CHROMEOS) || defined(OS_ANDROID) - // ChromeOS and Android builds MUST use their own class factory. -#if !defined(OS_CHROMEOS) - // TODO(oshima): ash_shell do not have access to chromeos'es - // notifier yet. Re-enable this when chromeos'es notifier moved to - // chromeos root directory. crbug.com/119298. +#elif defined(OS_ANDROID) + // Android builds MUST use their own class factory. CHECK(false); -#endif return NULL; +#elif defined(OS_CHROMEOS) + return new NetworkChangeNotifierChromeos(); #elif defined(OS_LINUX) return new NetworkChangeNotifierLinux(std::unordered_set<std::string>()); #elif defined(OS_MACOSX)
diff --git a/net/base/network_change_notifier_chromeos.cc b/net/base/network_change_notifier_chromeos.cc new file mode 100644 index 0000000..6eb948b6 --- /dev/null +++ b/net/base/network_change_notifier_chromeos.cc
@@ -0,0 +1,144 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "base/bind.h" +#include "net/base/network_change_notifier_chromeos.h" +#include "net/dns/dns_config_service_posix.h" + +namespace net { + +// DNS config services on Chrome OS are signalled by the network state handler +// rather than relying on watching files in /etc. +class NetworkChangeNotifierChromeos::DnsConfigService + : public net::internal::DnsConfigServicePosix { + public: + DnsConfigService() = default; + ~DnsConfigService() override = default; + + // net::internal::DnsConfigService() overrides. + bool StartWatching() override { + // DNS config changes are handled and notified by the network + // state handlers. + return true; + } + + void OnNetworkChange() { + InvalidateConfig(); + InvalidateHosts(); + ReadNow(); + } +}; + +NetworkChangeNotifierChromeos::NotifierThread::NotifierThread() + : base::Thread("NetworkChangeNotifier") { + DETACH_FROM_SEQUENCE(sequence_checker_); +} + +NetworkChangeNotifierChromeos::NotifierThread::~NotifierThread() { + DCHECK(!Thread::IsRunning()); +} + +void NetworkChangeNotifierChromeos::NotifierThread::OnNetworkChange() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + dns_config_service_->OnNetworkChange(); +} + +void NetworkChangeNotifierChromeos::NotifierThread::Init() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + dns_config_service_.reset(new DnsConfigService()); + dns_config_service_->WatchConfig( + base::BindRepeating(&NetworkChangeNotifier::SetDnsConfig)); + dns_config_service_->OnNetworkChange(); +} + +void NetworkChangeNotifierChromeos::NotifierThread::CleanUp() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + dns_config_service_.reset(); +} + +NetworkChangeNotifierChromeos::NetworkChangeNotifierChromeos() + : NetworkChangeNotifier(NetworkChangeCalculatorParamsChromeos()), + connection_type_(CONNECTION_NONE), + max_bandwidth_mbps_( + NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype( + SUBTYPE_NONE)) { + notifier_thread_.StartWithOptions( + base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); +} + +NetworkChangeNotifierChromeos::~NetworkChangeNotifierChromeos() { + notifier_thread_.Stop(); +} + +void NetworkChangeNotifierChromeos::OnDNSChanged() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + // The Unretained thread pointer is ok here because if the thread gets + // deleted, the callback won't be called. + notifier_thread_.task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + &NetworkChangeNotifierChromeos::NotifierThread::OnNetworkChange, + base::Unretained(¬ifier_thread_))); +} + +void NetworkChangeNotifierChromeos::OnIPAddressChanged() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); +} + +void NetworkChangeNotifierChromeos::OnConnectionChanged( + NetworkChangeNotifier::ConnectionType connection_type) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + { + base::AutoLock scoped_lock(lock_); + connection_type_ = connection_type; + } + NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange(); +} + +void NetworkChangeNotifierChromeos::OnConnectionSubtypeChanged( + NetworkChangeNotifier::ConnectionType connection_type, + NetworkChangeNotifier::ConnectionSubtype connection_subtype) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + double max_bandwidth_mbps = + GetMaxBandwidthMbpsForConnectionSubtype(connection_subtype); + { + base::AutoLock scoped_lock(lock_); + max_bandwidth_mbps_ = max_bandwidth_mbps; + } + NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChange(max_bandwidth_mbps, + connection_type); +} + +NetworkChangeNotifier::ConnectionType +NetworkChangeNotifierChromeos::GetCurrentConnectionType() const { + base::AutoLock scoped_lock(lock_); + return connection_type_; +} + +void NetworkChangeNotifierChromeos::GetCurrentMaxBandwidthAndConnectionType( + double* max_bandwidth_mbps, + ConnectionType* connection_type) const { + base::AutoLock scoped_lock(lock_); + *connection_type = connection_type_; + *max_bandwidth_mbps = max_bandwidth_mbps_; +} + +// static +NetworkChangeNotifier::NetworkChangeCalculatorParams +NetworkChangeNotifierChromeos::NetworkChangeCalculatorParamsChromeos() { + NetworkChangeCalculatorParams params; + // Delay values arrived at by simple experimentation and adjusted so as to + // produce a single signal when switching between network connections. + params.ip_address_offline_delay_ = base::TimeDelta::FromMilliseconds(4000); + params.ip_address_online_delay_ = base::TimeDelta::FromMilliseconds(1000); + params.connection_type_offline_delay_ = + base::TimeDelta::FromMilliseconds(500); + params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(500); + return params; +} + +} // namespace net
diff --git a/net/base/network_change_notifier_chromeos.h b/net/base/network_change_notifier_chromeos.h new file mode 100644 index 0000000..822d3f6c --- /dev/null +++ b/net/base/network_change_notifier_chromeos.h
@@ -0,0 +1,94 @@ +// 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 NET_BASE_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_ +#define NET_BASE_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_ + +#include "base/gtest_prod_util.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread.h" +#include "base/threading/thread_checker.h" +#include "net/base/net_export.h" +#include "net/base/network_change_notifier.h" + +namespace net { + +// A NetworkChangeNotifier that needs to be told about network changes by some +// other object. This class can't directly listen for network changes because +// on ChromeOS only objects running in the browser process can listen for +// network state changes. +class NET_EXPORT NetworkChangeNotifierChromeos : public NetworkChangeNotifier { + public: + NetworkChangeNotifierChromeos(); + ~NetworkChangeNotifierChromeos() override; + + // These methods are used to notify this object that a network property has + // changed. These must be called from the thread that owns this object. + void OnDNSChanged(); + void OnIPAddressChanged(); + void OnConnectionChanged( + NetworkChangeNotifier::ConnectionType connection_type); + void OnConnectionSubtypeChanged( + NetworkChangeNotifier::ConnectionType connection_type, + NetworkChangeNotifier::ConnectionSubtype connection_subtype); + + protected: + // NetworkChangeNotifier overrides. + NetworkChangeNotifier::ConnectionType GetCurrentConnectionType() + const override; + void GetCurrentMaxBandwidthAndConnectionType( + double* max_bandwidth_mbps, + ConnectionType* connection_type) const override; + + private: + FRIEND_TEST_ALL_PREFIXES(NetworkChangeNotifierChromeosTest, + ConnectionTypeFromShill); + friend class NetworkChangeNotifierChromeosTest; + + class DnsConfigService; + + // Thread on which we can run DnsConfigService, which requires a TYPE_IO + // message loop. + class NotifierThread : public base::Thread { + public: + NotifierThread(); + ~NotifierThread() override; + + void OnNetworkChange(); + + protected: + // base::Thread + void Init() override; + void CleanUp() override; + + private: + std::unique_ptr<DnsConfigService> dns_config_service_; + SEQUENCE_CHECKER(sequence_checker_); + + DISALLOW_COPY_AND_ASSIGN(NotifierThread); + }; + + // Calculates parameters used for network change notifier online/offline + // signals. + static NetworkChangeNotifier::NetworkChangeCalculatorParams + NetworkChangeCalculatorParamsChromeos(); + + THREAD_CHECKER(thread_checker_); + + mutable base::Lock lock_; + NetworkChangeNotifier::ConnectionType + connection_type_; // Guarded by |lock_|. + double max_bandwidth_mbps_; // Guarded by |lock_|. + + NotifierThread notifier_thread_; + + DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierChromeos); +}; + +} // namespace net + +#endif // NET_BASE_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_
diff --git a/net/base/network_change_notifier_chromeos_unittest.cc b/net/base/network_change_notifier_chromeos_unittest.cc new file mode 100644 index 0000000..00d7ad2 --- /dev/null +++ b/net/base/network_change_notifier_chromeos_unittest.cc
@@ -0,0 +1,87 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/network_change_notifier_chromeos.h" + +#include "base/test/scoped_task_environment.h" +#include "net/base/network_change_notifier.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace net { + +class NetworkChangeNotifierChromeosTest : public testing::Test { + public: + NetworkChangeNotifierChromeosTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME), + notifier_(new NetworkChangeNotifierChromeos()) {} + + void FastForwardUntilIdle() { + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + } + + NetworkChangeNotifierChromeos* notifier() { return notifier_.get(); } + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + net::NetworkChangeNotifier::DisableForTest mock_notifier_disabler_; + std::unique_ptr<NetworkChangeNotifierChromeos> notifier_; +}; + +class MockIPAddressObserver : public NetworkChangeNotifier::IPAddressObserver { + public: + MOCK_METHOD0(OnIPAddressChanged, void()); +}; + +TEST_F(NetworkChangeNotifierChromeosTest, OnIPAddressChanged) { + testing::StrictMock<MockIPAddressObserver> observer; + NetworkChangeNotifier::AddIPAddressObserver(&observer); + + EXPECT_CALL(observer, OnIPAddressChanged()); + notifier()->OnIPAddressChanged(); + FastForwardUntilIdle(); + + NetworkChangeNotifier::RemoveIPAddressObserver(&observer); +} + +class MockNetworkChangeObserver + : public NetworkChangeNotifier::NetworkChangeObserver { + public: + MOCK_METHOD1(OnNetworkChanged, void(NetworkChangeNotifier::ConnectionType)); +}; + +TEST_F(NetworkChangeNotifierChromeosTest, OnNetworkChanged) { + testing::StrictMock<MockNetworkChangeObserver> observer; + NetworkChangeNotifier::AddNetworkChangeObserver(&observer); + + EXPECT_CALL(observer, + OnNetworkChanged(NetworkChangeNotifier::CONNECTION_NONE)); + EXPECT_CALL(observer, OnNetworkChanged(NetworkChangeNotifier::CONNECTION_3G)); + notifier()->OnConnectionChanged(NetworkChangeNotifier::CONNECTION_3G); + FastForwardUntilIdle(); + + NetworkChangeNotifier::RemoveNetworkChangeObserver(&observer); +} + +class MockMaxBandwidthObserver + : public NetworkChangeNotifier::MaxBandwidthObserver { + public: + MOCK_METHOD2(OnMaxBandwidthChanged, + void(double, NetworkChangeNotifier::ConnectionType)); +}; + +TEST_F(NetworkChangeNotifierChromeosTest, OnMaxBandwidthChanged) { + testing::StrictMock<MockMaxBandwidthObserver> observer; + NetworkChangeNotifier::AddMaxBandwidthObserver(&observer); + + EXPECT_CALL(observer, + OnMaxBandwidthChanged(3.6, NetworkChangeNotifier::CONNECTION_4G)); + notifier()->OnConnectionSubtypeChanged(NetworkChangeNotifier::CONNECTION_4G, + NetworkChangeNotifier::SUBTYPE_HSPA); + FastForwardUntilIdle(); + + NetworkChangeNotifier::RemoveMaxBandwidthObserver(&observer); +} + +} // namespace net
diff --git a/net/dns/dns_config_service_posix_unittest.cc b/net/dns/dns_config_service_posix_unittest.cc index 543fab7..b94a8dce 100644 --- a/net/dns/dns_config_service_posix_unittest.cc +++ b/net/dns/dns_config_service_posix_unittest.cc
@@ -189,6 +189,7 @@ new internal::DnsConfigServicePosix()); service->ReadConfig(base::Bind(&DummyConfigCallback)); service.reset(); + scoped_task_environment.RunUntilIdle(); base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1000)); } @@ -215,6 +216,7 @@ void TearDown() override { ASSERT_TRUE(base::DeleteFile(temp_file_, false)); } + base::test::ScopedTaskEnvironment scoped_task_environment_; bool seen_config_; base::FilePath temp_file_; std::unique_ptr<DnsConfigServicePosix> service_; @@ -223,11 +225,9 @@ // Regression test for https://crbug.com/704662. TEST_F(DnsConfigServicePosixTest, ChangeConfigMultipleTimes) { - base::test::ScopedTaskEnvironment scoped_task_environment; - service_->WatchConfig(base::Bind(&DnsConfigServicePosixTest::OnConfigChanged, base::Unretained(this))); - scoped_task_environment.RunUntilIdle(); + scoped_task_environment_.RunUntilIdle(); for (int i = 0; i < 5; i++) { service_->OnConfigChanged(true); @@ -235,7 +235,7 @@ // called if the new config is different from the old one, so this can't be // ExpectChange(). base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50)); - scoped_task_environment.RunUntilIdle(); + scoped_task_environment_.RunUntilIdle(); } // There should never be more than 4 nameservers in a real config.
diff --git a/net/dns/serial_worker.cc b/net/dns/serial_worker.cc index 815c0d8..520bd3a 100644 --- a/net/dns/serial_worker.cc +++ b/net/dns/serial_worker.cc
@@ -7,11 +7,16 @@ #include "base/bind.h" #include "base/location.h" #include "base/task/post_task.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h" namespace net { -SerialWorker::SerialWorker() : state_(IDLE), weak_factory_(this) {} +SerialWorker::SerialWorker() + : base::RefCountedDeleteOnSequence<SerialWorker>( + base::SequencedTaskRunnerHandle::Get()), + state_(IDLE), + weak_factory_(this) {} SerialWorker::~SerialWorker() = default;
diff --git a/net/dns/serial_worker.h b/net/dns/serial_worker.h index dd2a4f8..01b0058 100644 --- a/net/dns/serial_worker.h +++ b/net/dns/serial_worker.h
@@ -9,7 +9,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" +#include "base/memory/ref_counted_delete_on_sequence.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/task/task_traits.h" @@ -34,7 +34,7 @@ // This implementation avoids locking by using the |state_| member to ensure // that |DoWork| and |OnWorkFinished| cannot execute in parallel. class NET_EXPORT_PRIVATE SerialWorker - : public base::RefCountedThreadSafe<SerialWorker> { + : public base::RefCountedDeleteOnSequence<SerialWorker> { public: SerialWorker(); @@ -48,7 +48,8 @@ bool IsCancelled() const { return state_ == CANCELLED; } protected: - friend class base::RefCountedThreadSafe<SerialWorker>; + friend class base::DeleteHelper<SerialWorker>; + friend class base::RefCountedDeleteOnSequence<SerialWorker>; // protected to allow sub-classing, but prevent deleting virtual ~SerialWorker();
diff --git a/net/http/http_stream_factory_job_controller.cc b/net/http/http_stream_factory_job_controller.cc index d6410c9..205edf85 100644 --- a/net/http/http_stream_factory_job_controller.cc +++ b/net/http/http_stream_factory_job_controller.cc
@@ -259,6 +259,10 @@ DCHECK(!is_websocket_); DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, request_->stream_type()); OnJobSucceeded(job); + + // TODO(bnc): Remove when https://crbug.com/461981 is fixed. + CHECK(request_); + DCHECK(request_->completed()); delegate_->OnStreamReady(used_ssl_config, job->proxy_info(), std::move(stream));
diff --git a/remoting/resources/remoting_strings.grd b/remoting/resources/remoting_strings.grd index 52f0f228..a1d83469 100644 --- a/remoting/resources/remoting_strings.grd +++ b/remoting/resources/remoting_strings.grd
@@ -1364,6 +1364,20 @@ <message name="IDS_HOST_AUTHENTICATION_PROMPT" desc="The prompt to be displayed in the authentication dialog when making changes to the system. The system will add a sentence asking for an administrator's name and password. Mac-only."> <ph name="PRODUCT_NAME">$1<ex>Chrome Remote Desktop</ex></ph> wants to make changes. </message> + <message name="IDS_ACCESSIBILITY_PERMISSION_DIALOG_TITLE" desc="The title of the prompt used to ask the user to enable the Chrome Remote Desktop service in the accessibility section of the privacy and security preferences pane. Mac-only."> + Allow remote users to control this machine + </message> + <message name="IDS_ACCESSIBILITY_PERMISSION_DIALOG_BODY_TEXT" desc="The body text of the prompt used to ask the user to enable the Chrome Remote Desktop service in the accessibility section of the privacy and security preferences pane. Mac-only."> +An additional configuration step is required before you can control this machine remotely using <ph name="PRODUCT_NAME">$1<ex>Chrome Remote Desktop</ex></ph>. + +To enable this functionality, select '<ph name="BUTTON_NAME">$2<ex>Open Preferences</ex></ph>' to display the Security and Privacy preferences pane, then check the box next to '<ph name="SERVICE_SCRIPT_NAME">$3<ex>org.chromium.chromoting.me2me.sh</ex></ph>'. + </message> + <message name="IDS_ACCESSIBILITY_PERMISSION_DIALOG_OPEN_BUTTON" desc="The button text of the prompt used to ask the user to enable the Chrome Remote Desktop service in the accessibility section of the privacy and security preferences pane. Selecting this button will open the security and preferences pane. Mac-only."> + Open Preferences + </message> + <message name="IDS_ACCESSIBILITY_PERMISSION_DIALOG_NOT_NOW_BUTTON" desc="The button text of the prompt used to ask the user to enable the Chrome Remote Desktop service in the accessibility section of the privacy and security preferences pane. Selecting this button will close the dialog. Mac-only."> + Not Now + </message> </if> </messages> </release>
diff --git a/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_BODY_TEXT.png.sha1 b/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_BODY_TEXT.png.sha1 new file mode 100644 index 0000000..70c7357 --- /dev/null +++ b/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_BODY_TEXT.png.sha1
@@ -0,0 +1 @@ +4ed45b5fc798ccd11fc72fece0e5d732fa0f3d39 \ No newline at end of file
diff --git a/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_NOT_NOW_BUTTON.png.sha1 b/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_NOT_NOW_BUTTON.png.sha1 new file mode 100644 index 0000000..70c7357 --- /dev/null +++ b/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_NOT_NOW_BUTTON.png.sha1
@@ -0,0 +1 @@ +4ed45b5fc798ccd11fc72fece0e5d732fa0f3d39 \ No newline at end of file
diff --git a/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_OPEN_BUTTON.png.sha1 b/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_OPEN_BUTTON.png.sha1 new file mode 100644 index 0000000..70c7357 --- /dev/null +++ b/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_OPEN_BUTTON.png.sha1
@@ -0,0 +1 @@ +4ed45b5fc798ccd11fc72fece0e5d732fa0f3d39 \ No newline at end of file
diff --git a/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_TITLE.png.sha1 b/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_TITLE.png.sha1 new file mode 100644 index 0000000..70c7357 --- /dev/null +++ b/remoting/resources/remoting_strings_grd/IDS_ACCESSIBILITY_PERMISSION_DIALOG_TITLE.png.sha1
@@ -0,0 +1 @@ +4ed45b5fc798ccd11fc72fece0e5d732fa0f3d39 \ No newline at end of file
diff --git a/services/network/network_change_manager.cc b/services/network/network_change_manager.cc index 00532f6..a1ed9786 100644 --- a/services/network/network_change_manager.cc +++ b/services/network/network_change_manager.cc
@@ -9,6 +9,7 @@ #include "base/logging.h" #include "net/base/network_change_notifier.h" +#include "net/base/network_change_notifier_chromeos.h" namespace network { @@ -43,6 +44,34 @@ clients_.push_back(std::move(client_ptr)); } +#if defined(OS_CHROMEOS) +void NetworkChangeManager::OnNetworkChanged( + bool dns_changed, + bool ip_address_changed, + bool connection_type_changed, + mojom::ConnectionType new_connection_type, + bool connection_subtype_changed, + mojom::ConnectionSubtype new_connection_subtype) { + DCHECK(network_change_notifier_); + net::NetworkChangeNotifierChromeos* notifier = + static_cast<net::NetworkChangeNotifierChromeos*>( + network_change_notifier_.get()); + if (dns_changed) + notifier->OnDNSChanged(); + if (ip_address_changed) + notifier->OnIPAddressChanged(); + if (connection_type_changed) { + notifier->OnConnectionChanged( + net::NetworkChangeNotifier::ConnectionType(new_connection_type)); + } + if (connection_type_changed || connection_subtype_changed) { + notifier->OnConnectionSubtypeChanged( + net::NetworkChangeNotifier::ConnectionType(new_connection_type), + net::NetworkChangeNotifier::ConnectionSubtype(new_connection_subtype)); + } +} +#endif + size_t NetworkChangeManager::GetNumClientsForTesting() const { return clients_.size(); }
diff --git a/services/network/network_change_manager.h b/services/network/network_change_manager.h index 0800582..6dd4dc9f 100644 --- a/services/network/network_change_manager.h +++ b/services/network/network_change_manager.h
@@ -41,6 +41,16 @@ void RequestNotifications( mojom::NetworkChangeManagerClientPtr client_ptr) override; +#if defined(OS_CHROMEOS) + void OnNetworkChanged( + bool dns_changed, + bool ip_address_changed, + bool connection_type_changed, + mojom::ConnectionType new_connection_type, + bool connection_subtype_changed, + mojom::ConnectionSubtype new_connection_subtype) override; +#endif + size_t GetNumClientsForTesting() const; private:
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc index 6f2838a..6bb321c 100644 --- a/services/network/network_context_unittest.cc +++ b/services/network/network_context_unittest.cc
@@ -239,6 +239,7 @@ NetworkContextTest() : scoped_task_environment_( base::test::ScopedTaskEnvironment::MainThreadType::IO), + network_change_notifier_(net::NetworkChangeNotifier::CreateMock()), network_service_(NetworkService::CreateForTesting()) {} ~NetworkContextTest() override {} @@ -325,6 +326,7 @@ protected: base::test::ScopedTaskEnvironment scoped_task_environment_; + std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; std::unique_ptr<NetworkService> network_service_; // Stores the NetworkContextPtr of the most recently created NetworkContext. // Not strictly needed, but seems best to mimic real-world usage.
diff --git a/services/network/network_service.cc b/services/network/network_service.cc index 9acc02e..7686e91 100644 --- a/services/network/network_service.cc +++ b/services/network/network_service.cc
@@ -89,11 +89,9 @@ // On Android, NetworkChangeNotifier objects are always set up in process // before NetworkService is run. return nullptr; -#elif defined(OS_CHROMEOS) || defined(OS_IOS) || defined(OS_FUCHSIA) - // ChromeOS has its own implementation of NetworkChangeNotifier that lives - // outside of //net. iOS doesn't embed //content. Fuchsia doesn't have an - // implementation yet. - // TODO(xunjieli): Figure out what to do for these 3 platforms. +#elif defined(OS_IOS) || defined(OS_FUCHSIA) + // iOS doesn't embed //content. Fuchsia doesn't have an implementation yet. + // TODO(xunjieli): Figure out what to do for these 2 platforms. NOTIMPLEMENTED(); return nullptr; #endif
diff --git a/services/network/public/mojom/network_change_manager.mojom b/services/network/public/mojom/network_change_manager.mojom index ce157d50..ed0c245 100644 --- a/services/network/public/mojom/network_change_manager.mojom +++ b/services/network/public/mojom/network_change_manager.mojom
@@ -18,6 +18,44 @@ CONNECTION_LAST = CONNECTION_BLUETOOTH }; +// This needs to match the definition of net::ConnectionSubtype. +enum ConnectionSubtype { + SUBTYPE_UNKNOWN = 0, + SUBTYPE_NONE, + SUBTYPE_OTHER, + SUBTYPE_GSM, + SUBTYPE_IDEN, + SUBTYPE_CDMA, + SUBTYPE_1XRTT, + SUBTYPE_GPRS, + SUBTYPE_EDGE, + SUBTYPE_UMTS, + SUBTYPE_EVDO_REV_0, + SUBTYPE_EVDO_REV_A, + SUBTYPE_HSPA, + SUBTYPE_EVDO_REV_B, + SUBTYPE_HSDPA, + SUBTYPE_HSUPA, + SUBTYPE_EHRPD, + SUBTYPE_HSPAP, + SUBTYPE_LTE, + SUBTYPE_LTE_ADVANCED, + SUBTYPE_BLUETOOTH_1_2, + SUBTYPE_BLUETOOTH_2_1, + SUBTYPE_BLUETOOTH_3_0, + SUBTYPE_BLUETOOTH_4_0, + SUBTYPE_ETHERNET, + SUBTYPE_FAST_ETHERNET, + SUBTYPE_GIGABIT_ETHERNET, + SUBTYPE_10_GIGABIT_ETHERNET, + SUBTYPE_WIFI_B, + SUBTYPE_WIFI_G, + SUBTYPE_WIFI_N, + SUBTYPE_WIFI_AC, + SUBTYPE_WIFI_AD, + SUBTYPE_LAST = SUBTYPE_WIFI_AD +}; + // A client interface that subscribes to network change events from // NetworkChangeManager. interface NetworkChangeManagerClient { @@ -43,8 +81,22 @@ OnNetworkChanged(ConnectionType type); }; -// An interface that broadcasts network change events. +// An interface for facilitating notifications of network change events. interface NetworkChangeManager { // Requests to receive notification when there is a network change. RequestNotifications(NetworkChangeManagerClient client_ptr); + + // Notifies the network service that the network configuration has changed. + // This is needed for ChromeOS because only one process can listen for network + // changes from Shill, and currently that has to be the browser process. This + // allows the browser process to forward the network changes to the network + // service. + [EnableIf=is_chromeos] + OnNetworkChanged( + bool dns_changed, + bool ip_address_changed, + bool connection_type_changed, + ConnectionType new_connection_type, + bool connection_subtype_changed, + ConnectionSubtype new_connection_subtype); };
diff --git a/services/viz/public/cpp/compositing/compositor_frame_struct_traits.h b/services/viz/public/cpp/compositing/compositor_frame_struct_traits.h index 0e72b8d..160dd52 100644 --- a/services/viz/public/cpp/compositing/compositor_frame_struct_traits.h +++ b/services/viz/public/cpp/compositing/compositor_frame_struct_traits.h
@@ -28,6 +28,8 @@ } static const viz::RenderPassList& passes(const viz::CompositorFrame& input) { + DCHECK(!input.render_pass_list.empty()); + DCHECK(!input.render_pass_list.back()->output_rect.size().IsEmpty()); return input.render_pass_list; }
diff --git a/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom b/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom index f6f7f5d..2b4f7244 100644 --- a/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom +++ b/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom
@@ -84,13 +84,9 @@ // rid of it. DidReceiveCompositorFrameAck(array<ReturnedResource> resources); - // Notification that a CompositorFrame with given |presentation_token| has - // been turned into light the first time on display (or that it failed). - DidPresentCompositorFrame(uint32 presentation_token, - gfx.mojom.PresentationFeedback feedback); - // Notification for the client to generate a CompositorFrame. - OnBeginFrame(BeginFrameArgs args); + OnBeginFrame(BeginFrameArgs args, + map<uint32, gfx.mojom.PresentationFeedback> presentations); // Inform the client that OnBeginFrame may not be called for some time. OnBeginFramePausedChanged(bool paused);
diff --git a/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter index bdd1987a..e04919fc 100644 --- a/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter
@@ -13,26 +13,6 @@ # https://crbug.com/892357 -KioskUpdateTest.LaunchCachedOfflineEnabledAppNoNetwork -# |NetworkChangeNotifier()| Not implemented. -# https://crbug.com/882610 --ChromeBrowserMainBrowserTest.VariationsServiceStartsRequestOnNetworkChange --NetworkConnectionTrackerBrowserTest.SimulateNetworkServiceCrash --BackgroundFetchBrowserTest.FetchCanBePausedAndResumed --BackgroundFetchBrowserTest.FetchesRunToCompletionAndUpdateTitle_Failed --BackgroundFetchBrowserTest.FetchesRunToCompletionAndUpdateTitle_Fetched --BackgroundFetchBrowserTest.FetchFromChildFrameWithPermissions --BackgroundFetchBrowserTest.FetchFromServiceWorker --BackgroundFetchBrowserTest.OfflineItemCollection_VerifyResourceDownloadedWhenDownloadTotalLargerThanActualSize --BackgroundFetchBrowserTest.OfflineItemCollection_VerifyResourceDownloadedWhenDownloadTotalSmallerThanActualSize - -# Stuck at 'Network not available' page, should be related to the -# |NetworkChangeNotifier()| issue. -# https://crbug.com/882610 --WizardControllerDeviceStateExplicitRequirement/WizardControllerDeviceStateExplicitRequirementTest.ControlFlowForcedReEnrollment/0 --WizardControllerDeviceStateExplicitRequirement/WizardControllerDeviceStateExplicitRequirementTest.ControlFlowForcedReEnrollment/1 --WizardControllerDeviceStateTest.ControlFlowDeviceDisabled --WizardControllerDeviceStateWithInitialEnrollmentTest.ControlFlowInitialEnrollment - # Flaky with error: `Check failed: (sequence_checker_).CalledOnValidSequence()`. -DevToolsSanityTest.DisposeEmptyBrowserContext
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 031413d..8721da8 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -92,7 +92,6 @@ crbug.com/591099 external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html [ Failure ] crbug.com/591099 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-002.html [ Pass ] -crbug.com/591099 external/wpt/css/css-text/white-space/pre-wrap-002.html [ Pass ] crbug.com/40634 external/wpt/css/css-text/white-space/trailing-space-before-br-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/white-space/white-space-pre-wrap-trailing-spaces-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Pass ] @@ -238,7 +237,7 @@ crbug.com/591099 external/wpt/fetch/api/redirect/redirect-count.any.worker.html [ Pass ] crbug.com/591099 external/wpt/fetch/api/request/request-keepalive-quota.html?include=slow-2 [ Pass ] crbug.com/591099 external/wpt/fetch/http-cache/basic-auth-cache-test.html [ Timeout ] -crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure Pass ] +crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ] crbug.com/591099 external/wpt/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html [ Timeout ] crbug.com/591099 external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Pass ] crbug.com/591099 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_parent [ Timeout ] @@ -264,7 +263,7 @@ crbug.com/591099 fast/css-intrinsic-dimensions/height-positioned.html [ Pass ] crbug.com/807708 fast/css-intrinsic-dimensions/width-avoid-floats.html [ Failure ] crbug.com/591099 fast/css/absolute-inline-alignment-2.html [ Pass ] -crbug.com/591099 fast/css/css-properties-position-relative-as-parent-fixed.html [ Failure Pass ] +crbug.com/591099 fast/css/css-properties-position-relative-as-parent-fixed.html [ Failure ] crbug.com/835484 fast/css/focus-ring-recursive-continuations.html [ Failure ] crbug.com/835484 fast/css/outline-narrowLine.html [ Failure ] crbug.com/591099 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under.html [ Failure ] @@ -279,10 +278,8 @@ crbug.com/835484 fast/inline/inline-focus-ring-under-absolute-enclosing-relative-div.html [ Failure ] crbug.com/889721 fast/inline/outline-continuations.html [ Failure ] crbug.com/591099 fast/overflow/overflow-update-transform.html [ Failure ] -crbug.com/591099 fast/overflow/scrollRevealButton.html [ Pass ] crbug.com/591099 fast/replaced/replaced-breaking.html [ Failure Pass ] crbug.com/591099 fast/scroll-snap/snaps-after-keyboard-scrolling-rtl.html [ Failure ] -crbug.com/591099 fast/scrolling/editor-command-scroll-page-scale.html [ Pass ] crbug.com/591099 fast/sub-pixel/sub-pixel-border-2.html [ Failure ] crbug.com/591099 fast/table/height-percent-test-vertical.html [ Failure ] crbug.com/591099 fast/table/unbreakable-images-quirk.html [ Failure ] @@ -318,11 +315,12 @@ crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ] crbug.com/591099 http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Crash ] crbug.com/591099 http/tests/webaudio/autoplay-crossorigin.html [ Failure Timeout ] -crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Crash Pass Timeout ] +crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Crash Pass ] crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-pseudo-element.js [ Failure ] crbug.com/714962 inspector-protocol/layout-fonts/languages-emoji-rare-glyphs.js [ Failure ] crbug.com/591099 inspector-protocol/timeline/page-frames.js [ Failure ] crbug.com/591099 intersection-observer/v2/text-shadow.html [ Failure ] +crbug.com/591099 media/controls/buttons-after-reset.html [ Failure Pass ] crbug.com/591099 media/controls/lazy-loaded-style.html [ Failure ] crbug.com/591099 paint/float/float-under-inline-self-painting-change.html [ Failure ] crbug.com/835484 paint/inline/focus-ring-under-absolute-with-relative-continuation.html [ Failure ] @@ -356,9 +354,9 @@ crbug.com/591099 paint/invalidation/table/table-two-pass-layout-overpaint.html [ Failure ] crbug.com/591099 printing/absolute-position-headers-and-footers.html [ Failure ] crbug.com/591099 printing/iframe-svg-in-object-print.html [ Failure ] -crbug.com/591099 rootscroller/rootscroller-during-fullscreen.html [ Pass ] +crbug.com/591099 printing/single-line-must-not-be-split-into-two-pages.html [ Failure ] crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ] -crbug.com/591099 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Pass Timeout ] +crbug.com/591099 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Pass ] crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ] crbug.com/591099 svg/zoom/page/zoom-img-preserveAspectRatio-support-1.html [ Failure ] crbug.com/591099 svg/zoom/page/zoom-svg-float-border-padding.xml [ Pass ] @@ -372,7 +370,7 @@ crbug.com/591099 tables/mozilla/bugs/bug50695-2.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug55527.html [ Failure ] crbug.com/870008 virtual/android/rootscroller/position-fixed-in-unscrollable-document-iframe.html [ Failure Pass ] -crbug.com/591099 virtual/android/rootscroller/set-root-scroller.html [ Failure ] +crbug.com/591099 virtual/android/rootscroller/set-root-scroller.html [ Failure Pass ] crbug.com/591099 virtual/android/rootscroller/set-rootscroller-before-load.html [ Pass ] crbug.com/591099 virtual/android/url-bar/bottom-and-top-fixed-sticks-to-top.html [ Failure ] crbug.com/591099 virtual/exotic-color-space/ [ Skip ] @@ -418,6 +416,5 @@ crbug.com/591099 virtual/user-activation-v2/fast/events/mouse-cursor.html [ Failure ] crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ] crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects.html [ Failure ] -crbug.com/591099 virtual/user-activation-v2/fast/events/touch/gesture/touch-gesture-scroll-input-field.html [ Pass ] crbug.com/591099 virtual/video-surface-layer/media/stable/video-object-fit-stable.html [ Failure ] crbug.com/591099 virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Pass ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json index b1036086..09ec427 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
@@ -47161,6 +47161,42 @@ {} ] ], + "css/css-grid/grid-model/grid-container-scrollbar-001.html": [ + [ + "/css/css-grid/grid-model/grid-container-scrollbar-001.html", + [ + [ + "/css/css-grid/grid-model/grid-container-scrollbar-001-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001.html": [ + [ + "/css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001.html", + [ + [ + "/css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001.html": [ + [ + "/css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001.html", + [ + [ + "/css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-grid/grid-model/grid-display-grid-001.html": [ [ "/css/css-grid/grid-model/grid-display-grid-001.html", @@ -133973,6 +134009,21 @@ {} ] ], + "css/css-grid/grid-model/grid-container-scrollbar-001-ref.html": [ + [ + {} + ] + ], + "css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001-ref.html": [ + [ + {} + ] + ], + "css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001-ref.html": [ + [ + {} + ] + ], "css/css-grid/grid-model/support/grid.css": [ [ {} @@ -336419,6 +336470,30 @@ "140d7bf115115043a844ac83852efc842340d42c", "testharness" ], + "css/css-grid/grid-model/grid-container-scrollbar-001-ref.html": [ + "31a9ef3db8e08d76b218a4f2bf1ea5cde5d889b3", + "support" + ], + "css/css-grid/grid-model/grid-container-scrollbar-001.html": [ + "1b3c6eef691d9959b4bc899b3d88c9c7e3f57e28", + "reftest" + ], + "css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001-ref.html": [ + "512fb8a81d57788eb06e004982de9c897df3dd0f", + "support" + ], + "css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001.html": [ + "ecdc7b768406922628b1bcf2e17b6ba7ee6b162b", + "reftest" + ], + "css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001-ref.html": [ + "d8eeedfa07d572d5150e2e480b572769273fc1f3", + "support" + ], + "css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001.html": [ + "f2ab39ff505401436e23947feea4bffbff12629c", + "reftest" + ], "css/css-grid/grid-model/grid-display-grid-001.html": [ "732d67c8ec1a55adc09af9bf7a3cae59d03152aa", "reftest" @@ -428948,7 +429023,7 @@ "support" ], "service-workers/service-worker/navigation-redirect.https.html": [ - "6f03fd8f2f0db54f4895d284a2ced78723d9965c", + "e8b8e9afd5820acf9422d11f4410c0158fa31732", "testharness" ], "service-workers/service-worker/navigation-redirect.https_client-expected.txt": [ @@ -429948,7 +430023,7 @@ "support" ], "service-workers/service-worker/resources/redirect-worker.js": [ - "0c5bc3bd9aa5bff83df74ce5e0a8a244f21a85a7", + "ddcc2cf5478942292dc8c5e30d156dc42886365e", "support" ], "service-workers/service-worker/resources/redirect.py": [ @@ -438464,7 +438539,7 @@ "testharness" ], "webrtc/RTCConfiguration-rtcpMuxPolicy.html": [ - "1d99aa29d85a5dabddf21bc4d758c6cdf96ff9c2", + "7d0c81f5eabfddd5fbe66a2eab60ebb6fcec33f5", "testharness" ], "webrtc/RTCDTMFSender-helper.js": [ @@ -438680,7 +438755,7 @@ "support" ], "webrtc/RTCPeerConnection-iceGatheringState.html": [ - "fb9e514194b98062acc3fdd33111a2d740bb9d52", + "e6d8d062701a795a289ad011fa4cfae143a342e9", "testharness" ], "webrtc/RTCPeerConnection-ondatachannel-expected.txt": [ @@ -438696,7 +438771,7 @@ "support" ], "webrtc/RTCPeerConnection-onnegotiationneeded.html": [ - "8f9ea2be7806efc18b7511d27634d4c1f5dacf0c", + "7e55ac3fadd046f8805174c3d9b1de92f704ca12", "testharness" ], "webrtc/RTCPeerConnection-ontrack.https-expected.txt": [ @@ -438760,7 +438835,7 @@ "support" ], "webrtc/RTCPeerConnection-setLocalDescription-rollback.html": [ - "0147b3185cce20c7345fe640dd6e466209d0e3ca", + "630f84faa47f2d8589989674a2cb6d39797520ac", "testharness" ], "webrtc/RTCPeerConnection-setLocalDescription.html": [ @@ -438780,7 +438855,7 @@ "support" ], "webrtc/RTCPeerConnection-setRemoteDescription-offer.html": [ - "565fddc59be02c409835749aac090db1af7a38af", + "cae62b24b6c180c06be87dd48ffac364427624db", "testharness" ], "webrtc/RTCPeerConnection-setRemoteDescription-pranswer.html": [ @@ -438800,7 +438875,7 @@ "support" ], "webrtc/RTCPeerConnection-setRemoteDescription-rollback.html": [ - "ec90e561cbcf76559356dcd46c77547fb8262dcb", + "c317f3e1ae690a3e0101a5c596f0108ff23e822a", "testharness" ], "webrtc/RTCPeerConnection-setRemoteDescription-tracks.https-expected.txt": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCConfiguration-rtcpMuxPolicy.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCConfiguration-rtcpMuxPolicy.html index 1d99aa29..7d0c81f5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCConfiguration-rtcpMuxPolicy.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCConfiguration-rtcpMuxPolicy.html
@@ -3,6 +3,7 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="RTCConfiguration-helper.js"></script> +<script src="RTCPeerConnection-helper.js"></script> <script> 'use strict'; @@ -188,8 +189,8 @@ const pc = new RTCPeerConnection({rtcpMuxPolicy: 'require'}); t.add_cleanup(() => pc.close()); - await pc.createOffer({offerToReceiveAudio: true}) - .then(offer => pc.setLocalDescription(offer)); + const offer = await generateAudioReceiveOnlyOffer(pc); + await pc.setLocalDescription(offer); return promise_rejects(t, 'InvalidAccessError', pc.setRemoteDescription({type: 'answer', sdp})); }, 'setRemoteDescription throws InvalidAccessError when called with an answer without rtcp-mux and rtcpMuxPolicy is set to require'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-iceGatheringState.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-iceGatheringState.html index fb9e514..e6d8d062 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-iceGatheringState.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-iceGatheringState.html
@@ -11,8 +11,9 @@ // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html // The following helper functions are called from RTCPeerConnection-helper.js: - // exchangeIceCandidates // doSignalingHandshake + // exchangeIceCandidates + // generateAudioReceiveOnlyOffer /* 4.3.2. Interface Definition @@ -72,7 +73,7 @@ pc.addEventListener('icegatheringstatechange', onIceGatheringStateChange); - pc.createOffer({ offerToReceiveAudio: true }) + generateAudioReceiveOnlyOffer(pc) .then(offer => pc.setLocalDescription(offer)) .then(err => t.step_func(err => assert_unreached(`Unhandled rejection ${err.name}: ${err.message}`)));
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html index 8f9ea2be..7e55ac3 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html
@@ -12,6 +12,7 @@ // The following helper functions are called from RTCPeerConnection-helper.js: // generateAnswer + // generateAudioReceiveOnlyOffer // test_never_resolve // Listen to the negotiationneeded event on a peer connection @@ -165,7 +166,7 @@ const pc = new RTCPeerConnection(); const negotiated = awaitNegotiation(pc); - return pc.createOffer({ offerToReceiveAudio: true }) + return generateAudioReceiveOnlyOffer(pc) .then(offer => pc.setLocalDescription(offer)) .then(() => negotiated) .then(({nextPromise}) => { @@ -190,7 +191,7 @@ return assert_first_promise_fulfill_after_second( awaitNegotiation(pc), - pc.createOffer({ offerToReceiveAudio: true }) + generateAudioReceiveOnlyOffer(pc) .then(offer => pc.setLocalDescription(offer) .then(() => {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-rollback.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-rollback.html index 0147b31..630f84f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-rollback.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-rollback.html
@@ -12,6 +12,7 @@ // The following helper functions are called from RTCPeerConnection-helper.js: // assert_session_desc_similar + // generateAudioReceiveOnlyOffer /* 4.3.2. Interface Definition @@ -105,7 +106,7 @@ promise_test(t => { const pc = new RTCPeerConnection(); t.add_cleanup(() => pc.close()); - return pc.createOffer({ offerToReceiveAudio: true }) + return generateAudioReceiveOnlyOffer(pc) .then(offer => pc.setRemoteDescription(offer) .then(() => pc.createAnswer()))
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-offer.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-offer.html index 565fddc5..cae62b24 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-offer.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-offer.html
@@ -12,6 +12,7 @@ // The following helper functions are called from RTCPeerConnection-helper.js: // assert_session_desc_similar() + // generateAudioReceiveOnlyOffer /* 4.3.2. Interface Definition @@ -115,7 +116,7 @@ .then(offer1 => { return pc1.setLocalDescription(offer1) .then(()=> { - return pc1.createOffer({ offerToReceiveAudio: true }) + return generateAudioReceiveOnlyOffer(pc1) .then(offer2 => { assert_session_desc_not_similar(offer1, offer2);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html index ec90e56..c317f3e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html
@@ -11,8 +11,9 @@ // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html // The following helper functions are called from RTCPeerConnection-helper.js: - // generateDataChannelOffer // assert_session_desc_similar + // generateAudioReceiveOnlyOffer + // generateDataChannelOffer /* 4.3.2. Interface Definition @@ -105,7 +106,7 @@ promise_test(t => { const pc = new RTCPeerConnection(); t.add_cleanup(() => pc.close()); - return pc.createOffer({ offerToReceiveAudio: true }) + return generateAudioReceiveOnlyOffer(pc) .then(offer => pc.setRemoteDescription(offer)) .then(() => pc.setRemoteDescription({ type: 'rollback',
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Range/range-expand-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Range/range-expand-expected.txt deleted file mode 100644 index a7246497..0000000 --- a/third_party/WebKit/LayoutTests/fast/dom/Range/range-expand-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -CONSOLE WARNING: line 57: 'Range.expand()' is deprecated. Please use 'Selection.modify()' instead. -This is the begin of a block. A block is a collection of sentences. Each sentence begins with capital letter and ends with a punctuation. - -Now, a sentence is divided into multiple lines. - -Roll the mouse around the page. The coordinates of the mouse pointer are currently atop an element -whose ID is:"". - -Cell A1 Cell B1 -Cell A2 Cell B2 -Section 1 - -text. - -Section 2 - -text. - -Here is a positioned element. -在甲型H1N1流感可能出现大流行的警告声中,昨天召开的江苏省2009-2010年度流感防制研讨会注定与往年不同。每年都会召开的一次例会,今年足足提前了一个月;会上研讨的主题,已从以前的季节性流感,变成以甲型H1N1流感为重点。 -בלשכת שר החוץ הגיבו להתקפות עליו בעקבות הנחייתו לדרוש מהמועמדים לקורס צוערים שירות צבאי או לאומי: "המתקיפים צבועים, מי שרוצה לייצג את המדינה רוצה גם לשרת אותה"
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Range/range-expand.html b/third_party/WebKit/LayoutTests/fast/dom/Range/range-expand.html index b453547f..cbae6e7 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/Range/range-expand.html +++ b/third_party/WebKit/LayoutTests/fast/dom/Range/range-expand.html
@@ -1,205 +1,230 @@ +<!doctype html> <html> <head> <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=UTF-8"> <title>Test for Range.expand()</title> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> <script> -function log(str) -{ - var li = document.createElement("li"); - li.appendChild(document.createTextNode(str)); - var console = document.getElementById("console"); - console.appendChild(li); +function expandRangeString(startId, startOffset, endId, endOffset, expandUnit, firstChild) { + const range = document.createRange(); + let startNode = document.getElementById(startId); + if (firstChild == true) + startNode = startNode.firstChild; + let endNode = document.getElementById(endId); + if (firstChild == true) + endNode = endNode.firstChild; + range.setStart(startNode, startOffset); + range.setEnd(endNode, endOffset); + range.expand(expandUnit); + return range.toString(); } -function assertEqual(test_name, actual, expected) -{ - if (actual != expected) { - log("=================================="); - log("FAILED test " + test_name); - log("actual: " + actual); - log("expected: " + expected); - if (actual.length != expected.length) { - log("length !=" + "; actual.length: " + actual.length + "; expected.length: " + expected.length); - log("escaped actual: " + escape(actual)); - log("escaped expected: " + escape(expected)); - var length = actual.length; - if (actual.length > expected.length) - length = expected.length; - for (var i=0; i<length; ++i) { - log("i: " + i + "; actual: " + actual[i] + "; expected: " + expected[i]); - if (actual[i] != expected[i]) - log("!="); - } - } - else { - log("actual: " + escape(actual)); - log("expected: " + escape(expected)); - for (var i=0; i<actual.length; ++i) { - log("i: " + i + "; actual: " + actual[i] + "; expected: " + expected[i]); - if (actual[i] != expected[i]) - log("!="); - } - - } - } -} +function runTests() { + // test 1 - Expand to document. + test(() => { + const actual = expandRangeString('myspan', 0, 'myspan', 0, 'document', false); + const expected = 'This is the begin of a block. A block is a collection of sentences. Each sentence begins with capital\x0Aletter and ends with a punctuation.\x0A\x0ANow, a sentence\x0Ais divided into\x0Amultiple lines.\x0A\x0ARoll the mouse around the page. The coordinates\x0Aof the mouse pointer are currently atop an elementwhose ID \x0Ais:"".\x0A\x0A\x0A\x0A Cell A1\x0A Cell B1\x0A\x0A\x0A Cell A2\x0A Cell B2\x0A\x0A\x0ASection 1\x0Atext.\x0ASection 2\x0Atext.\x0A\x0AHere is a positioned element.\x0A在甲型H1N1流感可能出现大流行的警告声中,昨天召开的江苏省2009-2010年度流感防制研讨会注定与往年不同。每年都会召开的一次例会,今年足足提前了一个月;会上研讨的主题,已从以前的季节性流感,变成以甲型H1N1流感为重点。\x0Aבלשכת שר החוץ הגיבו להתקפות עליו בעקבות הנחייתו לדרוש מהמועמדים לקורס צוערים שירות צבאי או לאומי: "המתקיפים צבועים, מי שרוצה לייצג את המדינה רוצה גם לשרת אותה"' + assert_equals(actual, expected); + }, 'document1'); -function expandRangeString(range, startId, startOffset, endId, endOffset, expandUnit, firstChild) -{ - var startNode = document.getElementById(startId); - if (firstChild == true) - startNode = startNode.firstChild; - var endNode = document.getElementById(endId); - if (firstChild == true) - endNode = endNode.firstChild; - range.setStart(startNode, startOffset); - range.setEnd(endNode, endOffset); - range.expand(expandUnit); - return range.toString(); -} + // test 2 - Expand to block. + test(() => { + const actual = expandRangeString('td_A1', 0, 'td_A1', 0, 'block', false); + assert_equals(actual, 'Cell A1'); + }, 'block2'); -function test() -{ - if (window.testRunner) - testRunner.dumpAsText(); + // test 3 - Expand to block, different range start and end offset. + test(() => { + const actual = expandRangeString('td_A1', 1, 'td_A1', 2, 'block', true); + assert_equals(actual, 'Cell A1'); + }, 'block3'); - // test 1 - Expand to document. - var range = document.createRange(); - var actual = expandRangeString(range, 'myspan', 0, 'myspan', 0, 'document', false); - var expected = 'This is the begin of a block. A block is a collection of sentences. Each sentence begins with capital\x0Aletter and ends with a punctuation.\x0A\x0ANow, a sentence\x0Ais divided into\x0Amultiple lines.\x0A\x0ARoll the mouse around the page. The coordinates\x0Aof the mouse pointer are currently atop an elementwhose ID \x0Ais:"".\x0A\x0A\x0A\x0A Cell A1\x0A Cell B1\x0A\x0A\x0A Cell A2\x0A Cell B2\x0A\x0A\x0ASection 1\x0Atext.\x0ASection 2\x0Atext.\x0A\x0AHere is a positioned element.\x0A在甲型H1N1流感可能出现大流行的警告声中,昨天召开的江苏省2009-2010年度流感防制研讨会注定与往年不同。每年都会召开的一次例会,今年足足提前了一个月;会上研讨的主题,已从以前的季节性流感,变成以甲型H1N1流感为重点。\x0Aבלשכת שר החוץ הגיבו להתקפות עליו בעקבות הנחייתו לדרוש מהמועמדים לקורס צוערים שירות צבאי או לאומי: "המתקיפים צבועים, מי שרוצה לייצג את המדינה רוצה גם לשרת אותה"' - assertEqual("document1", actual, expected); + // test 4 - Expand to block, different range start and end node. + test(() => { + const actual = expandRangeString('td_A1', 0, 'td_B1', 0, 'block', false); + assert_equals(actual, 'Cell A1\x0A Cell B1'); + }, 'block4'); - // test 2 - Expand to block. - actual = expandRangeString(range, 'td_A1', 0, 'td_A1', 0, 'block', false); - assertEqual("block2", actual, "Cell A1"); + // test 5 - Expand to sentence. + test(() => { + const actual = expandRangeString('instructions', 0, 'instructions', 0, 'sentence', false); + assert_equals(actual, 'Roll the mouse around the page. '); + }, 'sentence5'); - // test 3 - Expand to block, different range start and end offset. - actual = expandRangeString(range, 'td_A1', 1, 'td_A1', 2, 'block', true); - assertEqual("block3", actual, "Cell A1"); + // test 6 - Expand to sentence, different range start and end offset. + test(() => { + const actual = expandRangeString('instructions', 1, 'instructions', 2, 'sentence', true); + assert_equals(actual, 'Roll the mouse around the page. '); + }, 'sentence6'); - // test 4 - Expand to block, different range start and end node. - actual = expandRangeString(range, 'td_A1', 0, 'td_B1', 0, 'block', false); - assertEqual("block4", actual, "Cell A1\x0A Cell B1"); + // test 7 - Expand to sentence, different range start and end node. + test(() => { + const actual = expandRangeString('instructions', 0, 'mybr', 0, 'sentence', false); + assert_equals(actual, 'Roll the mouse around the page. The coordinates\x0Aof the mouse pointer are currently atop an element'); + }, 'sentence7'); - // test 5 - Expand to sentence. - actual = expandRangeString(range, 'instructions', 0, 'instructions', 0, 'sentence', false); - assertEqual("sentence5", actual, "Roll the mouse around the page. "); + // test 8 + test(() => { + const actual = expandRangeString('multilineSentence', 0, 'multilineSentence', 0, 'sentence', false); + assert_equals(actual, 'Now, a sentence\n'); + }, 'sentence8'); - // test 6 - Expand to sentence, different range start and end offset. - actual = expandRangeString(range, 'instructions', 1, 'instructions', 2, 'sentence', true); - assertEqual("sentence6", actual, "Roll the mouse around the page. "); + test(() => { + const actual = expandRangeString('multilineSentence', 1, 'multilineSentence', 5, 'sentence', true); + assert_equals(actual, 'Now, a sentence\n'); + }, 'sentence9'); - // test 7 - Expand to sentence, different range start and end node. - actual = expandRangeString(range, 'instructions', 0, 'mybr', 0, 'sentence', false); - assertEqual("sentence7", actual, "Roll the mouse around the page. The coordinates\x0Aof the mouse pointer are currently atop an element"); + test(() => { + const actual = expandRangeString('multilineSentence', 20, 'multilineSentence', 20, 'sentence', true); + assert_equals(actual, 'is divided into\n'); + }, 'sentence10'); - // test 8 - Sentence does not go upstream? - actual = expandRangeString(range, 'multilineSentence', 0, 'multilineSentence', 0, 'sentence', false); - assertEqual("sentence8", actual, "Now, a sentence\x0Ais divided into\x0Amultiple lines."); - - actual = expandRangeString(range, 'multilineSentence', 1, 'multilineSentence', 5, 'sentence', true); - assertEqual("sentence9", actual, "Now, a sentence\x0Ais divided into\x0Amultiple lines."); - - actual = expandRangeString(range, 'multilineSentence', 20, 'multilineSentence', 20, 'sentence', true); - assertEqual("sentence10", actual, "is divided into\x0Amultiple lines."); - - actual = expandRangeString(range, 'multilineSentence', 40, 'multilineSentence', 40, 'sentence', true); - assertEqual("sentence11", actual, "multiple lines."); - - // Expand word. - // Same range start and end, both at the begin of word. - actual = expandRangeString(range, 'mydiv', 0, 'mydiv', 0, 'word', false); - assertEqual("word1", actual, "Here"); - - // Same range start and end, both at the begin of a word. - actual = expandRangeString(range, 'mydiv', 1, 'mydiv', 1, 'word', true); - assertEqual("word2", actual, "Here"); - - // Same range start and end, both at the middle of a word. - actual = expandRangeString(range, 'mydiv', 3, 'mydiv', 3, 'word', true); - assertEqual("word3", actual, "Here"); - - // Same range start and end, both at the end of a word. - actual = expandRangeString(range, 'mydiv', 4, 'mydiv', 4, 'word', true); - assertEqual("word4", actual, "Here"); - - // Different range start and end offset, both at the middle of a word. - actual = expandRangeString(range, 'mydiv', 2, 'mydiv', 3, 'word', true); - assertEqual("word5", actual, "Here"); - - // Different range start and end offset, start at the begin of a word, - // and end at the end of a word. - actual = expandRangeString(range, 'mydiv', 5, 'mydiv', 4, 'word', true); - assertEqual("word6", actual, "Here"); - - // Different range start and end offset, start at the begin of a word, - // and end at the middle of a word. - actual = expandRangeString(range, 'mydiv', 1, 'mydiv', 3, 'word', true); - assertEqual("word7", actual, "Here"); - - // Different range start and end offset, start at the middle of a word, - // and end at the end of a word. - actual = expandRangeString(range, 'mydiv', 2, 'mydiv', 4, 'word', true); - assertEqual("word8", actual, "Here"); - - // Across more than 1 word. - // Start at the begin of 1st word, end at the end of last word. - actual = expandRangeString(range, 'mydiv', 1, 'mydiv', 7, 'word', true); - assertEqual("word9", actual, "Here is"); - - // Start at the middle of 1st word, end at the middle of last word. - actual = expandRangeString(range, 'mydiv', 2, 'mydiv', 6, 'word', true); - assertEqual("word10", actual, "Here is"); + test(() => { + const actual = expandRangeString('multilineSentence', 40, 'multilineSentence', 40, 'sentence', true); + assert_equals(actual, 'multiple lines.'); + }, 'sentence11'); - // Start at the begin of 1st word, end at the middle of last word. - actual = expandRangeString(range, 'mydiv', 1, 'mydiv', 6, 'word', true); - assertEqual("word11", actual, "Here is"); + // Expand word. + // Same range start and end, both at the begin of word. + test(() => { + const actual = expandRangeString('mydiv', 0, 'mydiv', 0, 'word', false); + assert_equals(actual, 'Here'); + }, 'word1'); - // Start at the middle of 1st word, end at the end of last word. - actual = expandRangeString(range, 'mydiv', 2, 'mydiv', 7, 'word', true); - assertEqual("word12", actual, "Here is"); + // Same range start and end, both at the begin of a word. + test(() => { + const actual = expandRangeString('mydiv', 1, 'mydiv', 1, 'word', true); + assert_equals(actual, 'Here'); + }, 'word2'); - // Word and space. - actual = expandRangeString(range, 'mydiv', 4, 'mydiv', 5, 'word', true); - assertEqual("word13", actual, "Here "); + // Same range start and end, both at the middle of a word. + test(() => { + const actual = expandRangeString('mydiv', 3, 'mydiv', 3, 'word', true); + assert_equals(actual, 'Here'); + }, 'word3'); - // Word across different nodes. - actual = expandRangeString(range, 'mydiv', 1, 'he-div', 0, 'word', true); - assertEqual("word14", actual, "Here is a positioned element.\x0A在甲型H1N1流感可能出现大流行的警告声中,昨天召开的江苏省2009-2010年度流感防制研讨会注定与往年不同。每年都会召开的一次例会,今年足足提前了一个月;会上研讨的主题,已从以前的季节性流感,变成以甲型H1N1流感为重点。\x0Aבלשכת"); + // Same range start and end, both at the end of a word. + test(() => { + const actual = expandRangeString('mydiv', 4, 'mydiv', 4, 'word', true); + assert_equals(actual, 'Here'); + }, 'word4'); - // Test for Chinese. No Chinese segmentation in platform/mac. - actual = expandRangeString(range, 'zh-CN-div', 0, 'zh-CN-div', 0, 'word', true); - assertEqual("Chinese word0", actual, "在"); - actual = expandRangeString(range, 'zh-CN-div', 1, 'zh-CN-div', 1, 'word', true); - assertEqual("Chinese word1", actual, "甲"); - actual = expandRangeString(range, 'zh-CN-div', 2, 'zh-CN-div', 2, 'word', true); - assertEqual("Chinese word1", actual, "型"); + // Different range start and end offset, both at the middle of a word. + test(() => { + const actual = expandRangeString('mydiv', 2, 'mydiv', 3, 'word', true); + assert_equals(actual, 'Here'); + }, 'word5'); - actual = expandRangeString(range, 'zh-CN-div', 3, 'zh-CN-div', 3, 'sentence', true); - assertEqual("Chinese sentence: ", actual, "在甲型H1N1流感可能出现大流行的警告声中,昨天召开的江苏省2009-2010年度流感防制研讨会注定与往年不同。"); + // Different range start and end offset, start at the begin of a word, + // and end at the end of a word. + test(() => { + const actual = expandRangeString('mydiv', 5, 'mydiv', 4, 'word', true); + assert_equals(actual, 'Here'); + }, 'word6'); - actual = expandRangeString(range, 'zh-CN-div', 3, 'zh-CN-div', 3, 'block', true); - assertEqual("Chinese block: ", actual, "在甲型H1N1流感可能出现大流行的警告声中,昨天召开的江苏省2009-2010年度流感防制研讨会注定与往年不同。每年都会召开的一次例会,今年足足提前了一个月;会上研讨的主题,已从以前的季节性流感,变成以甲型H1N1流感为重点。"); + // Different range start and end offset, start at the begin of a word, + // and end at the middle of a word. + test(() => { + const actual = expandRangeString('mydiv', 1, 'mydiv', 3, 'word', true); + assert_equals(actual, 'Here'); + }, 'word7'); - // Test for Hebrew. - actual = expandRangeString(range, 'he-div', 1, 'he-div', 1, 'word', true); - assertEqual("Hebrew word", actual, "בלשכת"); + // Different range start and end offset, start at the middle of a word, + // and end at the end of a word. + test(() => { + const actual = expandRangeString('mydiv', 2, 'mydiv', 4, 'word', true); + assert_equals(actual, 'Here'); + }, 'word8'); - actual = expandRangeString(range, 'he-div', 1, 'he-div', 1, 'sentence', true); - assertEqual("Hebrew sentence", actual, 'בלשכת שר החוץ הגיבו להתקפות עליו בעקבות הנחייתו לדרוש מהמועמדים לקורס צוערים שירות צבאי או לאומי: "המתקיפים צבועים, מי שרוצה לייצג את המדינה רוצה גם לשרת אותה"' ); + // Across more than 1 word. + // Start at the begin of 1st word, end at the end of last word. + test(() => { + const actual = expandRangeString('mydiv', 1, 'mydiv', 7, 'word', true); + assert_equals(actual, 'Here is'); + }, 'word9'); - actual = expandRangeString(range, 'he-div', 0, 'he-div', 0, 'sentence', false); - assertEqual("Hebrew block", actual, 'בלשכת שר החוץ הגיבו להתקפות עליו בעקבות הנחייתו לדרוש מהמועמדים לקורס צוערים שירות צבאי או לאומי: "המתקיפים צבועים, מי שרוצה לייצג את המדינה רוצה גם לשרת אותה"' ); + // Start at the middle of 1st word, end at the middle of last word. + test(() => { + const actual = expandRangeString('mydiv', 2, 'mydiv', 6, 'word', true); + assert_equals(actual, 'Here is'); + }, 'word10'); + + // Start at the begin of 1st word, end at the middle of last word. + test(() => { + const actual = expandRangeString('mydiv', 1, 'mydiv', 6, 'word', true); + assert_equals(actual, 'Here is'); + }, 'word11'); + + // Start at the middle of 1st word, end at the end of last word. + test(() => { + const actual = expandRangeString('mydiv', 2, 'mydiv', 7, 'word', true); + assert_equals(actual, 'Here is'); + }, 'word12'); + + // Word and space. + test(() => { + const actual = expandRangeString('mydiv', 4, 'mydiv', 5, 'word', true); + assert_equals(actual, 'Here '); + }, 'word13'); + + // Word across different nodes. + test(() => { + const actual = expandRangeString('mydiv', 1, 'he-div', 0, 'word', true); + assert_equals(actual, 'Here is a positioned element.\x0A在甲型H1N1流感可能出现大流行的警告声中,昨天召开的江苏省2009-2010年度流感防制研讨会注定与往年不同。每年都会召开的一次例会,今年足足提前了一个月;会上研讨的主题,已从以前的季节性流感,变成以甲型H1N1流感为重点。\x0Aבלשכת'); + }, 'word14'); + + // Test for Chinese. No Chinese segmentation in platform/mac. + test(() => { + const actual = expandRangeString('zh-CN-div', 0, 'zh-CN-div', 0, 'word', true); + assert_equals(actual, '在'); + }, 'Chinese word0'); + + test(() => { + const actual = expandRangeString('zh-CN-div', 1, 'zh-CN-div', 1, 'word', true); + assert_equals(actual, '甲'); + }, 'Chinese word1'); + + test(() => { + const actual = expandRangeString('zh-CN-div', 2, 'zh-CN-div', 2, 'word', true); + assert_equals(actual, '型'); + }, 'Chinese word2'); + + test(() => { + const actual = expandRangeString('zh-CN-div', 3, 'zh-CN-div', 3, 'sentence', true); + assert_equals(actual, '在甲型H1N1流感可能出现大流行的警告声中,昨天召开的江苏省2009-2010年度流感防制研讨会注定与往年不同。'); + }, 'Chinese sentence'); + + test(() => { + const actual = expandRangeString('zh-CN-div', 3, 'zh-CN-div', 3, 'block', true); + assert_equals(actual, '在甲型H1N1流感可能出现大流行的警告声中,昨天召开的江苏省2009-2010年度流感防制研讨会注定与往年不同。每年都会召开的一次例会,今年足足提前了一个月;会上研讨的主题,已从以前的季节性流感,变成以甲型H1N1流感为重点。'); + }, 'Chinese block'); + + // Test for Hebrew. + test(() => { + const actual = expandRangeString('he-div', 1, 'he-div', 1, 'word', true); + assert_equals(actual, 'בלשכת'); + }, 'Hebrew word'); + + test(() => { + const actual = expandRangeString('he-div', 1, 'he-div', 1, 'sentence', true); + assert_equals(actual, 'בלשכת שר החוץ הגיבו להתקפות עליו בעקבות הנחייתו לדרוש מהמועמדים לקורס צוערים שירות צבאי או לאומי: "המתקיפים צבועים, מי שרוצה לייצג את המדינה רוצה גם לשרת אותה"' ); + }, 'Hebrew sentence'); + + test(() => { + const actual = expandRangeString('he-div', 0, 'he-div', 0, 'sentence', false); + assert_equals(actual, 'בלשכת שר החוץ הגיבו להתקפות עליו בעקבות הנחייתו לדרוש מהמועמדים לקורס צוערים שירות צבאי או לאומי: "המתקיפים צבועים, מי שרוצה לייצג את המדינה רוצה גם לשרת אותה"' ); + }, 'Hebrew block'); } </script> -<body onload="test()"> +<body> <p>This is the begin of a block. A block is a collection of sentences. Each sentence begins with capital letter and ends with a punctuation. </p> -<p id="multilineSentence">Now, a sentence +<pre id="multilineSentence">Now, a sentence is divided into multiple lines. -</p> +</pre> <p id="instructions">Roll the mouse around the page. The coordinates of the mouse pointer are currently atop an element<br id="mybr">whose ID is:"<span id="myspan" style="font-weight:bold"></span>".</p> @@ -222,7 +247,9 @@ Here is a positioned element.</div> <div id="zh-CN-div">在甲型H1N1流感可能出现大流行的警告声中,昨天召开的江苏省2009-2010年度流感防制研讨会注定与往年不同。每年都会召开的一次例会,今年足足提前了一个月;会上研讨的主题,已从以前的季节性流感,变成以甲型H1N1流感为重点。</div> <div id="he-div">בלשכת שר החוץ הגיבו להתקפות עליו בעקבות הנחייתו לדרוש מהמועמדים לקורס צוערים שירות צבאי או לאומי: "המתקיפים צבועים, מי שרוצה לייצג את המדינה רוצה גם לשרת אותה"</div> -<ul id="console"></ul> +<script> +runTests(); +</script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 5a13296..ebc6091 100644 --- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -76,6 +76,16 @@ interface ByteLengthQueuingStrategy method constructor method size +interface CSSSkewX : CSSTransformComponent + attribute @@toStringTag + getter ax + method constructor + setter ax +interface CSSSkewY : CSSTransformComponent + attribute @@toStringTag + getter ay + method constructor + setter ay interface Cache attribute @@toStringTag method add @@ -627,6 +637,12 @@ method constructor method observe method unobserve +interface IDBObserverChanges + attribute @@toStringTag + getter database + getter records + getter transaction + method constructor interface IDBOpenDBRequest : IDBRequest attribute @@toStringTag getter onblocked
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt index a7ed5e3..02dec236 100644 --- a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -86,6 +86,14 @@ CONSOLE MESSAGE: line 153: method constructor CONSOLE MESSAGE: line 153: setter ax CONSOLE MESSAGE: line 153: setter ay +CONSOLE MESSAGE: line 153: interface CSSSkewX : CSSTransformComponent +CONSOLE MESSAGE: line 153: getter ax +CONSOLE MESSAGE: line 153: method constructor +CONSOLE MESSAGE: line 153: setter ax +CONSOLE MESSAGE: line 153: interface CSSSkewY : CSSTransformComponent +CONSOLE MESSAGE: line 153: getter ay +CONSOLE MESSAGE: line 153: method constructor +CONSOLE MESSAGE: line 153: setter ay CONSOLE MESSAGE: line 153: interface CSSStyleValue CONSOLE MESSAGE: line 153: method constructor CONSOLE MESSAGE: line 153: method toString @@ -339,6 +347,14 @@ CONSOLE MESSAGE: line 153: method constructor CONSOLE MESSAGE: line 153: setter ax CONSOLE MESSAGE: line 153: setter ay +CONSOLE MESSAGE: line 153: interface CSSSkewX : CSSTransformComponent +CONSOLE MESSAGE: line 153: getter ax +CONSOLE MESSAGE: line 153: method constructor +CONSOLE MESSAGE: line 153: setter ax +CONSOLE MESSAGE: line 153: interface CSSSkewY : CSSTransformComponent +CONSOLE MESSAGE: line 153: getter ay +CONSOLE MESSAGE: line 153: method constructor +CONSOLE MESSAGE: line 153: setter ay CONSOLE MESSAGE: line 153: interface CSSStyleValue CONSOLE MESSAGE: line 153: method constructor CONSOLE MESSAGE: line 153: method toString
diff --git a/third_party/WebKit/LayoutTests/mojo/bindings-lite.html b/third_party/WebKit/LayoutTests/mojo/bindings-lite.html index d9427de..10a65f3 100644 --- a/third_party/WebKit/LayoutTests/mojo/bindings-lite.html +++ b/third_party/WebKit/LayoutTests/mojo/bindings-lite.html
@@ -18,6 +18,7 @@ poke() { this.numPokes++; } ping() { return Promise.resolve(); } repeat(message, numbers) { return {message: message, numbers: numbers}; } + flatten(values) {} requestSubinterface(request, client) {} } @@ -118,4 +119,13 @@ subinterfaceProxy.flush(); }); }, 'can send and receive interface requests and proxies'); + +promise_test(() => { + let targetRouter = new liteJsTest.mojom.TestMessageTargetCallbackRouter; + let targetProxy = targetRouter.createProxy(); + targetRouter.flatten.addListener(values => ({values: values.map(v => v.x)})); + return targetProxy.flatten([{x: 1}, {x: 2}, {x: 3}]).then(reply => { + assert_array_equals(reply.values, [1, 2, 3]); + }); +}, 'regression test for complex array serialization'); </script>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-update-text-popup-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-update-text-popup-expected.txt index 1c181e0..34f9d77e 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-update-text-popup-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-update-text-popup-expected.txt
@@ -4,7 +4,7 @@ A B C -layer at (0,0) size 31x20 backgroundClip at (8,50) size 31x20 clip at (8,50) size 31x20 +layer at (0,0) size 31x20 LayoutBlockFlow (positioned) {DIV} at (8,50) size 31x20 LayoutMenuList {SELECT} at (0,0) size 31x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] LayoutBlockFlow (anonymous) at (1,1) size 29x18
diff --git a/third_party/WebKit/LayoutTests/platform/linux/printing/forced-break-tree-dump-only-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/printing/forced-break-tree-dump-only-expected.txt index 9df1359..247c6e5 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/printing/forced-break-tree-dump-only-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/printing/forced-break-tree-dump-only-expected.txt
@@ -1,6 +1,6 @@ layer at (0,0) size 800x600 scrollHeight 827 LayoutView at (0,0) size 1066x799 -layer at (0,0) size 1066x827 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600 +layer at (0,0) size 1066x827 LayoutBlockFlow {HTML} at (0,0) size 1066x827 LayoutBlockFlow {BODY} at (8,16) size 1050x803 LayoutBlockFlow {P} at (0,0) size 1050x40
diff --git a/third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/printing/single-line-must-not-be-split-into-two-pages-expected.txt similarity index 99% rename from third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt rename to third_party/WebKit/LayoutTests/platform/linux/printing/single-line-must-not-be-split-into-two-pages-expected.txt index 4ac39a4..248b432 100644 --- a/third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/printing/single-line-must-not-be-split-into-two-pages-expected.txt
@@ -2,7 +2,7 @@ Non-overflowed lines: -layer at (0,0) size 769x8000 backgroundClip at (8,84) size 769x8000 clip at (8,84) size 769x8000 +layer at (0,0) size 769x8000 LayoutBlockFlow (relative positioned) {DIV} at (0,76) size 769x8000 LayoutText {#text} at (0,0) size 90x19 text run at (0,0) width 90: "WWWWWW" @@ -1206,7 +1206,7 @@ LayoutBR {BR} at (90,7995) size 0x0 Overflowed lines: -layer at (0,0) size 769x8000 backgroundClip at (8,8084) size 769x8000 clip at (8,8084) size 769x8000 +layer at (0,0) size 769x8000 LayoutBlockFlow (relative positioned) {DIV} at (0,8076) size 769x8000 LayoutText {#text} at (0,0) size 4710x19 text run at (0,0) width 4710: "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/printing/forced-break-tree-dump-only-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/printing/forced-break-tree-dump-only-expected.txt index 9df1359..247c6e5 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/printing/forced-break-tree-dump-only-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/printing/forced-break-tree-dump-only-expected.txt
@@ -1,6 +1,6 @@ layer at (0,0) size 800x600 scrollHeight 827 LayoutView at (0,0) size 1066x799 -layer at (0,0) size 1066x827 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600 +layer at (0,0) size 1066x827 LayoutBlockFlow {HTML} at (0,0) size 1066x827 LayoutBlockFlow {BODY} at (8,16) size 1050x803 LayoutBlockFlow {P} at (0,0) size 1050x40
diff --git a/third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/printing/single-line-must-not-be-split-into-two-pages-expected.txt similarity index 99% copy from third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt copy to third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/printing/single-line-must-not-be-split-into-two-pages-expected.txt index 4ac39a4..248b432 100644 --- a/third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/threaded/printing/single-line-must-not-be-split-into-two-pages-expected.txt
@@ -2,7 +2,7 @@ Non-overflowed lines: -layer at (0,0) size 769x8000 backgroundClip at (8,84) size 769x8000 clip at (8,84) size 769x8000 +layer at (0,0) size 769x8000 LayoutBlockFlow (relative positioned) {DIV} at (0,76) size 769x8000 LayoutText {#text} at (0,0) size 90x19 text run at (0,0) width 90: "WWWWWW" @@ -1206,7 +1206,7 @@ LayoutBR {BR} at (90,7995) size 0x0 Overflowed lines: -layer at (0,0) size 769x8000 backgroundClip at (8,8084) size 769x8000 clip at (8,8084) size 769x8000 +layer at (0,0) size 769x8000 LayoutBlockFlow (relative positioned) {DIV} at (0,8076) size 769x8000 LayoutText {#text} at (0,0) size 4710x19 text run at (0,0) width 4710: "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-update-text-popup-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-update-text-popup-expected.txt index 41f91fef..be4ad91d 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-update-text-popup-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-update-text-popup-expected.txt
@@ -4,7 +4,7 @@ A B C -layer at (0,0) size 40x18 backgroundClip at (8,50) size 40x18 clip at (8,50) size 40x18 +layer at (0,0) size 40x18 LayoutBlockFlow (positioned) {DIV} at (8,50) size 40x18 LayoutMenuList {SELECT} at (0,0) size 40x18 [bgcolor=#F8F8F8] LayoutBlockFlow (anonymous) at (0,0) size 40x18
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-update-text-popup-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-update-text-popup-expected.txt index 95973b8a..6ca42650 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-update-text-popup-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-update-text-popup-expected.txt
@@ -4,7 +4,7 @@ A B C -layer at (0,0) size 39x18 backgroundClip at (8,50) size 39x18 clip at (8,50) size 39x18 +layer at (0,0) size 39x18 LayoutBlockFlow (positioned) {DIV} at (8,50) size 39x18 LayoutMenuList {SELECT} at (0,0) size 39x18 [bgcolor=#F8F8F8] LayoutBlockFlow (anonymous) at (0,0) size 39x18
diff --git a/third_party/WebKit/LayoutTests/platform/mac/printing/forced-break-tree-dump-only-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/printing/forced-break-tree-dump-only-expected.txt index 0964f56..3cbf712 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/printing/forced-break-tree-dump-only-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/printing/forced-break-tree-dump-only-expected.txt
@@ -1,6 +1,6 @@ layer at (0,0) size 800x600 scrollHeight 825 LayoutView at (0,0) size 1066x799 -layer at (0,0) size 1066x825 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600 +layer at (0,0) size 1066x825 LayoutBlockFlow {HTML} at (0,0) size 1066x825 LayoutBlockFlow {BODY} at (8,16) size 1050x801 LayoutBlockFlow {P} at (0,0) size 1050x36
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-update-text-popup-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-update-text-popup-expected.txt index 2a7436c..d3a2841 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-update-text-popup-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-update-text-popup-expected.txt
@@ -4,7 +4,7 @@ A B C -layer at (0,0) size 31x20 backgroundClip at (8,50) size 31x20 clip at (8,50) size 31x20 +layer at (0,0) size 31x20 LayoutBlockFlow (positioned) {DIV} at (8,50) size 31x20 LayoutMenuList {SELECT} at (0,0) size 31x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)] LayoutBlockFlow (anonymous) at (1,1) size 29x18
diff --git a/third_party/WebKit/LayoutTests/platform/win/printing/forced-break-tree-dump-only-expected.txt b/third_party/WebKit/LayoutTests/platform/win/printing/forced-break-tree-dump-only-expected.txt index 2e8f01a..20a8f4d7 100644 --- a/third_party/WebKit/LayoutTests/platform/win/printing/forced-break-tree-dump-only-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/printing/forced-break-tree-dump-only-expected.txt
@@ -1,6 +1,6 @@ layer at (0,0) size 800x600 scrollHeight 827 LayoutView at (0,0) size 1066x799 -layer at (0,0) size 1066x827 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600 +layer at (0,0) size 1066x827 LayoutBlockFlow {HTML} at (0,0) size 1066x827 LayoutBlockFlow {BODY} at (8,16) size 1050x803 LayoutBlockFlow {P} at (0,0) size 1050x40
diff --git a/third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/printing/single-line-must-not-be-split-into-two-pages-expected.txt similarity index 99% copy from third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt copy to third_party/WebKit/LayoutTests/platform/win7/printing/single-line-must-not-be-split-into-two-pages-expected.txt index 4ac39a4..248b432 100644 --- a/third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win7/printing/single-line-must-not-be-split-into-two-pages-expected.txt
@@ -2,7 +2,7 @@ Non-overflowed lines: -layer at (0,0) size 769x8000 backgroundClip at (8,84) size 769x8000 clip at (8,84) size 769x8000 +layer at (0,0) size 769x8000 LayoutBlockFlow (relative positioned) {DIV} at (0,76) size 769x8000 LayoutText {#text} at (0,0) size 90x19 text run at (0,0) width 90: "WWWWWW" @@ -1206,7 +1206,7 @@ LayoutBR {BR} at (90,7995) size 0x0 Overflowed lines: -layer at (0,0) size 769x8000 backgroundClip at (8,8084) size 769x8000 clip at (8,8084) size 769x8000 +layer at (0,0) size 769x8000 LayoutBlockFlow (relative positioned) {DIV} at (0,8076) size 769x8000 LayoutText {#text} at (0,0) size 4710x19 text run at (0,0) width 4710: "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
diff --git a/third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/virtual/threaded/printing/single-line-must-not-be-split-into-two-pages-expected.txt similarity index 99% copy from third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt copy to third_party/WebKit/LayoutTests/platform/win7/virtual/threaded/printing/single-line-must-not-be-split-into-two-pages-expected.txt index 4ac39a4..248b432 100644 --- a/third_party/WebKit/LayoutTests/platform/win/printing/single-line-must-not-be-split-into-two-pages-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win7/virtual/threaded/printing/single-line-must-not-be-split-into-two-pages-expected.txt
@@ -2,7 +2,7 @@ Non-overflowed lines: -layer at (0,0) size 769x8000 backgroundClip at (8,84) size 769x8000 clip at (8,84) size 769x8000 +layer at (0,0) size 769x8000 LayoutBlockFlow (relative positioned) {DIV} at (0,76) size 769x8000 LayoutText {#text} at (0,0) size 90x19 text run at (0,0) width 90: "WWWWWW" @@ -1206,7 +1206,7 @@ LayoutBR {BR} at (90,7995) size 0x0 Overflowed lines: -layer at (0,0) size 769x8000 backgroundClip at (8,8084) size 769x8000 clip at (8,8084) size 769x8000 +layer at (0,0) size 769x8000 LayoutBlockFlow (relative positioned) {DIV} at (0,8076) size 769x8000 LayoutText {#text} at (0,0) size 4710x19 text run at (0,0) width 4710: "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
diff --git a/third_party/WebKit/LayoutTests/printing/iframe-svg-in-object-print-expected.txt b/third_party/WebKit/LayoutTests/printing/iframe-svg-in-object-print-expected.txt index 128dd5e8..f00a62a 100644 --- a/third_party/WebKit/LayoutTests/printing/iframe-svg-in-object-print-expected.txt +++ b/third_party/WebKit/LayoutTests/printing/iframe-svg-in-object-print-expected.txt
@@ -1,6 +1,6 @@ layer at (0,0) size 800x600 LayoutView at (0,0) size 1066x799 -layer at (0,0) size 1066x799 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600 +layer at (0,0) size 1066x799 LayoutBlockFlow {HTML} at (0,0) size 1066x799 LayoutBlockFlow {BODY} at (8,8) size 1050x783 LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/printing/single-line-must-not-be-split-into-two-pages-expected.txt b/third_party/WebKit/LayoutTests/printing/single-line-must-not-be-split-into-two-pages-expected.txt similarity index 99% rename from third_party/WebKit/LayoutTests/platform/mac/printing/single-line-must-not-be-split-into-two-pages-expected.txt rename to third_party/WebKit/LayoutTests/printing/single-line-must-not-be-split-into-two-pages-expected.txt index 0dcfbb8..74c872c1 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/printing/single-line-must-not-be-split-into-two-pages-expected.txt +++ b/third_party/WebKit/LayoutTests/printing/single-line-must-not-be-split-into-two-pages-expected.txt
@@ -2,7 +2,7 @@ Non-overflowed lines: -layer at (0,0) size 769x7200 backgroundClip at (8,78) size 769x7200 clip at (8,78) size 769x7200 +layer at (0,0) size 769x7200 LayoutBlockFlow (relative positioned) {DIV} at (0,70) size 769x7200 LayoutText {#text} at (0,0) size 91x18 text run at (0,0) width 91: "WWWWWW" @@ -1206,7 +1206,7 @@ LayoutBR {BR} at (90,7196) size 1x0 Overflowed lines: -layer at (0,0) size 769x7200 backgroundClip at (8,7278) size 769x7200 clip at (8,7278) size 769x7200 +layer at (0,0) size 769x7200 LayoutBlockFlow (relative positioned) {DIV} at (0,7270) size 769x7200 LayoutText {#text} at (0,0) size 4742x18 text run at (0,0) width 4742: "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index f9e6ce3..3087dbe 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -33,6 +33,16 @@ interface ByteLengthQueuingStrategy method constructor method size +interface CSSSkewX : CSSTransformComponent + attribute @@toStringTag + getter ax + method constructor + setter ax +interface CSSSkewY : CSSTransformComponent + attribute @@toStringTag + getter ay + method constructor + setter ay interface Cache attribute @@toStringTag method add
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt index 9b1dcb8..286fba1 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -35,6 +35,16 @@ [Worker] interface ByteLengthQueuingStrategy [Worker] method constructor [Worker] method size +[Worker] interface CSSSkewX : CSSTransformComponent +[Worker] attribute @@toStringTag +[Worker] getter ax +[Worker] method constructor +[Worker] setter ax +[Worker] interface CSSSkewY : CSSTransformComponent +[Worker] attribute @@toStringTag +[Worker] getter ay +[Worker] method constructor +[Worker] setter ay [Worker] interface Cache [Worker] attribute @@toStringTag [Worker] method add
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt index a0a57b80..88a6e93 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -35,6 +35,16 @@ [Worker] interface ByteLengthQueuingStrategy [Worker] method constructor [Worker] method size +[Worker] interface CSSSkewX : CSSTransformComponent +[Worker] attribute @@toStringTag +[Worker] getter ax +[Worker] method constructor +[Worker] setter ax +[Worker] interface CSSSkewY : CSSTransformComponent +[Worker] attribute @@toStringTag +[Worker] getter ay +[Worker] method constructor +[Worker] setter ay [Worker] interface Cache [Worker] attribute @@toStringTag [Worker] method add
diff --git a/third_party/WebKit/LayoutTests/platform/mac/printing/single-line-must-not-be-split-into-two-pages-expected.txt b/third_party/WebKit/LayoutTests/virtual/threaded/printing/single-line-must-not-be-split-into-two-pages-expected.txt similarity index 99% copy from third_party/WebKit/LayoutTests/platform/mac/printing/single-line-must-not-be-split-into-two-pages-expected.txt copy to third_party/WebKit/LayoutTests/virtual/threaded/printing/single-line-must-not-be-split-into-two-pages-expected.txt index 0dcfbb8..74c872c1 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/printing/single-line-must-not-be-split-into-two-pages-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/threaded/printing/single-line-must-not-be-split-into-two-pages-expected.txt
@@ -2,7 +2,7 @@ Non-overflowed lines: -layer at (0,0) size 769x7200 backgroundClip at (8,78) size 769x7200 clip at (8,78) size 769x7200 +layer at (0,0) size 769x7200 LayoutBlockFlow (relative positioned) {DIV} at (0,70) size 769x7200 LayoutText {#text} at (0,0) size 91x18 text run at (0,0) width 91: "WWWWWW" @@ -1206,7 +1206,7 @@ LayoutBR {BR} at (90,7196) size 1x0 Overflowed lines: -layer at (0,0) size 769x7200 backgroundClip at (8,7278) size 769x7200 clip at (8,7278) size 769x7200 +layer at (0,0) size 769x7200 LayoutBlockFlow (relative positioned) {DIV} at (0,7270) size 769x7200 LayoutText {#text} at (0,0) size 4742x18 text run at (0,0) width 4742: "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
diff --git a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt index 0861101..bafe7db 100644 --- a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt
@@ -4,7 +4,7 @@ PASS addTransceiver() should fire negotiationneeded event FAIL Calling addTransceiver() twice should fire negotiationneeded event once assert_unreached: Pending promise should never be resolved. Instead it is fulfilled with: [object Object] Reached unreachable code FAIL Calling both addTransceiver() and createDataChannel() should fire negotiationneeded event once assert_unreached: Pending promise should never be resolved. Instead it is fulfilled with: [object Object] Reached unreachable code -PASS negotiationneeded event should not fire if signaling state is not stable +FAIL negotiationneeded event should not fire if signaling state is not stable assert_unreached: Pending promise should never be resolved. Instead it is fulfilled with: [object Object] Reached unreachable code FAIL negotiationneeded event should fire only after signaling state go back to stable assert_unreached: Expect negotiationneeded promise to resolve after pc has set remote answer and go back to stable state Reached unreachable code Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 246cd2a..cc61dbdf 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -63,6 +63,16 @@ [Worker] interface ByteLengthQueuingStrategy [Worker] method constructor [Worker] method size +[Worker] interface CSSSkewX : CSSTransformComponent +[Worker] attribute @@toStringTag +[Worker] getter ax +[Worker] method constructor +[Worker] setter ax +[Worker] interface CSSSkewY : CSSTransformComponent +[Worker] attribute @@toStringTag +[Worker] getter ay +[Worker] method constructor +[Worker] setter ay [Worker] interface Cache [Worker] attribute @@toStringTag [Worker] method add @@ -569,6 +579,12 @@ [Worker] method constructor [Worker] method observe [Worker] method unobserve +[Worker] interface IDBObserverChanges +[Worker] attribute @@toStringTag +[Worker] getter database +[Worker] getter records +[Worker] getter transaction +[Worker] method constructor [Worker] interface IDBOpenDBRequest : IDBRequest [Worker] attribute @@toStringTag [Worker] getter onblocked
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt index f4aa0dd..15cfa1c 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -63,6 +63,16 @@ [Worker] interface ByteLengthQueuingStrategy [Worker] method constructor [Worker] method size +[Worker] interface CSSSkewX : CSSTransformComponent +[Worker] attribute @@toStringTag +[Worker] getter ax +[Worker] method constructor +[Worker] setter ax +[Worker] interface CSSSkewY : CSSTransformComponent +[Worker] attribute @@toStringTag +[Worker] getter ay +[Worker] method constructor +[Worker] setter ay [Worker] interface Cache [Worker] attribute @@toStringTag [Worker] method add @@ -564,6 +574,12 @@ [Worker] method constructor [Worker] method observe [Worker] method unobserve +[Worker] interface IDBObserverChanges +[Worker] attribute @@toStringTag +[Worker] getter database +[Worker] getter records +[Worker] getter transaction +[Worker] method constructor [Worker] interface IDBOpenDBRequest : IDBRequest [Worker] attribute @@toStringTag [Worker] getter onblocked
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index c2c9f60..dc91fce 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -32,10 +32,6 @@ const base::Feature kMojoBlobURLs{"MojoBlobURLs", base::FEATURE_DISABLED_BY_DEFAULT}; -// Nested workers. See https://crbug.com/31666 -const base::Feature kNestedWorkers{"NestedWorkers", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Onion souping for all DOMStorage. https://crbug.com/781870 const base::Feature kOnionSoupDOMStorage{"OnionSoupDOMStorage", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 290e4ef..01679e3d 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -18,7 +18,6 @@ kEnableGpuRasterizationViewportRestriction; BLINK_COMMON_EXPORT extern const base::Feature kLayoutNG; BLINK_COMMON_EXPORT extern const base::Feature kMojoBlobURLs; -BLINK_COMMON_EXPORT extern const base::Feature kNestedWorkers; BLINK_COMMON_EXPORT extern const base::Feature kOnionSoupDOMStorage; BLINK_COMMON_EXPORT extern const base::Feature kPortals; BLINK_COMMON_EXPORT extern const base::Feature kRecordAnchorMetricsClicked;
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom index 6246a426..6b2811c2 100644 --- a/third_party/blink/public/platform/web_feature.mojom +++ b/third_party/blink/public/platform/web_feature.mojom
@@ -2079,6 +2079,8 @@ kPageLifeCycleFreeze = 2627, kDefaultInCustomIdent = 2628, kHTMLAnchorElementHrefTranslateAttribute = 2629, + kWebKitUserModifyEffective = 2630, + kPlainTextEditingEffective = 2631, // 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/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index ededd59..d04fd8f 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -119,7 +119,6 @@ BLINK_PLATFORM_EXPORT static void EnableMiddleClickAutoscroll(bool); BLINK_PLATFORM_EXPORT static void EnableModernMediaControls(bool); BLINK_PLATFORM_EXPORT static void EnableNavigatorContentUtils(bool); - BLINK_PLATFORM_EXPORT static void EnableNestedWorkers(bool); BLINK_PLATFORM_EXPORT static void EnableNetInfoDownlinkMax(bool); BLINK_PLATFORM_EXPORT static void EnableNetworkService(bool); BLINK_PLATFORM_EXPORT static void EnableNoHoverAfterLayoutChange(bool);
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_object_parser.h b/third_party/blink/renderer/bindings/core/v8/v8_object_parser.h index 4e2fcfa..2aa5cd1 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_object_parser.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_object_parser.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_OBJECT_PARSER_H_ #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" #include "v8/include/v8.h"
diff --git a/third_party/blink/renderer/bindings/scripts/compute_global_objects.py b/third_party/blink/renderer/bindings/scripts/compute_global_objects.py index 790002cb..78d74f82 100755 --- a/third_party/blink/renderer/bindings/scripts/compute_global_objects.py +++ b/third_party/blink/renderer/bindings/scripts/compute_global_objects.py
@@ -67,7 +67,7 @@ if not global_value: raise ValueError('[Global] must take an indentifier or an identifier list.\n' + full_path) - return global_value.strip('()').split(',') + return map(str.strip, global_value.strip('()').split(',')) def idl_files_to_interface_name_global_names(idl_files):
diff --git a/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py b/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py index 45f61bf9..d7568a0 100755 --- a/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py +++ b/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py
@@ -97,7 +97,8 @@ global_name_to_constructors[argument['exposed']].extend(new_constructors_list) else: # Exposed=env or Exposed=(env1,...) case - exposed_global_names = extended_attributes.get('Exposed', 'Window').strip('()').split(',') + exposed_value = extended_attributes.get('Exposed', 'Window') + exposed_global_names = map(str.strip, exposed_value.strip('()').split(',')) new_constructors_list = generate_global_constructors_list(interface_name, extended_attributes) for name in exposed_global_names: global_name_to_constructors[name].extend(new_constructors_list)
diff --git a/third_party/blink/renderer/bindings/scripts/utilities.py b/third_party/blink/renderer/bindings/scripts/utilities.py index b25d117..e582cbfe 100644 --- a/third_party/blink/renderer/bindings/scripts/utilities.py +++ b/third_party/blink/renderer/bindings/scripts/utilities.py
@@ -365,7 +365,7 @@ file_contents = re.sub(block_comment_re, '', file_contents) match = re.search( - r'(?:\[([^[]*)\]\s*)?' + r'(?:\[([^{};]*)\]\s*)?' r'(interface|callback\s+interface|partial\s+interface|dictionary)\s+' r'(\w+)\s*' r'(:\s*\w+\s*)?' @@ -373,22 +373,34 @@ file_contents, flags=re.DOTALL) return match + def get_interface_extended_attributes_from_idl(file_contents): match = match_interface_extended_attributes_and_name_from_idl(file_contents) if not match or not match.group(1): return {} - extended_attributes_string = match.group(1) - extended_attributes = {} - # FIXME: this splitting is WRONG: it fails on extended attributes where lists of - # multiple values are used, which are seperated by a comma and a space. + extended_attributes_string = match.group(1).strip() parts = [extended_attribute.strip() - for extended_attribute in re.split(',\s+', extended_attributes_string) + for extended_attribute in re.split(',', extended_attributes_string) # Discard empty parts, which may exist due to trailing comma if extended_attribute.strip()] + + # Joins |parts| with commas as far as the parences are not balanced, + # and then converts a (joined) term to a dict entry. + # ex. ['ab=c', 'ab(cd', 'ef', 'gh)', 'f=(a', 'b)'] + # => {'ab': 'c', 'ab(cd,ef,gh)': '', 'f': '(a,b)'} + extended_attributes = {} + concatenated = None for part in parts: - name, _, value = map(string.strip, part.partition('=')) - extended_attributes[name] = value + concatenated = (concatenated + ', ' + part) if concatenated else part + parences = concatenated.count('(') - concatenated.count(')') + square_brackets = concatenated.count('[') - concatenated.count(']') + if parences < 0 or square_brackets < 0: + raise ValueError('You have more close braces than open braces.') + if parences == 0 and square_brackets == 0: + name, _, value = map(string.strip, concatenated.partition('=')) + extended_attributes[name] = value + concatenated = None return extended_attributes @@ -410,6 +422,7 @@ def get_first_interface_name_from_idl(file_contents): + # TODO(peria): This function returns 'mixin' for interface mixins. match = match_interface_extended_attributes_and_name_from_idl(file_contents) if match: return match.group(3)
diff --git a/third_party/blink/renderer/build/scripts/make_css_property_names.py b/third_party/blink/renderer/build/scripts/core/css/make_css_property_names.py similarity index 92% rename from third_party/blink/renderer/build/scripts/make_css_property_names.py rename to third_party/blink/renderer/build/scripts/core/css/make_css_property_names.py index 4a9c81cf..5cb3e20 100755 --- a/third_party/blink/renderer/build/scripts/make_css_property_names.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_css_property_names.py
@@ -1,5 +1,9 @@ #!/usr/bin/env python +import os +import sys +sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) + from core.css import css_properties import gperf import json5_generator @@ -25,7 +29,7 @@ return " static_cast<CSSPropertyID>(%(enum_value)s), " \ "// %(property_id)s" % property_ - @template_expander.use_jinja('templates/css_property_names.h.tmpl') + @template_expander.use_jinja('core/css/templates/css_property_names.h.tmpl') def generate_header(self): return { 'alias_offset': self._css_properties.alias_offset, @@ -45,7 +49,7 @@ max(map(len, self._css_properties.properties_by_id)), } - @gperf.use_jinja_gperf_template('templates/css_property_names.cc.tmpl', + @gperf.use_jinja_gperf_template('core/css/templates/css_property_names.cc.tmpl', ['-Q', 'CSSPropStringPool']) def generate_implementation(self): enum_value_to_name = {}
diff --git a/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.h.tmpl index 0e41a3e..900fa592 100644 --- a/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.h.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.h.tmpl
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_AT_RULE_DESCRIPTORS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_AT_RULE_DESCRIPTORS_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/text/string_view.h" #include <string.h>
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl index 1947b2f..becfce1a 100644 --- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl
@@ -9,7 +9,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTY_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTY_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_value.h" #include "third_party/blink/renderer/core/css/properties/css_unresolved_property.h" #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_unresolved_property.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_unresolved_property.h.tmpl index 440453d..ea360d62 100644 --- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_unresolved_property.h.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_unresolved_property.h.tmpl
@@ -9,7 +9,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_UNRESOLVED_PROPERTY_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_UNRESOLVED_PROPERTY_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink {
diff --git a/third_party/blink/renderer/build/scripts/templates/css_property_names.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.cc.tmpl similarity index 95% rename from third_party/blink/renderer/build/scripts/templates/css_property_names.cc.tmpl rename to third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.cc.tmpl index 79cca4cf..25e3e6b 100644 --- a/third_party/blink/renderer/build/scripts/templates/css_property_names.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.cc.tmpl
@@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/core/{{file_basename}}.h" +#include "third_party/blink/renderer/core/css/{{file_basename}}.h" #include <string.h> #include "third_party/blink/renderer/core/css/hash_tools.h"
diff --git a/third_party/blink/renderer/build/scripts/templates/css_property_names.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.h.tmpl similarity index 89% rename from third_party/blink/renderer/build/scripts/templates/css_property_names.h.tmpl rename to third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.h.tmpl index b20372d..3b8186fa 100644 --- a/third_party/blink/renderer/build/scripts/templates/css_property_names.h.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.h.tmpl
@@ -1,8 +1,8 @@ {% from 'templates/macros.tmpl' import license %} {{license()}} -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTY_NAMES_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTY_NAMES_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAMES_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAMES_H_ #include <stddef.h> #include "third_party/blink/renderer/core/core_export.h" @@ -62,4 +62,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTY_NAMES_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAMES_H_
diff --git a/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl index 2747247..49cc3b8 100644 --- a/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl
@@ -25,7 +25,7 @@ #ifndef {{header_guard}} #define {{header_guard}} -#include "css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/properties/css_property.h" #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index a7a9c1a..bff8bc3 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1130,15 +1130,15 @@ } css_properties("make_core_generated_css_property_names") { - script = "../build/scripts/make_css_property_names.py" + script = "../build/scripts/core/css/make_css_property_names.py" other_inputs = [ "../build/scripts/gperf.py", - "../build/scripts/templates/css_property_names.cc.tmpl", - "../build/scripts/templates/css_property_names.h.tmpl", + "../build/scripts/core/css/templates/css_property_names.cc.tmpl", + "../build/scripts/core/css/templates/css_property_names.h.tmpl", ] outputs = [ - "$blink_core_output_dir/css_property_names.cc", - "$blink_core_output_dir/css_property_names.h", + "$blink_core_output_dir/css/css_property_names.cc", + "$blink_core_output_dir/css/css_property_names.h", ] }
diff --git a/third_party/blink/renderer/core/animation/animation.h b/third_party/blink/renderer/core/animation/animation.h index bd0ef52e..de4b824 100644 --- a/third_party/blink/renderer/core/animation/animation.h +++ b/third_party/blink/renderer/core/animation/animation.h
@@ -44,7 +44,7 @@ #include "third_party/blink/renderer/core/animation/compositor_animations.h" #include "third_party/blink/renderer/core/animation/document_timeline.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/events/event_target.h"
diff --git a/third_party/blink/renderer/core/animation/animation_input_helpers.h b/third_party/blink/renderer/core/animation/animation_input_helpers.h index 1dc56ae..1ea358c 100644 --- a/third_party/blink/renderer/core/animation/animation_input_helpers.h +++ b/third_party/blink/renderer/core/animation/animation_input_helpers.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATION_INPUT_HELPERS_H_ #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/third_party/blink/renderer/core/animation/color_property_functions.h b/third_party/blink/renderer/core/animation/color_property_functions.h index 21191f1..208e344 100644 --- a/third_party/blink/renderer/core/animation/color_property_functions.h +++ b/third_party/blink/renderer/core/animation/color_property_functions.h
@@ -5,8 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_COLOR_PROPERTY_FUNCTIONS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_COLOR_PROPERTY_FUNCTIONS_H_ +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/style_color.h" -#include "third_party/blink/renderer/core/css_property_names.h" namespace blink {
diff --git a/third_party/blink/renderer/core/animation/css/css_animatable_value_factory.h b/third_party/blink/renderer/core/animation/css/css_animatable_value_factory.h index 30243107..a4e34d54 100644 --- a/third_party/blink/renderer/core/animation/css/css_animatable_value_factory.h +++ b/third_party/blink/renderer/core/animation/css/css_animatable_value_factory.h
@@ -32,7 +32,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATABLE_VALUE_FACTORY_H_ #include "third_party/blink/renderer/core/animation/animatable/animatable_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink {
diff --git a/third_party/blink/renderer/core/animation/css/css_transition_data.h b/third_party/blink/renderer/core/animation/css/css_transition_data.h index 95801b6..24bec6a 100644 --- a/third_party/blink/renderer/core/animation/css/css_transition_data.h +++ b/third_party/blink/renderer/core/animation/css/css_transition_data.h
@@ -9,7 +9,7 @@ #include "base/memory/ptr_util.h" #include "third_party/blink/renderer/core/animation/css/css_timing_data.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink {
diff --git a/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc index e5646c6..1b9fb298 100644 --- a/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc
@@ -9,9 +9,9 @@ #include "base/memory/ptr_util.h" #include "third_party/blink/renderer/core/animation/basic_shape_interpolation_functions.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/style/basic_shapes.h" #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/core/style/data_equivalency.h"
diff --git a/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc index 17b3950..02b0d00 100644 --- a/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc
@@ -11,9 +11,9 @@ #include "third_party/blink/renderer/core/animation/length_interpolation_functions.h" #include "third_party/blink/renderer/core/animation/side_index.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_quad_value.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/style/computed_style.h" namespace blink {
diff --git a/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc index 0f7108de..eea3067 100644 --- a/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc
@@ -11,9 +11,9 @@ #include "third_party/blink/renderer/core/animation/filter_interpolation_functions.h" #include "third_party/blink/renderer/core/animation/list_interpolation_functions.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/style/computed_style.h" namespace blink {
diff --git a/third_party/blink/renderer/core/animation/css_image_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_image_interpolation_type.cc index 5231eb7..067f9b6 100644 --- a/third_party/blink/renderer/core/animation/css_image_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_image_interpolation_type.cc
@@ -9,8 +9,8 @@ #include "base/memory/ptr_util.h" #include "third_party/blink/renderer/core/css/css_crossfade_value.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/core/style/style_image.h"
diff --git a/third_party/blink/renderer/core/animation/css_paint_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_paint_interpolation_type.cc index 052bfa8..b3e63738 100644 --- a/third_party/blink/renderer/core/animation/css_paint_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_paint_interpolation_type.cc
@@ -9,9 +9,9 @@ #include "base/memory/ptr_util.h" #include "third_party/blink/renderer/core/animation/css_color_interpolation_type.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" #include "third_party/blink/renderer/core/css/style_color.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/style/computed_style.h" namespace blink {
diff --git a/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc index 7b032116..0071b81ef 100644 --- a/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc
@@ -11,10 +11,10 @@ #include "third_party/blink/renderer/core/animation/list_interpolation_functions.h" #include "third_party/blink/renderer/core/animation/shadow_interpolation_functions.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/resolver/style_builder.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/core/style/shadow_list.h"
diff --git a/third_party/blink/renderer/core/animation/document_animations.h b/third_party/blink/renderer/core/animation/document_animations.h index a0da056e..024c5c4 100644 --- a/third_party/blink/renderer/core/animation/document_animations.h +++ b/third_party/blink/renderer/core/animation/document_animations.h
@@ -32,7 +32,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_DOCUMENT_ANIMATIONS_H_ #include "base/optional.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/document_lifecycle.h" #include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
diff --git a/third_party/blink/renderer/core/animation/effect_model.h b/third_party/blink/renderer/core/animation/effect_model.h index 688e3b1..bec992b 100644 --- a/third_party/blink/renderer/core/animation/effect_model.h +++ b/third_party/blink/renderer/core/animation/effect_model.h
@@ -34,7 +34,7 @@ #include "third_party/blink/renderer/core/animation/animation_time_delta.h" #include "third_party/blink/renderer/core/animation/property_handle.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h"
diff --git a/third_party/blink/renderer/core/animation/image_list_property_functions.h b/third_party/blink/renderer/core/animation/image_list_property_functions.h index 3437057..39071e6 100644 --- a/third_party/blink/renderer/core/animation/image_list_property_functions.h +++ b/third_party/blink/renderer/core/animation/image_list_property_functions.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_IMAGE_LIST_PROPERTY_FUNCTIONS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_IMAGE_LIST_PROPERTY_FUNCTIONS_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/third_party/blink/renderer/core/animation/image_slice_property_functions.h b/third_party/blink/renderer/core/animation/image_slice_property_functions.h index 84c63903..ca090999 100644 --- a/third_party/blink/renderer/core/animation/image_slice_property_functions.h +++ b/third_party/blink/renderer/core/animation/image_slice_property_functions.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_IMAGE_SLICE_PROPERTY_FUNCTIONS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_IMAGE_SLICE_PROPERTY_FUNCTIONS_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/style/computed_style.h" namespace blink {
diff --git a/third_party/blink/renderer/core/animation/length_list_property_functions.h b/third_party/blink/renderer/core/animation/length_list_property_functions.h index a8a75f9..95b962c 100644 --- a/third_party/blink/renderer/core/animation/length_list_property_functions.h +++ b/third_party/blink/renderer/core/animation/length_list_property_functions.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_LENGTH_LIST_PROPERTY_FUNCTIONS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_LENGTH_LIST_PROPERTY_FUNCTIONS_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/geometry/length.h" #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/animation/length_property_functions.h b/third_party/blink/renderer/core/animation/length_property_functions.h index ae634f2..43e2f83d 100644 --- a/third_party/blink/renderer/core/animation/length_property_functions.h +++ b/third_party/blink/renderer/core/animation/length_property_functions.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_LENGTH_PROPERTY_FUNCTIONS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_LENGTH_PROPERTY_FUNCTIONS_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/platform/geometry/length.h" #include "third_party/blink/renderer/platform/wtf/allocator.h"
diff --git a/third_party/blink/renderer/core/animation/number_property_functions.h b/third_party/blink/renderer/core/animation/number_property_functions.h index c445795..4b32e30 100644 --- a/third_party/blink/renderer/core/animation/number_property_functions.h +++ b/third_party/blink/renderer/core/animation/number_property_functions.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_NUMBER_PROPERTY_FUNCTIONS_H_ #include "base/optional.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" namespace blink {
diff --git a/third_party/blink/renderer/core/animation/property_handle.h b/third_party/blink/renderer/core/animation/property_handle.h index 1a6d1349..eeca4b7 100644 --- a/third_party/blink/renderer/core/animation/property_handle.h +++ b/third_party/blink/renderer/core/animation/property_handle.h
@@ -7,8 +7,8 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/css_property_name.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/properties/css_property.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/qualified_name.h" #include "third_party/blink/renderer/platform/wtf/allocator.h"
diff --git a/third_party/blink/renderer/core/animation/size_list_property_functions.h b/third_party/blink/renderer/core/animation/size_list_property_functions.h index 2f22c58..cf3c147 100644 --- a/third_party/blink/renderer/core/animation/size_list_property_functions.h +++ b/third_party/blink/renderer/core/animation/size_list_property_functions.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SIZE_LIST_PROPERTY_FUNCTIONS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SIZE_LIST_PROPERTY_FUNCTIONS_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/style/fill_layer.h" #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer.cc b/third_party/blink/renderer/core/clipboard/data_transfer.cc index 3c2f733f..053d577 100644 --- a/third_party/blink/renderer/core/clipboard/data_transfer.cc +++ b/third_party/blink/renderer/core/clipboard/data_transfer.cc
@@ -122,9 +122,9 @@ .AbsoluteToLocalQuad(FloatQuad(absolute_bounding_box), kUseTransforms) .BoundingBox(); - PaintLayerPaintingInfo painting_info(layer, LayoutRect(bounding_box), - kGlobalPaintFlattenCompositingLayers, - LayoutSize()); + PaintLayerPaintingInfo painting_info( + layer, CullRect(EnclosingIntRect(bounding_box)), + kGlobalPaintFlattenCompositingLayers, LayoutSize()); PaintLayerFlags flags = kPaintLayerHaveTransparency | kPaintLayerUncachedClipRects; PaintRecordBuilder builder;
diff --git a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc index 1e62af8f..163d8275 100644 --- a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc +++ b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
@@ -29,13 +29,13 @@ #include "third_party/blink/renderer/core/css/css_primitive_value.h" #include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h" #include "third_party/blink/renderer/core/css/css_property_id_templates.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_selector.h" #include "third_party/blink/renderer/core/css/css_variable_data.h" #include "third_party/blink/renderer/core/css/parser/css_parser.h" #include "third_party/blink/renderer/core/css/properties/css_property_ref.h" #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/css/zoom_adjusted_pixel_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/pseudo_element.h" #include "third_party/blink/renderer/core/frame/use_counter.h"
diff --git a/third_party/blink/renderer/core/css/css_custom_ident_value.h b/third_party/blink/renderer/core/css/css_custom_ident_value.h index dd2cef1..86aa17f 100644 --- a/third_party/blink/renderer/core/css/css_custom_ident_value.h +++ b/third_party/blink/renderer/core/css/css_custom_ident_value.h
@@ -5,8 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_CUSTOM_IDENT_VALUE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_CUSTOM_IDENT_VALUE_H_ +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/css_paint_image_generator.h b/third_party/blink/renderer/core/css/css_paint_image_generator.h index bc333be..ccecc1e9 100644 --- a/third_party/blink/renderer/core/css/css_paint_image_generator.h +++ b/third_party/blink/renderer/core/css/css_paint_image_generator.h
@@ -6,8 +6,8 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PAINT_IMAGE_GENERATOR_H_ #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/cssom/css_style_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/geometry/float_size.h" #include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/third_party/blink/renderer/core/css/css_pending_substitution_value.h b/third_party/blink/renderer/core/css/css_pending_substitution_value.h index 8533f6f..4c847157 100644 --- a/third_party/blink/renderer/core/css/css_pending_substitution_value.h +++ b/third_party/blink/renderer/core/css/css_pending_substitution_value.h
@@ -5,9 +5,9 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PENDING_SUBSTITUTION_VALUE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PENDING_SUBSTITUTION_VALUE_H_ +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_value.h" #include "third_party/blink/renderer/core/css/css_variable_reference_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/css_primitive_value.h b/third_party/blink/renderer/core/css/css_primitive_value.h index e8ed235..0b60e4c 100644 --- a/third_party/blink/renderer/core/css/css_primitive_value.h +++ b/third_party/blink/renderer/core/css/css_primitive_value.h
@@ -23,8 +23,8 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PRIMITIVE_VALUE_H_ #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/platform/wtf/bit_vector.h" #include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/third_party/blink/renderer/core/css/css_property_equality.h b/third_party/blink/renderer/core/css/css_property_equality.h index 0e48b7c..33fe623 100644 --- a/third_party/blink/renderer/core/css/css_property_equality.h +++ b/third_party/blink/renderer/core/css/css_property_equality.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_EQUALITY_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_EQUALITY_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
diff --git a/third_party/blink/renderer/core/css/css_property_id_templates.h b/third_party/blink/renderer/core/css/css_property_id_templates.h index 8f32676..ac0f2f50b 100644 --- a/third_party/blink/renderer/core/css/css_property_id_templates.h +++ b/third_party/blink/renderer/core/css/css_property_id_templates.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_ID_TEMPLATES_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_ID_TEMPLATES_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/hash_functions.h" #include "third_party/blink/renderer/platform/wtf/hash_traits.h"
diff --git a/third_party/blink/renderer/core/css/css_property_name.h b/third_party/blink/renderer/core/css/css_property_name.h index c8f56767..517dd73 100644 --- a/third_party/blink/renderer/core/css/css_property_name.h +++ b/third_party/blink/renderer/core/css/css_property_name.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAME_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAME_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/css_property_value.h b/third_party/blink/renderer/core/css/css_property_value.h index b1a6c78..d956eb9d 100644 --- a/third_party/blink/renderer/core/css/css_property_value.h +++ b/third_party/blink/renderer/core/css/css_property_value.h
@@ -22,9 +22,9 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_VALUE_H_ #include "third_party/blink/renderer/core/css/css_property_name.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_value.h" #include "third_party/blink/renderer/core/css/properties/css_property.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/css_property_value_set.h b/third_party/blink/renderer/core/css/css_property_value_set.h index 195468b..08f48f0 100644 --- a/third_party/blink/renderer/core/css/css_property_value_set.h +++ b/third_party/blink/renderer/core/css/css_property_value_set.h
@@ -25,10 +25,10 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" #include "third_party/blink/renderer/core/css/css_property_name.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value.h" #include "third_party/blink/renderer/core/css/parser/css_parser_mode.h" #include "third_party/blink/renderer/core/css/property_set_css_style_declaration.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/wtf/noncopyable.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/core/css/css_style_declaration.cc b/third_party/blink/renderer/core/css/css_style_declaration.cc index 4032f2f..d4c6148 100644 --- a/third_party/blink/renderer/core/css/css_style_declaration.cc +++ b/third_party/blink/renderer/core/css/css_style_declaration.cc
@@ -34,11 +34,11 @@ #include "third_party/blink/renderer/core/css/css_primitive_value.h" #include "third_party/blink/renderer/core/css/css_property_id_templates.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_style_declaration.h" #include "third_party/blink/renderer/core/css/css_value.h" #include "third_party/blink/renderer/core/css/parser/css_parser.h" #include "third_party/blink/renderer/core/css/properties/css_property.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/wtf/ascii_ctype.h"
diff --git a/third_party/blink/renderer/core/css/css_style_declaration.h b/third_party/blink/renderer/core/css/css_style_declaration.h index e2ce951b..6dae920 100644 --- a/third_party/blink/renderer/core/css/css_style_declaration.h +++ b/third_party/blink/renderer/core/css/css_style_declaration.h
@@ -23,7 +23,7 @@ #include "base/macros.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/third_party/blink/renderer/core/css/css_value_pool.h b/third_party/blink/renderer/core/css/css_value_pool.h index 1f2cb9d1..40b6bfc9 100644 --- a/third_party/blink/renderer/core/css/css_value_pool.h +++ b/third_party/blink/renderer/core/css/css_value_pool.h
@@ -37,9 +37,9 @@ #include "third_party/blink/renderer/core/css/css_initial_value.h" #include "third_party/blink/renderer/core/css/css_invalid_variable_value.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_unset_value.h" #include "third_party/blink/renderer/core/css/css_value_list.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
diff --git a/third_party/blink/renderer/core/css/cssom/css_style_value.h b/third_party/blink/renderer/core/css/cssom/css_style_value.h index d3c9df2..2d1f43b 100644 --- a/third_party/blink/renderer/core/css/cssom/css_style_value.h +++ b/third_party/blink/renderer/core/css/cssom/css_style_value.h
@@ -8,8 +8,8 @@ #include "base/macros.h" #include "base/optional.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.cc b/third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.cc index 894e474..3da34b0 100644 --- a/third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.cc +++ b/third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.cc
@@ -4,8 +4,8 @@ #include "third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/parser/css_parser.h" -#include "third_party/blink/renderer/core/css_property_names.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/cssom/cssom_keywords.h b/third_party/blink/renderer/core/css/cssom/cssom_keywords.h index 3e5388e..86bd5e2 100644 --- a/third_party/blink/renderer/core/css/cssom/cssom_keywords.h +++ b/third_party/blink/renderer/core/css/cssom/cssom_keywords.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSSOM_KEYWORDS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSSOM_KEYWORDS_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/cssom/cssom_types.h b/third_party/blink/renderer/core/css/cssom/cssom_types.h index 9b3340d..d43ebea5 100644 --- a/third_party/blink/renderer/core/css/cssom/cssom_types.h +++ b/third_party/blink/renderer/core/css/cssom/cssom_types.h
@@ -5,8 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSSOM_TYPES_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSSOM_TYPES_H_ +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/cssom/css_style_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc index fa822e5..a3e889f 100644 --- a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc +++ b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h" #include "third_party/blink/renderer/core/css/css_custom_property_declaration.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/css_variable_reference_value.h" #include "third_party/blink/renderer/core/css/cssom/css_style_value.h" @@ -14,7 +15,6 @@ #include "third_party/blink/renderer/core/css/properties/css_property.h" #include "third_party/blink/renderer/core/css/property_registration.h" #include "third_party/blink/renderer/core/css/property_registry.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/style_property_shorthand.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h"
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h index acf6c42..d3eda52 100644 --- a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h +++ b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h
@@ -8,8 +8,8 @@ #include "base/macros.h" #include "third_party/blink/renderer/bindings/core/v8/iterable.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/cssom/css_style_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/cssom/style_value_factory.h b/third_party/blink/renderer/core/css/cssom/style_value_factory.h index 603aa2f6..094c463 100644 --- a/third_party/blink/renderer/core/css/cssom/style_value_factory.h +++ b/third_party/blink/renderer/core/css/cssom/style_value_factory.h
@@ -6,8 +6,8 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_STYLE_VALUE_FACTORY_H_ #include "third_party/blink/renderer/bindings/core/v8/css_style_value_or_string.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/cssom/css_style_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/parser/css_parser.h b/third_party/blink/renderer/core/css/parser/css_parser.h index 118bb97..09c63756 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser.h +++ b/third_party/blink/renderer/core/css/parser/css_parser.h
@@ -7,9 +7,9 @@ #include <memory> #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/parser/css_parser_context.h" -#include "third_party/blink/renderer/core/css_property_names.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_context.h b/third_party/blink/renderer/core/css/parser/css_parser_context.h index 851e068e..1223a84 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_context.h +++ b/third_party/blink/renderer/core/css/parser/css_parser_context.h
@@ -6,8 +6,8 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_CSS_PARSER_CONTEXT_H_ #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/parser/css_parser_mode.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/frame/web_feature_forward.h" #include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h index 4d491dc3..17109539 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h +++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_CSS_PARSER_FAST_PATHS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_CSS_PARSER_FAST_PATHS_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/platform/graphics/color.h" #include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl.h b/third_party/blink/renderer/core/css/parser/css_parser_impl.h index 37bf28a..371b0fea 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_impl.h +++ b/third_party/blink/renderer/core/css/parser/css_parser_impl.h
@@ -8,11 +8,11 @@ #include <memory> #include "base/macros.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_source_data.h" #include "third_party/blink/renderer/core/css/css_property_value.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_local_context.h b/third_party/blink/renderer/core/css/parser/css_parser_local_context.h index 2f1fbf3a..9fcd63b 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_local_context.h +++ b/third_party/blink/renderer/core/css/parser/css_parser_local_context.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_CSS_PARSER_LOCAL_CONTEXT_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_CSS_PARSER_LOCAL_CONTEXT_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 022942f..b7c96bbf 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -19,6 +19,7 @@ #include "third_party/blink/renderer/core/css/css_initial_value.h" #include "third_party/blink/renderer/core/css/css_path_value.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_ray_value.h" #include "third_party/blink/renderer/core/css/css_shadow_value.h" #include "third_party/blink/renderer/core/css/css_timing_function_value.h" @@ -34,7 +35,6 @@ #include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h" #include "third_party/blink/renderer/core/css/properties/css_property.h" #include "third_party/blink/renderer/core/css/properties/longhand.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/frame/web_feature.h"
diff --git a/third_party/blink/renderer/core/css/resolver/animated_style_builder.h b/third_party/blink/renderer/core/css/resolver/animated_style_builder.h index bfe5802..196c1b6 100644 --- a/third_party/blink/renderer/core/css/resolver/animated_style_builder.h +++ b/third_party/blink/renderer/core/css/resolver/animated_style_builder.h
@@ -31,7 +31,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_ANIMATED_STYLE_BUILDER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_ANIMATED_STYLE_BUILDER_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/resolver/css_property_priority.h b/third_party/blink/renderer/core/css/resolver/css_property_priority.h index 74a835ca..0d90ca3 100644 --- a/third_party/blink/renderer/core/css/resolver/css_property_priority.h +++ b/third_party/blink/renderer/core/css/resolver/css_property_priority.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CSS_PROPERTY_PRIORITY_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CSS_PROPERTY_PRIORITY_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/resolver/css_to_style_map.h b/third_party/blink/renderer/core/css/resolver/css_to_style_map.h index 827b91c..a50c47a 100644 --- a/third_party/blink/renderer/core/css/resolver/css_to_style_map.h +++ b/third_party/blink/renderer/core/css/resolver/css_to_style_map.h
@@ -25,7 +25,7 @@ #include "third_party/blink/renderer/core/animation/css/css_transition_data.h" #include "third_party/blink/renderer/core/animation/timing.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/style/computed_style_constants.h" #include "third_party/blink/renderer/platform/animation/timing_function.h" #include "third_party/blink/renderer/platform/wtf/allocator.h"
diff --git a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc index 363efe4..1ae95aec 100644 --- a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
@@ -7,6 +7,7 @@ #include "third_party/blink/renderer/core/css/css_custom_property_declaration.h" #include "third_party/blink/renderer/core/css/css_invalid_variable_value.h" #include "third_party/blink/renderer/core/css/css_pending_substitution_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_unset_value.h" #include "third_party/blink/renderer/core/css/css_variable_data.h" #include "third_party/blink/renderer/core/css/css_variable_reference_value.h" @@ -21,7 +22,6 @@ #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_stats.h" #include "third_party/blink/renderer/core/css/style_engine.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/renderer/core/style/computed_style.h"
diff --git a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h index c137115..ac3678d 100644 --- a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h +++ b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h
@@ -5,8 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CSS_VARIABLE_RESOLVER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CSS_VARIABLE_RESOLVER_H_ +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/parser/css_parser_token.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
diff --git a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc index 6923834..010203b7 100644 --- a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc +++ b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
@@ -25,8 +25,8 @@ #include "third_party/blink/renderer/core/css/css_gradient_value.h" #include "third_party/blink/renderer/core/css/css_image_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_uri_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/tree_scope.h"
diff --git a/third_party/blink/renderer/core/css/resolver/element_style_resources.h b/third_party/blink/renderer/core/css/resolver/element_style_resources.h index 08ebe761..f90ebdba 100644 --- a/third_party/blink/renderer/core/css/resolver/element_style_resources.h +++ b/third_party/blink/renderer/core/css/resolver/element_style_resources.h
@@ -26,7 +26,7 @@ #include "base/macros.h" #include "third_party/blink/renderer/core/css/css_property_id_templates.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/cross_origin_attribute_value.h" #include "third_party/blink/renderer/platform/graphics/color.h" #include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder.h b/third_party/blink/renderer/core/css/resolver/style_builder.h index fef3b08..455e2f8 100644 --- a/third_party/blink/renderer/core/css/resolver/style_builder.h +++ b/third_party/blink/renderer/core/css/resolver/style_builder.h
@@ -32,8 +32,8 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_STYLE_BUILDER_H_ #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/properties/css_property.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/heap/handle.h" namespace blink {
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index 85511ebd..0da4cbed 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -46,6 +46,7 @@ #include "third_party/blink/renderer/core/css/css_identifier_value.h" #include "third_party/blink/renderer/core/css/css_keyframe_rule.h" #include "third_party/blink/renderer/core/css/css_keyframes_rule.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/css_reflect_value.h" #include "third_party/blink/renderer/core/css/css_rule_list.h" @@ -75,7 +76,6 @@ #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/css/style_rule_import.h" #include "third_party/blink/renderer/core/css/style_sheet_contents.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/first_letter_pseudo_element.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/dom/shadow_root.h"
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.h b/third_party/blink/renderer/core/css/resolver/style_resolver_state.h index fc9664a..b50afc5 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.h +++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
@@ -28,12 +28,12 @@ #include "third_party/blink/renderer/core/animation/css/css_animation_update.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/css_pending_substitution_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h" #include "third_party/blink/renderer/core/css/resolver/css_to_style_map.h" #include "third_party/blink/renderer/core/css/resolver/element_resolve_context.h" #include "third_party/blink/renderer/core/css/resolver/element_style_resources.h" #include "third_party/blink/renderer/core/css/resolver/font_builder.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/style/cached_ua_style.h"
diff --git a/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h b/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h index 88ad5c4..4f8b8cd 100644 --- a/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h +++ b/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h
@@ -31,8 +31,8 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_VIEWPORT_STYLE_RESOLVER_H_ #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/rule_set.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/page/viewport_description.h" #include "third_party/blink/renderer/platform/geometry/length.h"
diff --git a/third_party/blink/renderer/core/css/threaded/css_parser_threaded_test.cc b/third_party/blink/renderer/core/css/threaded/css_parser_threaded_test.cc index 679d1af..83e290f 100644 --- a/third_party/blink/renderer/core/css/threaded/css_parser_threaded_test.cc +++ b/third_party/blink/renderer/core/css/threaded/css_parser_threaded_test.cc
@@ -6,9 +6,9 @@ #include "third_party/blink/renderer/core/css/parser/css_parser_context.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/threaded/multi_threaded_test_util.h" -#include "third_party/blink/renderer/core/css_property_names.h" namespace blink {
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 7ef69b1..08c4636 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -165,6 +165,41 @@ enum class ClassStringContent { kEmpty, kWhiteSpaceOnly, kHasClasses }; +namespace { + +bool IsRootEditableElementWithCounting(const Element& element) { + bool is_editable = IsRootEditableElement(element); + Document& doc = element.GetDocument(); + if (!doc.IsActive()) + return is_editable; + // -webkit-user-modify doesn't affect text control elements. + if (element.IsTextControl()) + return is_editable; + const auto* style = element.GetComputedStyle(); + if (!style) + return is_editable; + const AtomicString& ce_value = element.FastGetAttribute(kContenteditableAttr); + if (ce_value.IsNull() || DeprecatedEqualIgnoringCase(ce_value, "false")) { + if (style->UserModify() != EUserModify::kReadOnly) + UseCounter::Count(doc, WebFeature::kWebKitUserModifyEffective); + if (style->UserModify() == EUserModify::kReadWritePlaintextOnly) + UseCounter::Count(doc, WebFeature::kPlainTextEditingEffective); + } else if (ce_value.IsEmpty() || + DeprecatedEqualIgnoringCase(ce_value, "true")) { + if (style->UserModify() != EUserModify::kReadWrite) + UseCounter::Count(doc, WebFeature::kWebKitUserModifyEffective); + if (style->UserModify() == EUserModify::kReadWritePlaintextOnly) + UseCounter::Count(doc, WebFeature::kPlainTextEditingEffective); + } else if (DeprecatedEqualIgnoringCase(ce_value, "plaintext-only")) { + if (style->UserModify() != EUserModify::kReadWritePlaintextOnly) + UseCounter::Count(doc, WebFeature::kWebKitUserModifyEffective); + UseCounter::Count(doc, WebFeature::kPlainTextEditingEffective); + } + return is_editable; +} + +} // namespace + Element* Element::Create(const QualifiedName& tag_name, Document* document) { return new Element(tag_name, document, kCreateElement); } @@ -3214,7 +3249,7 @@ // it won't be focusable. Furthermore, supportsFocus cannot just return true // always or else tabIndex() will change for all HTML elements. return HasElementFlag(ElementFlags::kTabIndexWasSetExplicitly) || - IsRootEditableElement(*this) || + IsRootEditableElementWithCounting(*this) || (IsShadowHost(this) && AuthorShadowRoot() && AuthorShadowRoot()->delegatesFocus()) || SupportsSpatialNavigationFocus() ||
diff --git a/third_party/blink/renderer/core/dom/processing_instruction.cc b/third_party/blink/renderer/core/dom/processing_instruction.cc index 315e2f34..83e4afe9 100644 --- a/third_party/blink/renderer/core/dom/processing_instruction.cc +++ b/third_party/blink/renderer/core/dom/processing_instruction.cc
@@ -87,8 +87,11 @@ } void ProcessingInstruction::DidAttributeChanged() { - if (sheet_) + if (sheet_) { + if (sheet_->IsLoading()) + RemovePendingSheet(); ClearSheet(); + } String href; String charset; @@ -180,8 +183,7 @@ bool ProcessingInstruction::SheetLoaded() { if (!IsLoading()) { if (!DocumentXSLT::SheetLoaded(GetDocument(), this)) - GetDocument().GetStyleEngine().RemovePendingSheet(*this, - style_engine_context_); + RemovePendingSheet(); return true; } return false; @@ -265,6 +267,9 @@ *this, insertion_point); } + if (IsLoading()) + RemovePendingSheet(); + if (sheet_) { DCHECK_EQ(sheet_->ownerNode(), this); ClearSheet(); @@ -276,12 +281,14 @@ void ProcessingInstruction::ClearSheet() { DCHECK(sheet_); - if (sheet_->IsLoading()) - GetDocument().GetStyleEngine().RemovePendingSheet(*this, - style_engine_context_); sheet_.Release()->ClearOwnerNode(); } +void ProcessingInstruction::RemovePendingSheet() { + GetDocument().GetStyleEngine().RemovePendingSheet(*this, + style_engine_context_); +} + void ProcessingInstruction::Trace(blink::Visitor* visitor) { visitor->Trace(sheet_); visitor->Trace(listener_for_xslt_);
diff --git a/third_party/blink/renderer/core/dom/processing_instruction.h b/third_party/blink/renderer/core/dom/processing_instruction.h index 66e8683..e30343c 100644 --- a/third_party/blink/renderer/core/dom/processing_instruction.h +++ b/third_party/blink/renderer/core/dom/processing_instruction.h
@@ -91,6 +91,7 @@ void ParseStyleSheet(const String& sheet); void ClearSheet(); + void RemovePendingSheet(); String DebugName() const override { return "ProcessingInstruction"; }
diff --git a/third_party/blink/renderer/core/editing/commands/apply_style_command.cc b/third_party/blink/renderer/core/editing/commands/apply_style_command.cc index 215f173..e31fc21 100644 --- a/third_party/blink/renderer/core/editing/commands/apply_style_command.cc +++ b/third_party/blink/renderer/core/editing/commands/apply_style_command.cc
@@ -27,8 +27,8 @@ #include "third_party/blink/renderer/core/css/css_computed_style_declaration.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/node_list.h"
diff --git a/third_party/blink/renderer/core/editing/commands/composite_edit_command.h b/third_party/blink/renderer/core/editing/commands/composite_edit_command.h index 4a791b3..635d59a9 100644 --- a/third_party/blink/renderer/core/editing/commands/composite_edit_command.h +++ b/third_party/blink/renderer/core/editing/commands/composite_edit_command.h
@@ -27,7 +27,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_COMPOSITE_EDIT_COMMAND_H_ #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/editing/commands/edit_command.h" #include "third_party/blink/renderer/core/editing/commands/editing_state.h" #include "third_party/blink/renderer/core/editing/commands/undo_step.h"
diff --git a/third_party/blink/renderer/core/editing/commands/editor_command.cc b/third_party/blink/renderer/core/editing/commands/editor_command.cc index 16a589ba..2e631eeb 100644 --- a/third_party/blink/renderer/core/editing/commands/editor_command.cc +++ b/third_party/blink/renderer/core/editing/commands/editor_command.cc
@@ -29,8 +29,8 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_editing_command_type.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/tag_collection.h"
diff --git a/third_party/blink/renderer/core/editing/commands/remove_css_property_command.h b/third_party/blink/renderer/core/editing/commands/remove_css_property_command.h index c5402b8..5428e07 100644 --- a/third_party/blink/renderer/core/editing/commands/remove_css_property_command.h +++ b/third_party/blink/renderer/core/editing/commands/remove_css_property_command.h
@@ -26,7 +26,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_REMOVE_CSS_PROPERTY_COMMAND_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_REMOVE_CSS_PROPERTY_COMMAND_H_ -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/editing/commands/edit_command.h" namespace blink {
diff --git a/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc b/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc index 774a0bd..7b946dbb 100644 --- a/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc +++ b/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc
@@ -27,9 +27,9 @@ #include "third_party/blink/renderer/core/editing/commands/replace_selection_command.h" #include "base/macros.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/css_style_declaration.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/document_fragment.h" #include "third_party/blink/renderer/core/dom/element.h"
diff --git a/third_party/blink/renderer/core/editing/editing_style.h b/third_party/blink/renderer/core/editing/editing_style.h index f777be5..6bcaf1c3 100644 --- a/third_party/blink/renderer/core/editing/editing_style.h +++ b/third_party/blink/renderer/core/editing/editing_style.h
@@ -33,7 +33,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_EDITING_STYLE_H_ #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/editing/forward.h" #include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/third_party/blink/renderer/core/editing/editing_style_utilities.cc b/third_party/blink/renderer/core/editing/editing_style_utilities.cc index 14692dc4..84676040 100644 --- a/third_party/blink/renderer/core/editing/editing_style_utilities.cc +++ b/third_party/blink/renderer/core/editing/editing_style_utilities.cc
@@ -29,9 +29,9 @@ #include "third_party/blink/renderer/core/css/css_color_value.h" #include "third_party/blink/renderer/core/css/css_computed_style_declaration.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/parser/css_parser.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/text.h" #include "third_party/blink/renderer/core/editing/editing_style.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h"
diff --git a/third_party/blink/renderer/core/editing/editor.cc b/third_party/blink/renderer/core/editing/editor.cc index 07d94fe1..5caff9a 100644 --- a/third_party/blink/renderer/core/editing/editor.cc +++ b/third_party/blink/renderer/core/editing/editor.cc
@@ -33,8 +33,8 @@ #include "third_party/blink/renderer/core/clipboard/data_transfer_access_policy.h" #include "third_party/blink/renderer/core/clipboard/system_clipboard.h" #include "third_party/blink/renderer/core/css/css_computed_style_declaration.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document_fragment.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
diff --git a/third_party/blink/renderer/core/editing/serializers/serialization.h b/third_party/blink/renderer/core/editing/serializers/serialization.h index 0dc9a4f..9ffe3ae 100644 --- a/third_party/blink/renderer/core/editing/serializers/serialization.h +++ b/third_party/blink/renderer/core/editing/serializers/serialization.h
@@ -27,7 +27,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SERIALIZERS_SERIALIZATION_H_ #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/parser_content_policy.h" #include "third_party/blink/renderer/core/editing/forward.h" #include "third_party/blink/renderer/core/editing/serializers/html_interchange.h"
diff --git a/third_party/blink/renderer/core/exported/web_document_test.cc b/third_party/blink/renderer/core/exported/web_document_test.cc index 6e13d631..0f691ce 100644 --- a/third_party/blink/renderer/core/exported/web_document_test.cc +++ b/third_party/blink/renderer/core/exported/web_document_test.cc
@@ -11,8 +11,8 @@ #include "third_party/blink/public/common/origin_trials/origin_trial_policy.h" #include "third_party/blink/public/common/origin_trials/trial_token_validator.h" #include "third_party/blink/public/web/web_origin_trials.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/style_engine.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/frame/frame_test_helpers.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc index 6f54b499..505f36a1 100644 --- a/third_party/blink/renderer/core/exported/web_view_test.cc +++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -529,7 +529,7 @@ // would. LocalFrameView* view = web_view_helper_.LocalMainFrame()->GetFrameView(); PaintLayer* root_layer = view->GetLayoutView()->Layer(); - LayoutRect paint_rect(0, 0, kWidth, kHeight); + CullRect paint_rect(IntRect(0, 0, kWidth, kHeight)); PaintLayerPaintingInfo painting_info(root_layer, paint_rect, kGlobalPaintNormalPhase, LayoutSize());
diff --git a/third_party/blink/renderer/core/frame/ad_tracker_test.cc b/third_party/blink/renderer/core/frame/ad_tracker_test.cc index b914ede..128a79f 100644 --- a/third_party/blink/renderer/core/frame/ad_tracker_test.cc +++ b/third_party/blink/renderer/core/frame/ad_tracker_test.cc
@@ -482,8 +482,6 @@ main_resource_->Start(); } - void TearDown() override { SimTest::TearDown(); } - std::unique_ptr<SimRequest> main_resource_; };
diff --git a/third_party/blink/renderer/core/frame/deprecation.h b/third_party/blink/renderer/core/frame/deprecation.h index 6ff0372..6cc1eff3 100644 --- a/third_party/blink/renderer/core/frame/deprecation.h +++ b/third_party/blink/renderer/core/frame/deprecation.h
@@ -7,7 +7,7 @@ #include "base/macros.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/platform/wtf/bit_vector.h"
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 3ba9332..908f669 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2820,7 +2820,7 @@ } PaintInternal(graphics_context, kGlobalPaintNormalPhase, - CullRect(LayoutRect::InfiniteIntRect())); + CullRect::Infinite()); paint_controller_->CommitNewDisplayItems(); } } else {
diff --git a/third_party/blink/renderer/core/frame/use_counter.h b/third_party/blink/renderer/core/frame/use_counter.h index 469777e..22481b4 100644 --- a/third_party/blink/renderer/core/frame/use_counter.h +++ b/third_party/blink/renderer/core/frame/use_counter.h
@@ -28,8 +28,8 @@ #include "base/macros.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/parser/css_parser_mode.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/third_party/blink/renderer/core/html/forms/color_input_type.cc b/third_party/blink/renderer/core/html/forms/color_input_type.cc index 26166ed..88a556c 100644 --- a/third_party/blink/renderer/core/html/forms/color_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/color_input_type.cc
@@ -31,7 +31,7 @@ #include "third_party/blink/renderer/core/html/forms/color_input_type.h" #include "third_party/blink/renderer/bindings/core/v8/script_controller.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/renderer/core/events/mouse_event.h"
diff --git a/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.cc b/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.cc index be00a6a..d27d52b 100644 --- a/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.cc +++ b/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.cc
@@ -25,7 +25,7 @@ #include "third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/events/keyboard_event.h" #include "third_party/blink/renderer/platform/fonts/font.h"
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc index 81cef5f..e40a687 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -34,8 +34,8 @@ #include "third_party/blink/public/platform/web_scroll_into_view_params.h" #include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/style_change_reason.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h" #include "third_party/blink/renderer/core/dom/id_target_observer.h"
diff --git a/third_party/blink/renderer/core/html/html_br_element.cc b/third_party/blink/renderer/core/html/html_br_element.cc index 3473faf..b11c391 100644 --- a/third_party/blink/renderer/core/html/html_br_element.cc +++ b/third_party/blink/renderer/core/html/html_br_element.cc
@@ -22,7 +22,7 @@ #include "third_party/blink/renderer/core/html/html_br_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/layout/layout_br.h"
diff --git a/third_party/blink/renderer/core/html/html_details_element.cc b/third_party/blink/renderer/core/html/html_details_element.cc index b8dbaa6..1fe24870 100644 --- a/third_party/blink/renderer/core/html/html_details_element.cc +++ b/third_party/blink/renderer/core/html/html_details_element.cc
@@ -21,7 +21,7 @@ #include "third_party/blink/renderer/core/html/html_details_element.h" #include "third_party/blink/public/platform/task_type.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/events/event.h"
diff --git a/third_party/blink/renderer/core/html/html_div_element.cc b/third_party/blink/renderer/core/html/html_div_element.cc index 1545f09..fbc2f5d 100644 --- a/third_party/blink/renderer/core/html/html_div_element.cc +++ b/third_party/blink/renderer/core/html/html_div_element.cc
@@ -22,7 +22,7 @@ #include "third_party/blink/renderer/core/html/html_div_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/html_names.h"
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc index 8704211ff..c77dd27 100644 --- a/third_party/blink/renderer/core/html/html_element.cc +++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -31,9 +31,9 @@ #include "third_party/blink/renderer/bindings/core/v8/string_treat_null_as_empty_string_or_trusted_script.h" #include "third_party/blink/renderer/core/css/css_color_value.h" #include "third_party/blink/renderer/core/css/css_markup.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/style_change_reason.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/document_fragment.h" #include "third_party/blink/renderer/core/dom/element_traversal.h"
diff --git a/third_party/blink/renderer/core/html/html_embed_element.cc b/third_party/blink/renderer/core/html/html_embed_element.cc index 8bcc56c7..1f152c3 100644 --- a/third_party/blink/renderer/core/html/html_embed_element.cc +++ b/third_party/blink/renderer/core/html/html_embed_element.cc
@@ -24,7 +24,7 @@ #include "third_party/blink/renderer/core/html/html_embed_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/attribute.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/shadow_root.h"
diff --git a/third_party/blink/renderer/core/html/html_font_element.cc b/third_party/blink/renderer/core/html/html_font_element.cc index c5e2614d..d61a02c0 100644 --- a/third_party/blink/renderer/core/html/html_font_element.cc +++ b/third_party/blink/renderer/core/html/html_font_element.cc
@@ -22,11 +22,11 @@ #include "third_party/blink/renderer/core/html/html_font_element.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/css_value_pool.h" #include "third_party/blink/renderer/core/css/parser/css_parser.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
diff --git a/third_party/blink/renderer/core/html/html_frame_set_element.cc b/third_party/blink/renderer/core/html/html_frame_set_element.cc index 2b79c384..42150f9a 100644 --- a/third_party/blink/renderer/core/html/html_frame_set_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_set_element.cc
@@ -24,8 +24,8 @@ #include "third_party/blink/renderer/core/html/html_frame_set_element.h" #include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/style_change_reason.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/events/mouse_event.h"
diff --git a/third_party/blink/renderer/core/html/html_hr_element.cc b/third_party/blink/renderer/core/html/html_hr_element.cc index 3729778..9ac4214 100644 --- a/third_party/blink/renderer/core/html/html_hr_element.cc +++ b/third_party/blink/renderer/core/html/html_hr_element.cc
@@ -23,8 +23,8 @@ #include "third_party/blink/renderer/core/html/html_hr_element.h" #include "third_party/blink/renderer/core/css/css_color_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/html/forms/html_opt_group_element.h" #include "third_party/blink/renderer/core/html/forms/html_select_element.h"
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc index 8cc63590..e6ecce4 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -26,7 +26,7 @@ #include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h" #include "third_party/blink/renderer/bindings/core/v8/v8_html_iframe_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/feature_policy/iframe_policy.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_party/blink/renderer/core/html/html_image_element.cc index df8e718..b2ab5e3 100644 --- a/third_party/blink/renderer/core/html/html_image_element.cc +++ b/third_party/blink/renderer/core/html/html_image_element.cc
@@ -23,11 +23,11 @@ #include "third_party/blink/renderer/core/html/html_image_element.h" #include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/media_query_matcher.h" #include "third_party/blink/renderer/core/css/media_values_dynamic.h" #include "third_party/blink/renderer/core/css/parser/sizes_attribute_parser.h" #include "third_party/blink/renderer/core/css/style_change_reason.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/attribute.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
diff --git a/third_party/blink/renderer/core/html/html_li_element.cc b/third_party/blink/renderer/core/html/html_li_element.cc index 7d2fc83..15953cd9 100644 --- a/third_party/blink/renderer/core/html/html_li_element.cc +++ b/third_party/blink/renderer/core/html/html_li_element.cc
@@ -22,7 +22,7 @@ #include "third_party/blink/renderer/core/html/html_li_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
diff --git a/third_party/blink/renderer/core/html/html_marquee_element.cc b/third_party/blink/renderer/core/html/html_marquee_element.cc index 6a63210..a1edeaf 100644 --- a/third_party/blink/renderer/core/html/html_marquee_element.cc +++ b/third_party/blink/renderer/core/html/html_marquee_element.cc
@@ -33,9 +33,9 @@ #include "third_party/blink/renderer/core/animation/optional_effect_timing.h" #include "third_party/blink/renderer/core/animation/string_keyframe.h" #include "third_party/blink/renderer/core/animation/timing_input.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/css_style_declaration.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/events/event_listener.h" #include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h"
diff --git a/third_party/blink/renderer/core/html/html_olist_element.cc b/third_party/blink/renderer/core/html/html_olist_element.cc index 78fe970..7fff18f 100644 --- a/third_party/blink/renderer/core/html/html_olist_element.cc +++ b/third_party/blink/renderer/core/html/html_olist_element.cc
@@ -22,7 +22,7 @@ #include "third_party/blink/renderer/core/html/html_olist_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/html/list_item_ordinal.h"
diff --git a/third_party/blink/renderer/core/html/html_paragraph_element.cc b/third_party/blink/renderer/core/html/html_paragraph_element.cc index 3fc9ec4..0deb8c28 100644 --- a/third_party/blink/renderer/core/html/html_paragraph_element.cc +++ b/third_party/blink/renderer/core/html/html_paragraph_element.cc
@@ -22,7 +22,7 @@ #include "third_party/blink/renderer/core/html/html_paragraph_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/html_names.h"
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc index dec73f77..f3ecab34 100644 --- a/third_party/blink/renderer/core/html/html_plugin_element.cc +++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -25,7 +25,7 @@ #include "services/network/public/mojom/request_context_frame_type.mojom-blink.h" #include "third_party/blink/public/platform/web_url_request.h" #include "third_party/blink/renderer/bindings/core/v8/script_controller.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/node.h"
diff --git a/third_party/blink/renderer/core/html/html_pre_element.cc b/third_party/blink/renderer/core/html/html_pre_element.cc index 4cf0916..d0d52b9f 100644 --- a/third_party/blink/renderer/core/html/html_pre_element.cc +++ b/third_party/blink/renderer/core/html/html_pre_element.cc
@@ -22,8 +22,8 @@ #include "third_party/blink/renderer/core/html/html_pre_element.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/html_names.h"
diff --git a/third_party/blink/renderer/core/html/html_table_caption_element.cc b/third_party/blink/renderer/core/html/html_table_caption_element.cc index c754f11..dd542cb5 100644 --- a/third_party/blink/renderer/core/html/html_table_caption_element.cc +++ b/third_party/blink/renderer/core/html/html_table_caption_element.cc
@@ -24,7 +24,7 @@ #include "third_party/blink/renderer/core/html/html_table_caption_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/html_names.h" namespace blink {
diff --git a/third_party/blink/renderer/core/html/html_table_cell_element.cc b/third_party/blink/renderer/core/html/html_table_cell_element.cc index 30afae92..a1101778 100644 --- a/third_party/blink/renderer/core/html/html_table_cell_element.cc +++ b/third_party/blink/renderer/core/html/html_table_cell_element.cc
@@ -24,7 +24,7 @@ #include "third_party/blink/renderer/core/html/html_table_cell_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/attribute.h" #include "third_party/blink/renderer/core/dom/element_traversal.h"
diff --git a/third_party/blink/renderer/core/html/html_table_col_element.cc b/third_party/blink/renderer/core/html/html_table_col_element.cc index 10e8e717e..d431c99 100644 --- a/third_party/blink/renderer/core/html/html_table_col_element.cc +++ b/third_party/blink/renderer/core/html/html_table_col_element.cc
@@ -25,7 +25,7 @@ #include "third_party/blink/renderer/core/html/html_table_col_element.h" #include <algorithm> -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/html/html_table_cell_element.h" #include "third_party/blink/renderer/core/html/html_table_element.h" #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
diff --git a/third_party/blink/renderer/core/html/html_table_element.cc b/third_party/blink/renderer/core/html/html_table_element.cc index 93c609a..09fcb4d 100644 --- a/third_party/blink/renderer/core/html/html_table_element.cc +++ b/third_party/blink/renderer/core/html/html_table_element.cc
@@ -28,9 +28,9 @@ #include "third_party/blink/renderer/core/css/css_identifier_value.h" #include "third_party/blink/renderer/core/css/css_image_value.h" #include "third_party/blink/renderer/core/css/css_inherited_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/style_change_reason.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/attribute.h" #include "third_party/blink/renderer/core/dom/element_traversal.h"
diff --git a/third_party/blink/renderer/core/html/html_table_part_element.cc b/third_party/blink/renderer/core/html/html_table_part_element.cc index 8ad0629..3f98eae 100644 --- a/third_party/blink/renderer/core/html/html_table_part_element.cc +++ b/third_party/blink/renderer/core/html/html_table_part_element.cc
@@ -25,8 +25,8 @@ #include "third_party/blink/renderer/core/html/html_table_part_element.h" #include "third_party/blink/renderer/core/css/css_image_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
diff --git a/third_party/blink/renderer/core/html/html_ulist_element.cc b/third_party/blink/renderer/core/html/html_ulist_element.cc index ac0d1ab..f458780 100644 --- a/third_party/blink/renderer/core/html/html_ulist_element.cc +++ b/third_party/blink/renderer/core/html/html_ulist_element.cc
@@ -22,7 +22,7 @@ #include "third_party/blink/renderer/core/html/html_ulist_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/html_names.h" namespace blink {
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc index 56339df..6556fba 100644 --- a/third_party/blink/renderer/core/html/media/html_video_element.cc +++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -28,7 +28,7 @@ #include <memory> #include "cc/paint/paint_canvas.h" #include "third_party/blink/public/platform/web_fullscreen_video_status.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/attribute.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/dom_exception.h"
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc b/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc index a147bf0f..4d63cc0e 100644 --- a/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc +++ b/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc
@@ -30,7 +30,7 @@ #include "third_party/blink/renderer/core/html/track/vtt/vtt_cue.h" #include "third_party/blink/renderer/bindings/core/v8/double_or_auto_keyword.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/document_fragment.h" #include "third_party/blink/renderer/core/dom/events/event.h"
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc index 4e94f2c..5320cada 100644 --- a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -34,6 +34,7 @@ #include "third_party/blink/renderer/core/css/css_import_rule.h" #include "third_party/blink/renderer/core/css/css_keyframe_rule.h" #include "third_party/blink/renderer/core/css/css_media_rule.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/css_rule.h" #include "third_party/blink/renderer/core/css/css_rule_list.h" @@ -56,7 +57,6 @@ #include "third_party/blink/renderer/core/css/style_sheet.h" #include "third_party/blink/renderer/core/css/style_sheet_contents.h" #include "third_party/blink/renderer/core/css/style_sheet_list.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/dom/node.h"
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h b/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h index 4f7f0964..5e29bd3 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_DOM_SNAPSHOT_AGENT_H_ #include "base/macros.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/inspector/inspector_base_agent.h" #include "third_party/blink/renderer/core/inspector/protocol/DOMSnapshot.h"
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc index c0be47b..f6d6085 100644 --- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc +++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -31,6 +31,7 @@ #include "third_party/blink/renderer/core/css/css_keyframe_rule.h" #include "third_party/blink/renderer/core/css/css_keyframes_rule.h" #include "third_party/blink/renderer/core/css/css_media_rule.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/css_rule_list.h" #include "third_party/blink/renderer/core/css/css_style_rule.h" @@ -41,7 +42,6 @@ #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/core/css/style_sheet_contents.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/dom/element.h"
diff --git a/third_party/blink/renderer/core/layout/custom/css_layout_definition.h b/third_party/blink/renderer/core/layout/custom/css_layout_definition.h index bec75b9..7364c99 100644 --- a/third_party/blink/renderer/core/layout/custom/css_layout_definition.h +++ b/third_party/blink/renderer/core/layout/custom/css_layout_definition.h
@@ -5,8 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_CUSTOM_CSS_LAYOUT_DEFINITION_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_CUSTOM_CSS_LAYOUT_DEFINITION_H_ +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/cssom/css_style_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/platform/bindings/name_client.h" #include "third_party/blink/renderer/platform/bindings/scoped_persistent.h" #include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
diff --git a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc index e76bad8b..8bc8cf5 100644 --- a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc +++ b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc
@@ -6,7 +6,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_object_parser.h" #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
diff --git a/third_party/blink/renderer/core/layout/layout_fieldset.cc b/third_party/blink/renderer/core/layout/layout_fieldset.cc index 7d33944..540740d 100644 --- a/third_party/blink/renderer/core/layout/layout_fieldset.cc +++ b/third_party/blink/renderer/core/layout/layout_fieldset.cc
@@ -23,7 +23,7 @@ #include "third_party/blink/renderer/core/layout/layout_fieldset.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/html/forms/html_legend_element.h" #include "third_party/blink/renderer/core/paint/fieldset_painter.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
diff --git a/third_party/blink/renderer/core/layout/layout_table.h b/third_party/blink/renderer/core/layout/layout_table.h index 983880a8..a12c2bc 100644 --- a/third_party/blink/renderer/core/layout/layout_table.h +++ b/third_party/blink/renderer/core/layout/layout_table.h
@@ -28,7 +28,7 @@ #include <memory> #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/layout/layout_block.h" #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc index 634f527..ab89c956 100644 --- a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc +++ b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
@@ -585,9 +585,7 @@ if (auto* layout_view = ToLocalFrameView(frame_view)->GetLayoutView()) { layout_view->GetDocument().UpdateStyleAndLayout(); if (auto* layer = layout_view->Layer()) { - LayoutTreeAsText::WriteLayers( - ts, layer, layer, layer->RectIgnoringNeedsPositionUpdate(), - indent + 1, behavior); + LayoutTreeAsText::WriteLayers(ts, layer, layer, indent + 1, behavior); } } } @@ -705,7 +703,6 @@ void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts, const PaintLayer* root_layer, PaintLayer* layer, - const LayoutRect& paint_rect, int indent, LayoutAsTextBehavior behavior, const PaintLayer* marked_layer) { @@ -717,7 +714,7 @@ ClipRectsContext(root_layer, &root_layer->GetLayoutObject().FirstFragment(), kUncachedClipRects), - &layer->GetLayoutObject().FirstFragment(), &paint_rect, layer_bounds, + &layer->GetLayoutObject().FirstFragment(), nullptr, layer_bounds, damage_rect, clip_rect_to_apply); LayoutPoint offset_from_root; @@ -758,8 +755,8 @@ ++curr_indent; } for (unsigned i = 0; i != neg_list->size(); ++i) { - WriteLayers(ts, root_layer, neg_list->at(i), paint_rect, curr_indent, - behavior, marked_layer); + WriteLayers(ts, root_layer, neg_list->at(i), curr_indent, behavior, + marked_layer); } } } @@ -783,8 +780,8 @@ ++curr_indent; } for (unsigned i = 0; i != normal_flow_list.size(); ++i) { - WriteLayers(ts, root_layer, normal_flow_list.at(i), paint_rect, - curr_indent, behavior, marked_layer); + WriteLayers(ts, root_layer, normal_flow_list.at(i), curr_indent, + behavior, marked_layer); } } @@ -797,8 +794,8 @@ ++curr_indent; } for (unsigned i = 0; i != pos_list->size(); ++i) { - WriteLayers(ts, root_layer, pos_list->at(i), paint_rect, curr_indent, - behavior, marked_layer); + WriteLayers(ts, root_layer, pos_list->at(i), curr_indent, behavior, + marked_layer); } } } @@ -872,9 +869,7 @@ return ts.Release(); PaintLayer* layer = layout_object->Layer(); - LayoutTreeAsText::WriteLayers(ts, layer, layer, - layer->RectIgnoringNeedsPositionUpdate(), 0, - behavior, marked_layer); + LayoutTreeAsText::WriteLayers(ts, layer, layer, 0, behavior, marked_layer); WriteSelection(ts, layout_object); return ts.Release(); }
diff --git a/third_party/blink/renderer/core/layout/layout_tree_as_text.h b/third_party/blink/renderer/core/layout/layout_tree_as_text.h index 2c6191a..9b46537 100644 --- a/third_party/blink/renderer/core/layout/layout_tree_as_text.h +++ b/third_party/blink/renderer/core/layout/layout_tree_as_text.h
@@ -36,7 +36,6 @@ class Color; class PaintLayer; class Element; -class LayoutRect; class LocalFrame; class LayoutBlockFlow; class LayoutObject; @@ -94,7 +93,6 @@ static void WriteLayers(WTF::TextStream&, const PaintLayer* root_layer, PaintLayer*, - const LayoutRect& paint_dirty_rect, int indent = 0, LayoutAsTextBehavior = kLayoutAsTextBehaviorNormal, const PaintLayer* marked_layer = nullptr);
diff --git a/third_party/blink/renderer/core/layout/line/inline_flow_box.cc b/third_party/blink/renderer/core/layout/line/inline_flow_box.cc index 46ff879..6de638a 100644 --- a/third_party/blink/renderer/core/layout/line/inline_flow_box.cc +++ b/third_party/blink/renderer/core/layout/line/inline_flow_box.cc
@@ -22,7 +22,7 @@ #include <math.h> #include <algorithm> -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/layout/api/line_layout_api_shim.h" #include "third_party/blink/renderer/core/layout/api/line_layout_box.h"
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc index 931780b0..ca511fb 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
@@ -774,6 +774,10 @@ wtf_size_t index = static_cast<wtf_size_t>(std::distance(items_->begin(), item)); items_->EraseAt(index); + for (BoxInfo& box : boxes_) { + if (box.item_index >= index) + --box.item_index; + } if (index == items_->size()) return; // Re-compute |item| because |EraseAt| may have reallocated the buffer.
diff --git a/third_party/blink/renderer/core/paint/block_painter_test.cc b/third_party/blink/renderer/core/paint/block_painter_test.cc index 0719691b..180c207 100644 --- a/third_party/blink/renderer/core/paint/block_painter_test.cc +++ b/third_party/blink/renderer/core/paint/block_painter_test.cc
@@ -262,7 +262,7 @@ IsSameId(touchaction, DisplayItem::kHitTest))); const auto& hit_test_client = *touchaction->EnclosingLayer(); - EXPECT_SUBSEQUENCE(hit_test_client, 1u, 2u); + EXPECT_SUBSEQUENCE(hit_test_client, 1, 2); PaintChunk::Id root_chunk_id(scrolling_client, kDocumentBackgroundType); auto root_chunk_properties = @@ -289,7 +289,7 @@ EXPECT_EQ(2, NumCachedNewItems()); CommitAndFinishCycle(); - EXPECT_SUBSEQUENCE(hit_test_client, 1u, 2u); + EXPECT_SUBSEQUENCE(hit_test_client, 1, 2); EXPECT_THAT( RootPaintController().PaintChunks(),
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc index 7573d64..997375ff 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -3113,7 +3113,7 @@ kPaintsIntoGroupedBacking) { // FIXME: GraphicsLayers need a way to split for multicol. PaintLayerPaintingInfo painting_info( - paint_info.paint_layer, LayoutRect(dirty_rect), kGlobalPaintNormalPhase, + paint_info.paint_layer, CullRect(dirty_rect), kGlobalPaintNormalPhase, paint_info.paint_layer->SubpixelAccumulation()); PaintLayerPainter(*paint_info.paint_layer) .PaintLayerContents(context, painting_info, paint_layer_flags); @@ -3126,7 +3126,7 @@ } } else { PaintLayerPaintingInfo painting_info( - paint_info.paint_layer, LayoutRect(dirty_rect), kGlobalPaintNormalPhase, + paint_info.paint_layer, CullRect(dirty_rect), kGlobalPaintNormalPhase, paint_info.paint_layer->SubpixelAccumulation()); PaintLayerPainter(*paint_info.paint_layer) .Paint(context, painting_info, paint_layer_flags);
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc index e134348c..6f8823d 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
@@ -55,8 +55,6 @@ RenderingTest::SetUp(); EnableCompositing(); } - - void TearDown() override { RenderingTest::TearDown(); } }; // Tests the pre-BlinkGenPropertyTrees composited layer mapping code. With BGPT,
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc index b9802967..40dbf39e 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
@@ -5,7 +5,7 @@ #include "third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h" #include "third_party/blink/renderer/core/animation/scroll_timeline.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h"
diff --git a/third_party/blink/renderer/core/paint/frame_painter.cc b/third_party/blink/renderer/core/paint/frame_painter.cc index 12b6df67..d5f2881b 100644 --- a/third_party/blink/renderer/core/paint/frame_painter.cc +++ b/third_party/blink/renderer/core/paint/frame_painter.cc
@@ -101,11 +101,11 @@ root_layer->GetLayoutObject().GetFrame()); context.SetDeviceScaleFactor(device_scale_factor); - layer_painter.Paint(context, LayoutRect(rect), updated_global_paint_flags, + layer_painter.Paint(context, CullRect(rect), updated_global_paint_flags, root_layer_paint_flags); if (root_layer->ContainsDirtyOverlayScrollbars()) { - layer_painter.PaintOverlayScrollbars(context, LayoutRect(rect), + layer_painter.PaintOverlayScrollbars(context, CullRect(rect), updated_global_paint_flags); }
diff --git a/third_party/blink/renderer/core/paint/image_element_timing.cc b/third_party/blink/renderer/core/paint/image_element_timing.cc index d20e0edf..346e103 100644 --- a/third_party/blink/renderer/core/paint/image_element_timing.cc +++ b/third_party/blink/renderer/core/paint/image_element_timing.cc
@@ -57,7 +57,9 @@ return; // Skip the computations below if the element is not same origin. - DCHECK(layout_image->CachedImage()); + if (!layout_image->CachedImage()) + return; + const KURL& url = layout_image->CachedImage()->Url(); DCHECK(GetSupplementable()->document() == &layout_image->GetDocument()); if (!SecurityOrigin::AreSameSchemeHostPort(layout_image->GetDocument().Url(),
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc index 86837c5..d0588ee7 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc
@@ -4,7 +4,7 @@ #include "third_party/blink/renderer/core/paint/ng/ng_text_painter.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h"
diff --git a/third_party/blink/renderer/core/paint/paint_controller_paint_test.h b/third_party/blink/renderer/core/paint/paint_controller_paint_test.h index 360e2ef..10a82a0078 100644 --- a/third_party/blink/renderer/core/paint/paint_controller_paint_test.h +++ b/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
@@ -47,8 +47,7 @@ GraphicsContext graphics_context(RootPaintController()); GetDocument().View()->Paint( graphics_context, kGlobalPaintNormalPhase, - interest_rect ? CullRect(*interest_rect) - : CullRect(LayoutRect::InfiniteIntRect())); + interest_rect ? CullRect(*interest_rect) : CullRect::Infinite()); return true; } GetDocument().View()->Lifecycle().AdvanceTo( @@ -142,12 +141,12 @@ DisplayItem::PaintPhaseToClipType( PaintPhase::kDescendantBlockBackgroundsOnly); -#define EXPECT_SUBSEQUENCE(client, expected_start, expected_end) \ - do { \ - auto* subsequence = GetSubsequenceMarkers(client); \ - ASSERT_NE(nullptr, subsequence); \ - EXPECT_EQ(expected_start, subsequence->start); \ - EXPECT_EQ(expected_end, subsequence->end); \ +#define EXPECT_SUBSEQUENCE(client, expected_start, expected_end) \ + do { \ + auto* subsequence = GetSubsequenceMarkers(client); \ + ASSERT_NE(nullptr, subsequence); \ + EXPECT_EQ(static_cast<size_t>(expected_start), subsequence->start); \ + EXPECT_EQ(static_cast<size_t>(expected_end), subsequence->end); \ } while (false) #define EXPECT_NO_SUBSEQUENCE(client) \
diff --git a/third_party/blink/renderer/core/paint/paint_info.h b/third_party/blink/renderer/core/paint/paint_info.h index b2a7247..fa4838b 100644 --- a/third_party/blink/renderer/core/paint/paint_info.h +++ b/third_party/blink/renderer/core/paint/paint_info.h
@@ -145,9 +145,7 @@ const CullRect& GetCullRect() const { return cull_rect_; } - void ApplyInfiniteCullRect() { - cull_rect_ = CullRect(LayoutRect::InfiniteIntRect()); - } + void ApplyInfiniteCullRect() { cull_rect_ = CullRect::Infinite(); } void TransformCullRect(const TransformPaintPropertyNode* transform) { cull_rect_.ApplyTransform(transform);
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index c4bb27b..64d2fb7 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -48,8 +48,8 @@ #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/core/animation/scroll_timeline.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/pseudo_style_request.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/renderer/core/frame/local_frame.h" @@ -117,7 +117,7 @@ LayoutUnit layout_units[4]; IntSize size; Persistent<PaintLayerScrollableArea> scrollable_area; - LayoutRect previous_dirty_rect; + CullRect previous_cull_rect; }; static_assert(sizeof(PaintLayer) == sizeof(SameSizeAsPaintLayer), @@ -1662,7 +1662,7 @@ void PaintLayer::AppendSingleFragmentIgnoringPagination( PaintLayerFragments& fragments, const PaintLayer* root_layer, - const LayoutRect* dirty_rect, + const CullRect* cull_rect, OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior, ShouldRespectOverflowClipType respect_overflow_clip, const LayoutPoint* offset_from_root, @@ -1674,7 +1674,7 @@ respect_overflow_clip, sub_pixel_accumulation); Clipper(kUseGeometryMapper) .CalculateRects(clip_rects_context, &GetLayoutObject().FirstFragment(), - dirty_rect, fragment.layer_bounds, + cull_rect, fragment.layer_bounds, fragment.background_rect, fragment.foreground_rect, offset_from_root); fragment.root_fragment_data = &root_layer->GetLayoutObject().FirstFragment(); @@ -1703,7 +1703,7 @@ void PaintLayer::CollectFragments( PaintLayerFragments& fragments, const PaintLayer* root_layer, - const LayoutRect* dirty_rect, + const CullRect* cull_rect, OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior, ShouldRespectOverflowClipType respect_overflow_clip, const LayoutPoint* offset_from_root, @@ -1760,20 +1760,20 @@ overlay_scrollbar_clip_behavior, respect_overflow_clip, sub_pixel_accumulation); - base::Optional<LayoutRect> fragment_dirty_rect; - if (dirty_rect) { - // |dirty_rect| is in the coordinate space of |root_layer| (i.e. the + base::Optional<CullRect> fragment_cull_rect; + if (cull_rect) { + // |cull_rect| is in the coordinate space of |root_layer| (i.e. the // space of |root_layer|'s first fragment). Map the rect to the space of // the current root fragment. - fragment_dirty_rect = *dirty_rect; - first_root_fragment_data.MapRectToFragment(*root_fragment_data, - *fragment_dirty_rect); + auto rect = cull_rect->Rect(); + first_root_fragment_data.MapRectToFragment(*root_fragment_data, rect); + fragment_cull_rect.emplace(rect); } Clipper(kUseGeometryMapper) .CalculateRects( clip_rects_context, fragment_data, - fragment_dirty_rect ? &*fragment_dirty_rect : nullptr, + fragment_cull_rect ? &*fragment_cull_rect : nullptr, fragment.layer_bounds, fragment.background_rect, fragment.foreground_rect, offset_from_root_can_be_used ? offset_from_root : nullptr);
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 94f6702..bf62c42 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -59,6 +59,7 @@ #include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h" #include "third_party/blink/renderer/core/paint/paint_result.h" #include "third_party/blink/renderer/platform/graphics/compositing_reasons.h" +#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h" #include "third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" @@ -292,10 +293,6 @@ void SetSizeHackForLayoutTreeAsText(const LayoutSize& size) { size_ = size; } - // For LayoutTreeAsText - LayoutRect RectIgnoringNeedsPositionUpdate() const { - return LayoutRect(LocationInternal(), size_); - } #if DCHECK_IS_ON() bool NeedsPositionUpdate() const { return needs_position_update_; } #endif @@ -916,7 +913,7 @@ void AppendSingleFragmentIgnoringPagination( PaintLayerFragments&, const PaintLayer* root_layer, - const LayoutRect* dirty_rect, + const CullRect* cull_rect, OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize, ShouldRespectOverflowClipType = kRespectOverflowClip, const LayoutPoint* offset_from_root = nullptr, @@ -925,7 +922,7 @@ void CollectFragments( PaintLayerFragments&, const PaintLayer* root_layer, - const LayoutRect* dirty_rect, + const CullRect* cull_rect, OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize, ShouldRespectOverflowClipType = kRespectOverflowClip, const LayoutPoint* offset_from_root = nullptr, @@ -964,12 +961,8 @@ // shouldCreateSubsequence() in PaintLayerPainter.cpp for the cases we use // subsequence when painting a PaintLayer. - LayoutRect PreviousPaintDirtyRect() const { - return previous_paint_dirty_rect_; - } - void SetPreviousPaintDirtyRect(const LayoutRect& rect) { - previous_paint_dirty_rect_ = rect; - } + CullRect PreviousCullRect() const { return previous_cull_rect_; } + void SetPreviousCullRect(const CullRect& rect) { previous_cull_rect_ = rect; } PaintResult PreviousPaintResult() const { return static_cast<PaintResult>(previous_paint_result_); @@ -1340,7 +1333,7 @@ std::unique_ptr<PaintLayerStackingNode> stacking_node_; - LayoutRect previous_paint_dirty_rect_; + CullRect previous_cull_rect_; std::unique_ptr<PaintLayerRareData> rare_data_;
diff --git a/third_party/blink/renderer/core/paint/paint_layer_clipper.cc b/third_party/blink/renderer/core/paint/paint_layer_clipper.cc index 3b0d15b..42311bd 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_clipper.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_clipper.cc
@@ -271,7 +271,7 @@ void PaintLayerClipper::CalculateRectsWithGeometryMapper( const ClipRectsContext& context, const FragmentData& fragment_data, - const LayoutRect* paint_dirty_rect, + const CullRect* cull_rect, LayoutRect& layer_bounds, ClipRect& background_rect, ClipRect& foreground_rect, @@ -293,8 +293,8 @@ context, fragment_data, kRespectOverflowClip, background_rect); foreground_rect.Reset(); - if (paint_dirty_rect) - background_rect.Intersect(*paint_dirty_rect); + if (cull_rect) + background_rect.Intersect(LayoutRect(cull_rect->Rect())); if (ShouldClipOverflow(context)) { LayoutBoxModelObject& layout_object = layer_.GetLayoutObject(); @@ -313,7 +313,7 @@ void PaintLayerClipper::CalculateRects( const ClipRectsContext& context, const FragmentData* fragment_data, - const LayoutRect* paint_dirty_rect, + const CullRect* cull_rect, LayoutRect& layer_bounds, ClipRect& background_rect, ClipRect& foreground_rect, @@ -326,7 +326,7 @@ // TODO(chrishtr): find the root cause of not having a fragment and fix it. if (!fragment_data->HasLocalBorderBoxProperties()) return; - CalculateRectsWithGeometryMapper(context, *fragment_data, paint_dirty_rect, + CalculateRectsWithGeometryMapper(context, *fragment_data, cull_rect, layer_bounds, background_rect, foreground_rect, offset_from_root); return; @@ -340,8 +340,8 @@ CalculateBackgroundClipRect(context, background_rect); background_rect.Move(context.sub_pixel_accumulation); } - if (paint_dirty_rect) - background_rect.Intersect(*paint_dirty_rect); + if (cull_rect) + background_rect.Intersect(LayoutRect(cull_rect->Rect())); foreground_rect = background_rect;
diff --git a/third_party/blink/renderer/core/paint/paint_layer_clipper.h b/third_party/blink/renderer/core/paint/paint_layer_clipper.h index 50bde01..dc5b2f7 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_clipper.h +++ b/third_party/blink/renderer/core/paint/paint_layer_clipper.h
@@ -47,9 +47,8 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/paint/clip_rects_cache.h" - +#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h" #include "third_party/blink/renderer/platform/scroll/scroll_types.h" - #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { @@ -191,11 +190,11 @@ // include subpixel accumualation. Otherwise it is set to the offset from // |layer_| to |root_layer|, plus |context.sub_pixel_accumuation|. // |fragment_data| is only used in kUseGeometryMapper mode. - // If |paint_dirty_rect| is provided, intersects |background_rect| - // and |foreground_rect| with it. + // If |cull_rect| is provided, intersects |background_rect| and + // |foreground_rect| with it. void CalculateRects(const ClipRectsContext&, const FragmentData*, - const LayoutRect* paint_dirty_rect, + const CullRect* cull_rect, LayoutRect& layer_bounds, ClipRect& background_rect, ClipRect& foreground_rect, @@ -232,7 +231,7 @@ ALWAYS_INLINE void CalculateRectsWithGeometryMapper( const ClipRectsContext&, const FragmentData&, - const LayoutRect* paint_dirty_rect, + const CullRect* cull_rect, LayoutRect& layer_bounds, ClipRect& background_rect, ClipRect& foreground_rect,
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter.cc b/third_party/blink/renderer/core/paint/paint_layer_painter.cc index fe82fe7..9be0877 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painter.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_painter.cc
@@ -38,12 +38,11 @@ } void PaintLayerPainter::Paint(GraphicsContext& context, - const LayoutRect& damage_rect, + const CullRect& cull_rect, const GlobalPaintFlags global_paint_flags, PaintLayerFlags paint_flags) { - PaintLayerPaintingInfo painting_info( - &paint_layer_, LayoutRect(EnclosingIntRect(damage_rect)), - global_paint_flags, LayoutSize()); + PaintLayerPaintingInfo painting_info(&paint_layer_, cull_rect, + global_paint_flags, LayoutSize()); if (!paint_layer_.PaintsIntoOwnOrGroupedBacking(global_paint_flags)) Paint(context, painting_info, paint_flags); } @@ -213,23 +212,23 @@ // Repaint if previously the layer might be clipped by paintDirtyRect and // paintDirtyRect changes. - if ((paint_layer.PreviousPaintResult() == kMayBeClippedByPaintDirtyRect || + if ((paint_layer.PreviousPaintResult() == kMayBeClippedByCullRect || // When PaintUnderInvalidationChecking is enabled, always repaint the // subsequence when the paint rect changes because we will strictly match // new and cached subsequences. Normally we can reuse the cached fully // painted subsequence even if we would partially paint this time. RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) && - paint_layer.PreviousPaintDirtyRect() != painting_info.paint_dirty_rect) { + paint_layer.PreviousCullRect() != painting_info.cull_rect) { needs_repaint = true; } - paint_layer.SetPreviousPaintDirtyRect(painting_info.paint_dirty_rect); + paint_layer.SetPreviousCullRect(painting_info.cull_rect); return needs_repaint; } -static bool ShouldUseInfiniteDirtyRect(const GraphicsContext& context, - const PaintLayer& layer, - PaintLayerPaintingInfo& painting_info) { +static bool ShouldUseInfiniteCullRect(const GraphicsContext& context, + const PaintLayer& layer, + PaintLayerPaintingInfo& painting_info) { // Cull rects and clips can't be propagated across a filter which moves // pixels, since the input of the filter may be outside the cull rect / // clips yet still result in painted output. @@ -262,13 +261,12 @@ PaintLayerFlags& paint_flags) { const auto& first_fragment = paint_layer_.GetLayoutObject().FirstFragment(); - bool is_using_infinite_dirty_rect = painting_info.paint_dirty_rect == - LayoutRect(LayoutRect::InfiniteIntRect()); - bool should_use_infinite_dirty_rect = - ShouldUseInfiniteDirtyRect(context, paint_layer_, painting_info); - if (!is_using_infinite_dirty_rect && should_use_infinite_dirty_rect) { - painting_info.paint_dirty_rect = LayoutRect(LayoutRect::InfiniteIntRect()); - is_using_infinite_dirty_rect = true; + bool is_using_infinite_cull_rect = painting_info.cull_rect.IsInfinite(); + bool should_use_infinite_cull_rect = + ShouldUseInfiniteCullRect(context, paint_layer_, painting_info); + if (!is_using_infinite_cull_rect && should_use_infinite_cull_rect) { + painting_info.cull_rect = CullRect::Infinite(); + is_using_infinite_cull_rect = true; } if (painting_info.root_layer == &paint_layer_) @@ -283,20 +281,22 @@ // Will use the current layer as the new root layer if the layer requires // infinite dirty rect or has different transform space from the current // root layer. - if (!should_use_infinite_dirty_rect && !transform_changed) + if (!should_use_infinite_cull_rect && !transform_changed) return; - if (!is_using_infinite_dirty_rect && transform_changed) { - // painting_info.paint_dirty_rect is currently in - // |painting_info.root_layer|'s pixel-snapped border box space. We need to - // adjust it into |paint_layer_|'s space. - // This handles the following cases: + if (!is_using_infinite_cull_rect && transform_changed) { + // painting_info.cull_rect is currently in |painting_info.root_layer|'s + // pixel-snapped border box space. We need to adjust it into + // |paint_layer_|'s space. This handles the following cases: // - The current layer has PaintOffsetTranslation; // - The current layer's transform state escapes the root layers contents // transform, e.g. a fixed-position layer; // - Scroll offsets. - first_root_fragment.MapRectToFragment(first_fragment, - painting_info.paint_dirty_rect); + // TODO(wangxianzhu): Use CullRect::ApplyTransform() which will support + // SPv2 interest rect expansion for composited scrolling. + auto rect = painting_info.cull_rect.Rect(); + first_root_fragment.MapRectToFragment(first_fragment, rect); + painting_info.cull_rect = CullRect(rect); } // Make the current layer the new root layer. @@ -331,8 +331,8 @@ // TODO(crbug.com/848056): This can happen e.g. when we paint a filter // referencing a SVG foreign object through feImage, especially when there // is circular references. Should find a better solution. - paint_layer_.SetPreviousPaintDirtyRect(LayoutRect()); - return kMayBeClippedByPaintDirtyRect; + paint_layer_.SetPreviousCullRect(CullRect()); + return kMayBeClippedByCullRect; } DCHECK(paint_layer_.IsSelfPaintingLayer() || @@ -393,8 +393,8 @@ offset_from_root.Move(subpixel_accumulation); LayoutRect bounds = paint_layer_.PhysicalBoundingBox(offset_from_root); - if (!painting_info.paint_dirty_rect.Contains(bounds)) - result = kMayBeClippedByPaintDirtyRect; + if (!LayoutRect(painting_info.cull_rect.Rect()).Contains(bounds)) + result = kMayBeClippedByCullRect; // These helpers output clip and compositing operations using a RAII pattern. // Stack-allocated-varibles are destructed in the reverse order of @@ -436,7 +436,7 @@ // clipping container. This handles nested border radius by including // all of them in the mask. // - // The paint rect is in this layer's space, so convert it to the clipper's + // The cull rect is in this layer's space, so convert it to the clipper's // layer's space. The root_layer is also changed to the clipper's layer to // simplify coordinate system adjustments. The change to root_layer must // persist to correctly record the clips. @@ -445,22 +445,24 @@ local_painting_info.root_layer = paint_layer_for_fragments; paint_layer_.ConvertToLayerCoords(local_painting_info.root_layer, offset_to_clipper); - local_painting_info.paint_dirty_rect.MoveBy(offset_to_clipper); + LayoutRect new_cull_rect(local_painting_info.cull_rect.Rect()); + new_cull_rect.MoveBy(offset_to_clipper); + local_painting_info.cull_rect = CullRect(EnclosingIntRect(new_cull_rect)); // Overflow clip of the compositing container is irrelevant. respect_overflow_clip = kIgnoreOverflowClip; } paint_layer_for_fragments->CollectFragments( layer_fragments, local_painting_info.root_layer, - &local_painting_info.paint_dirty_rect, - kIgnorePlatformOverlayScrollbarSize, respect_overflow_clip, - &offset_from_root, local_painting_info.sub_pixel_accumulation); + &local_painting_info.cull_rect, kIgnorePlatformOverlayScrollbarSize, + respect_overflow_clip, &offset_from_root, + local_painting_info.sub_pixel_accumulation); // PaintLayer::CollectFragments depends on the paint dirty rect in // complicated ways. For now, always assume a partially painted output // for fragmented content. if (layer_fragments.size() > 1) - result = kMayBeClippedByPaintDirtyRect; + result = kMayBeClippedByCullRect; if (paint_flags & kPaintLayerPaintingAncestorClippingMaskPhase) { // Fragment offsets have been computed in the clipping container's @@ -477,7 +479,7 @@ should_paint_content = AtLeastOneFragmentIntersectsDamageRect( layer_fragments, local_painting_info, paint_flags, offset_from_root); if (!should_paint_content) - result = kMayBeClippedByPaintDirtyRect; + result = kMayBeClippedByCullRect; } } @@ -533,8 +535,8 @@ paint_layer_, DisplayItem::kLayerChunkNegativeZOrderChildren); } if (PaintChildren(kNegativeZOrderChildren, context, painting_info, - paint_flags) == kMayBeClippedByPaintDirtyRect) - result = kMayBeClippedByPaintDirtyRect; + paint_flags) == kMayBeClippedByCullRect) + result = kMayBeClippedByCullRect; } if (should_paint_own_contents) { @@ -555,9 +557,8 @@ DisplayItem::kLayerChunkNormalFlowAndPositiveZOrderChildren); } if (PaintChildren(kNormalFlowChildren | kPositiveZOrderChildren, context, - painting_info, - paint_flags) == kMayBeClippedByPaintDirtyRect) - result = kMayBeClippedByPaintDirtyRect; + painting_info, paint_flags) == kMayBeClippedByCullRect) + result = kMayBeClippedByCullRect; } if (should_paint_overlay_scrollbars) { @@ -698,8 +699,8 @@ continue; if (PaintLayerPainter(*child).Paint(context, painting_info, paint_flags) == - kMayBeClippedByPaintDirtyRect) - result = kMayBeClippedByPaintDirtyRect; + kMayBeClippedByCullRect) + result = kMayBeClippedByCullRect; } return result; @@ -947,14 +948,13 @@ void PaintLayerPainter::PaintOverlayScrollbars( GraphicsContext& context, - const LayoutRect& damage_rect, + const CullRect& cull_rect, const GlobalPaintFlags paint_flags) { if (!paint_layer_.ContainsDirtyOverlayScrollbars()) return; - PaintLayerPaintingInfo painting_info( - &paint_layer_, LayoutRect(EnclosingIntRect(damage_rect)), paint_flags, - LayoutSize()); + PaintLayerPaintingInfo painting_info(&paint_layer_, cull_rect, paint_flags, + LayoutSize()); Paint(context, painting_info, kPaintLayerPaintingOverlayScrollbars); paint_layer_.SetContainsDirtyOverlayScrollbars(false);
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter.h b/third_party/blink/renderer/core/paint/paint_layer_painter.h index e1ca592..4c39e00 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painter.h +++ b/third_party/blink/renderer/core/paint/paint_layer_painter.h
@@ -13,6 +13,7 @@ namespace blink { +class CullRect; class ClipRect; class ComputedStyle; class DisplayItemClient; @@ -30,11 +31,11 @@ public: PaintLayerPainter(PaintLayer& paint_layer) : paint_layer_(paint_layer) {} - // The Paint() method paints the layers that intersect the damage rect from + // The Paint() method paints the layers that intersect the cull rect from // back to front. paint() assumes that the caller will clip to the bounds of // damageRect if necessary. void Paint(GraphicsContext&, - const LayoutRect& damage_rect, + const CullRect&, const GlobalPaintFlags = kGlobalPaintNormalPhase, PaintLayerFlags = 0); // Paint() assumes that the caller will clip to the bounds of the painting @@ -49,7 +50,7 @@ PaintLayerFlags); void PaintOverlayScrollbars(GraphicsContext&, - const LayoutRect& damage_rect, + const CullRect&, const GlobalPaintFlags); // Returns true if the painted output of this PaintLayer and its children is
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc b/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc index 1ebf901..18d92a1 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
@@ -28,7 +28,7 @@ PaintLayer* target_layer = ToLayoutBox(GetLayoutObjectByElementId(element_name))->Layer(); - PaintLayerPaintingInfo painting_info(nullptr, LayoutRect(), + PaintLayerPaintingInfo painting_info(nullptr, CullRect(), kGlobalPaintNormalPhase, LayoutSize()); bool invisible = PaintLayerPainter(*target_layer) @@ -282,7 +282,7 @@ </div> )HTML"); GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); - // PaintResult of all subsequences will be MayBeClippedByPaintDirtyRect. + // PaintResult of all subsequences will be MayBeClippedByCullRect. IntRect interest_rect(0, 0, 50, 300); Paint(&interest_rect); @@ -352,11 +352,11 @@ ElementsAre(IsSameId(&view_client, kDocumentBackgroundType), IsSameId(content1, kBackgroundType))); // |target| is partially painted. - EXPECT_EQ(kMayBeClippedByPaintDirtyRect, target_layer->PreviousPaintResult()); - EXPECT_EQ(LayoutRect(0, 0, 800, 4600), - target_layer->PreviousPaintDirtyRect()); + EXPECT_EQ(kMayBeClippedByCullRect, target_layer->PreviousPaintResult()); + EXPECT_EQ(CullRect(IntRect(0, 0, 800, 4600)), + target_layer->PreviousCullRect()); // |target| created subsequence. - EXPECT_SUBSEQUENCE(*target_layer, 1u, 2u); + EXPECT_SUBSEQUENCE(*target_layer, 1, 2); // Change something that triggers a repaint but |target| should use cached // subsequence. @@ -373,11 +373,11 @@ ElementsAre(IsSameId(&view_client, kDocumentBackgroundType), IsSameId(content1, kBackgroundType))); // |target| is still partially painted. - EXPECT_EQ(kMayBeClippedByPaintDirtyRect, target_layer->PreviousPaintResult()); - EXPECT_EQ(LayoutRect(0, 0, 800, 4600), - target_layer->PreviousPaintDirtyRect()); + EXPECT_EQ(kMayBeClippedByCullRect, target_layer->PreviousPaintResult()); + EXPECT_EQ(CullRect(IntRect(0, 0, 800, 4600)), + target_layer->PreviousCullRect()); // |target| still created subsequence (cached). - EXPECT_SUBSEQUENCE(*target_layer, 1u, 2u); + EXPECT_SUBSEQUENCE(*target_layer, 1, 2); // Scroll the view so that both |content1| and |content2| are in the interest // rect. @@ -397,11 +397,11 @@ IsSameId(content1, kBackgroundType), IsSameId(content2, kBackgroundType))); // |target| is still partially painted. - EXPECT_EQ(kMayBeClippedByPaintDirtyRect, target_layer->PreviousPaintResult()); - EXPECT_EQ(LayoutRect(0, 0, 800, 7600), - target_layer->PreviousPaintDirtyRect()); + EXPECT_EQ(kMayBeClippedByCullRect, target_layer->PreviousPaintResult()); + EXPECT_EQ(CullRect(IntRect(0, 0, 800, 7600)), + target_layer->PreviousCullRect()); // |target| still created subsequence (repainted). - EXPECT_SUBSEQUENCE(*target_layer, 1u, 3u); + EXPECT_SUBSEQUENCE(*target_layer, 1, 3); } TEST_P(PaintLayerPainterTest, PaintPhaseOutline) {
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painting_info.h b/third_party/blink/renderer/core/paint/paint_layer_painting_info.h index 3c90598..bee6fa8e 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painting_info.h +++ b/third_party/blink/renderer/core/paint/paint_layer_painting_info.h
@@ -47,7 +47,7 @@ #include "base/logging.h" #include "third_party/blink/renderer/core/paint/paint_phase.h" -#include "third_party/blink/renderer/platform/geometry/layout_rect.h" +#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #if DCHECK_IS_ON() @@ -88,20 +88,20 @@ STACK_ALLOCATED(); public: - PaintLayerPaintingInfo(PaintLayer* in_root_layer, - const LayoutRect& in_dirty_rect, + PaintLayerPaintingInfo(PaintLayer* root_layer, + const CullRect& cull_rect, GlobalPaintFlags global_paint_flags, - const LayoutSize& in_sub_pixel_accumulation) - : root_layer(in_root_layer), - paint_dirty_rect(in_dirty_rect), - sub_pixel_accumulation(in_sub_pixel_accumulation), + const LayoutSize& sub_pixel_accumulation) + : root_layer(root_layer), + cull_rect(cull_rect), + sub_pixel_accumulation(sub_pixel_accumulation), global_paint_flags_(global_paint_flags) {} GlobalPaintFlags GetGlobalPaintFlags() const { return global_paint_flags_; } // TODO(jchaffraix): We should encapsulate all these fields. const PaintLayer* root_layer; - LayoutRect paint_dirty_rect; // relative to rootLayer; + CullRect cull_rect; // relative to rootLayer; LayoutSize sub_pixel_accumulation; private:
diff --git a/third_party/blink/renderer/core/paint/paint_result.h b/third_party/blink/renderer/core/paint/paint_result.h index 5bad1819..7f11d3e 100644 --- a/third_party/blink/renderer/core/paint/paint_result.h +++ b/third_party/blink/renderer/core/paint/paint_result.h
@@ -12,12 +12,12 @@ // The layer/object is fully painted. This includes cases that nothing needs // painting regardless of the paint rect. kFullyPainted, - // Some part of the layer/object is out of the paint rect and may be not fully - // painted. The results cannot be cached because they may change when paint + // Some part of the layer/object is out of the cull rect and may be not fully + // painted. The results cannot be cached because they may change when cull // rect changes. - kMayBeClippedByPaintDirtyRect, + kMayBeClippedByCullRect, - kMaxPaintResult = kMayBeClippedByPaintDirtyRect, + kMaxPaintResult = kMayBeClippedByCullRect, }; } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc b/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc index 495ecd4..cb53167f 100644 --- a/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc +++ b/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc
@@ -45,8 +45,7 @@ // cull rects under transform are intentionally reset to infinity, // to improve cache invalidation performance in the pre-paint tree // walk (see https://http://crrev.com/482854). - LayoutRect(LayoutRect::InfiniteIntRect()), - paint_info.GetGlobalPaintFlags(), LayoutSize()); + CullRect::Infinite(), paint_info.GetGlobalPaintFlags(), LayoutSize()); PaintLayerPainter(*layout_svg_foreign_object_.Layer()) .Paint(paint_info.context, layer_painting_info, paint_info.PaintFlags()); }
diff --git a/third_party/blink/renderer/core/paint/table_row_painter.cc b/third_party/blink/renderer/core/paint/table_row_painter.cc index 6ce5b1f2..9ba2b74 100644 --- a/third_party/blink/renderer/core/paint/table_row_painter.cc +++ b/third_party/blink/renderer/core/paint/table_row_painter.cc
@@ -63,7 +63,7 @@ dirtied_columns == layout_table_row_.Section()->FullTableEffectiveColumnSpan() ? kFullyPainted - : kMayBeClippedByPaintDirtyRect; + : kMayBeClippedByCullRect; layout_table_row_.GetMutableForPainting().UpdatePaintResult( paint_result, paint_info.GetCullRect()); }
diff --git a/third_party/blink/renderer/core/paint/table_section_painter.cc b/third_party/blink/renderer/core/paint/table_section_painter.cc index a9a4b7d7..78f6d28 100644 --- a/third_party/blink/renderer/core/paint/table_section_painter.cc +++ b/third_party/blink/renderer/core/paint/table_section_painter.cc
@@ -278,7 +278,7 @@ dirtied_columns == layout_table_section_.FullTableEffectiveColumnSpan() && dirtied_rows == layout_table_section_.FullSectionRowSpan() ? kFullyPainted - : kMayBeClippedByPaintDirtyRect; + : kMayBeClippedByCullRect; layout_table_section_.GetMutableForPainting().UpdatePaintResult( paint_result, paint_info.GetCullRect());
diff --git a/third_party/blink/renderer/core/paint/text_painter.cc b/third_party/blink/renderer/core/paint/text_painter.cc index 65369c3..1e91b6d 100644 --- a/third_party/blink/renderer/core/paint/text_painter.cc +++ b/third_party/blink/renderer/core/paint/text_painter.cc
@@ -4,7 +4,7 @@ #include "third_party/blink/renderer/core/paint/text_painter.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/layout/api/line_layout_api_shim.h" #include "third_party/blink/renderer/core/layout/api/line_layout_item.h"
diff --git a/third_party/blink/renderer/core/paint/text_painter_test.cc b/third_party/blink/renderer/core/paint/text_painter_test.cc index e6e0f46..99a269a 100644 --- a/third_party/blink/renderer/core/paint/text_painter_test.cc +++ b/third_party/blink/renderer/core/paint/text_painter_test.cc
@@ -7,7 +7,7 @@ #include <memory> #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/layout/api/line_layout_text.h"
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index d9553fe..fdb526a 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -28,10 +28,10 @@ #include <memory> #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/properties/css_property.h" #include "third_party/blink/renderer/core/css/style_auto_color.h" #include "third_party/blink/renderer/core/css/style_color.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/style/border_value.h" #include "third_party/blink/renderer/core/style/computed_style_base.h" #include "third_party/blink/renderer/core/style/computed_style_constants.h"
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 index 4512cfd0..3ad5d04f 100644 --- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 +++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -869,7 +869,7 @@ field_group: "*->will-change", default_value: "Vector<CSSPropertyID>()", include_paths: ["third_party/blink/renderer/platform/wtf/vector.h", - "third_party/blink/renderer/core/css_property_names.h"], + "third_party/blink/renderer/core/css/css_property_names.h"], }, { name: "WillChangeContents",
diff --git a/third_party/blink/renderer/core/svg/properties/svg_animated_property.h b/third_party/blink/renderer/core/svg/properties/svg_animated_property.h index 2ecf296..cd8948b 100644 --- a/third_party/blink/renderer/core/svg/properties/svg_animated_property.h +++ b/third_party/blink/renderer/core/svg/properties/svg_animated_property.h
@@ -32,7 +32,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_PROPERTIES_SVG_ANIMATED_PROPERTY_H_ #include "base/macros.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/qualified_name.h" #include "third_party/blink/renderer/core/svg/properties/svg_property_info.h" #include "third_party/blink/renderer/core/svg/properties/svg_property_tear_off.h"
diff --git a/third_party/blink/renderer/core/svg/svg_animate_element.h b/third_party/blink/renderer/core/svg/svg_animate_element.h index 63c98242..796237f 100644 --- a/third_party/blink/renderer/core/svg/svg_animate_element.h +++ b/third_party/blink/renderer/core/svg/svg_animate_element.h
@@ -25,7 +25,7 @@ #include <base/gtest_prod_util.h> #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/svg/svg_animation_element.h" #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/third_party/blink/renderer/core/svg/svg_image_element.cc b/third_party/blink/renderer/core/svg/svg_image_element.cc index c4a2e0f..2556bfc 100644 --- a/third_party/blink/renderer/core/svg/svg_image_element.cc +++ b/third_party/blink/renderer/core/svg/svg_image_element.cc
@@ -22,8 +22,8 @@ #include "third_party/blink/renderer/core/svg/svg_image_element.h" #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/style_change_reason.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/html/media/media_element_parser_helpers.h" #include "third_party/blink/renderer/core/inspector/console_message.h"
diff --git a/third_party/blink/renderer/core/svg/svg_text_content_element.cc b/third_party/blink/renderer/core/svg/svg_text_content_element.cc index 8754b4d..307267c 100644 --- a/third_party/blink/renderer/core/svg/svg_text_content_element.cc +++ b/third_party/blink/renderer/core/svg/svg_text_content_element.cc
@@ -20,7 +20,7 @@ #include "third_party/blink/renderer/core/svg/svg_text_content_element.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/editing/frame_selection.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc index d1fbf4c..80f3e7a 100644 --- a/third_party/blink/renderer/core/testing/internals.cc +++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -43,10 +43,10 @@ #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h" #include "third_party/blink/renderer/core/animation/document_timeline.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/properties/css_unresolved_property.h" #include "third_party/blink/renderer/core/css/select_rule_feature_set.h" #include "third_party/blink/renderer/core/css/style_engine.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/dom/dom_string_list.h"
diff --git a/third_party/blink/renderer/core/workers/worker.idl b/third_party/blink/renderer/core/workers/worker.idl index 3441c246..3830550e 100644 --- a/third_party/blink/renderer/core/workers/worker.idl +++ b/third_party/blink/renderer/core/workers/worker.idl
@@ -31,7 +31,7 @@ ActiveScriptWrappable, Constructor(DOMString scriptURL, optional WorkerOptions options), ConstructorCallWith=ExecutionContext, - Exposed(Window StableBlinkFeatures,DedicatedWorker NestedWorkers), + Exposed=(Window,DedicatedWorker), RaisesException=Constructor, ImplementedAs=DedicatedWorker ] interface Worker : EventTarget {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index a5f9add..ef3daae 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -29,7 +29,7 @@ #include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h" #include "third_party/blink/renderer/core/aom/accessible_node.h" -#include "third_party/blink/renderer/core/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/range.h" #include "third_party/blink/renderer/core/dom/shadow_root.h"
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc index ce5ca358..9d14c13 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -39,10 +39,10 @@ #include "third_party/blink/renderer/bindings/modules/v8/rendering_context.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" #include "third_party/blink/renderer/core/css/css_font_selector.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" #include "third_party/blink/renderer/core/css/style_engine.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/events/mouse_event.h" #include "third_party/blink/renderer/core/frame/settings.h"
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.cc index 41e05dc1..8ef08377 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.cc
@@ -29,9 +29,9 @@ #include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.h" #include "base/memory/scoped_refptr.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/parser/css_parser.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h" #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h" #include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h"
diff --git a/third_party/blink/renderer/modules/csspaint/css_paint_definition.h b/third_party/blink/renderer/modules/csspaint/css_paint_definition.h index ee779ac..0c43c786 100644 --- a/third_party/blink/renderer/modules/csspaint/css_paint_definition.h +++ b/third_party/blink/renderer/modules/csspaint/css_paint_definition.h
@@ -5,9 +5,9 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_CSS_PAINT_DEFINITION_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_CSS_PAINT_DEFINITION_H_ +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_syntax_descriptor.h" #include "third_party/blink/renderer/core/css/cssom/css_style_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_settings.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/bindings/name_client.h"
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc index d23b511b..b805ef0 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc
@@ -9,8 +9,8 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_object_parser.h" #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_paint_rendering_context_2d_settings.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_syntax_descriptor.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
diff --git a/third_party/blink/renderer/modules/device_orientation/device_acceleration.cc b/third_party/blink/renderer/modules/device_orientation/device_acceleration.cc index 51d85df9..d92dd7c 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_acceleration.cc +++ b/third_party/blink/renderer/modules/device_orientation/device_acceleration.cc
@@ -24,40 +24,42 @@ */ #include "third_party/blink/renderer/modules/device_orientation/device_acceleration.h" +#include "third_party/blink/renderer/modules/device_orientation/device_acceleration_init.h" namespace blink { -DeviceAcceleration::DeviceAcceleration( - DeviceMotionData::Acceleration* acceleration) - : acceleration_(acceleration) {} +DeviceAcceleration* DeviceAcceleration::Create(double x, double y, double z) { + return new DeviceAcceleration(x, y, z); +} -void DeviceAcceleration::Trace(blink::Visitor* visitor) { - visitor->Trace(acceleration_); - ScriptWrappable::Trace(visitor); +DeviceAcceleration* DeviceAcceleration::Create( + const DeviceAccelerationInit* init) { + double x = init->hasX() ? init->x() : NAN; + double y = init->hasY() ? init->y() : NAN; + double z = init->hasZ() ? init->z() : NAN; + return DeviceAcceleration::Create(x, y, z); +} + +DeviceAcceleration::DeviceAcceleration(double x, double y, double z) + : x_(x), y_(y), z_(z) {} + +bool DeviceAcceleration::HasAccelerationData() const { + return !std::isnan(x_) || !std::isnan(y_) || !std::isnan(z_); } double DeviceAcceleration::x(bool& is_null) const { - if (acceleration_->CanProvideX()) - return acceleration_->X(); - - is_null = true; - return 0; + is_null = std::isnan(x_); + return x_; } double DeviceAcceleration::y(bool& is_null) const { - if (acceleration_->CanProvideY()) - return acceleration_->Y(); - - is_null = true; - return 0; + is_null = std::isnan(y_); + return y_; } double DeviceAcceleration::z(bool& is_null) const { - if (acceleration_->CanProvideZ()) - return acceleration_->Z(); - - is_null = true; - return 0; + is_null = std::isnan(z_); + return z_; } } // namespace blink
diff --git a/third_party/blink/renderer/modules/device_orientation/device_acceleration.h b/third_party/blink/renderer/modules/device_orientation/device_acceleration.h index b01d264..7f99a82d 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_acceleration.h +++ b/third_party/blink/renderer/modules/device_orientation/device_acceleration.h
@@ -27,29 +27,33 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_ACCELERATION_H_ #include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h" +#include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/handle.h" namespace blink { -class DeviceAcceleration final : public ScriptWrappable { +class DeviceAccelerationInit; + +class MODULES_EXPORT DeviceAcceleration final : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - static DeviceAcceleration* Create( - DeviceMotionData::Acceleration* acceleration) { - return new DeviceAcceleration(acceleration); - } - void Trace(blink::Visitor*) override; + static DeviceAcceleration* Create(double x, double y, double z); + static DeviceAcceleration* Create(const DeviceAccelerationInit*); + + bool HasAccelerationData() const; double x(bool& is_null) const; double y(bool& is_null) const; double z(bool& is_null) const; private: - explicit DeviceAcceleration(DeviceMotionData::Acceleration*); + DeviceAcceleration(double x, double y, double z); - Member<DeviceMotionData::Acceleration> acceleration_; + const double x_; + const double y_; + const double z_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_data.cc b/third_party/blink/renderer/modules/device_orientation/device_motion_data.cc index ff0dd3ec..07a0a8e 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_motion_data.cc +++ b/third_party/blink/renderer/modules/device_orientation/device_motion_data.cc
@@ -24,87 +24,18 @@ */ #include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h" - +#include "third_party/blink/renderer/modules/device_orientation/device_acceleration.h" #include "third_party/blink/renderer/modules/device_orientation/device_acceleration_init.h" #include "third_party/blink/renderer/modules/device_orientation/device_motion_event_init.h" +#include "third_party/blink/renderer/modules/device_orientation/device_rotation_rate.h" #include "third_party/blink/renderer/modules/device_orientation/device_rotation_rate_init.h" namespace blink { -DeviceMotionData::Acceleration* DeviceMotionData::Acceleration::Create( - bool can_provide_x, - double x, - bool can_provide_y, - double y, - bool can_provide_z, - double z) { - return new DeviceMotionData::Acceleration(can_provide_x, x, can_provide_y, y, - can_provide_z, z); -} - -DeviceMotionData::Acceleration* DeviceMotionData::Acceleration::Create( - const DeviceAccelerationInit* init) { - return new DeviceMotionData::Acceleration( - init->hasX(), init->hasX() ? init->x() : 0, init->hasY(), - init->hasY() ? init->y() : 0, init->hasZ(), init->hasZ() ? init->z() : 0); -} - -DeviceMotionData::Acceleration::Acceleration(bool can_provide_x, - double x, - bool can_provide_y, - double y, - bool can_provide_z, - double z) - : x_(x), - y_(y), - z_(z), - can_provide_x_(can_provide_x), - can_provide_y_(can_provide_y), - can_provide_z_(can_provide_z) - -{} - -DeviceMotionData::RotationRate* DeviceMotionData::RotationRate::Create( - bool can_provide_alpha, - double alpha, - bool can_provide_beta, - double beta, - bool can_provide_gamma, - double gamma) { - return new DeviceMotionData::RotationRate(can_provide_alpha, alpha, - can_provide_beta, beta, - can_provide_gamma, gamma); -} - -DeviceMotionData::RotationRate* DeviceMotionData::RotationRate::Create( - const DeviceRotationRateInit* init) { - return new DeviceMotionData::RotationRate( - init->hasAlpha(), init->hasAlpha() ? init->alpha() : 0, init->hasBeta(), - init->hasBeta() ? init->beta() : 0, init->hasGamma(), - init->hasGamma() ? init->gamma() : 0); -} - -DeviceMotionData::RotationRate::RotationRate(bool can_provide_alpha, - double alpha, - bool can_provide_beta, - double beta, - bool can_provide_gamma, - double gamma) - : alpha_(alpha), - beta_(beta), - gamma_(gamma), - can_provide_alpha_(can_provide_alpha), - can_provide_beta_(can_provide_beta), - can_provide_gamma_(can_provide_gamma) {} - -DeviceMotionData* DeviceMotionData::Create() { - return new DeviceMotionData; -} - DeviceMotionData* DeviceMotionData::Create( - Acceleration* acceleration, - Acceleration* acceleration_including_gravity, - RotationRate* rotation_rate, + DeviceAcceleration* acceleration, + DeviceAcceleration* acceleration_including_gravity, + DeviceRotationRate* rotation_rate, double interval) { return new DeviceMotionData(acceleration, acceleration_including_gravity, rotation_rate, interval); @@ -112,25 +43,27 @@ DeviceMotionData* DeviceMotionData::Create(const DeviceMotionEventInit* init) { return DeviceMotionData::Create( - init->hasAcceleration() - ? DeviceMotionData::Acceleration::Create(init->acceleration()) - : nullptr, + init->hasAcceleration() ? DeviceAcceleration::Create(init->acceleration()) + : nullptr, init->hasAccelerationIncludingGravity() - ? DeviceMotionData::Acceleration::Create( - init->accelerationIncludingGravity()) + ? DeviceAcceleration::Create(init->accelerationIncludingGravity()) : nullptr, - init->hasRotationRate() - ? DeviceMotionData::RotationRate::Create(init->rotationRate()) - : nullptr, + init->hasRotationRate() ? DeviceRotationRate::Create(init->rotationRate()) + : nullptr, init->interval()); } +DeviceMotionData* DeviceMotionData::Create() { + return new DeviceMotionData; +} + DeviceMotionData::DeviceMotionData() : interval_(0) {} -DeviceMotionData::DeviceMotionData(Acceleration* acceleration, - Acceleration* acceleration_including_gravity, - RotationRate* rotation_rate, - double interval) +DeviceMotionData::DeviceMotionData( + DeviceAcceleration* acceleration, + DeviceAcceleration* acceleration_including_gravity, + DeviceRotationRate* rotation_rate, + double interval) : acceleration_(acceleration), acceleration_including_gravity_(acceleration_including_gravity), rotation_rate_(rotation_rate), @@ -144,18 +77,12 @@ bool DeviceMotionData::CanProvideEventData() const { const bool has_acceleration = - acceleration_ && - (acceleration_->CanProvideX() || acceleration_->CanProvideY() || - acceleration_->CanProvideZ()); + acceleration_ && acceleration_->HasAccelerationData(); const bool has_acceleration_including_gravity = acceleration_including_gravity_ && - (acceleration_including_gravity_->CanProvideX() || - acceleration_including_gravity_->CanProvideY() || - acceleration_including_gravity_->CanProvideZ()); + acceleration_including_gravity_->HasAccelerationData(); const bool has_rotation_rate = - rotation_rate_ && - (rotation_rate_->CanProvideAlpha() || rotation_rate_->CanProvideBeta() || - rotation_rate_->CanProvideGamma()); + rotation_rate_ && rotation_rate_->HasRotationData(); return has_acceleration || has_acceleration_including_gravity || has_rotation_rate;
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_data.h b/third_party/blink/renderer/modules/device_orientation/device_motion_data.h index cb2afd87..7c9c32f 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_motion_data.h +++ b/third_party/blink/renderer/modules/device_orientation/device_motion_data.h
@@ -31,100 +31,27 @@ namespace blink { -class DeviceAccelerationInit; +class DeviceAcceleration; +class DeviceRotationRate; class DeviceMotionEventInit; -class DeviceRotationRateInit; class MODULES_EXPORT DeviceMotionData final : public GarbageCollected<DeviceMotionData> { public: - class Acceleration final - : public GarbageCollected<DeviceMotionData::Acceleration> { - public: - static Acceleration* Create(bool can_provide_x, - double x, - bool can_provide_y, - double y, - bool can_provide_z, - double z); - static Acceleration* Create(const DeviceAccelerationInit*); - void Trace(blink::Visitor* visitor) {} - - bool CanProvideX() const { return can_provide_x_; } - bool CanProvideY() const { return can_provide_y_; } - bool CanProvideZ() const { return can_provide_z_; } - - double X() const { return x_; } - double Y() const { return y_; } - double Z() const { return z_; } - - private: - Acceleration(bool can_provide_x, - double x, - bool can_provide_y, - double y, - bool can_provide_z, - double z); - - double x_; - double y_; - double z_; - - bool can_provide_x_; - bool can_provide_y_; - bool can_provide_z_; - }; - - class RotationRate final - : public GarbageCollected<DeviceMotionData::RotationRate> { - public: - static RotationRate* Create(bool can_provide_alpha, - double alpha, - bool can_provide_beta, - double beta, - bool can_provide_gamma, - double gamma); - static RotationRate* Create(const DeviceRotationRateInit*); - void Trace(blink::Visitor* visitor) {} - - bool CanProvideAlpha() const { return can_provide_alpha_; } - bool CanProvideBeta() const { return can_provide_beta_; } - bool CanProvideGamma() const { return can_provide_gamma_; } - - double Alpha() const { return alpha_; } - double Beta() const { return beta_; } - double Gamma() const { return gamma_; } - - private: - RotationRate(bool can_provide_alpha, - double alpha, - bool can_provide_beta, - double beta, - bool can_provide_gamma, - double gamma); - - double alpha_; - double beta_; - double gamma_; - - bool can_provide_alpha_; - bool can_provide_beta_; - bool can_provide_gamma_; - }; - static DeviceMotionData* Create(); - static DeviceMotionData* Create(Acceleration*, - Acceleration* acceleration_including_gravity, - RotationRate*, - double interval); + static DeviceMotionData* Create( + DeviceAcceleration*, + DeviceAcceleration* acceleration_including_gravity, + DeviceRotationRate*, + double interval); static DeviceMotionData* Create(const DeviceMotionEventInit*); void Trace(blink::Visitor*); - Acceleration* GetAcceleration() const { return acceleration_.Get(); } - Acceleration* GetAccelerationIncludingGravity() const { + DeviceAcceleration* GetAcceleration() const { return acceleration_.Get(); } + DeviceAcceleration* GetAccelerationIncludingGravity() const { return acceleration_including_gravity_.Get(); } - RotationRate* GetRotationRate() const { return rotation_rate_.Get(); } + DeviceRotationRate* GetRotationRate() const { return rotation_rate_.Get(); } double Interval() const { return interval_; } @@ -132,14 +59,14 @@ private: DeviceMotionData(); - DeviceMotionData(Acceleration*, - Acceleration* acceleration_including_gravity, - RotationRate*, + DeviceMotionData(DeviceAcceleration*, + DeviceAcceleration* acceleration_including_gravity, + DeviceRotationRate*, double interval); - Member<Acceleration> acceleration_; - Member<Acceleration> acceleration_including_gravity_; - Member<RotationRate> rotation_rate_; + Member<DeviceAcceleration> acceleration_; + Member<DeviceAcceleration> acceleration_including_gravity_; + Member<DeviceRotationRate> rotation_rate_; double interval_; };
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_event.cc b/third_party/blink/renderer/modules/device_orientation/device_motion_event.cc index e4ab8dc..ff7f834 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_motion_event.cc +++ b/third_party/blink/renderer/modules/device_orientation/device_motion_event.cc
@@ -48,36 +48,15 @@ device_motion_data_(device_motion_data) {} DeviceAcceleration* DeviceMotionEvent::acceleration() { - if (!device_motion_data_->GetAcceleration()) - return nullptr; - - if (!acceleration_) - acceleration_ = - DeviceAcceleration::Create(device_motion_data_->GetAcceleration()); - - return acceleration_.Get(); + return device_motion_data_->GetAcceleration(); } DeviceAcceleration* DeviceMotionEvent::accelerationIncludingGravity() { - if (!device_motion_data_->GetAccelerationIncludingGravity()) - return nullptr; - - if (!acceleration_including_gravity_) - acceleration_including_gravity_ = DeviceAcceleration::Create( - device_motion_data_->GetAccelerationIncludingGravity()); - - return acceleration_including_gravity_.Get(); + return device_motion_data_->GetAccelerationIncludingGravity(); } DeviceRotationRate* DeviceMotionEvent::rotationRate() { - if (!device_motion_data_->GetRotationRate()) - return nullptr; - - if (!rotation_rate_) - rotation_rate_ = - DeviceRotationRate::Create(device_motion_data_->GetRotationRate()); - - return rotation_rate_.Get(); + return device_motion_data_->GetRotationRate(); } double DeviceMotionEvent::interval() const { @@ -90,9 +69,6 @@ void DeviceMotionEvent::Trace(blink::Visitor* visitor) { visitor->Trace(device_motion_data_); - visitor->Trace(acceleration_); - visitor->Trace(acceleration_including_gravity_); - visitor->Trace(rotation_rate_); Event::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_event.h b/third_party/blink/renderer/modules/device_orientation/device_motion_event.h index e46096cc..4b9ed58a 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_motion_event.h +++ b/third_party/blink/renderer/modules/device_orientation/device_motion_event.h
@@ -70,9 +70,6 @@ DeviceMotionEvent(const AtomicString& event_type, const DeviceMotionData*); Member<const DeviceMotionData> device_motion_data_; - Member<DeviceAcceleration> acceleration_; - Member<DeviceAcceleration> acceleration_including_gravity_; - Member<DeviceRotationRate> rotation_rate_; }; DEFINE_TYPE_CASTS(DeviceMotionEvent,
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc index 47deaede..29eae48 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc +++ b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc
@@ -10,8 +10,10 @@ #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/platform_event_controller.h" +#include "third_party/blink/renderer/modules/device_orientation/device_acceleration.h" #include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h" #include "third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h" +#include "third_party/blink/renderer/modules/device_orientation/device_rotation_rate.h" #include "ui/gfx/geometry/angle_conversions.h" namespace { @@ -121,56 +123,43 @@ } DeviceMotionData* DeviceMotionEventPump::GetDataFromSharedMemory() { - DeviceMotionData::Acceleration* acceleration = nullptr; - DeviceMotionData::Acceleration* acceleration_including_gravity = nullptr; - DeviceMotionData::RotationRate* rotation_rate = nullptr; + DeviceAcceleration* acceleration = nullptr; + DeviceAcceleration* acceleration_including_gravity = nullptr; + DeviceRotationRate* rotation_rate = nullptr; if (accelerometer_.SensorReadingCouldBeRead()) { if (accelerometer_.reading.timestamp() == 0.0) return nullptr; - acceleration_including_gravity = DeviceMotionData::Acceleration::Create( - !std::isnan(accelerometer_.reading.accel.x.value()), - accelerometer_.reading.accel.x, - !std::isnan(accelerometer_.reading.accel.y.value()), - accelerometer_.reading.accel.y, - !std::isnan(accelerometer_.reading.accel.z.value()), + acceleration_including_gravity = DeviceAcceleration::Create( + accelerometer_.reading.accel.x, accelerometer_.reading.accel.y, accelerometer_.reading.accel.z); } else { - acceleration_including_gravity = DeviceMotionData::Acceleration::Create( - false, 0.0, false, 0.0, false, 0.0); + acceleration_including_gravity = DeviceAcceleration::Create(NAN, NAN, NAN); } if (linear_acceleration_sensor_.SensorReadingCouldBeRead()) { if (linear_acceleration_sensor_.reading.timestamp() == 0.0) return nullptr; - acceleration = DeviceMotionData::Acceleration::Create( - !std::isnan(linear_acceleration_sensor_.reading.accel.x.value()), - linear_acceleration_sensor_.reading.accel.x, - !std::isnan(linear_acceleration_sensor_.reading.accel.y.value()), - linear_acceleration_sensor_.reading.accel.y, - !std::isnan(linear_acceleration_sensor_.reading.accel.z.value()), - linear_acceleration_sensor_.reading.accel.z); + acceleration = + DeviceAcceleration::Create(linear_acceleration_sensor_.reading.accel.x, + linear_acceleration_sensor_.reading.accel.y, + linear_acceleration_sensor_.reading.accel.z); } else { - acceleration = DeviceMotionData::Acceleration::Create(false, 0.0, false, - 0.0, false, 0.0); + acceleration = DeviceAcceleration::Create(NAN, NAN, NAN); } if (gyroscope_.SensorReadingCouldBeRead()) { if (gyroscope_.reading.timestamp() == 0.0) return nullptr; - rotation_rate = DeviceMotionData::RotationRate::Create( - !std::isnan(gyroscope_.reading.gyro.x.value()), - gfx::RadToDeg(gyroscope_.reading.gyro.x), - !std::isnan(gyroscope_.reading.gyro.y.value()), - gfx::RadToDeg(gyroscope_.reading.gyro.y), - !std::isnan(gyroscope_.reading.gyro.z.value()), - gfx::RadToDeg(gyroscope_.reading.gyro.z)); + rotation_rate = + DeviceRotationRate::Create(gfx::RadToDeg(gyroscope_.reading.gyro.x), + gfx::RadToDeg(gyroscope_.reading.gyro.y), + gfx::RadToDeg(gyroscope_.reading.gyro.z)); } else { - rotation_rate = DeviceMotionData::RotationRate::Create(false, 0.0, false, - 0.0, false, 0.0); + rotation_rate = DeviceRotationRate::Create(NAN, NAN, NAN); } // The device orientation spec states that interval should be in
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc index 3001690..b8c44df 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc +++ b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
@@ -11,8 +11,10 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/renderer/core/frame/platform_event_controller.h" +#include "third_party/blink/renderer/modules/device_orientation/device_acceleration.h" #include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h" #include "third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h" +#include "third_party/blink/renderer/modules/device_orientation/device_rotation_rate.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "ui/gfx/geometry/angle_conversions.h" @@ -224,26 +226,34 @@ const DeviceMotionData* received_data = controller()->data(); EXPECT_TRUE(controller()->did_change_device_motion()); - EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideX()); - EXPECT_EQ(1, received_data->GetAccelerationIncludingGravity()->X()); - EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideY()); - EXPECT_EQ(2, received_data->GetAccelerationIncludingGravity()->Y()); - EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideZ()); - EXPECT_EQ(3, received_data->GetAccelerationIncludingGravity()->Z()); + bool is_null; + EXPECT_TRUE( + received_data->GetAccelerationIncludingGravity()->HasAccelerationData()); + EXPECT_EQ(1, received_data->GetAccelerationIncludingGravity()->x(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(2, received_data->GetAccelerationIncludingGravity()->y(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(3, received_data->GetAccelerationIncludingGravity()->z(is_null)); + EXPECT_FALSE(is_null); - EXPECT_TRUE(received_data->GetAcceleration()->CanProvideX()); - EXPECT_EQ(4, received_data->GetAcceleration()->X()); - EXPECT_TRUE(received_data->GetAcceleration()->CanProvideY()); - EXPECT_EQ(5, received_data->GetAcceleration()->Y()); - EXPECT_TRUE(received_data->GetAcceleration()->CanProvideZ()); - EXPECT_EQ(6, received_data->GetAcceleration()->Z()); + EXPECT_TRUE(received_data->GetAcceleration()->HasAccelerationData()); + EXPECT_EQ(4, received_data->GetAcceleration()->x(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(5, received_data->GetAcceleration()->y(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(6, received_data->GetAcceleration()->z(is_null)); + EXPECT_FALSE(is_null); - EXPECT_TRUE(received_data->GetRotationRate()->CanProvideAlpha()); - EXPECT_EQ(gfx::RadToDeg(7.0), received_data->GetRotationRate()->Alpha()); - EXPECT_TRUE(received_data->GetRotationRate()->CanProvideBeta()); - EXPECT_EQ(gfx::RadToDeg(8.0), received_data->GetRotationRate()->Beta()); - EXPECT_TRUE(received_data->GetRotationRate()->CanProvideGamma()); - EXPECT_EQ(gfx::RadToDeg(9.0), received_data->GetRotationRate()->Gamma()); + EXPECT_TRUE(received_data->GetRotationRate()->HasRotationData()); + EXPECT_EQ(gfx::RadToDeg(7.0), + received_data->GetRotationRate()->alpha(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(gfx::RadToDeg(8.0), + received_data->GetRotationRate()->beta(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(gfx::RadToDeg(9.0), + received_data->GetRotationRate()->gamma(is_null)); + EXPECT_FALSE(is_null); controller()->motion_pump()->Stop(); @@ -270,23 +280,33 @@ const DeviceMotionData* received_data = controller()->data(); EXPECT_TRUE(controller()->did_change_device_motion()); - EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideX()); - EXPECT_EQ(1, received_data->GetAccelerationIncludingGravity()->X()); - EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideY()); - EXPECT_EQ(2, received_data->GetAccelerationIncludingGravity()->Y()); - EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideZ()); - EXPECT_EQ(3, received_data->GetAccelerationIncludingGravity()->Z()); + bool is_null; + EXPECT_TRUE( + received_data->GetAccelerationIncludingGravity()->HasAccelerationData()); + EXPECT_EQ(1, received_data->GetAccelerationIncludingGravity()->x(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(2, received_data->GetAccelerationIncludingGravity()->y(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(3, received_data->GetAccelerationIncludingGravity()->z(is_null)); + EXPECT_FALSE(is_null); - EXPECT_FALSE(received_data->GetAcceleration()->CanProvideX()); - EXPECT_FALSE(received_data->GetAcceleration()->CanProvideY()); - EXPECT_FALSE(received_data->GetAcceleration()->CanProvideZ()); + received_data->GetAcceleration()->x(is_null); + EXPECT_TRUE(is_null); + received_data->GetAcceleration()->y(is_null); + EXPECT_TRUE(is_null); + received_data->GetAcceleration()->z(is_null); + EXPECT_TRUE(is_null); - EXPECT_TRUE(received_data->GetRotationRate()->CanProvideAlpha()); - EXPECT_EQ(gfx::RadToDeg(7.0), received_data->GetRotationRate()->Alpha()); - EXPECT_TRUE(received_data->GetRotationRate()->CanProvideBeta()); - EXPECT_EQ(gfx::RadToDeg(8.0), received_data->GetRotationRate()->Beta()); - EXPECT_TRUE(received_data->GetRotationRate()->CanProvideGamma()); - EXPECT_EQ(gfx::RadToDeg(9.0), received_data->GetRotationRate()->Gamma()); + EXPECT_TRUE(received_data->GetRotationRate()->HasRotationData()); + EXPECT_EQ(gfx::RadToDeg(7.0), + received_data->GetRotationRate()->alpha(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(gfx::RadToDeg(8.0), + received_data->GetRotationRate()->beta(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(gfx::RadToDeg(9.0), + received_data->GetRotationRate()->gamma(is_null)); + EXPECT_FALSE(is_null); controller()->motion_pump()->Stop(); @@ -312,23 +332,30 @@ const DeviceMotionData* received_data = controller()->data(); EXPECT_TRUE(controller()->did_change_device_motion()); - EXPECT_FALSE(received_data->GetAccelerationIncludingGravity()->CanProvideX()); - EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideY()); - EXPECT_EQ(2, received_data->GetAccelerationIncludingGravity()->Y()); - EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideZ()); - EXPECT_EQ(3, received_data->GetAccelerationIncludingGravity()->Z()); + bool is_null; + received_data->GetAccelerationIncludingGravity()->x(is_null); + EXPECT_TRUE(is_null); + EXPECT_EQ(2, received_data->GetAccelerationIncludingGravity()->y(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(3, received_data->GetAccelerationIncludingGravity()->z(is_null)); + EXPECT_FALSE(is_null); - EXPECT_TRUE(received_data->GetAcceleration()->CanProvideX()); - EXPECT_EQ(4, received_data->GetAcceleration()->X()); - EXPECT_FALSE(received_data->GetAcceleration()->CanProvideY()); - EXPECT_TRUE(received_data->GetAcceleration()->CanProvideZ()); - EXPECT_EQ(6, received_data->GetAcceleration()->Z()); + EXPECT_EQ(4, received_data->GetAcceleration()->x(is_null)); + EXPECT_FALSE(is_null); + received_data->GetAcceleration()->y(is_null); + EXPECT_TRUE(is_null); + EXPECT_EQ(6, received_data->GetAcceleration()->z(is_null)); + EXPECT_FALSE(is_null); - EXPECT_TRUE(received_data->GetRotationRate()->CanProvideAlpha()); - EXPECT_EQ(gfx::RadToDeg(7.0), received_data->GetRotationRate()->Alpha()); - EXPECT_TRUE(received_data->GetRotationRate()->CanProvideBeta()); - EXPECT_EQ(gfx::RadToDeg(8.0), received_data->GetRotationRate()->Beta()); - EXPECT_FALSE(received_data->GetRotationRate()->CanProvideGamma()); + EXPECT_TRUE(received_data->GetAcceleration()->HasAccelerationData()); + EXPECT_EQ(gfx::RadToDeg(7.0), + received_data->GetRotationRate()->alpha(is_null)); + EXPECT_FALSE(is_null); + EXPECT_EQ(gfx::RadToDeg(8.0), + received_data->GetRotationRate()->beta(is_null)); + EXPECT_FALSE(is_null); + received_data->GetRotationRate()->gamma(is_null); + EXPECT_TRUE(is_null); controller()->motion_pump()->Stop(); @@ -353,17 +380,12 @@ const DeviceMotionData* received_data = controller()->data(); EXPECT_TRUE(controller()->did_change_device_motion()); - EXPECT_FALSE(received_data->GetAcceleration()->CanProvideX()); - EXPECT_FALSE(received_data->GetAcceleration()->CanProvideY()); - EXPECT_FALSE(received_data->GetAcceleration()->CanProvideZ()); + EXPECT_FALSE(received_data->GetAcceleration()->HasAccelerationData()); - EXPECT_FALSE(received_data->GetAccelerationIncludingGravity()->CanProvideX()); - EXPECT_FALSE(received_data->GetAccelerationIncludingGravity()->CanProvideY()); - EXPECT_FALSE(received_data->GetAccelerationIncludingGravity()->CanProvideZ()); + EXPECT_FALSE( + received_data->GetAccelerationIncludingGravity()->HasAccelerationData()); - EXPECT_FALSE(received_data->GetRotationRate()->CanProvideAlpha()); - EXPECT_FALSE(received_data->GetRotationRate()->CanProvideBeta()); - EXPECT_FALSE(received_data->GetRotationRate()->CanProvideGamma()); + EXPECT_FALSE(received_data->GetRotationRate()->HasRotationData()); controller()->motion_pump()->Stop();
diff --git a/third_party/blink/renderer/modules/device_orientation/device_rotation_rate.cc b/third_party/blink/renderer/modules/device_orientation/device_rotation_rate.cc index dfe19984..85e18fd7 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_rotation_rate.cc +++ b/third_party/blink/renderer/modules/device_orientation/device_rotation_rate.cc
@@ -24,40 +24,44 @@ */ #include "third_party/blink/renderer/modules/device_orientation/device_rotation_rate.h" +#include "third_party/blink/renderer/modules/device_orientation/device_rotation_rate_init.h" namespace blink { -DeviceRotationRate::DeviceRotationRate( - DeviceMotionData::RotationRate* rotation_rate) - : rotation_rate_(rotation_rate) {} +DeviceRotationRate* DeviceRotationRate::Create(double alpha, + double beta, + double gamma) { + return new DeviceRotationRate(alpha, beta, gamma); +} -void DeviceRotationRate::Trace(blink::Visitor* visitor) { - visitor->Trace(rotation_rate_); - ScriptWrappable::Trace(visitor); +DeviceRotationRate* DeviceRotationRate::Create( + const DeviceRotationRateInit* init) { + double alpha = init->hasAlpha() ? init->alpha() : NAN; + double beta = init->hasBeta() ? init->beta() : NAN; + double gamma = init->hasGamma() ? init->gamma() : NAN; + return DeviceRotationRate::Create(alpha, beta, gamma); +} + +DeviceRotationRate::DeviceRotationRate(double alpha, double beta, double gamma) + : alpha_(alpha), beta_(beta), gamma_(gamma) {} + +bool DeviceRotationRate::HasRotationData() const { + return !std::isnan(alpha_) || !std::isnan(beta_) || !std::isnan(gamma_); } double DeviceRotationRate::alpha(bool& is_null) const { - if (rotation_rate_->CanProvideAlpha()) - return rotation_rate_->Alpha(); - - is_null = true; - return 0; + is_null = std::isnan(alpha_); + return alpha_; } double DeviceRotationRate::beta(bool& is_null) const { - if (rotation_rate_->CanProvideBeta()) - return rotation_rate_->Beta(); - - is_null = true; - return 0; + is_null = std::isnan(beta_); + return beta_; } double DeviceRotationRate::gamma(bool& is_null) const { - if (rotation_rate_->CanProvideGamma()) - return rotation_rate_->Gamma(); - - is_null = true; - return 0; + is_null = std::isnan(gamma_); + return gamma_; } } // namespace blink
diff --git a/third_party/blink/renderer/modules/device_orientation/device_rotation_rate.h b/third_party/blink/renderer/modules/device_orientation/device_rotation_rate.h index 7b52ea8..c5c2c33 100644 --- a/third_party/blink/renderer/modules/device_orientation/device_rotation_rate.h +++ b/third_party/blink/renderer/modules/device_orientation/device_rotation_rate.h
@@ -27,29 +27,33 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_ROTATION_RATE_H_ #include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h" +#include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/handle.h" namespace blink { -class DeviceRotationRate final : public ScriptWrappable { +class DeviceRotationRateInit; + +class MODULES_EXPORT DeviceRotationRate final : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - static DeviceRotationRate* Create( - DeviceMotionData::RotationRate* rotation_rate) { - return new DeviceRotationRate(rotation_rate); - } - void Trace(blink::Visitor*) override; + static DeviceRotationRate* Create(double alpha, double beta, double gamma); + static DeviceRotationRate* Create(const DeviceRotationRateInit*); + + bool HasRotationData() const; double alpha(bool& is_null) const; double beta(bool& is_null) const; double gamma(bool& is_null) const; private: - explicit DeviceRotationRate(DeviceMotionData::RotationRate*); + DeviceRotationRate(double alpha, double beta, double gamma); - Member<DeviceMotionData::RotationRate> rotation_rate_; + const double alpha_; + const double beta_; + const double gamma_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index 664f1df1..0758440c 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -252,10 +252,6 @@ RuntimeEnabledFeatures::SetNavigatorContentUtilsEnabled(enable); } -void WebRuntimeFeatures::EnableNestedWorkers(bool enable) { - RuntimeEnabledFeatures::SetNestedWorkersEnabled(enable); -} - void WebRuntimeFeatures::EnableNetInfoDownlinkMax(bool enable) { RuntimeEnabledFeatures::SetNetInfoDownlinkMaxEnabled(enable); }
diff --git a/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc b/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc index cdee4a5..ed6279a 100644 --- a/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc +++ b/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
@@ -92,7 +92,9 @@ compositor_frame_sink_->SetNeedsBeginFrame(true); } -void BeginFrameProvider::OnBeginFrame(const viz::BeginFrameArgs& args) { +void BeginFrameProvider::OnBeginFrame( + const viz::BeginFrameArgs& args, + WTF::HashMap<uint32_t, ::gfx::mojom::blink::PresentationFeedbackPtr>) { // If there was no need for a BeginFrame, just skip it. if (needs_begin_frame_ && requested_needs_begin_frame_) { requested_needs_begin_frame_ = false;
diff --git a/third_party/blink/renderer/platform/graphics/begin_frame_provider.h b/third_party/blink/renderer/platform/graphics/begin_frame_provider.h index 409ea51..1ffd6f5 100644 --- a/third_party/blink/renderer/platform/graphics/begin_frame_provider.h +++ b/third_party/blink/renderer/platform/graphics/begin_frame_provider.h
@@ -41,12 +41,10 @@ const WTF::Vector<viz::ReturnedResource>& resources) final { NOTIMPLEMENTED(); } - void DidPresentCompositorFrame( - uint32_t presentation_token, - ::gfx::mojom::blink::PresentationFeedbackPtr feedback) final { - NOTIMPLEMENTED(); - } - void OnBeginFrame(const viz::BeginFrameArgs&) final; + void OnBeginFrame( + const viz::BeginFrameArgs&, + WTF::HashMap<uint32_t, ::gfx::mojom::blink::PresentationFeedbackPtr>) + final; void OnBeginFramePausedChanged(bool paused) final {} void ReclaimResources( const WTF::Vector<viz::ReturnedResource>& resources) final {
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc index 67d56c9f..67a041a 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
@@ -285,12 +285,6 @@ DCHECK_GE(pending_compositor_frames_, 0); } -void CanvasResourceDispatcher::DidPresentCompositorFrame( - uint32_t presentation_token, - ::gfx::mojom::blink::PresentationFeedbackPtr feedback) { - NOTIMPLEMENTED(); -} - void CanvasResourceDispatcher::SetNeedsBeginFrame(bool needs_begin_frame) { if (needs_begin_frame_ == needs_begin_frame) return; @@ -313,7 +307,8 @@ } void CanvasResourceDispatcher::OnBeginFrame( - const viz::BeginFrameArgs& begin_frame_args) { + const viz::BeginFrameArgs& begin_frame_args, + WTF::HashMap<uint32_t, ::gfx::mojom::blink::PresentationFeedbackPtr>) { current_begin_frame_ack_ = viz::BeginFrameAck(begin_frame_args, false); if (pending_compositor_frames_ >= kMaxPendingCompositorFrames || (begin_frame_args.type == viz::BeginFrameArgs::MISSED &&
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h index 55a6fbe..64999252 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
@@ -63,10 +63,10 @@ // viz::mojom::blink::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const WTF::Vector<viz::ReturnedResource>& resources) final; - void DidPresentCompositorFrame( - uint32_t presentation_token, - ::gfx::mojom::blink::PresentationFeedbackPtr feedback) final; - void OnBeginFrame(const viz::BeginFrameArgs&) final; + void OnBeginFrame( + const viz::BeginFrameArgs&, + WTF::HashMap<uint32_t, ::gfx::mojom::blink::PresentationFeedbackPtr>) + final; void OnBeginFramePausedChanged(bool paused) final{}; void ReclaimResources( const WTF::Vector<viz::ReturnedResource>& resources) final;
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc index 8d05b81b..c14f863 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
@@ -672,7 +672,9 @@ bool switched_to_chunk_state = false; for (const auto& item : display_items.ItemsInPaintChunk(chunk)) { - DCHECK(item.IsDrawing()); + if (!item.IsDrawing()) + continue; + auto record = static_cast<const DrawingDisplayItem&>(item).GetPaintRecord(); // If we have an empty paint record, then we would prefer not to draw it.
diff --git a/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc b/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc index a7e8280..f09986c 100644 --- a/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc +++ b/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc
@@ -14,16 +14,16 @@ namespace blink { bool CullRect::Intersects(const IntRect& rect) const { - return rect.Intersects(rect_); + return IsInfinite() || rect.Intersects(rect_); } bool CullRect::Intersects(const LayoutRect& rect) const { - return rect_.Intersects(EnclosingIntRect(rect)); + return IsInfinite() || rect_.Intersects(EnclosingIntRect(rect)); } bool CullRect::IntersectsTransformed(const AffineTransform& transform, const FloatRect& rect) const { - return transform.MapRect(rect).Intersects(rect_); + return IsInfinite() || transform.MapRect(rect).Intersects(rect_); } bool CullRect::IntersectsHorizontalRange(LayoutUnit lo, LayoutUnit hi) const { @@ -35,16 +35,19 @@ } void CullRect::MoveBy(const IntPoint& offset) { - if (rect_ != LayoutRect::InfiniteIntRect()) + if (!IsInfinite()) rect_.MoveBy(offset); } void CullRect::Move(const IntSize& offset) { - if (rect_ != LayoutRect::InfiniteIntRect()) + if (!IsInfinite()) rect_.Move(offset); } void CullRect::ApplyTransform(const TransformPaintPropertyNode* transform) { + if (IsInfinite()) + return; + if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { if (const auto* scroll = transform->ScrollNode()) { rect_.Intersect(scroll->ContainerRect()); @@ -59,8 +62,7 @@ } } - if (rect_ != LayoutRect::InfiniteIntRect()) - rect_ = transform->Matrix().Inverse().MapRect(rect_); + rect_ = transform->Matrix().Inverse().MapRect(rect_); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/cull_rect.h b/third_party/blink/renderer/platform/graphics/paint/cull_rect.h index db46799..be806a5 100644 --- a/third_party/blink/renderer/platform/graphics/paint/cull_rect.h +++ b/third_party/blink/renderer/platform/graphics/paint/cull_rect.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CULL_RECT_H_ #include "third_party/blink/renderer/platform/geometry/int_rect.h" +#include "third_party/blink/renderer/platform/geometry/layout_rect.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -26,6 +27,10 @@ CullRect() = default; explicit CullRect(const IntRect& rect) : rect_(rect) {} + static CullRect Infinite() { return CullRect(LayoutRect::InfiniteIntRect()); } + + bool IsInfinite() const { return rect_ == LayoutRect::InfiniteIntRect(); } + bool Intersects(const IntRect&) const; bool Intersects(const LayoutRect&) const; bool IntersectsTransformed(const AffineTransform&, const FloatRect&) const; @@ -42,17 +47,19 @@ private: IntRect rect_; - - friend bool operator==(const CullRect&, const CullRect&); }; inline bool operator==(const CullRect& a, const CullRect& b) { - return a.rect_ == b.rect_; + return a.Rect() == b.Rect(); } inline bool operator!=(const CullRect& a, const CullRect& b) { return !(a == b); } +inline std::ostream& operator<<(std::ostream& os, const CullRect& cull_rect) { + return os << cull_rect.Rect(); +} + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CULL_RECT_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.cc b/third_party/blink/renderer/platform/graphics/paint/display_item.cc index 81e23a7..8077c0e9 100644 --- a/third_party/blink/renderer/platform/graphics/paint/display_item.cc +++ b/third_party/blink/renderer/platform/graphics/paint/display_item.cc
@@ -88,6 +88,7 @@ DEBUG_STRING_CASE(PopupListBoxRow); DEBUG_STRING_CASE(PrintedContentDestinationLocations); DEBUG_STRING_CASE(PrintedContentPDFURLRect); + DEBUG_STRING_CASE(ReflectionMask); DEBUG_STRING_CASE(Resizer); DEBUG_STRING_CASE(SVGClip); DEBUG_STRING_CASE(SVGFilter); @@ -107,10 +108,8 @@ DEBUG_STRING_CASE(SelectionTint); DEBUG_STRING_CASE(TableCollapsedBorders); DEBUG_STRING_CASE(VideoBitmap); - DEBUG_STRING_CASE(WebPlugin); DEBUG_STRING_CASE(WebFont); - DEBUG_STRING_CASE(ReflectionMask); - DEBUG_STRING_CASE(HitTest); + DEBUG_STRING_CASE(WebPlugin); DEFAULT_CASE; } @@ -146,6 +145,7 @@ PAINT_PHASE_BASED_DEBUG_STRINGS(SVGEffect); switch (type) { + DEBUG_STRING_CASE(HitTest); DEBUG_STRING_CASE(ScrollHitTest); DEBUG_STRING_CASE(LayerChunkBackground); DEBUG_STRING_CASE(LayerChunkNegativeZOrderChildren);
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.h b/third_party/blink/renderer/platform/graphics/paint/display_item.h index b98ea13..c9e9c34 100644 --- a/third_party/blink/renderer/platform/graphics/paint/display_item.h +++ b/third_party/blink/renderer/platform/graphics/paint/display_item.h
@@ -81,6 +81,7 @@ kPopupListBoxRow, kPrintedContentDestinationLocations, kPrintedContentPDFURLRect, + kReflectionMask, kResizer, kSVGClip, kSVGFilter, @@ -100,15 +101,9 @@ kSelectionTint, kTableCollapsedBorders, kVideoBitmap, - kWebPlugin, kWebFont, - kReflectionMask, - // Compositor hit testing requires that layers are created and sized to - // include content that does not paint. Hit test display items ensure - // a layer exists and is sized properly even if no content would otherwise - // be painted. - kHitTest, - kDrawingLast = kHitTest, + kWebPlugin, + kDrawingLast = kWebPlugin, kForeignLayerFirst, kForeignLayerCanvas = kForeignLayerFirst, @@ -131,6 +126,12 @@ kSVGEffectPaintPhaseFirst, kSVGEffectPaintPhaseLast = kSVGEffectPaintPhaseFirst + kPaintPhaseMax, + // Compositor hit testing requires that layers are created and sized to + // include content that does not paint. Hit test display items ensure + // a layer exists and is sized properly even if no content would otherwise + // be painted. + kHitTest, + kScrollHitTest, kLayerChunkBackground,
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item_list.h b/third_party/blink/renderer/platform/graphics/paint/display_item_list.h index 6bfffbb7..5a6df08 100644 --- a/third_party/blink/renderer/platform/graphics/paint/display_item_list.h +++ b/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
@@ -7,7 +7,7 @@ #include "third_party/blink/renderer/platform/graphics/contiguous_container.h" #include "third_party/blink/renderer/platform/graphics/paint/display_item.h" -#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h" +#include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h" #include "third_party/blink/renderer/platform/wtf/alignment.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" @@ -20,8 +20,9 @@ // each derived display item; the ideal value is the least common multiple. // The validity of kDisplayItemAlignment and kMaximumDisplayItemSize are checked // in PaintController::CreateAndAppend(). -static const size_t kDisplayItemAlignment = WTF_ALIGN_OF(HitTestDisplayItem); -static const size_t kMaximumDisplayItemSize = sizeof(HitTestDisplayItem); +static const size_t kDisplayItemAlignment = + WTF_ALIGN_OF(ForeignLayerDisplayItem); +static const size_t kMaximumDisplayItemSize = sizeof(ForeignLayerDisplayItem); // A container for a list of display items. class PLATFORM_EXPORT DisplayItemList @@ -74,9 +75,10 @@ #if DCHECK_IS_ON() enum JsonOptions { kDefault = 0, - kShowPaintRecords = 1 << 0, - kClientKnownToBeAlive = 1 << 1, - kShownOnlyDisplayItemTypes = 1 << 2 + kShowPaintRecords = 1, + kSkipNonDrawings = 1 << 1, + kClientKnownToBeAlive = 1 << 2, + kShownOnlyDisplayItemTypes = 1 << 3 }; typedef unsigned JsonFlags;
diff --git a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h index 6623e9f..dd79922 100644 --- a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h +++ b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
@@ -25,14 +25,13 @@ // PaintRecord, and is in the space of the DisplayItemList. This allows the // visual_rect to be compared between DrawingDisplayItems, and to give bounds // around what the user can actually see from the PaintRecord. -class PLATFORM_EXPORT DrawingDisplayItem : public DisplayItem { +class PLATFORM_EXPORT DrawingDisplayItem final : public DisplayItem { public: DISABLE_CFI_PERF DrawingDisplayItem(const DisplayItemClient& client, Type type, sk_sp<const PaintRecord> record, - bool known_to_be_opaque = false, - size_t derived_size = sizeof(DrawingDisplayItem)); + bool known_to_be_opaque = false); void Replay(GraphicsContext&) const final; void AppendToDisplayItemList(const FloatSize& visual_rect_offset, @@ -46,14 +45,13 @@ return known_to_be_opaque_; } - bool Equals(const DisplayItem& other) const override; - - protected: -#if DCHECK_IS_ON() - void PropertiesAsJSON(JSONObject&) const override; -#endif + bool Equals(const DisplayItem& other) const final; private: +#if DCHECK_IS_ON() + void PropertiesAsJSON(JSONObject&) const final; +#endif + sk_sp<const PaintRecord> record_; // True if there are no transparent areas. Only used for SlimmingPaintV2. @@ -65,9 +63,8 @@ inline DrawingDisplayItem::DrawingDisplayItem(const DisplayItemClient& client, Type type, sk_sp<const PaintRecord> record, - bool known_to_be_opaque, - size_t derived_size) - : DisplayItem(client, type, derived_size), + bool known_to_be_opaque) + : DisplayItem(client, type, sizeof(*this)), record_(record && record->size() ? std::move(record) : nullptr), known_to_be_opaque_(known_to_be_opaque) { DCHECK(IsDrawingType(type));
diff --git a/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.cc index f1d7fcb..bd1f443 100644 --- a/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.cc +++ b/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.cc
@@ -26,13 +26,13 @@ #if DCHECK_IS_ON() void HitTestDisplayItem::PropertiesAsJSON(JSONObject& json) const { - DrawingDisplayItem::PropertiesAsJSON(json); + DisplayItem::PropertiesAsJSON(json); json.SetString("hitTestRect", hit_test_rect_.ToString()); } #endif bool HitTestDisplayItem::Equals(const DisplayItem& other) const { - return DrawingDisplayItem::Equals(other) && + return DisplayItem::Equals(other) && hit_test_rect_ == static_cast<const HitTestDisplayItem&>(other).hit_test_rect_; }
diff --git a/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h b/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h index dde46b2..024a318 100644 --- a/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h +++ b/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h
@@ -5,18 +5,18 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DISPLAY_ITEM_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DISPLAY_ITEM_H_ -#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h" +#include "third_party/blink/renderer/platform/graphics/paint/display_item.h" #include "third_party/blink/renderer/platform/graphics/hit_test_rect.h" namespace blink { // A special DrawingDisplayItem containing hit test data. -class PLATFORM_EXPORT HitTestDisplayItem final : public DrawingDisplayItem { +class PLATFORM_EXPORT HitTestDisplayItem final : public DisplayItem { public: HitTestDisplayItem(const DisplayItemClient& client, const HitTestRect& hit_test_rect) - : DrawingDisplayItem(client, kHitTest, nullptr, false, sizeof(*this)), + : DisplayItem(client, kHitTest, sizeof(*this)), hit_test_rect_(hit_test_rect) { DCHECK(RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()); }
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc index c3eb2b9..f4d24ce 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc +++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
@@ -10,6 +10,7 @@ #include "third_party/blink/renderer/platform/graphics/graphics_layer.h" #include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h" #include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h" +#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/skia/include/core/SkRegion.h"
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc index fac7788..d737574f 100644 --- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc +++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -312,7 +312,9 @@ waiting_for_compositor_ack_ = true; } -void VideoFrameSubmitter::OnBeginFrame(const viz::BeginFrameArgs& args) { +void VideoFrameSubmitter::OnBeginFrame( + const viz::BeginFrameArgs& args, + WTF::HashMap<uint32_t, ::gfx::mojom::blink::PresentationFeedbackPtr>) { TRACE_EVENT0("media", "VideoFrameSubmitter::OnBeginFrame"); DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); viz::BeginFrameAck current_begin_frame_ack(args, false); @@ -399,10 +401,6 @@ resource_provider_->ReceiveReturnsFromParent(std_resources); } -void VideoFrameSubmitter::DidPresentCompositorFrame( - uint32_t presentation_token, - ::gfx::mojom::blink::PresentationFeedbackPtr feedback) {} - void VideoFrameSubmitter::DidAllocateSharedBitmap( mojo::ScopedSharedBufferHandle buffer, const viz::SharedBitmapId& id) {
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.h b/third_party/blink/renderer/platform/graphics/video_frame_submitter.h index 57ee1ae..3b4fcbf 100644 --- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.h +++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
@@ -73,10 +73,10 @@ // cc::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const WTF::Vector<viz::ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - ::gfx::mojom::blink::PresentationFeedbackPtr feedback) final; - void OnBeginFrame(const viz::BeginFrameArgs&) override; + void OnBeginFrame( + const viz::BeginFrameArgs&, + WTF::HashMap<uint32_t, ::gfx::mojom::blink::PresentationFeedbackPtr>) + override; void OnBeginFramePausedChanged(bool paused) override {} void ReclaimResources( const WTF::Vector<viz::ReturnedResource>& resources) override;
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc index 9aa7ec5..5e4b0ff 100644 --- a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc +++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
@@ -422,7 +422,7 @@ viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs( BEGINFRAME_FROM_HERE, now_src_.get()); - submitter_->OnBeginFrame(args); + submitter_->OnBeginFrame(args, {}); scoped_task_environment_.RunUntilIdle(); { @@ -447,7 +447,7 @@ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _)); EXPECT_CALL(*resource_provider_, ReleaseFrameResources()); - submitter_->OnBeginFrame(args); + submitter_->OnBeginFrame(args, {}); scoped_task_environment_.RunUntilIdle(); } @@ -534,7 +534,7 @@ viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs( BEGINFRAME_FROM_HERE, now_src_.get()); - submitter_->OnBeginFrame(args); + submitter_->OnBeginFrame(args, {}); scoped_task_environment_.RunUntilIdle(); { @@ -576,7 +576,7 @@ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _)); EXPECT_CALL(*resource_provider_, ReleaseFrameResources()); - submitter_->OnBeginFrame(args); + submitter_->OnBeginFrame(args, {}); scoped_task_environment_.RunUntilIdle(); // Updating |is_opaque_| with the same value should not cause a frame submit. @@ -603,7 +603,7 @@ viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs( BEGINFRAME_FROM_HERE, now_src_.get()); - submitter_->OnBeginFrame(args); + submitter_->OnBeginFrame(args, {}); scoped_task_environment_.RunUntilIdle(); } @@ -613,7 +613,7 @@ viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs( BEGINFRAME_FROM_HERE, now_src_.get()); args.type = viz::BeginFrameArgs::MISSED; - submitter_->OnBeginFrame(args); + submitter_->OnBeginFrame(args, {}); scoped_task_environment_.RunUntilIdle(); } @@ -624,7 +624,7 @@ viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs( BEGINFRAME_FROM_HERE, now_src_.get()); - submitter_->OnBeginFrame(args); + submitter_->OnBeginFrame(args, {}); scoped_task_environment_.RunUntilIdle(); } @@ -638,7 +638,7 @@ viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs( BEGINFRAME_FROM_HERE, now_src_.get()); - submitter_->OnBeginFrame(args); + submitter_->OnBeginFrame(args, {}); scoped_task_environment_.RunUntilIdle(); } @@ -651,7 +651,7 @@ viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs( BEGINFRAME_FROM_HERE, now_src_.get()); - submitter_->OnBeginFrame(args); + submitter_->OnBeginFrame(args, {}); scoped_task_environment_.RunUntilIdle(); } @@ -688,7 +688,7 @@ viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs( BEGINFRAME_FROM_HERE, now_src_.get()); - submitter_->OnBeginFrame(args); + submitter_->OnBeginFrame(args, {}); scoped_task_environment_.RunUntilIdle(); // DidNotProduceFrame should be called because no frame will be submitted @@ -703,7 +703,7 @@ std::make_unique<base::SimpleTestTickClock>(); args = begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE, new_time.get()); - submitter_->OnBeginFrame(args); + submitter_->OnBeginFrame(args, {}); scoped_task_environment_.RunUntilIdle(); }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index a22b9de..0f01902e2 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -798,10 +798,6 @@ status: "stable", }, { - name: "NestedWorkers", - status: "stable", - }, - { name: "NetInfoDownlinkMax", status: "stable", },
diff --git a/third_party/closure_compiler/externs/chrome_extensions.js b/third_party/closure_compiler/externs/chrome_extensions.js index 512b8a7..6adc5351 100644 --- a/third_party/closure_compiler/externs/chrome_extensions.js +++ b/third_party/closure_compiler/externs/chrome_extensions.js
@@ -10179,6 +10179,17 @@ /** + * Connects to the given device. This will only throw an error if the device + * address is invalid or the device is already connected. Otherwise this will + * succeed and invoke |callback| with ConnectResultType. + * @param {string} deviceAddress + * @param {function(!chrome.bluetoothPrivate.ConnectResultType):void=} callback + */ +chrome.bluetoothPrivate.connect = function(deviceAddress, callback) {}; + + + +/** * @param {string} deviceAddress * @param {function():void=} callback */
diff --git a/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java b/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java index 56e04fa..4bb10e3 100644 --- a/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java +++ b/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java
@@ -319,7 +319,7 @@ private final String mSpeculationMode; private final int mDelayToMayLaunchUrl; private final int mDelayToLaunchUrl; - public boolean mWarmupCompleted = false; + public boolean mWarmupCompleted; private long mIntentSentMs = NONE; private long mPageLoadStartedMs = NONE; private long mPageLoadFinishedMs = NONE;
diff --git a/tools/grit/grit/grit_runner.py b/tools/grit/grit/grit_runner.py index cc094661..367623e 100755 --- a/tools/grit/grit/grit_runner.py +++ b/tools/grit/grit/grit_runner.py
@@ -155,7 +155,7 @@ def ReadOptions(self, args): """Reads options from the start of args and returns the remainder.""" - (opts, args) = getopt.getopt(args, 'vxi:p:h:') + (opts, args) = getopt.getopt(args, 'vxi:p:h:', ('help',)) for (key, val) in opts: if key == '-h': self.hash = val elif key == '-i': self.input = val @@ -168,6 +168,9 @@ self.extra_verbose = True util.extra_verbose = True elif key == '-p': self.profile_dest = val + elif key == '--help': + PrintUsage() + sys.exit(0) if not self.input: if 'GRIT_INPUT' in os.environ:
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index aa6152b79..3472b803 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -20765,6 +20765,8 @@ <int value="2627" label="PageLifeCycleFreeze"/> <int value="2628" label="DefaultInCustomIdent"/> <int value="2629" label="HTMLAnchorElementHrefTranslateAttribute"/> + <int value="2630" label="WebKitUserModifyEffective"/> + <int value="2631" label="PlainTextEditingEffective"/> </enum> <enum name="FeaturePolicyFeature"> @@ -30587,6 +30589,7 @@ <int value="709850261" label="disable-touch-editing"/> <int value="711424932" label="enable-cloud-print-xps"/> <int value="715617684" label="OriginTrials:disabled"/> + <int value="716073306" label="AssistantVoiceMatch:disabled"/> <int value="716080990" label="restrict-iframe-permissions"/> <int value="719267310" label="KeepAliveRendererForKeepaliveRequests:disabled"/> @@ -30795,6 +30798,7 @@ <int value="1092896354" label="EnableFullscreenAppList:disabled"/> <int value="1094506652" label="UseGoogleLocalNtp:enabled"/> <int value="1095061640" label="enable-prominent-url-app-flow"/> + <int value="1096477444" label="AssistantVoiceMatch:enabled"/> <int value="1098823967" label="ash-enable-window-cycle-ui"/> <int value="1104948452" label="manual-enhanced-bookmarks-optout"/> <int value="1105439588" label="enable-swipe-selection"/> @@ -34394,6 +34398,14 @@ <int value="2" label="kCopyStateFrom"/> </enum> +<enum name="NavigationPredictorActionTaken"> + <int value="0" label="Unknown"/> + <int value="1" label="None"/> + <int value="2" label="A host was preresolved"/> + <int value="3" label="A host was preconnected to"/> + <int value="4" label="A URL was prefetched"/> +</enum> + <enum name="NavigationScheme"> <int value="0" label="(Unknown)"/> <int value="1" label="http"/> @@ -53387,6 +53399,7 @@ <int value="10" label="Blob"/> <int value="11" label="Content"/> <int value="12" label="Intent"/> + <int value="13" label="android_asset or android_res"/> </enum> <enum name="WelcomeSignInPromptOutcome">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 796e8d8d..82fdd5e1 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -2739,6 +2739,19 @@ </summary> </histogram> +<histogram name="Android.WebView.LoadUrl.UrlScheme" enum="WebViewUrlScheme" + expires_after="2019-05-05"> + <owner>ntfschr@chromium.org</owner> + <owner>torne@chromium.org</owner> + <summary> + Records the scheme for the URL loaded by a browser-initiated navigation. + Specifically, this is the scheme of the URL passed to loadUrl() (and its + overloads), postUrl(), and loadData (this is implicitly "data:"). + also records if this value is "empty", which means either null or + "about:blank". This intentionally excludes loadDataWithBaseURL(). + </summary> +</histogram> + <histogram name="Android.WebView.SplitApkWorkaroundResult" enum="SplitApkWorkaroundResult" expires_after="M72"> <owner>tiborg@chromium.org</owner> @@ -53183,6 +53196,26 @@ </summary> </histogram> +<histogram name="NavigationPredictor.OnDSE.ActionTaken" + enum="NavigationPredictorActionTaken"> + <owner>tbansal@chromium.org</owner> + <summary> + Tracks action taken by navigation predictor. Recorded at the time of page + load. Recorded only for pages whose URL matches the URL of the search + results page of the user's default search engine. + </summary> +</histogram> + +<histogram name="NavigationPredictor.OnNonDSE.ActionTaken" + enum="NavigationPredictorActionTaken"> + <owner>tbansal@chromium.org</owner> + <summary> + Tracks action taken by navigation predictor. Recorded at the time of page + load. Recorded only for pages whose URL does not match the URL of the search + results page of the user's default search engine. + </summary> +</histogram> + <histogram name="NavigationSuggestion.Event" enum="NavigationSuggestionEvent"> <owner>meacer@chromium.org</owner> <summary>
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc index cdf3925..be44a4f 100644 --- a/ui/accessibility/ax_node.cc +++ b/ui/accessibility/ax_node.cc
@@ -473,4 +473,68 @@ } } +bool AXNode::IsPosInSetUsedInRole() const { + switch (data().role) { + case ax::mojom::Role::kArticle: + case ax::mojom::Role::kListItem: + case ax::mojom::Role::kMenuItem: + case ax::mojom::Role::kMenuItemRadio: + case ax::mojom::Role::kTab: + case ax::mojom::Role::kMenuItemCheckBox: + case ax::mojom::Role::kTreeItem: + case ax::mojom::Role::kListBoxOption: + case ax::mojom::Role::kRadioButton: + return true; + + default: + return false; + } +} + +// Finds the position of this node within a list. +// Only takes into account elements that have same role as node. +int32_t AXNode::PosInSet() const { + AXNode* parent = GetUnignoredParent(); + + // Error checks + if (!parent) + return 0; + if (parent->data().role != ax::mojom::Role::kList) + return 0; + if (!IsPosInSetUsedInRole()) + return 0; + + int position = 0; + for (int i = 0; i < parent->GetUnignoredChildCount(); ++i) { + AXNode* candidate = parent->GetUnignoredChildAtIndex(i); + if (candidate->data().role == data().role) + ++position; + if (candidate == this) + return position; + } + return 0; +} + +// Finds the total number of elements of the list this node is contained within. +// Only counts the elements that have the same role as node. +int32_t AXNode::SetSize() const { + AXNode* parent = GetUnignoredParent(); + + // Error checks + if (!parent) + return 0; + if (parent->data().role != ax::mojom::Role::kList) + return 0; + if (!IsPosInSetUsedInRole()) + return 0; + + int count = 0; + for (int i = 0; i < parent->GetUnignoredChildCount(); ++i) { + AXNode* child = parent->GetUnignoredChildAtIndex(i); + if (child->data().role == data().role) + ++count; + } + return count; +} + } // namespace ui
diff --git a/ui/accessibility/ax_node.h b/ui/accessibility/ax_node.h index e815816..2320285e 100644 --- a/ui/accessibility/ax_node.h +++ b/ui/accessibility/ax_node.h
@@ -181,6 +181,15 @@ return data().GetHtmlAttribute(attribute, value); } + // Returns the position of node within a list. Returns 1-based index if + // contained within a list, and 0 if not. + int32_t PosInSet() const; + // Returns the total number of nodes in the same list as node. Returns 0 + // if the node is not contained wihtin a list. + int32_t SetSize() const; + // Returns true if the aria-posinset attribute is used in node's role + bool IsPosInSetUsedInRole() const; + const std::string& GetInheritedStringAttribute( ax::mojom::StringAttribute attribute) const; base::string16 GetInheritedString16Attribute(
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc index d8446754..13ad383 100644 --- a/ui/accessibility/ax_tree_unittest.cc +++ b/ui/accessibility/ax_tree_unittest.cc
@@ -1472,4 +1472,83 @@ EXPECT_EQ(0U, child_tree_93_nodes.size()); } +// Simple test for PosInSet and SetSize. +TEST(AXTreeTest, GetPosInSetSetSize) { + AXTreeUpdate tree_update; + tree_update.root_id = 1; + tree_update.nodes.resize(4); + tree_update.nodes[0].id = 1; + tree_update.nodes[0].role = ax::mojom::Role::kList; + tree_update.nodes[0].child_ids = {2, 3, 4}; + tree_update.nodes[1].id = 2; + tree_update.nodes[1].role = ax::mojom::Role::kListItem; + tree_update.nodes[2].id = 3; + tree_update.nodes[2].role = ax::mojom::Role::kListItem; + tree_update.nodes[3].id = 4; + tree_update.nodes[3].role = ax::mojom::Role::kListItem; + AXTree tree(tree_update); + + AXNode* item1 = tree.GetFromId(2); + EXPECT_EQ(item1->PosInSet(), 1); + EXPECT_EQ(item1->SetSize(), 3); + AXNode* item2 = tree.GetFromId(3); + EXPECT_EQ(item2->PosInSet(), 2); + EXPECT_EQ(item2->SetSize(), 3); + AXNode* item3 = tree.GetFromId(4); + EXPECT_EQ(item3->PosInSet(), 3); + EXPECT_EQ(item3->SetSize(), 3); +} + +// A test for PosInSet and SetSize on a list containing various roles. +TEST(AXTreeTest, GetPosInSetSetSizeDiverseList) { + AXTreeUpdate tree_update; + tree_update.root_id = 1; + tree_update.nodes.resize(9); + tree_update.nodes[0].id = 1; + tree_update.nodes[0].role = ax::mojom::Role::kList; + tree_update.nodes[0].child_ids = {2, 3, 4, 5, 6, 7, 8, 9}; + tree_update.nodes[1].id = 2; + tree_update.nodes[1].role = ax::mojom::Role::kListItem; + tree_update.nodes[2].id = 3; + tree_update.nodes[2].role = ax::mojom::Role::kListItem; + tree_update.nodes[3].id = 4; + tree_update.nodes[3].role = ax::mojom::Role::kMenuItem; + tree_update.nodes[4].id = 5; + tree_update.nodes[4].role = ax::mojom::Role::kMenuItem; + tree_update.nodes[5].id = 6; + tree_update.nodes[5].role = ax::mojom::Role::kArticle; + tree_update.nodes[6].id = 7; + tree_update.nodes[6].role = ax::mojom::Role::kArticle; + tree_update.nodes[7].id = 8; + tree_update.nodes[7].role = ax::mojom::Role::kListItem; + tree_update.nodes[8].id = 9; + tree_update.nodes[8].role = ax::mojom::Role::kImage; + AXTree tree(tree_update); + + AXNode* listitem1 = tree.GetFromId(2); + EXPECT_EQ(listitem1->PosInSet(), 1); + EXPECT_EQ(listitem1->SetSize(), 3); + AXNode* listitem2 = tree.GetFromId(3); + EXPECT_EQ(listitem2->PosInSet(), 2); + EXPECT_EQ(listitem2->SetSize(), 3); + AXNode* menuitem1 = tree.GetFromId(4); + EXPECT_EQ(menuitem1->PosInSet(), 1); + EXPECT_EQ(menuitem1->SetSize(), 2); + AXNode* menuitem2 = tree.GetFromId(5); + EXPECT_EQ(menuitem2->PosInSet(), 2); + EXPECT_EQ(menuitem2->SetSize(), 2); + AXNode* article1 = tree.GetFromId(6); + EXPECT_EQ(article1->PosInSet(), 1); + EXPECT_EQ(article1->SetSize(), 2); + AXNode* article2 = tree.GetFromId(7); + EXPECT_EQ(article2->PosInSet(), 2); + EXPECT_EQ(article2->SetSize(), 2); + AXNode* listitem3 = tree.GetFromId(8); + EXPECT_EQ(listitem3->PosInSet(), 3); + EXPECT_EQ(listitem3->SetSize(), 3); + AXNode* image1 = tree.GetFromId(9); + EXPECT_EQ(image1->PosInSet(), 0); + EXPECT_EQ(image1->SetSize(), 0); +} + } // namespace ui
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc index 54251f4..74b63d2 100644 --- a/ui/android/delegated_frame_host_android.cc +++ b/ui/android/delegated_frame_host_android.cc
@@ -377,13 +377,10 @@ client_->DidReceiveCompositorFrameAck(resources); } -void DelegatedFrameHostAndroid::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) { - client_->DidPresentCompositorFrame(presentation_token, feedback); -} - -void DelegatedFrameHostAndroid::OnBeginFrame(const viz::BeginFrameArgs& args) { +void DelegatedFrameHostAndroid::OnBeginFrame( + const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) { + client_->DidPresentCompositorFrames(feedbacks); if (enable_viz_) { NOTREACHED(); return;
diff --git a/ui/android/delegated_frame_host_android.h b/ui/android/delegated_frame_host_android.h index 5424e2f..348bb62 100644 --- a/ui/android/delegated_frame_host_android.h +++ b/ui/android/delegated_frame_host_android.h
@@ -44,9 +44,9 @@ virtual ~Client() {} virtual void SetBeginFrameSource( viz::BeginFrameSource* begin_frame_source) = 0; - virtual void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) = 0; + virtual void DidPresentCompositorFrames( + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) = 0; virtual void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) = 0; virtual void ReclaimResources( @@ -147,10 +147,9 @@ // viz::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override; - void OnBeginFrame(const viz::BeginFrameArgs& args) override; + void OnBeginFrame(const viz::BeginFrameArgs& args, + const base::flat_map<uint32_t, gfx::PresentationFeedback>& + feedbacks) override; void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override; void OnBeginFramePausedChanged(bool paused) override;
diff --git a/ui/android/delegated_frame_host_android_unittest.cc b/ui/android/delegated_frame_host_android_unittest.cc index 994b57d..2398963 100644 --- a/ui/android/delegated_frame_host_android_unittest.cc +++ b/ui/android/delegated_frame_host_android_unittest.cc
@@ -37,8 +37,9 @@ void(const std::vector<viz::ReturnedResource>&)); MOCK_METHOD1(ReclaimResources, void(const std::vector<viz::ReturnedResource>&)); - MOCK_METHOD2(DidPresentCompositorFrame, - void(uint32_t, const gfx::PresentationFeedback&)); + MOCK_METHOD1( + DidPresentCompositorFrames, + void(const base::flat_map<uint32_t, gfx::PresentationFeedback>&)); MOCK_METHOD1(OnFrameTokenChanged, void(uint32_t)); MOCK_METHOD0(WasEvicted, void()); };
diff --git a/ui/file_manager/externs/background/crostini.js b/ui/file_manager/externs/background/crostini.js new file mode 100644 index 0000000..462d60f --- /dev/null +++ b/ui/file_manager/externs/background/crostini.js
@@ -0,0 +1,47 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Crostini shared path state handler. + * @constructor + */ +function Crostini() {} + +/** + * Set from feature 'crostini-files'. + * @param {boolean} enabled + */ +Crostini.prototype.setEnabled = function(enabled) {}; + +/** + * @return {boolean} Whether crostini is enabled. + */ +Crostini.prototype.isEnabled = function() {}; + +/** + * Registers an entry as a shared path. + * @param {!Entry} entry + */ +Crostini.prototype.registerSharedPath = function(entry) {}; + +/** + * Unregisters entry as a shared path. + * @param {!Entry} entry + */ +Crostini.prototype.unregisterSharedPath = function(entry) {}; + +/** + * Returns true if entry is shared. + * @param {!Entry} entry + * @return {boolean} True if path is shared either by a direct + * share or from one of its ancestor directories. + */ +Crostini.prototype.isPathShared = function(entry) {}; + +/** + * Returns true if entry can be shared with Crostini. + * @param {!Entry} entry + * @param {boolean} persist If path is to be persisted. + */ +Crostini.prototype.canSharePath = function(entry, persist) {};
diff --git a/ui/file_manager/externs/background/file_browser_background_full.js b/ui/file_manager/externs/background/file_browser_background_full.js index 97859e91..f4f610f53 100644 --- a/ui/file_manager/externs/background/file_browser_background_full.js +++ b/ui/file_manager/externs/background/file_browser_background_full.js
@@ -44,3 +44,8 @@ * @type {!importer.HistoryLoader} */ FileBrowserBackgroundFull.prototype.historyLoader; + +/** + * @type {!Crostini} + */ +FileBrowserBackgroundFull.prototype.crostini;
diff --git a/ui/file_manager/externs/command_handler_deps.js b/ui/file_manager/externs/command_handler_deps.js index 1fdfea3..de1e3fd 100644 --- a/ui/file_manager/externs/command_handler_deps.js +++ b/ui/file_manager/externs/command_handler_deps.js
@@ -107,3 +107,8 @@ * @type {MetadataModel} */ CommandHandlerDeps.prototype.metadataModel; + +/** + * @type {Crostini} + */ +CommandHandlerDeps.prototype.crostini;
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn index 6626e68..ad9a456 100644 --- a/ui/file_manager/file_manager/background/js/BUILD.gn +++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -36,6 +36,7 @@ ":background", ":background_base", ":closure_compile_externs", + ":crostini", ":device_handler", ":drive_sync_handler", ":duplicate_finder", @@ -96,6 +97,7 @@ deps = [ ":app_windows", ":background_base", + ":crostini", ":device_handler", ":drive_sync_handler", ":duplicate_finder", @@ -124,6 +126,22 @@ ] } +js_library("crostini") { + deps = [ + "../../common/js:metrics", + "//ui/file_manager/base/js:volume_manager_types", + "//ui/file_manager/externs:volume_manager", + ] +} + +js_unittest("crostini_unittest") { + deps = [ + ":crostini", + "../../common/js:mock_entry", + "//ui/webui/resources/js:webui_resource_test", + ] +} + js_library("device_handler") { deps = [ ":volume_manager_factory", @@ -333,6 +351,7 @@ js_unit_tests("unit_tests") { deps = [ + ":crostini_unittest", ":volume_manager_unittest", ] }
diff --git a/ui/file_manager/file_manager/background/js/background.js b/ui/file_manager/file_manager/background/js/background.js index 5ddb65a8..086eb56 100644 --- a/ui/file_manager/file_manager/background/js/background.js +++ b/ui/file_manager/file_manager/background/js/background.js
@@ -82,6 +82,9 @@ this.progressCenter, this.historyLoader, this.dispositionChecker_, this.driveSyncHandler); + /** @type {!Crostini} */ + this.crostini = new Crostini(); + /** * String assets. * @type {Object<string>} @@ -101,7 +104,7 @@ chrome.contextMenus.onClicked.addListener( this.onContextMenuClicked_.bind(this)); - // Initializa string and volume manager related stuffs. + // Initialize string and volume manager related stuffs. this.initializationPromise_.then(function(strings) { this.stringData = strings; this.initContextMenu_(); @@ -110,6 +113,9 @@ volumeManager.addEventListener( VolumeManagerCommon.VOLUME_ALREADY_MOUNTED, this.handleViewEvent_.bind(this)); + + this.crostini.init(volumeManager); + this.crostini.listen(); }.bind(this)); this.fileOperationManager = new FileOperationManager();
diff --git a/ui/file_manager/file_manager/background/js/background_scripts.js b/ui/file_manager/file_manager/background/js/background_scripts.js index bda05b9..8008208 100644 --- a/ui/file_manager/file_manager/background/js/background_scripts.js +++ b/ui/file_manager/file_manager/background/js/background_scripts.js
@@ -12,6 +12,7 @@ // <include src="../../common/js/progress_center_common.js"> // <include src="../../common/js/importer_common.js"> // <include src="metadata_proxy.js"> +// <include src="crostini.js"> // <include src="device_handler.js"> // <include src="drive_sync_handler.js"> // <include src="duplicate_finder.js">
diff --git a/ui/file_manager/file_manager/background/js/crostini.js b/ui/file_manager/file_manager/background/js/crostini.js new file mode 100644 index 0000000..3e37ed5 --- /dev/null +++ b/ui/file_manager/file_manager/background/js/crostini.js
@@ -0,0 +1,182 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Crostini shared path state handler. + * @constructor + */ +function Crostini() { + /** @private {boolean} */ + this.enabled_ = false; + + /** + * Maintains a list of paths shared with the crostini container. + * Keyed by VolumeManagerCommon.RootType, with boolean set values + * of string paths. e.g. {'Downloads': {'/foo': true, '/bar': true}}. + * @private @dict {!Object<!Object<boolean>>} + */ + this.shared_paths_ = {}; +} + +/** + * Keep in sync with histograms.xml:FileBrowserCrostiniSharedPathsDepth + * histogram_suffix. + * @type {!Map<VolumeManagerCommon.RootType, string>} + * @const + */ +Crostini.VALID_ROOT_TYPES_FOR_SHARE = new Map([ + [VolumeManagerCommon.RootType.DOWNLOADS, 'Downloads'], + [VolumeManagerCommon.RootType.REMOVABLE, 'Removable'], +]); + +/** + * Can be collapsed into VALID_ROOT_TYPES_FOR_SHARE once + * DriveFS flag is removed. + * Keep in sync with histograms.xml:FileBrowserCrostiniSharedPathsDepth + * histogram_suffix. + * @type {!Map<VolumeManagerCommon.RootType, string>} + * @const + */ +Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE = new Map([ + [VolumeManagerCommon.RootType.COMPUTERS_GRAND_ROOT, 'DriveComputers'], + [VolumeManagerCommon.RootType.COMPUTER, 'DriveComputers'], + [VolumeManagerCommon.RootType.DRIVE, 'MyDrive'], + [VolumeManagerCommon.RootType.TEAM_DRIVES_GRAND_ROOT, 'TeamDrive'], + [VolumeManagerCommon.RootType.TEAM_DRIVE, 'TeamDrive'], +]); + +/** @private {string} */ +Crostini.UMA_ROOT_TYPE_OTHER = 'Other'; + +/** + * Initialize Volume Manager. + * @param {!VolumeManager} volumeManager + */ +Crostini.prototype.init = function(volumeManager) { + this.volumeManager_ = volumeManager; +}; + +/** + * Register for any shared path changes. + */ +Crostini.prototype.listen = function() { + chrome.fileManagerPrivate.onCrostiniSharedPathsChanged.addListener( + this.onChange_.bind(this)); +}; + +/** + * Set from feature 'crostini-files'. + * @param {boolean} enabled + */ +Crostini.prototype.setEnabled = function(enabled) { + this.enabled_ = enabled; +}; + +/** + * @return {boolean} Whether crostini is enabled. + */ +Crostini.prototype.isEnabled = function() { + return this.enabled_; +}; + +/** + * Registers an entry as a shared path. + * @param {!Entry} entry + */ +Crostini.prototype.registerSharedPath = function(entry) { + const info = this.volumeManager_.getLocationInfo(entry); + if (!info) + return; + let paths = this.shared_paths_[info.rootType]; + if (!paths) { + paths = {}; + this.shared_paths_[info.rootType] = paths; + } + // Remove any existing paths that are children of the new path. + for (let path in paths) { + if (path.startsWith(entry.fullPath)) + delete paths[path]; + } + paths[entry.fullPath] = true; + + // Record UMA. + let suffix = Crostini.VALID_ROOT_TYPES_FOR_SHARE.get(info.rootType) || + Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE.get(info.rootType) || + Crostini.UMA_ROOT_TYPE_OTHER; + metrics.recordSmallCount( + 'CrostiniSharedPaths.Depth.' + suffix, + entry.fullPath.split('/').length - 1); +}; + +/** + * Unregisters entry as a shared path. + * @param {!Entry} entry + */ +Crostini.prototype.unregisterSharedPath = function(entry) { + const info = this.volumeManager_.getLocationInfo(entry); + if (!info) + return; + const paths = this.shared_paths_[info.rootType]; + if (paths) { + delete paths[entry.fullPath]; + } +}; + +/** + * Handles shared path changes. + * @param {chrome.fileManagerPrivate.CrostiniSharedPathsChangedEvent} event + * @private + */ +Crostini.prototype.onChange_ = function(event) { + if (event.eventType === 'share') { + for (const entry of event.entries) { + this.registerSharedPath(entry); + } + } else if (event.eventType === 'unshare') { + for (const entry of event.entries) { + this.unregisterSharedPath(entry); + } + } +}; + +/** + * Returns true if entry is shared. + * @param {!Entry} entry + * @return {boolean} True if path is shared either by a direct + * share or from one of its ancestor directories. + */ +Crostini.prototype.isPathShared = function(entry) { + const root = this.volumeManager_.getLocationInfo(entry).rootType; + const paths = this.shared_paths_[root]; + if (!paths) + return false; + // Check path and all ancestor directories. + let path = entry.fullPath; + while (path.length > 1) { + if (paths[path]) + return true; + path = path.substring(0, path.lastIndexOf('/')); + } + return !!paths['/']; +}; + +/** + * Returns true if entry can be shared with Crostini. + * @param {!Entry} entry + * @param {boolean} persist If path is to be persisted. + */ +Crostini.prototype.canSharePath = function(entry, persist) { + if (!this.enabled_) + return false; + + // Only directories for persistent shares. + if (persist && !entry.isDirectory) + return false; + + // Allow Downloads, and Drive if DriveFS is enabled. + const rootType = this.volumeManager_.getLocationInfo(entry).rootType; + return Crostini.VALID_ROOT_TYPES_FOR_SHARE.has(rootType) || + (loadTimeData.getBoolean('DRIVE_FS_ENABLED') && + Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE.has(rootType)); +};
diff --git a/ui/file_manager/file_manager/background/js/crostini_unittest.js b/ui/file_manager/file_manager/background/js/crostini_unittest.js new file mode 100644 index 0000000..39a0dbff --- /dev/null +++ b/ui/file_manager/file_manager/background/js/crostini_unittest.js
@@ -0,0 +1,130 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +window.metrics = { + recordSmallCount: function() {}, +}; + +window.loadTimeData = { + data: {'DRIVE_FS_ENABLED': false}, + getBoolean: function(key) { + return window.loadTimeData.data[key]; + } +}; + +let volumeManagerRootType = 'testroot'; +const volumeManager = /** @type {!VolumeManager} */ ({ + getLocationInfo: (entry) => { + return {rootType: volumeManagerRootType}; + }, +}); + + +const crostini = new Crostini(); +crostini.init(volumeManager); + +function testIsPathShared() { + const mockFileSystem = new MockFileSystem('volumeId'); + const root = new MockDirectoryEntry(mockFileSystem, '/'); + const a = new MockDirectoryEntry(mockFileSystem, '/a'); + const aa = new MockDirectoryEntry(mockFileSystem, '/a/a'); + const ab = new MockDirectoryEntry(mockFileSystem, '/a/b'); + const b = new MockDirectoryEntry(mockFileSystem, '/b'); + const bb = new MockDirectoryEntry(mockFileSystem, '/b/b'); + + assertFalse(crostini.isPathShared(a)); + + crostini.registerSharedPath(a); + assertFalse(crostini.isPathShared(root)); + assertTrue(crostini.isPathShared(a)); + assertTrue(crostini.isPathShared(aa)); + + crostini.registerSharedPath(bb); + assertFalse(crostini.isPathShared(b)); + assertTrue(crostini.isPathShared(bb)); + + crostini.unregisterSharedPath(bb); + assertFalse(crostini.isPathShared(bb)); + + // Test collapsing. Setup with /a/a, /a/b, /b + crostini.unregisterSharedPath(a); + crostini.registerSharedPath(aa); + crostini.registerSharedPath(ab); + crostini.registerSharedPath(b); + assertFalse(crostini.isPathShared(a)); + assertTrue(crostini.isPathShared(aa)); + assertTrue(crostini.isPathShared(ab)); + assertTrue(crostini.isPathShared(b)); + // Add /a, collapses /a/a, /a/b + crostini.registerSharedPath(a); + assertTrue(crostini.isPathShared(a)); + assertTrue(crostini.isPathShared(aa)); + assertTrue(crostini.isPathShared(ab)); + assertTrue(crostini.isPathShared(b)); + // Unregister /a, /a/a and /a/b should be lost. + crostini.unregisterSharedPath(a); + assertFalse(crostini.isPathShared(a)); + assertFalse(crostini.isPathShared(aa)); + assertFalse(crostini.isPathShared(ab)); + assertTrue(crostini.isPathShared(b)); + // Register root, collapses all. + crostini.registerSharedPath(root); + assertTrue(crostini.isPathShared(a)); + assertTrue(crostini.isPathShared(aa)); + assertTrue(crostini.isPathShared(ab)); + assertTrue(crostini.isPathShared(b)); + // Unregister root, all should be lost. + crostini.unregisterSharedPath(root); + assertFalse(crostini.isPathShared(a)); + assertFalse(crostini.isPathShared(aa)); + assertFalse(crostini.isPathShared(ab)); + assertFalse(crostini.isPathShared(b)); +} + +function testCanSharePath() { + crostini.setEnabled(true); + + const mockFileSystem = new MockFileSystem('test'); + const root = new MockDirectoryEntry(mockFileSystem, '/'); + const rootFile = new MockEntry(mockFileSystem, '/file'); + const rootFolder = new MockDirectoryEntry(mockFileSystem, '/folder'); + const fooFile = new MockEntry(mockFileSystem, '/foo/file'); + const fooFolder = new MockDirectoryEntry(mockFileSystem, '/foo/folder'); + + window.loadTimeData.data['DRIVE_FS_ENABLED'] = false; + const disallowed = new Map(Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE); + disallowed.set('test', 'test'); + for (let type of disallowed.keys()) { + volumeManagerRootType = type; + assertFalse(crostini.canSharePath(root, true)); + assertFalse(crostini.canSharePath(root, false)); + assertFalse(crostini.canSharePath(rootFile, true)); + assertFalse(crostini.canSharePath(rootFile, false)); + assertFalse(crostini.canSharePath(rootFolder, true)); + assertFalse(crostini.canSharePath(rootFolder, false)); + assertFalse(crostini.canSharePath(fooFile, true)); + assertFalse(crostini.canSharePath(fooFile, false)); + assertFalse(crostini.canSharePath(fooFolder, true)); + assertFalse(crostini.canSharePath(fooFolder, false)); + } + + window.loadTimeData.data['DRIVE_FS_ENABLED'] = true; + const allowed = new Map([ + ...Crostini.VALID_ROOT_TYPES_FOR_SHARE, + ...Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE + ]); + for (let type of allowed.keys()) { + volumeManagerRootType = type; + assertTrue(crostini.canSharePath(root, true)); + assertTrue(crostini.canSharePath(root, false)); + assertFalse(crostini.canSharePath(rootFile, true)); + assertTrue(crostini.canSharePath(rootFile, false)); + assertTrue(crostini.canSharePath(rootFolder, true)); + assertTrue(crostini.canSharePath(rootFolder, false)); + assertFalse(crostini.canSharePath(fooFile, true)); + assertTrue(crostini.canSharePath(fooFile, false)); + assertTrue(crostini.canSharePath(fooFolder, true)); + assertTrue(crostini.canSharePath(fooFolder, false)); + } +}
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn index 68e961f..9806c37 100644 --- a/ui/file_manager/file_manager/foreground/js/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -28,7 +28,6 @@ ":closure_compile_externs", ":column_visibility_controller", ":constants", - ":crostini", ":dialog_action_controller", ":dialog_type", ":directory_contents", @@ -84,6 +83,7 @@ "$externs_path/metrics_private.js", "$externs_path/web_animations.js", "../../../externs/app_window_common.js", + "../../../externs/background/crostini.js", "../../../externs/background/drive_sync_handler.js", "../../../externs/background/file_browser_background.js", "../../../externs/background/file_browser_background_full.js", @@ -216,22 +216,6 @@ ] } -js_library("crostini") { - deps = [ - "../../common/js:metrics", - "//ui/file_manager/base/js:volume_manager_types", - "//ui/file_manager/externs:volume_manager", - ] -} - -js_unittest("crostini_unittest") { - deps = [ - ":crostini", - "../../common/js:mock_entry", - "//ui/webui/resources/js:webui_resource_test", - ] -} - js_library("dialog_type") { } @@ -376,7 +360,6 @@ js_library("file_tasks") { deps = [ - ":crostini", ":directory_model", ":task_history", "metadata:metadata_model", @@ -683,7 +666,6 @@ js_unit_tests("unit_tests") { deps = [ - ":crostini_unittest", ":thumbnail_loader_unittest", ] }
diff --git a/ui/file_manager/file_manager/foreground/js/crostini.js b/ui/file_manager/file_manager/foreground/js/crostini.js deleted file mode 100644 index 8c46d93..0000000 --- a/ui/file_manager/file_manager/foreground/js/crostini.js +++ /dev/null
@@ -1,175 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -const Crostini = {}; - -/** - * Set from cmd line flag 'crostini-files'. - * @type {boolean} - */ -Crostini.IS_CROSTINI_FILES_ENABLED = false; - -/** - * Keep in sync with histograms.xml:FileBrowserCrostiniSharedPathsDepth - * histogram_suffix. - * @type {!Map<VolumeManagerCommon.RootType, string>} - */ -Crostini.VALID_ROOT_TYPES_FOR_SHARE = new Map([ - [VolumeManagerCommon.RootType.DOWNLOADS, 'Downloads'], - [VolumeManagerCommon.RootType.REMOVABLE, 'Removable'], -]); - -/** - * Can be collapsed into VALD_ROOT_TYPES_FOR_SHARE once - * DriveFS flag is removed. - * Keep in sync with histograms.xml:FileBrowserCrostiniSharedPathsDepth - * histogram_suffix. - * @type {!Map<VolumeManagerCommon.RootType, string>} - */ -Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE = new Map([ - [VolumeManagerCommon.RootType.COMPUTERS_GRAND_ROOT, 'DriveComputers'], - [VolumeManagerCommon.RootType.COMPUTER, 'DriveComputers'], - [VolumeManagerCommon.RootType.DRIVE, 'MyDrive'], - [VolumeManagerCommon.RootType.TEAM_DRIVE, 'TeamDrive'], -]); - -/** @private {string} */ -Crostini.UMA_ROOT_TYPE_OTHER = 'Other'; - -/** - * Maintains a list of paths shared with the crostini container. - * Keyed by VolumeManagerCommon.RootType, with boolean set values - * of string paths. e.g. {'Downloads': {'/foo': true, '/bar': true}}. - * @private @dict {!Object<!Object<boolean>>} - */ -Crostini.SHARED_PATHS_ = {}; - -/** - * Registers an entry as a shared path. - * @param {!Entry} entry - * @param {!VolumeManager} volumeManager - */ -Crostini.registerSharedPath = function(entry, volumeManager) { - const info = volumeManager.getLocationInfo(entry); - if (!info) - return; - let paths = Crostini.SHARED_PATHS_[info.rootType]; - if (!paths) { - paths = {}; - Crostini.SHARED_PATHS_[info.rootType] = paths; - } - // Remove any existing paths that are children of the new path. - for (let path in paths) { - if (path.startsWith(entry.fullPath)) - delete paths[path]; - } - paths[entry.fullPath] = true; - - // Record UMA. - let suffix = Crostini.VALID_ROOT_TYPES_FOR_SHARE.get(info.rootType) || - Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE.get(info.rootType) || - Crostini.UMA_ROOT_TYPE_OTHER; - metrics.recordSmallCount( - 'CrostiniSharedPaths.Depth.' + suffix, - entry.fullPath.split('/').length - 1); -}; - -/** - * Unregisters entry as a shared path. - * @param {!Entry} entry - * @param {!VolumeManager} volumeManager - */ -Crostini.unregisterSharedPath = function(entry, volumeManager) { - const info = volumeManager.getLocationInfo(entry); - if (!info) - return; - const paths = Crostini.SHARED_PATHS_[info.rootType]; - if (paths) { - delete paths[entry.fullPath]; - } -}; - -/** - * Handles shared path changes. - * @param {!VolumeManager} volumeManager - * @param {chrome.fileManagerPrivate.CrostiniSharedPathsChangedEvent} event - */ -Crostini.onSharedPathsChanged = function(volumeManager, event) { - if (event.eventType === 'share') { - for (const entry of event.entries) { - Crostini.registerSharedPath(entry, volumeManager); - } - } else if (event.eventType === 'unshare') { - for (const entry of event.entries) { - Crostini.unregisterSharedPath(entry, volumeManager); - } - } -}; - -/** - * Returns true if entry is shared. - * @param {!Entry} entry - * @param {!VolumeManager} volumeManager - * @return {boolean} True if path is shared either by a direct - * share or from one of its ancestor directories. - */ -Crostini.isPathShared = function(entry, volumeManager) { - const root = volumeManager.getLocationInfo(entry).rootType; - const paths = Crostini.SHARED_PATHS_[root]; - if (!paths) - return false; - // Check path and all ancestor directories. - let path = entry.fullPath; - while (path.length > 1) { - if (paths[path]) - return true; - path = path.substring(0, path.lastIndexOf('/')); - } - return !!paths['/']; -}; - -/** - * @param {!Entry} entry - * @param {!VolumeManager} volumeManager - * @return {boolean} True if the entry is from crostini. - */ -Crostini.isCrostiniEntry = function(entry, volumeManager) { - return volumeManager.getLocationInfo(entry).rootType === - VolumeManagerCommon.RootType.CROSTINI; -}; - -/** - * Returns true if entry can be shared with Crostini. - * @param {!Entry} entry - * @param {boolean} persist If path is to be persisted. - * @param {!VolumeManager} volumeManager - */ -Crostini.canSharePath = function(entry, persist, volumeManager) { - - // Check crostini-files flag and valid volume. - if (!Crostini.IS_CROSTINI_FILES_ENABLED) - return false; - - // Only directories for persistent shares. - if (persist && !entry.isDirectory) - return false; - - // Allow Downloads, and Drive if DriveFS is enabled. - const rootType = volumeManager.getLocationInfo(entry).rootType; - return Crostini.VALID_ROOT_TYPES_FOR_SHARE.has(rootType) || - (loadTimeData.getBoolean('DRIVE_FS_ENABLED') && - Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE.has(rootType)); -}; - -/** - * Returns true if task requires entries to be shared before executing task. - * @param {!chrome.fileManagerPrivate.FileTask} task Task to run. - * @return {boolean} true if task requires entries to be shared. - */ -Crostini.taskRequiresSharing = function(task) { - const taskParts = task.taskId.split('|'); - const taskType = taskParts[1]; - const actionId = taskParts[2]; - return taskType === 'crostini' || actionId === 'install-linux-package'; -};
diff --git a/ui/file_manager/file_manager/foreground/js/crostini_unittest.js b/ui/file_manager/file_manager/foreground/js/crostini_unittest.js deleted file mode 100644 index 5d797fbb..0000000 --- a/ui/file_manager/file_manager/foreground/js/crostini_unittest.js +++ /dev/null
@@ -1,138 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -window.metrics = { - recordSmallCount: function() {}, -}; - -window.loadTimeData = { - data: {'DRIVE_FS_ENABLED': false}, - getBoolean: function(key) { - return window.loadTimeData.data[key]; - } -}; - -let volumeManagerRootType = 'testroot'; -const volumeManager = /** @type {!VolumeManager} */ ({ - getLocationInfo: (entry) => { - return {rootType: volumeManagerRootType}; - }, -}); - -function testIsPathShared() { - const mockFileSystem = new MockFileSystem('volumeId'); - const root = new MockDirectoryEntry(mockFileSystem, '/'); - const a = new MockDirectoryEntry(mockFileSystem, '/a'); - const aa = new MockDirectoryEntry(mockFileSystem, '/a/a'); - const ab = new MockDirectoryEntry(mockFileSystem, '/a/b'); - const b = new MockDirectoryEntry(mockFileSystem, '/b'); - const bb = new MockDirectoryEntry(mockFileSystem, '/b/b'); - - assertFalse(Crostini.isPathShared(a, volumeManager)); - - Crostini.registerSharedPath(a, volumeManager); - assertFalse(Crostini.isPathShared(root, volumeManager)); - assertTrue(Crostini.isPathShared(a, volumeManager)); - assertTrue(Crostini.isPathShared(aa, volumeManager)); - - Crostini.registerSharedPath(bb, volumeManager); - assertFalse(Crostini.isPathShared(b, volumeManager)); - assertTrue(Crostini.isPathShared(bb, volumeManager)); - - Crostini.unregisterSharedPath(bb, volumeManager); - assertFalse(Crostini.isPathShared(bb, volumeManager)); - - // Test collapsing. Setup with /a/a, /a/b, /b - Crostini.unregisterSharedPath(a, volumeManager); - Crostini.registerSharedPath(aa, volumeManager); - Crostini.registerSharedPath(ab, volumeManager); - Crostini.registerSharedPath(b, volumeManager); - assertFalse(Crostini.isPathShared(a, volumeManager)); - assertTrue(Crostini.isPathShared(aa, volumeManager)); - assertTrue(Crostini.isPathShared(ab, volumeManager)); - assertTrue(Crostini.isPathShared(b, volumeManager)); - // Add /a, collapses /a/a, /a/b - Crostini.registerSharedPath(a, volumeManager); - assertTrue(Crostini.isPathShared(a, volumeManager)); - assertTrue(Crostini.isPathShared(aa, volumeManager)); - assertTrue(Crostini.isPathShared(ab, volumeManager)); - assertTrue(Crostini.isPathShared(b, volumeManager)); - // Unregister /a, /a/a and /a/b should be lost. - Crostini.unregisterSharedPath(a, volumeManager); - assertFalse(Crostini.isPathShared(a, volumeManager)); - assertFalse(Crostini.isPathShared(aa, volumeManager)); - assertFalse(Crostini.isPathShared(ab, volumeManager)); - assertTrue(Crostini.isPathShared(b, volumeManager)); - // Register root, collapses all. - Crostini.registerSharedPath(root, volumeManager); - assertTrue(Crostini.isPathShared(a, volumeManager)); - assertTrue(Crostini.isPathShared(aa, volumeManager)); - assertTrue(Crostini.isPathShared(ab, volumeManager)); - assertTrue(Crostini.isPathShared(b, volumeManager)); - // Unregister root, all should be lost. - Crostini.unregisterSharedPath(root, volumeManager); - assertFalse(Crostini.isPathShared(a, volumeManager)); - assertFalse(Crostini.isPathShared(aa, volumeManager)); - assertFalse(Crostini.isPathShared(ab, volumeManager)); - assertFalse(Crostini.isPathShared(b, volumeManager)); -} - - -function testCanSharePath() { - Crostini.IS_CROSTINI_FILES_ENABLED = true; - - const mockFileSystem = new MockFileSystem('test'); - const root = new MockDirectoryEntry(mockFileSystem, '/'); - const rootFile = new MockEntry(mockFileSystem, '/file'); - const rootFolder = new MockDirectoryEntry(mockFileSystem, '/folder'); - const fooFile = new MockEntry(mockFileSystem, '/foo/file'); - const fooFolder = new MockDirectoryEntry(mockFileSystem, '/foo/folder'); - - window.loadTimeData.data['DRIVE_FS_ENABLED'] = false; - const disallowed = new Map(Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE); - disallowed.set('test', 'test'); - for (let type of disallowed.keys()) { - volumeManagerRootType = type; - assertFalse(Crostini.canSharePath(root, true, volumeManager)); - assertFalse(Crostini.canSharePath(root, false, volumeManager)); - assertFalse(Crostini.canSharePath(rootFile, true, volumeManager)); - assertFalse(Crostini.canSharePath(rootFile, false, volumeManager)); - assertFalse(Crostini.canSharePath(rootFolder, true, volumeManager)); - assertFalse(Crostini.canSharePath(rootFolder, false, volumeManager)); - assertFalse(Crostini.canSharePath(fooFile, true, volumeManager)); - assertFalse(Crostini.canSharePath(fooFile, false, volumeManager)); - assertFalse(Crostini.canSharePath(fooFolder, true, volumeManager)); - assertFalse(Crostini.canSharePath(fooFolder, false, volumeManager)); - } - - window.loadTimeData.data['DRIVE_FS_ENABLED'] = true; - const allowed = new Map([ - ...Crostini.VALID_ROOT_TYPES_FOR_SHARE, - ...Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE - ]); - for (let type of allowed.keys()) { - volumeManagerRootType = type; - assertTrue(Crostini.canSharePath(root, true, volumeManager)); - assertTrue(Crostini.canSharePath(root, false, volumeManager)); - assertFalse(Crostini.canSharePath(rootFile, true, volumeManager)); - assertTrue(Crostini.canSharePath(rootFile, false, volumeManager)); - assertTrue(Crostini.canSharePath(rootFolder, true, volumeManager)); - assertTrue(Crostini.canSharePath(rootFolder, false, volumeManager)); - assertFalse(Crostini.canSharePath(fooFile, true, volumeManager)); - assertTrue(Crostini.canSharePath(fooFile, false, volumeManager)); - assertTrue(Crostini.canSharePath(fooFolder, true, volumeManager)); - assertTrue(Crostini.canSharePath(fooFolder, false, volumeManager)); - } -} - -function task(id) { - return /** @type{!chrome.fileManagerPrivate.FileTask} */ ({taskId: id}); -} - -function testTaskRequiresSharing() { - assertTrue(Crostini.taskRequiresSharing(task('app|crostini|open-with'))); - assertTrue( - Crostini.taskRequiresSharing(task('appId|x|install-linux-package'))); - assertFalse(Crostini.taskRequiresSharing(task('appId|x|open-with'))); -}
diff --git a/ui/file_manager/file_manager/foreground/js/directory_model.js b/ui/file_manager/file_manager/foreground/js/directory_model.js index 51e7525..4108ae5 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_model.js +++ b/ui/file_manager/file_manager/foreground/js/directory_model.js
@@ -699,7 +699,7 @@ var locationInfo = this.volumeManager_.getLocationInfo( assert(dirContents.getDirectoryEntry())); - var volumeInfo = locationInfo.volumeInfo; + var volumeInfo = locationInfo && locationInfo.volumeInfo; if (volumeInfo && volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS && locationInfo.isRootEntry) {
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js index fcf964a..a445087 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -26,6 +26,9 @@ /** @private {importer.HistoryLoader} */ this.historyLoader_ = null; + /** @private {Crostini} */ + this.crostini_ = null; + /** * ImportHistory. Non-null only once history observer is added in * {@code addHistoryObserver}. @@ -498,6 +501,12 @@ return this.historyLoader_; }, /** + * @return {Crostini} + */ + get crostini() { + return this.crostini_; + }, + /** * @return {importer.ImportRunner} */ get mediaImportHandler() { @@ -897,6 +906,7 @@ this.fileBrowserBackground_.mediaScanner; this.historyLoader_ = this.fileBrowserBackground_.historyLoader; + this.crostini_ = this.fileBrowserBackground_.crostini; metrics.recordInterval('Load.InitBackgroundPage'); resolve(); }.bind(this)); @@ -1139,13 +1149,9 @@ // Create task controller. this.taskController_ = new TaskController( - this.dialogType, - this.volumeManager_, - this.ui_, - this.metadataModel_, - this.directoryModel_, - this.selectionHandler_, - this.metadataUpdateController_); + this.dialogType, this.volumeManager_, this.ui_, this.metadataModel_, + this.directoryModel_, this.selectionHandler_, + this.metadataUpdateController_, assert(this.crostini_)); // Create search controller. this.searchController_ = new SearchController( @@ -1219,8 +1225,6 @@ this.getSourceRestriction_())) : null); - chrome.fileManagerPrivate.onCrostiniSharedPathsChanged.addListener( - Crostini.onSharedPathsChanged.bind(null, assert(this.volumeManager_))); this.setupCrostini_(); this.ui_.initDirectoryTree(directoryTree); @@ -1237,8 +1241,8 @@ FileManager.prototype.setupCrostini_ = function() { chrome.fileManagerPrivate.isCrostiniEnabled((crostiniEnabled) => { // Check for 'crostini-files' feature. - Crostini.IS_CROSTINI_FILES_ENABLED = - crostiniEnabled && loadTimeData.getBoolean('CROSTINI_FILES_ENABLED'); + this.crostini_.setEnabled( + crostiniEnabled && loadTimeData.getBoolean('CROSTINI_FILES_ENABLED')); // Setup Linux files fake root. this.directoryTree.dataModel.linuxFilesItem = crostiniEnabled ? @@ -1258,7 +1262,7 @@ // Load any existing shared paths. chrome.fileManagerPrivate.getCrostiniSharedPaths((entries) => { for (let i = 0; i < entries.length; i++) { - Crostini.registerSharedPath(entries[i], assert(this.volumeManager_)); + this.crostini_.registerSharedPath(entries[i]); } }); });
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js index cf9fc5b2..982472c8 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -1634,8 +1634,7 @@ /** - * Shares the selected (single only) Downloads subfolder with crostini - * container. + * Shares the selected (single only) directory with the crostini container. * @type {Command} */ CommandHandler.COMMANDS_['share-with-linux'] = /** @type {Command} */ ({ @@ -1645,8 +1644,13 @@ */ execute: function(event, fileManager) { const entry = CommandUtil.getCommandEntry(event.target); - if (entry && entry.isDirectory) { - const dir = /** @type {!DirectoryEntry} */ (entry); + if (!entry || !entry.isDirectory) + return; + const dir = /** @type {!DirectoryEntry} */ (entry); + const info = fileManager.volumeManager.getLocationInfo(dir); + if (!info) + return; + function share() { // Always persist shares via right-click > Share with Linux. chrome.fileManagerPrivate.sharePathsWithCrostini( [dir], true /* persist */, () => { @@ -1655,12 +1659,35 @@ 'Error sharing with linux: ' + chrome.runtime.lastError.message); } else { - Crostini.registerSharedPath(dir, fileManager.volumeManager); + fileManager.crostini.registerSharedPath(dir); } }); - CommandHandler.recordMenuItemSelected_( - CommandHandler.MenuCommandsForUMA.SHARE_WITH_LINUX); } + // Show a confirmation dialog if we are sharing the root of a volume. + // Non-Drive volume roots are always '/'. + if (dir.fullPath == '/') { + fileManager.ui_.confirmDialog.showHtml( + strf('SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE'), + strf('SHARE_ROOT_FOLDER_WITH_CROSTINI', info.volumeInfo.label), share, + () => {}); + } else if ( + info.isRootEntry && + (info.rootType == VolumeManagerCommon.RootType.DRIVE || + info.rootType == VolumeManagerCommon.RootType.COMPUTERS_GRAND_ROOT || + info.rootType == + VolumeManagerCommon.RootType.TEAM_DRIVES_GRAND_ROOT)) { + // Only show the dialog for My Drive, Team Drives Grand Root and + // Computers Grand Root. Do not show for roots of a single Team Drive + // or Computer. + fileManager.ui_.confirmDialog.showHtml( + strf('SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE'), + strf('SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE'), share, () => {}); + } else { + // This is not a root, share it without confirmation dialog. + share(); + } + CommandHandler.recordMenuItemSelected_( + CommandHandler.MenuCommandsForUMA.SHARE_WITH_LINUX); }, /** * @param {!Event} event Command event. @@ -1670,9 +1697,8 @@ // Must be single directory subfolder of Downloads not already shared. const entries = CommandUtil.getCommandEntries(event.target); event.canExecute = entries.length === 1 && entries[0].isDirectory && - !Crostini.isPathShared(entries[0], fileManager.volumeManager) && - Crostini.canSharePath( - entries[0], true /* persist */, fileManager.volumeManager); + !fileManager.crostini.isPathShared(entries[0]) && + fileManager.crostini.canSharePath(entries[0], true /* persist */); event.command.setHidden(!event.canExecute); } }); @@ -1697,7 +1723,7 @@ * @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use. */ canExecute: function(event, fileManager) { - event.canExecute = Crostini.IS_CROSTINI_FILES_ENABLED; + event.canExecute = fileManager.crostini.isEnabled(); event.command.setHidden(!event.canExecute); } });
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 1a0fd3f..cc265dd 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks.js +++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -15,12 +15,13 @@ * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks * @param {chrome.fileManagerPrivate.FileTask} defaultTask * @param {!TaskHistory} taskHistory + * @param {!Crostini} crostini * @constructor * @struct */ function FileTasks( volumeManager, metadataModel, directoryModel, ui, entries, mimeTypes, tasks, - defaultTask, taskHistory) { + defaultTask, taskHistory, crostini) { /** * @private {!VolumeManager} * @const @@ -74,6 +75,12 @@ * @const */ this.taskHistory_ = taskHistory; + + /** + * @private {!Crostini} + * @const + */ + this.crostini_ = crostini; } FileTasks.prototype = { @@ -155,11 +162,12 @@ * @param {!Array<!Entry>} entries * @param {!Array<?string>} mimeTypes * @param {!TaskHistory} taskHistory + * @param {!Crostini} crostini * @return {!Promise<!FileTasks>} */ FileTasks.create = function( volumeManager, metadataModel, directoryModel, ui, entries, mimeTypes, - taskHistory) { + taskHistory, crostini) { var tasksPromise = new Promise(function(fulfill) { // getFileTasks supports only native entries. entries = entries.filter(util.isNativeEntry); @@ -181,9 +189,8 @@ // a dialog with an error message, similar to when attempting to run // Crostini tasks with non-Crostini entries. if (entries.length !== 1 || - !(Crostini.isCrostiniEntry(entries[0], volumeManager) || - Crostini.canSharePath( - entries[0], false /* persist */, volumeManager))) { + !(FileTasks.isCrostiniEntry(entries[0], volumeManager) || + crostini.canSharePath(entries[0], false /* persist */))) { taskItems = taskItems.filter(function(item) { var taskParts = item.taskId.split('|'); var appId = taskParts[0]; @@ -213,7 +220,7 @@ return Promise.all([tasksPromise, defaultTaskPromise]).then(function(args) { return new FileTasks( volumeManager, metadataModel, directoryModel, ui, entries, mimeTypes, - args[0], args[1], taskHistory); + args[0], args[1], taskHistory, crostini); }); }; @@ -549,6 +556,28 @@ }; /** + * @param {!Entry} entry + * @param {!VolumeManager} volumeManager + * @return {boolean} True if the entry is from crostini. + */ +FileTasks.isCrostiniEntry = function(entry, volumeManager) { + return volumeManager.getLocationInfo(entry).rootType === + VolumeManagerCommon.RootType.CROSTINI; +}; + +/** + * Returns true if task requires entries to be shared before executing task. + * @param {!chrome.fileManagerPrivate.FileTask} task Task to run. + * @return {boolean} true if task requires entries to be shared. + */ +FileTasks.taskRequiresCrostiniSharing = function(task) { + const taskParts = task.taskId.split('|'); + const taskType = taskParts[1]; + const actionId = taskParts[2]; + return taskType === 'crostini' || actionId === 'install-linux-package'; +}; + +/** * Checks if task is a crostini task and all entries are accessible to, or can * be shared with crostini. Shares files as required if possible and invokes * callback, or shows Unable to Open error dialog and does not invoke callback. @@ -560,7 +589,7 @@ FileTasks.prototype.maybeShareWithCrostiniOrShowDialog_ = function( task, callback) { // Check if this is a crostini task. - if (!Crostini.taskRequiresSharing(task)) + if (!FileTasks.taskRequiresCrostiniSharing(task)) return callback(); let showUnableToOpen = false; @@ -568,12 +597,11 @@ for (let i = 0; i < this.entries_.length; i++) { const entry = this.entries_[i]; - if (Crostini.isCrostiniEntry(entry, this.volumeManager_) || - Crostini.isPathShared(entry, this.volumeManager_)) { + if (FileTasks.isCrostiniEntry(entry, this.volumeManager_) || + this.crostini_.isPathShared(entry)) { continue; } - if (!Crostini.canSharePath( - entry, false /* persist */, this.volumeManager_)) { + if (!this.crostini_.canSharePath(entry, false /* persist */)) { showUnableToOpen = true; break; } @@ -613,7 +641,7 @@ } // Register paths as shared, and now we are ready to execute. entriesToShare.forEach((entry) => { - Crostini.registerSharedPath(entry, this.volumeManager_); + this.crostini_.registerSharedPath(entry); }); callback(); }); @@ -711,7 +739,7 @@ .create( this.volumeManager_, this.metadataModel_, this.directoryModel_, this.ui_, this.entries_, - this.mimeTypes_, this.taskHistory_) + this.mimeTypes_, this.taskHistory_, this.crostini_) .then( function(tasks) { tasks.executeDefault();
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.html b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.html index 2975c1c..61ff38c 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.html
@@ -12,9 +12,9 @@ <script src="../../common/js/file_type.js"></script> <script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/util.js"></script> +<script src="../../background/js/crostini.js"></script> <script src="constants.js"></script> <script src="web_store_utils.js"></script> -<script src="crostini.js"></script> <script src="file_tasks.js"></script> <script src="file_tasks_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js index 91f7d301..fe0f48e 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js
@@ -15,6 +15,7 @@ }; loadTimeData.data = { + DRIVE_FS_ENABLED: false, MORE_ACTIONS_BUTTON_LABEL: 'MORE_ACTIONS_BUTTON_LABEL', NO_TASK_FOR_EXECUTABLE: 'NO_TASK_FOR_EXECUTABLE', NO_TASK_FOR_FILE_URL: 'NO_TASK_FOR_FILE_URL', @@ -62,7 +63,7 @@ * @return {!FileManager} */ function getMockFileManager() { - return { + const result = { volumeManager: { getLocationInfo: function(entry) { return {rootType: VolumeManagerCommon.RootType.DRIVE}; @@ -77,15 +78,19 @@ } }, ui: { - alertDialog: {showHtml: function(title, text, onOk, onCancel, onShow) {}} + alertDialog: + {showHtml: function(title, text, onOk, onCancel, onShow) {}} }, metadataModel: {}, directoryModel: { getCurrentRootType: function() { return null; } - } + }, + crostini: new Crostini(), }; + result.crostini.init(result.volumeManager); + return result; } /** @@ -111,7 +116,7 @@ .create( fileManager.volumeManager, fileManager.metadataModel, fileManager.directoryModel, fileManager.ui, entries, [null], - mockTaskHistory) + mockTaskHistory, fileManager.crostini) .then(function(tasks) { tasks.executeDefault(); }); @@ -138,7 +143,7 @@ .create( fileManager.volumeManager, fileManager.metadataModel, fileManager.directoryModel, fileManager.ui, entries, mimeTypes, - mockTaskHistory) + mockTaskHistory, fileManager.crostini) .then(function(tasks) { tasks.executeDefault(); }); @@ -166,7 +171,7 @@ .create( fileManager.volumeManager, fileManager.metadataModel, fileManager.directoryModel, fileManager.ui, entries, mimeTypes, - mockTaskHistory) + mockTaskHistory, fileManager.crostini) .then(function(tasks) { tasks.executeDefault(); }); @@ -231,7 +236,7 @@ } } }, - [entry], ['application/rtf'], mockTaskHistory) + [entry], ['application/rtf'], mockTaskHistory, fileManager.crostini) .then(function(tasks) { tasks.openSuggestAppsDialog( function() {}, function() {}, function() {}); @@ -256,7 +261,7 @@ .create( fileManager.volumeManager, fileManager.metadataModel, fileManager.directoryModel, fileManager.ui, [entry], [null], - mockTaskHistory) + mockTaskHistory, fileManager.crostini) .then(function(tasks) { tasks.openSuggestAppsDialog(function() {}, function() {}, resolve); }); @@ -361,7 +366,7 @@ .create( fileManager.volumeManager, fileManager.metadataModel, fileManager.directoryModel, fileManager.ui, [mockEntry], [null], - taskHistory) + taskHistory, fileManager.crostini) .then(function(tasks) { tasks.executeDefault(); assertEquals(latestTaskId, executedTask); @@ -426,7 +431,7 @@ .create( fileManager.volumeManager, fileManager.metadataModel, fileManager.directoryModel, fileManager.ui, [mockEntry], [null], - taskHistory) + taskHistory, fileManager.crostini) .then(function(tasks) { tasks.executeDefault(); assertEquals(zipArchiverTaskId, executedTask); @@ -470,7 +475,7 @@ .create( fileManager.volumeManager, fileManager.metadataModel, fileManager.directoryModel, fileManager.ui, [mockEntry], [null], - mockTaskHistory) + mockTaskHistory, fileManager.crostini) .then(function(tasks) { tasks.executeDefault(); }); @@ -487,7 +492,11 @@ const mockFsDownloads = new MockFileSystem('downloads'); const sharedDir = new MockDirectoryEntry(mockFsDownloads, '/shared'); const shared = new MockFileEntry(mockFsDownloads, '/shared/file'); - Crostini.registerSharedPath(sharedDir, volumeManagerDownloads); + + const crostini = new Crostini(); + crostini.init(volumeManagerDownloads); + crostini.setEnabled(true); + crostini.registerSharedPath(sharedDir, volumeManagerDownloads); const notShared1 = new MockFileEntry(mockFsDownloads, '/notShared/file1'); const notShared2 = new MockFileEntry(mockFsDownloads, '/notShared/file2'); const otherNotShared = @@ -510,6 +519,7 @@ } const fakeFilesTask = { entries_: entries, + crostini_: crostini, ui_: { alertDialog: {showHtml: showHtml}, confirmDialog: {showHtml: showHtml}, @@ -530,12 +540,12 @@ expect('No entries', [], true, '', ''); - Crostini.IS_CROSTINI_FILES_ENABLED = false; + crostini.setEnabled(false); expect( 'Single entry, crostini-files not enabled', [notShared1], false, 'UNABLE_TO_OPEN_CROSTINI_TITLE', 'UNABLE_TO_OPEN_CROSTINI'); - Crostini.IS_CROSTINI_FILES_ENABLED = true; + crostini.setEnabled(true); expect('Single entry, not shared', [notShared1], true, '', ''); @@ -565,3 +575,15 @@ '2 entries, 1 not sharable', [notShared1, unsharable], false, 'UNABLE_TO_OPEN_CROSTINI_TITLE', 'UNABLE_TO_OPEN_CROSTINI'); } + +function task(id) { + return /** @type{!chrome.fileManagerPrivate.FileTask} */ ({taskId: id}); +} + +function testTaskRequiresCrostiniSharing() { + assertTrue( + FileTasks.taskRequiresCrostiniSharing(task('app|crostini|open-with'))); + assertTrue(FileTasks.taskRequiresCrostiniSharing( + task('appId|x|install-linux-package'))); + assertFalse(FileTasks.taskRequiresCrostiniSharing(task('appId|x|open-with'))); +}
diff --git a/ui/file_manager/file_manager/foreground/js/main_scripts.js b/ui/file_manager/file_manager/foreground/js/main_scripts.js index 83fee15..dd25735 100644 --- a/ui/file_manager/file_manager/foreground/js/main_scripts.js +++ b/ui/file_manager/file_manager/foreground/js/main_scripts.js
@@ -108,7 +108,6 @@ // <include src="actions_model.js"> // <include src="app_state_controller.js"> // <include src="column_visibility_controller.js"> -// <include src="crostini.js"> // <include src="dialog_action_controller.js"> // <include src="dialog_type.js"> // <include src="directory_contents.js">
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller.js b/ui/file_manager/file_manager/foreground/js/task_controller.js index 1ef5ead..6f73af9 100644 --- a/ui/file_manager/file_manager/foreground/js/task_controller.js +++ b/ui/file_manager/file_manager/foreground/js/task_controller.js
@@ -10,12 +10,13 @@ * @param {!DirectoryModel} directoryModel * @param {!FileSelectionHandler} selectionHandler * @param {!MetadataUpdateController} metadataUpdateController + * @param {!Crostini} crostini * @constructor * @struct */ function TaskController( dialogType, volumeManager, ui, metadataModel, directoryModel, - selectionHandler, metadataUpdateController) { + selectionHandler, metadataUpdateController, crostini) { /** * @private {DialogType} * @const @@ -60,6 +61,13 @@ this.metadataUpdateController_ = metadataUpdateController; /** + * @type {!Crostini} + * @const + * @private + */ + this.crostini_ = crostini; + + /** * @type {!TaskHistory} * @const * @private @@ -376,7 +384,7 @@ .create( this.volumeManager_, this.metadataModel_, this.directoryModel_, this.ui_, selection.entries, assert(selection.mimeTypes), - this.taskHistory_) + this.taskHistory_, this.crostini_) .then(function(tasks) { if (this.selectionHandler_.selection !== selection) { if (util.isSameEntries(this.tasksEntries_, selection.entries)) @@ -467,7 +475,7 @@ .create( this.volumeManager_, this.metadataModel_, this.directoryModel_, this.ui_, [entry], [props[0].contentMimeType || null], - this.taskHistory_) + this.taskHistory_, this.crostini_) .then(function(tasks) { tasks.executeDefault(); });
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html index 3f2f704..23b3f0ef 100644 --- a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html
@@ -20,7 +20,7 @@ <script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/util.js"></script> <script src="../../../base/js/volume_manager_types.js"></script> -<script src="crostini.js"></script> +<script src="../../background/js/crostini.js"></script> <script src="dialog_type.js"></script> <script src="file_selection.js"></script> <script src="file_tasks.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.js b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.js index 5fbac07..6a4a737 100644 --- a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.js
@@ -2,6 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +window.loadTimeData = { + getBoolean: function(key) { + return false; + } +}; + window.metrics = { recordEnum: function() {} }; @@ -31,6 +37,16 @@ cr.ui.decorate('command', cr.ui.Command); } +function createCrostini() { + const crostini = new Crostini(); + crostini.init({ + getLocationInfo: () => { + return 'test'; + } + }); + return crostini; +} + function testExecuteEntryTask(callback) { window.chrome.fileManagerPrivate = { getFileTasks: function(entries, callback) { @@ -72,7 +88,7 @@ return null; } }, - new cr.EventTarget(), null); + new cr.EventTarget(), null, createCrostini()); controller.executeEntryTask(fileSystem.entries['/test.png']); reportPromise(new Promise(function(fulfill) { @@ -141,7 +157,7 @@ return null; } }, - selectionHandler, null); + selectionHandler, null, createCrostini()); } // TaskController.getFileTasks should not call fileManagerPrivate.getFileTasks
diff --git a/ui/file_manager/file_manager/test/BUILD.gn b/ui/file_manager/file_manager/test/BUILD.gn index e3ec2a5..5808d27 100644 --- a/ui/file_manager/file_manager/test/BUILD.gn +++ b/ui/file_manager/file_manager/test/BUILD.gn
@@ -57,6 +57,7 @@ "$externs_path/metrics_private.js", "../../externs/app_window_common.js", "../../externs/background/file_browser_background.js", + "../../externs/background/crostini.js", "../../externs/entry_location.js", "../../externs/volume_info.js", "../../externs/volume_info_list.js", @@ -74,7 +75,6 @@ js_library("crostini_mount") { deps = [ - "../foreground/js:crostini", "js:test_util", "//ui/webui/resources/js:webui_resource_test", ] @@ -82,7 +82,6 @@ js_library("crostini_share") { deps = [ - "../foreground/js:crostini", "js:test_util", "//ui/webui/resources/js:webui_resource_test", ] @@ -90,7 +89,6 @@ js_library("crostini_tasks") { deps = [ - "../foreground/js:crostini", "js:test_util", "//ui/webui/resources/js:webui_resource_test", ]
diff --git a/ui/file_manager/file_manager/test/crostini_share.js b/ui/file_manager/file_manager/test/crostini_share.js index 9f790d0..77d970af 100644 --- a/ui/file_manager/file_manager/test/crostini_share.js +++ b/ui/file_manager/file_manager/test/crostini_share.js
@@ -9,7 +9,14 @@ '[command="#share-with-linux"][hidden][disabled="disabled"]'; const menuShareWithLinux = '#file-context-menu:not([hidden]) ' + '[command="#share-with-linux"]:not([hidden]):not([disabled])'; + const shareWithLinux = '#file-context-menu [command="#share-with-linux"]'; + const menuShareWithLinuxDirTree = + '#directory-tree-context-menu:not([hidden]) ' + + '[command="#share-with-linux"]:not([hidden]):not([disabled])'; + const shareWithLinuxDirTree = + '#directory-tree-context-menu [command="#share-with-linux"]'; const photos = '#file-list [file-name="photos"]'; + const downloadsDirTree = '#directory-tree [volume-type-icon="downloads"]'; const oldSharePaths = chrome.fileManagerPrivate.sharePathsWithCrostini; let sharePathsCalled = false; let sharePathsPersist; @@ -21,11 +28,11 @@ callback(); }); }; - const oldCrostiniUnregister = Crostini.unregisterSharedPath; + const oldCrostiniUnregister = fileManager.crostini.unregisterSharedPath; let unregisterCalled = false; - Crostini.unregisterSharedPath = function(entry, volumeManager) { + fileManager.crostini.unregisterSharedPath = function(entry) { unregisterCalled = true; - oldCrostiniUnregister(entry, volumeManager); + oldCrostiniUnregister.call(fileManager.crostini, entry); }; chrome.metricsPrivate.smallCounts_ = []; chrome.metricsPrivate.values_ = []; @@ -39,10 +46,7 @@ }) .then(() => { // Click on 'Share with Linux'. - assertTrue( - test.fakeMouseClick( - '#file-context-menu [command="#share-with-linux"]'), - 'Share with Linux'); + assertTrue(test.fakeMouseClick(shareWithLinux, 'Share with Linux')); // Check sharePathsWithCrostini is called. return test.repeatUntil(() => { return sharePathsCalled || test.pending('wait for sharePathsCalled'); @@ -87,10 +91,29 @@ return test.waitForElement(menuShareWithLinux); }) .then(() => { + // Verify dialog is shown for Downloads root. + // Check 'Share with Linux' is shown in menu. + assertTrue( + test.fakeMouseRightClick(downloadsDirTree), + 'right-click downloads'); + return test.waitForElement(menuShareWithLinuxDirTree); + }) + .then(() => { + // Click 'Share with Linux', verify dialog. + assertTrue( + test.fakeMouseClick(shareWithLinuxDirTree, 'Share with Linux')); + return test.waitForElement('.cr-dialog-container.shown'); + }) + .then(() => { + // Click Cancel button to close. + assertTrue(test.fakeMouseClick('button.cr-dialog-cancel')); + return test.waitForElementLost('.cr-dialog-container'); + }) + .then(() => { // Restore fmp.*. chrome.fileManagerPrivate.sharePathsWithCrostini = oldSharePaths; - // Restore Crostini.unregisterSharedPath; - Crostini.unregisterSharedPath = oldCrostiniUnregister; + // Restore Crostini.unregisterSharedPath. + fileManager.crostini.unregisterSharedPath = oldCrostiniUnregister; done(); }); }; @@ -136,7 +159,7 @@ .getCurrentProfileVolumeInfo( VolumeManagerCommon.VolumeType.DOWNLOADS) .fileSystem.entries['/photos']; - Crostini.registerSharedPath(alreadySharedPhotosDir, mockVolumeManager); + fileManager.crostini.registerSharedPath(alreadySharedPhotosDir); assertTrue( test.fakeMouseRightClick('#file-list [file-name="photos"]'), 'right-click hello.txt'); @@ -229,8 +252,7 @@ // Unset DRIVE_FS_ENABLED. loadTimeData.data_['DRIVE_FS_ENABLED'] = false; // Clear Crostini shared folders. - Crostini.unregisterSharedPath( - alreadySharedPhotosDir, mockVolumeManager); + fileManager.crostini.unregisterSharedPath(alreadySharedPhotosDir); done(); }); }; @@ -247,13 +269,7 @@ test.setupAndWaitUntilReady() .then(() => { // Setup with crostini disabled. - chrome.fileManagerPrivate.crostiniEnabled_ = false; - fileManager.setupCrostini_(); - return test.repeatUntil( - () => !Crostini.IS_CROSTINI_FILES_ENABLED || - test.pending('crostini setup')); - }) - .then(() => { + fileManager.crostini.setEnabled(false); // Click gear menu, ensure 'Manage Linux sharing' is hidden. assertTrue(test.fakeMouseClick('#gear-button')); return test.waitForElement(manageLinuxSharingOptionHidden); @@ -265,13 +281,7 @@ }) .then(() => { // Setup with crostini enabled. - chrome.fileManagerPrivate.crostiniEnabled_ = true; - fileManager.setupCrostini_(); - return test.repeatUntil( - () => Crostini.IS_CROSTINI_FILES_ENABLED || - test.pending('crostini setup')); - }) - .then(() => { + fileManager.crostini.setEnabled(true); // Click gear menu, ensure 'Manage Linux sharing' is shown. assertTrue(test.fakeMouseClick('#gear-button')); return test.waitForElement(manageLinuxSharingOptionShown);
diff --git a/ui/file_manager/file_manager/test/js/externs.js b/ui/file_manager/file_manager/test/js/externs.js index 081425f..0edee71 100644 --- a/ui/file_manager/file_manager/test/js/externs.js +++ b/ui/file_manager/file_manager/test/js/externs.js
@@ -10,7 +10,10 @@ ChromeEvent.prototype.dispatchEvent = (var_args) => {}; /** @constructor */ -function FileManager() {} +function FileManager() { + /** @type {Crostini} */ + this.crostini; +} FileManager.prototype.setupCrostini_ = () => {}; /** @type {string} */
diff --git a/ui/views/test/ui_controls_factory_desktop_aurax11.cc b/ui/views/test/ui_controls_factory_desktop_aurax11.cc index 3ec1dcb..0180b30d 100644 --- a/ui/views/test/ui_controls_factory_desktop_aurax11.cc +++ b/ui/views/test/ui_controls_factory_desktop_aurax11.cc
@@ -250,12 +250,11 @@ DesktopWindowTreeHostX11::GetAllOpenWindows(); for (std::vector<aura::Window*>::const_iterator it = windows.begin(); it != windows.end(); ++it) { - if ((*it)->GetBoundsInScreen().Contains(point)) { + if ((*it)->GetBoundsInScreen().Contains(point) || (*it)->HasCapture()) return (*it)->GetRootWindow(); - } } - NOTREACHED() << "Coulding find RW for " << point.ToString() << " among " + NOTREACHED() << "Couldn't find RW for " << point.ToString() << " among " << windows.size() << " RWs."; return NULL; }
diff --git a/ui/webui/resources/js/action_link.js b/ui/webui/resources/js/action_link.js index ac67d32..99dc0fd 100644 --- a/ui/webui/resources/js/action_link.js +++ b/ui/webui/resources/js/action_link.js
@@ -27,90 +27,78 @@ // // NOTE: <action-link> and document.createElement('action-link') don't work. -/** - * See crbug.com/837381 - * @suppress {deprecated} - * - * @constructor - * @extends {HTMLAnchorElement} - */ -var ActionLink = document.registerElement('action-link', { - prototype: { - __proto__: HTMLAnchorElement.prototype, +class ActionLink extends HTMLAnchorElement { + connectedCallback() { + // Action links can start disabled (e.g. <a is="action-link" disabled>). + this.tabIndex = this.disabled ? -1 : 0; - /** @this {ActionLink} */ - createdCallback: function() { - // Action links can start disabled (e.g. <a is="action-link" disabled>). - this.tabIndex = this.disabled ? -1 : 0; + if (!this.hasAttribute('role')) + this.setAttribute('role', 'link'); - if (!this.hasAttribute('role')) - this.setAttribute('role', 'link'); - - this.addEventListener('keydown', function(e) { - if (!this.disabled && e.key == 'Enter' && !this.href) { - // Schedule a click asynchronously because other 'keydown' handlers - // may still run later (e.g. document.addEventListener('keydown')). - // Specifically options dialogs break when this timeout isn't here. - // NOTE: this affects the "trusted" state of the ensuing click. I - // haven't found anything that breaks because of this (yet). - window.setTimeout(this.click.bind(this), 0); - } - }); - - function preventDefault(e) { - e.preventDefault(); + this.addEventListener('keydown', function(e) { + if (!this.disabled && e.key == 'Enter' && !this.href) { + // Schedule a click asynchronously because other 'keydown' handlers + // may still run later (e.g. document.addEventListener('keydown')). + // Specifically options dialogs break when this timeout isn't here. + // NOTE: this affects the "trusted" state of the ensuing click. I + // haven't found anything that breaks because of this (yet). + window.setTimeout(this.click.bind(this), 0); } + }); - function removePreventDefault() { - document.removeEventListener('selectstart', preventDefault); - document.removeEventListener('mouseup', removePreventDefault); - } + function preventDefault(e) { + e.preventDefault(); + } - this.addEventListener('mousedown', function() { - // This handlers strives to match the behavior of <a href="...">. + function removePreventDefault() { + document.removeEventListener('selectstart', preventDefault); + document.removeEventListener('mouseup', removePreventDefault); + } - // While the mouse is down, prevent text selection from dragging. - document.addEventListener('selectstart', preventDefault); - document.addEventListener('mouseup', removePreventDefault); + this.addEventListener('mousedown', function() { + // This handlers strives to match the behavior of <a href="...">. - // If focus started via mouse press, don't show an outline. - if (document.activeElement != this) - this.classList.add('no-outline'); - }); + // While the mouse is down, prevent text selection from dragging. + document.addEventListener('selectstart', preventDefault); + document.addEventListener('mouseup', removePreventDefault); - this.addEventListener('blur', function() { - this.classList.remove('no-outline'); - }); - }, + // If focus started via mouse press, don't show an outline. + if (document.activeElement != this) + this.classList.add('no-outline'); + }); - /** @type {boolean} */ - set disabled(disabled) { - if (disabled) - HTMLAnchorElement.prototype.setAttribute.call(this, 'disabled', ''); - else - HTMLAnchorElement.prototype.removeAttribute.call(this, 'disabled'); - this.tabIndex = disabled ? -1 : 0; - }, - get disabled() { - return this.hasAttribute('disabled'); - }, + this.addEventListener('blur', function() { + this.classList.remove('no-outline'); + }); + } - /** @override */ - setAttribute: function(attr, val) { - if (attr.toLowerCase() == 'disabled') - this.disabled = true; - else - HTMLAnchorElement.prototype.setAttribute.apply(this, arguments); - }, + /** @param {boolean} disabled */ + set disabled(disabled) { + if (disabled) + HTMLAnchorElement.prototype.setAttribute.call(this, 'disabled', ''); + else + HTMLAnchorElement.prototype.removeAttribute.call(this, 'disabled'); + this.tabIndex = disabled ? -1 : 0; + } - /** @override */ - removeAttribute: function(attr) { - if (attr.toLowerCase() == 'disabled') - this.disabled = false; - else - HTMLAnchorElement.prototype.removeAttribute.apply(this, arguments); - }, - }, + get disabled() { + return this.hasAttribute('disabled'); + } - extends: 'a', -}); + /** @override */ + setAttribute(attr, val) { + if (attr.toLowerCase() == 'disabled') + this.disabled = true; + else + HTMLAnchorElement.prototype.setAttribute.apply(this, arguments); + } + + /** @override */ + removeAttribute(attr) { + if (attr.toLowerCase() == 'disabled') + this.disabled = false; + else + HTMLAnchorElement.prototype.removeAttribute.apply(this, arguments); + } +} +customElements.define('action-link', ActionLink, {extends: 'a'});
diff --git a/ui/webui/resources/polymer_resources.grdp b/ui/webui/resources/polymer_resources.grdp index 42592aee..dd298988 100644 --- a/ui/webui/resources/polymer_resources.grdp +++ b/ui/webui/resources/polymer_resources.grdp
@@ -128,14 +128,16 @@ file="../../../third_party/polymer/v1_0/components-chromium/iron-iconset-svg/iron-iconset-svg.html" type="chrome_html" compress="gzip" /> - <structure name="IDR_POLYMER_1_0_IRON_INPUT_IRON_INPUT_EXTRACTED_JS" - file="../../../third_party/polymer/v1_0/components-chromium/iron-input/iron-input-extracted.js" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_POLYMER_1_0_IRON_INPUT_IRON_INPUT_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/iron-input/iron-input.html" - type="chrome_html" - compress="gzip" /> + <if expr="chromeos"> + <structure name="IDR_POLYMER_1_0_IRON_INPUT_IRON_INPUT_EXTRACTED_JS" + file="../../../third_party/polymer/v1_0/components-chromium/iron-input/iron-input-extracted.js" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_POLYMER_1_0_IRON_INPUT_IRON_INPUT_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/iron-input/iron-input.html" + type="chrome_html" + compress="gzip" /> + </if> <structure name="IDR_POLYMER_1_0_IRON_LIST_IRON_LIST_EXTRACTED_JS" file="../../../third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js" type="chrome_html" @@ -540,50 +542,52 @@ file="../../../third_party/polymer/v1_0/components-chromium/paper-icon-button/paper-icon-button.html" type="chrome_html" compress="gzip" /> - <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_ADDON_BEHAVIOR_EXTRACTED_JS" - file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-addon-behavior-extracted.js" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_ADDON_BEHAVIOR_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-addon-behavior.html" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_CONTAINER_EXTRACTED_JS" - file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container-extracted.js" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_CONTAINER_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container.html" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_ERROR_EXTRACTED_JS" - file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-error-extracted.js" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_ERROR_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-error.html" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ICON_ITEM_EXTRACTED_JS" - file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item-extracted.js" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ICON_ITEM_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item.html" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ITEM_BEHAVIOR_EXTRACTED_JS" - file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior-extracted.js" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ITEM_BEHAVIOR_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior.html" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ITEM_SHARED_STYLES_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item-shared-styles.html" - type="chrome_html" - compress="gzip" /> + <if expr="chromeos"> + <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_ADDON_BEHAVIOR_EXTRACTED_JS" + file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-addon-behavior-extracted.js" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_ADDON_BEHAVIOR_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-addon-behavior.html" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_CONTAINER_EXTRACTED_JS" + file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container-extracted.js" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_CONTAINER_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container.html" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_ERROR_EXTRACTED_JS" + file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-error-extracted.js" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_POLYMER_1_0_PAPER_INPUT_PAPER_INPUT_ERROR_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-error.html" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ICON_ITEM_EXTRACTED_JS" + file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item-extracted.js" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ICON_ITEM_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item.html" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ITEM_BEHAVIOR_EXTRACTED_JS" + file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior-extracted.js" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ITEM_BEHAVIOR_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior.html" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ITEM_SHARED_STYLES_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item-shared-styles.html" + type="chrome_html" + compress="gzip" /> + </if> <structure name="IDR_POLYMER_1_0_PAPER_PROGRESS_PAPER_PROGRESS_EXTRACTED_JS" file="../../../third_party/polymer/v1_0/components-chromium/paper-progress/paper-progress-extracted.js" type="chrome_html"
diff --git a/ui/wm/core/window_animations_unittest.cc b/ui/wm/core/window_animations_unittest.cc index f8e993a..dfd3127 100644 --- a/ui/wm/core/window_animations_unittest.cc +++ b/ui/wm/core/window_animations_unittest.cc
@@ -50,8 +50,6 @@ public: WindowAnimationsTest() {} - void TearDown() override { AuraTestBase::TearDown(); } - private: DISALLOW_COPY_AND_ASSIGN(WindowAnimationsTest); };